Commit fc4a2462 authored by Administrator's avatar Administrator

first version of bargraph

parent d3702dc9
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.7/","dependencies":[]}],"android":[{"name":"flutter_secure_storage","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.7/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]},{"name":"shared_preferences_macos","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_macos-0.0.1+8/","dependencies":[]},{"name":"sqflite","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"url_launcher_macos","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+5/","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_web-0.1.2+5/","dependencies":[]},{"name":"url_launcher_web","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.1+5/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]},{"name":"uni_links","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]}],"date_created":"2020-05-29 07:02:43.692335","version":"1.17.1"}
\ No newline at end of file
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.7/","dependencies":[]}],"android":[{"name":"flutter_secure_storage","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.7/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]},{"name":"shared_preferences_macos","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_macos-0.0.1+8/","dependencies":[]},{"name":"sqflite","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"url_launcher_macos","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+5/","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_web-0.1.2+5/","dependencies":[]},{"name":"url_launcher_web","path":"/home/stefan/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.1+5/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]},{"name":"uni_links","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]}],"date_created":"2020-05-29 09:43:01.135624","version":"1.17.1"}
\ No newline at end of file
import 'package:encrateia/models/power_zone.dart';
import 'heart_rate_zone.dart';
class BarZone {
BarZone({this.lower, this.upper, this.color});
static List<BarZone> fromPowerZones(
List<PowerZone> powerZones,
) {
return <BarZone>[
for (final PowerZone powerZone in powerZones)
BarZone(
lower: powerZone.db.lowerLimit.toDouble(),
upper: powerZone.db.upperLimit.toDouble(),
color: powerZone.db.color,
)
];
}
static List<BarZone> fromHeartRateZones(
List<HeartRateZone> heartRateZones,
) {
return <BarZone>[
for (final HeartRateZone heartRateZone in heartRateZones)
BarZone(
lower: heartRateZone.db.lowerLimit.toDouble(),
upper: heartRateZone.db.upperLimit.toDouble(),
color: heartRateZone.db.color,
)
];
}
double lower;
double upper;
int color;
}
import 'package:encrateia/models/athlete.dart';
import 'package:encrateia/utils/my_color.dart';
import 'package:encrateia/widgets/activity_widgets/activity_bargraph_widget.dart';
import 'package:encrateia/widgets/activity_widgets/activity_metadata_widget.dart';
import 'package:encrateia/widgets/activity_widgets/activity_overview_widget.dart';
import 'package:encrateia/widgets/activity_widgets/activity_power_ratio_widget.dart';
......@@ -70,6 +71,16 @@ class _ShowActivityScreenState extends State<ShowActivityScreen> {
athlete: widget.athlete,
),
),
navigationButton(
color: MyColor.settings,
title: 'Bargraphs',
icon: MyIcon.barGraph,
context: context,
nextWidget: ActivityBarGraphWidget(
activity: widget.activity,
athlete: widget.athlete,
),
),
navigationButton(
title: 'Laps List',
color: MyColor.lap,
......
import 'package:encrateia/models/bar_zone.dart';
import 'package:encrateia/utils/my_color.dart';
import 'package:flutter/material.dart';
class BarChartPainter extends CustomPainter {
BarChartPainter({
@required this.width,
@required this.height,
@required this.value,
@required this.maximum,
@required this.minimum,
@required this.barZones,
});
final double width;
final double height;
final double value;
final double maximum;
final double minimum;
final double strokeWidth = 2;
final List<BarZone> barZones;
@override
void paint(Canvas canvas, Size size) {
canvas.drawRect(
Rect.fromPoints(
Offset(0 + strokeWidth / 2, strokeWidth / 2),
Offset(width - strokeWidth / 2, height - strokeWidth / 2),
),
Paint()
..color = MyColor.darkGray
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth,
);
if (barZones.isEmpty) {
final double barWidth =
(width - strokeWidth) / (maximum - minimum) * (value - minimum);
canvas.drawRect(
Rect.fromPoints(
Offset(0 + strokeWidth, strokeWidth),
Offset(barWidth, height - strokeWidth),
),
Paint()
..color = MyColor.grapeFruit
..strokeWidth = strokeWidth
..style = PaintingStyle.fill);
} else {
for (final BarZone barZone in barZones) {
double lowerInPixel;
double upperInPixel;
if (value < barZone.lower) continue;
if (value >= barZone.upper) {
lowerInPixel = (width - 2 * strokeWidth) /
(maximum - minimum) *
(barZone.lower - minimum) +
strokeWidth;
upperInPixel = (width - 2 * strokeWidth) /
(maximum - minimum) *
(barZone.upper - minimum) +
strokeWidth;
} else {
lowerInPixel = (width - 2 * strokeWidth) /
(maximum - minimum) *
(barZone.lower - minimum) +
strokeWidth;
upperInPixel = (width - 2 * strokeWidth) /
(maximum - minimum) *
(value - minimum) +
strokeWidth;
}
canvas.drawRect(
Rect.fromPoints(
Offset(lowerInPixel, strokeWidth),
Offset(upperInPixel, height - strokeWidth),
),
Paint()
..color = Color(barZone.color)
..strokeWidth = strokeWidth
..style = PaintingStyle.fill);
}
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
......@@ -14,6 +14,7 @@ class MyIcon {
);
static final Icon average = Icon(Icons.filter_tilt_shift);
// B
static final Icon barGraph = Icon(Icons.storage);
static final Icon brokenConnection = Icon(Icons.link_off);
// C
static final Icon cadence = Icon(Icons.pets);
......@@ -52,7 +53,7 @@ class MyIcon {
static final Icon legSpringStiffness = Icon(Icons.airline_seat_recline_extra);
// M
static final Icon maximum = Icon(Icons.expand_less);
static final Icon metaData = Icon(Icons.storage);
static final Icon metaData = Icon(Icons.list);
static final Icon minimum = Icon(Icons.expand_more);
// N
static final Icon number = amount;
......
import 'dart:math' as math;
import 'package:encrateia/models/bar_zone.dart';
import 'package:encrateia/models/heart_rate_zone.dart';
import 'package:encrateia/models/power_zone.dart';
import 'package:flutter/material.dart';
import 'bar_chart_painter.dart';
class MyBarChart extends StatelessWidget {
MyBarChart({
int width,
int height,
@required num value,
num maximum,
num minimum,
List<PowerZone> powerZones,
List<HeartRateZone> heartRateZones,
}) : _width = width?.toDouble() ?? 300.0,
_height = height?.toDouble() ?? 30.0,
_value = value.toDouble(),
_maximum = maxFromZones(
powerZones: powerZones,
heartRateZones: heartRateZones,
maximum: maximum,
),
_minimum = minFromZones(
powerZones: powerZones,
heartRateZones: heartRateZones,
minimum: minimum,
),
_barZones = toBarZones(
powerZones: powerZones,
heartRateZones: heartRateZones,
);
final double _width;
final double _height;
final double _value;
final double _maximum;
final double _minimum;
final List<BarZone> _barZones;
@override
Widget build(BuildContext context) {
return SizedBox(
width: _width,
height: _height,
child: CustomPaint(
painter: BarChartPainter(
width: _width,
height: _height,
value: _value,
maximum: _maximum,
minimum: _minimum,
barZones: _barZones,
),
),
);
}
static List<BarZone> toBarZones({
List<PowerZone> powerZones,
List<HeartRateZone> heartRateZones,
}) {
if (powerZones != null)
return BarZone.fromPowerZones(powerZones);
else if (heartRateZones != null)
return BarZone.fromHeartRateZones(heartRateZones);
else
return <BarZone>[];
}
static double maxFromZones(
{List<PowerZone> powerZones,
List<HeartRateZone> heartRateZones,
num maximum}) {
if (maximum != null)
return maximum.toDouble();
else if (powerZones != null)
return powerZones
.map((PowerZone powerZone) => powerZone.db.upperLimit.toDouble())
.reduce(math.max);
else if (heartRateZones != null)
return heartRateZones
.map((HeartRateZone heartRateZone) =>
heartRateZone.db.upperLimit.toDouble())
.reduce(math.max);
else
return 100.0;
}
static double minFromZones(
{List<PowerZone> powerZones,
List<HeartRateZone> heartRateZones,
num minimum}) {
if (minimum != null)
return minimum.toDouble();
else if (powerZones != null)
return powerZones
.map((PowerZone powerZone) => powerZone.db.lowerLimit.toDouble())
.reduce(math.min);
else if (heartRateZones != null)
return heartRateZones
.map((HeartRateZone heartRateZone) =>
heartRateZone.db.lowerLimit.toDouble())
.reduce(math.min);
else
return 0.0;
}
}
import 'package:encrateia/models/heart_rate_zone.dart';
import 'package:encrateia/models/heart_rate_zone_schema.dart';
import 'package:encrateia/models/athlete.dart';
import 'package:encrateia/models/lap.dart';
import 'package:encrateia/models/power_zone.dart';
import 'package:encrateia/models/power_zone_schema.dart';
import 'package:encrateia/utils/my_bar_chart.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:encrateia/models/activity.dart';
......@@ -24,6 +27,7 @@ class _ActivityBarGraphWidgetState extends State<ActivityBarGraphWidget> {
HeartRateZoneSchema _heartRateZoneSchema;
List<PowerZone> _powerZones = <PowerZone>[];
List<HeartRateZone> _heartRateZones = <HeartRateZone>[];
List<Lap> _laps = <Lap>[];
@override
void initState() {
......@@ -33,22 +37,96 @@ class _ActivityBarGraphWidgetState extends State<ActivityBarGraphWidget> {
@override
Widget build(BuildContext context) {
return const Text('hi!');
if (_powerZones.isNotEmpty && _laps.isNotEmpty) {
return DataTable(
showCheckboxColumn: false,
onSelectAll: (_) {},
columns: const <DataColumn>[
DataColumn(label: Text('Title'), numeric: false),
DataColumn(label: Text('Value'), numeric: true),
DataColumn(label: Text('Bar'), numeric: false),
],
rows: <DataRow>[
const DataRow(cells: <DataCell>[
DataCell(Text('Power')),
DataCell(Text('')),
DataCell(Text('')),
]),
DataRow(cells: <DataCell>[
const DataCell(Text('Activity')),
DataCell(
Text(widget.activity.db.avgPower.toStringAsFixed(1)),
),
DataCell(
MyBarChart(
value: widget.activity.db.avgPower,
powerZones: _powerZones,
),
),
]),
for (Lap lap in _laps)
DataRow(cells: <DataCell>[
DataCell(Text('Lap ' + lap.index.toString())),
DataCell(
Text(lap.db.avgPower.toStringAsFixed(1)),
),
DataCell(
MyBarChart(
value: lap.db.avgPower,
powerZones: _powerZones,
),
),
]),
const DataRow(cells: <DataCell>[
DataCell(Text('Heart Rate')),
DataCell(Text('')),
DataCell(Text('')),
]),
DataRow(cells: <DataCell>[
const DataCell(Text('Activity')),
DataCell(Text(
widget.activity.db.avgHeartRate.toString(),
)),
DataCell(
MyBarChart(
value: widget.activity.db.avgHeartRate,
heartRateZones: _heartRateZones,
),
)
]),
for (Lap lap in _laps)
DataRow(cells: <DataCell>[
DataCell(Text('Lap ' + lap.index.toString())),
DataCell(
Text(lap.db.avgHeartRate.toString()),
),
DataCell(
MyBarChart(
value: lap.db.avgHeartRate,
heartRateZones: _heartRateZones,
),
),
]),
]);
} else {
return const Center(
child: Text('Loading'),
);
}
}
Future<void> getData() async {
final Activity activity = widget.activity;
_laps = await activity.laps;
_powerZoneSchema = await activity.powerZoneSchema;
if (_powerZoneSchema != null)
_powerZones = await _powerZoneSchema.powerZones;
print(_powerZones.length);
_heartRateZoneSchema = await activity.heartRateZoneSchema;
if (_heartRateZoneSchema != null)
_heartRateZones = await _heartRateZoneSchema.heartRateZones;
print(_heartRateZones.length);
setState(() {});
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment