Commit e0533981 authored by Stefan Haslinger's avatar Stefan Haslinger

transfer selection on interval screen into corresponding record

parent 51c85003
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.10/","dependencies":[]}],"android":[{"name":"flutter_secure_storage","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.10/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]},{"name":"shared_preferences_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_macos-0.0.1+8/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"url_launcher_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+5/","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_web-0.1.2+5/","dependencies":[]},{"name":"url_launcher_web","path":"/daten/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-07-24 11:46:33.173231","version":"1.17.5"}
\ 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":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.10/","dependencies":[]}],"android":[{"name":"flutter_secure_storage","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.10/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]},{"name":"shared_preferences_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_macos-0.0.1+8/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"url_launcher_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+5/","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_web-0.1.2+5/","dependencies":[]},{"name":"url_launcher_web","path":"/daten/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-07-24 14:01:48.348055","version":"1.17.5"}
\ No newline at end of file
......@@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:encrateia/models/activity.dart';
import 'package:encrateia/models/event.dart';
import 'package:encrateia/widgets/charts/activity_charts/activity_intervals_chart.dart';
import 'package:encrateia/utils/icon_utils.dart';
class ActivityIntervalsWidget extends StatefulWidget {
const ActivityIntervalsWidget({
......@@ -16,7 +15,8 @@ class ActivityIntervalsWidget extends StatefulWidget {
final Athlete athlete;
@override
_ActivityIntervalsWidgetState createState() => _ActivityIntervalsWidgetState();
_ActivityIntervalsWidgetState createState() =>
_ActivityIntervalsWidgetState();
}
class _ActivityIntervalsWidgetState extends State<ActivityIntervalsWidget> {
......@@ -38,39 +38,12 @@ class _ActivityIntervalsWidgetState extends State<ActivityIntervalsWidget> {
.toList();
if (paceRecords.isNotEmpty) {
return ListTileTheme(
iconColor: Colors.deepOrange,
child: ListView(
padding: const EdgeInsets.only(left: 25),
children: <Widget>[
ActivityIntervalsChart(
records: RecordList<Event>(paceRecords),
activity: widget.activity,
athlete: widget.athlete,
minimum: widget.activity.avgSpeed * 3.6 / 2,
maximum: widget.activity.avgSpeed * 3.6 * 2,
),
Text('${widget.athlete.recordAggregationCount} records are '
'aggregated into one point in the plot. Only records where '
'speed > 0 m/s are shown.'),
const Divider(),
ListTile(
leading: MyIcon.average,
title: Text(avgSpeedString),
subtitle: const Text('average speed'),
),
ListTile(
leading: MyIcon.standardDeviation,
title: Text(sdevSpeedString),
subtitle: const Text('standard deviation speed'),
),
ListTile(
leading: MyIcon.amount,
title: Text(paceRecords.length.toString()),
subtitle: const Text('number of measurements'),
),
],
),
return ActivityIntervalsChart(
records: RecordList<Event>(paceRecords),
activity: widget.activity,
athlete: widget.athlete,
minimum: widget.activity.avgSpeed * 3.6 / 1.5,
maximum: widget.activity.avgSpeed * 3.6 * 1.5,
);
} else {
return const Center(
......@@ -87,9 +60,7 @@ class _ActivityIntervalsWidgetState extends State<ActivityIntervalsWidget> {
Future<void> getData() async {
final Activity activity = widget.activity;
records = RecordList<Event>(await activity.records);
avgSpeedString =
activity.avgSpeed != null ? (activity.avgSpeed * 3.6).toStringAsFixed(2) + 'km/h' : '- - -';
sdevSpeedString = (activity.sdevSpeed * 3.6).toStringAsFixed(2) + ' km/h';
avgSpeedString = (activity.avgSpeed * 3.6).toStringAsFixed(2) + 'km/h';
setState(() {});
}
}
......@@ -7,10 +7,10 @@ import 'package:encrateia/models/event.dart';
import 'package:encrateia/models/lap.dart';
import 'package:encrateia/models/plot_point.dart';
import 'package:encrateia/utils/graph_utils.dart';
import 'package:encrateia/utils/my_line_chart.dart';
import 'package:encrateia/utils/enums.dart';
import 'package:charts_common/common.dart' as common show ChartBehavior;
class ActivityIntervalsChart extends StatelessWidget {
class ActivityIntervalsChart extends StatefulWidget {
const ActivityIntervalsChart({
this.records,
@required this.activity,
......@@ -25,14 +25,42 @@ class ActivityIntervalsChart extends StatelessWidget {
final double minimum;
final double maximum;
@override
_ActivityIntervalsChartState createState() => _ActivityIntervalsChartState();
}
class _ActivityIntervalsChartState extends State<ActivityIntervalsChart> {
DoublePlotPoint selectedPlotPoint;
Event selectedRecord;
List<Lap> laps = <Lap>[];
@override
void initState() {
getData();
super.initState();
}
void _onSelectionChanged(SelectionModel<num> model) {
final List<SeriesDatum<dynamic>> selectedDatum = model.selectedDatum;
if (selectedDatum.isNotEmpty) {
selectedPlotPoint = selectedDatum[0].datum as DoublePlotPoint;
selectedRecord = widget.records.firstWhere(
(Event record) => record.distance.round() == selectedPlotPoint.domain);
setState(() {});
}
}
@override
Widget build(BuildContext context) {
final List<DoublePlotPoint> smoothedRecords = records.toDoubleDataPoints(
final List<DoublePlotPoint> smoothedRecords =
widget.records.toDoubleDataPoints(
attribute: LapDoubleAttr.speed,
amount: athlete.recordAggregationCount,
amount: widget.athlete.recordAggregationCount,
);
final List<Series<DoublePlotPoint, int>> data = <Series<DoublePlotPoint, int>>[
final List<Series<DoublePlotPoint, int>> data =
<Series<DoublePlotPoint, int>>[
Series<DoublePlotPoint, int>(
id: 'Speed',
colorFn: (_, __) => Color.black,
......@@ -42,31 +70,60 @@ class ActivityIntervalsChart extends StatelessWidget {
)
];
return FutureBuilder<List<Lap>>(
future: activity.laps,
builder: (BuildContext context, AsyncSnapshot<List<Lap>> snapshot) {
if (snapshot.hasData) {
final List<Lap> laps = snapshot.data;
return Container(
if (laps.isNotEmpty)
return Column(
children: <Widget>[
Container(
height: 300,
child: MyLineChart(
data: data,
maxDomain: records.last.distance,
laps: laps,
domainTitle: 'Speed (km/h)',
measureTickProviderSpec: const BasicNumericTickProviderSpec(
zeroBound: false,
dataIsInWholeNumbers: false,
desiredTickCount: 5),
domainTickProviderSpec:
const BasicNumericTickProviderSpec(desiredTickCount: 6),
minimum: minimum,
maximum: maximum,
child: LineChart(
data,
defaultRenderer: LineRendererConfig<num>(
includeArea: true,
),
domainAxis: NumericAxisSpec(
viewport: NumericExtents(0, widget.records.last.distance + 500),
tickProviderSpec:
const BasicNumericTickProviderSpec(desiredTickCount: 6),
),
primaryMeasureAxis: NumericAxisSpec(
tickProviderSpec: const BasicNumericTickProviderSpec(
zeroBound: false,
dataIsInWholeNumbers: false,
desiredTickCount: 5),
viewport: NumericExtents(widget.minimum, widget.maximum)),
animate: false,
selectionModels: <SelectionModelConfig<num>>[
SelectionModelConfig<num>(
type: SelectionModelType.info,
changedListener: _onSelectionChanged,
)
],
layoutConfig: GraphUtils.layoutConfig,
behaviors: <ChartBehavior<common.ChartBehavior<dynamic>>>[
PanAndZoomBehavior(),
RangeAnnotation(GraphUtils.rangeAnnotations(laps: laps)),
] +
GraphUtils.axis(
measureTitle: 'Speed (km/h)',
),
),
);
} else
return GraphUtils.loadingContainer;
},
);
),
if (selectedRecord != null)
Container(
child: Text(selectedRecord.speed.toString()),
),
if (selectedRecord == null)
Container(
child: const Text('Select a record to continue.'),
),
],
);
else
return GraphUtils.loadingContainer;
}
Future<void> getData() async {
laps = await widget.activity.laps;
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