Commit 59d32b4e authored by Administrator's avatar Administrator

leg spring stiffness on activity level

parent 3bc93bce
......@@ -90,6 +90,8 @@ const tableActivity = SqfEntityTable(
SqfEntityField('sdevPower', DbType.real),
SqfEntityField('avgGroundTime', DbType.real),
SqfEntityField('sdevGroundTime', DbType.real),
SqfEntityField('avgLegSpringStiffness', DbType.real),
SqfEntityField('sdevLegSpringStiffness', DbType.real),
SqfEntityFieldRelationship(
parentTable: tableAthlete,
......@@ -181,7 +183,8 @@ const tableLap = SqfEntityTable(
SqfEntityField('sdevPower', DbType.real),
SqfEntityField('avgGroundTime', DbType.real),
SqfEntityField('sdevGroundTime', DbType.real),
SqfEntityField('avgLegSpringStiffness', DbType.real),
SqfEntityField('sdevLegSpringStiffness', DbType.real),
SqfEntityFieldRelationship(
parentTable: tableEvent,
......
This diff is collapsed.
......@@ -160,6 +160,26 @@ class Activity extends ChangeNotifier {
return db.sdevGroundTime;
}
Future<double> get avgLegSpringStiffness async {
if (db.avgLegSpringStiffness == null) {
List<Event> records = await this.records;
db.avgLegSpringStiffness = Lap.calculateAverageLegSpringStiffness(records: records);
await db.save();
notifyListeners();
}
return db.avgLegSpringStiffness;
}
Future<double> get sdevLegSpringStiffness async {
if (db.sdevLegSpringStiffness == null) {
List<Event> records = await this.records;
db.sdevLegSpringStiffness = Lap.calculateSdevLegSpringStiffness(records: records);
await db.save();
notifyListeners();
}
return db.sdevLegSpringStiffness;
}
parse({@required Athlete athlete}) async {
var appDocDir = await getApplicationDocumentsDirectory();
......
......@@ -191,4 +191,19 @@ class Lap {
records.map((record) => record.db.groundTime).nonZeroDoubles();
return groundTimes.sdev();
}
static double calculateAverageLegSpringStiffness({List<Event> records}) {
var legSpringStiffnesses =
records.map((record) => record.db.legSpringStiffness).nonZeroDoubles();
if (legSpringStiffnesses.length > 0) {
return legSpringStiffnesses.mean();
} else
return -1;
}
static double calculateSdevLegSpringStiffness({List<Event> records}) {
var legSpringStiffnesses =
records.map((record) => record.db.legSpringStiffness).nonZeroDoubles();
return legSpringStiffnesses.sdev();
}
}
......@@ -5,6 +5,7 @@ import 'package:encrateia/widgets/activity_heart_rate_widget.dart';
import 'package:encrateia/widgets/activity_power_widget.dart';
import 'package:encrateia/widgets/activity_power_duration_widget.dart';
import 'package:encrateia/widgets/activity_ground_time_widget.dart';
import 'package:encrateia/widgets/activity_leg_spring_stiffness_widget.dart';
import 'package:flutter/material.dart';
import 'package:encrateia/models/activity.dart';
......@@ -19,7 +20,7 @@ class ShowActivityScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 7,
length: 8,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
......@@ -49,6 +50,10 @@ class ShowActivityScreen extends StatelessWidget {
icon: Icon(Icons.vertical_align_bottom),
text: "Grnd.time",
),
Tab(
icon: Icon(Icons.airline_seat_recline_extra),
text: "Leg spr.stiff.",
),
Tab(
icon: Icon(Icons.storage),
text: "Metadata",
......@@ -67,6 +72,7 @@ class ShowActivityScreen extends StatelessWidget {
ActivityPowerWidget(activity: activity),
ActivityPowerDurationWidget(activity: activity),
ActivityGroundTimeWidget(activity: activity),
ActivityLegSpringStiffnessWidget(activity: activity),
ActivityMetadataWidget(activity: activity),
]),
),
......
......@@ -49,6 +49,13 @@ class ActivityGroundTimeChart extends StatelessWidget {
desiredTickCount: 6,
),
),
primaryMeasureAxis: NumericAxisSpec(
tickProviderSpec: BasicNumericTickProviderSpec(
zeroBound: false,
dataIsInWholeNumbers: false,
desiredTickCount: 5,
),
),
animate: false,
layoutConfig: LayoutConfig(
leftMarginSpec: MarginSpec.fixedPixel(60),
......
......@@ -17,8 +17,6 @@ class ActivityGroundTimeWidget extends StatefulWidget {
class _ActivityGroundTimeWidgetState extends State<ActivityGroundTimeWidget> {
List<Event> records = [];
String avgGroundTimeString = "Loading ...";
String minGroundTimeString = "Loading ...";
String maxGroundTimeString = "Loading ...";
String sdevGroundTimeString = "Loading ...";
@override
......
import 'package:charts_flutter/flutter.dart';
import 'package:flutter/material.dart';
import 'package:encrateia/models/activity.dart';
import 'package:encrateia/models/event.dart';
import 'package:encrateia/models/lap.dart';
import 'package:encrateia/models/plot_point.dart';
class ActivityLegSpringStiffnessChart extends StatelessWidget {
final List<Event> records;
final Activity activity;
final colorArray = [
MaterialPalette.white,
MaterialPalette.gray.shade200,
];
ActivityLegSpringStiffnessChart({this.records, @required this.activity});
@override
Widget build(BuildContext context) {
var nonZero = records.where((value) => value.db.groundTime > 0);
var smoothedRecords = Event.toDoubleDataPoints(
attribute: "legSpringStiffness",
records: nonZero,
amount: 30,
);
List<Series<dynamic, num>> data = [
new Series<DoublePlotPoint, int>(
id: 'Leg spring stiffness',
colorFn: (_, __) => MaterialPalette.green.shadeDefault,
domainFn: (DoublePlotPoint record, _) => record.domain,
measureFn: (DoublePlotPoint record, _) => record.measure,
data: smoothedRecords,
)
];
return FutureBuilder<List<Lap>>(
future: activity.laps,
builder: (BuildContext context, AsyncSnapshot<List<Lap>> snapshot) {
if (snapshot.hasData) {
var laps = snapshot.data;
return Container(
height: 300,
child: LineChart(
data,
domainAxis: NumericAxisSpec(
viewport: NumericExtents(0, nonZero.last.db.distance + 500),
tickProviderSpec: BasicNumericTickProviderSpec(
desiredTickCount: 6,
),
),
primaryMeasureAxis: NumericAxisSpec(
tickProviderSpec: BasicNumericTickProviderSpec(
zeroBound: false,
dataIsInWholeNumbers: false,
desiredTickCount: 5,
),
),
animate: false,
layoutConfig: LayoutConfig(
leftMarginSpec: MarginSpec.fixedPixel(60),
topMarginSpec: MarginSpec.fixedPixel(20),
rightMarginSpec: MarginSpec.fixedPixel(20),
bottomMarginSpec: MarginSpec.fixedPixel(40),
),
behaviors: [
RangeAnnotation(rangeAnnotations(laps: laps)),
ChartTitle(
'Leg Spring Stiffness (kN/m)',
titleStyleSpec: TextStyleSpec(fontSize: 13),
behaviorPosition: BehaviorPosition.start,
titleOutsideJustification: OutsideJustification.end,
),
ChartTitle(
'Distance (m)',
titleStyleSpec: TextStyleSpec(fontSize: 13),
behaviorPosition: BehaviorPosition.bottom,
titleOutsideJustification: OutsideJustification.end,
),
],
),
);
} else {
return Container(
height: 100,
child: Center(child: Text("Loading")),
);
}
},
);
}
rangeAnnotations({List<Lap> laps}) {
return [
for (int index = 0; index < laps.length; index++)
RangeAnnotationSegment(
laps
.sublist(0, index + 1)
.map((lap) => lap.db.totalDistance)
.reduce((a, b) => a + b) -
laps[index].db.totalDistance,
laps
.sublist(0, index + 1)
.map((lap) => lap.db.totalDistance)
.reduce((a, b) => a + b),
RangeAnnotationAxisType.domain,
color: colorArray[index % 2],
endLabel: 'Lap ${laps[index].index}',
)
];
}
}
import 'package:flutter/material.dart';
import 'package:encrateia/models/activity.dart';
import 'package:encrateia/models/event.dart';
import 'package:encrateia/utils/list_utils.dart';
import 'package:encrateia/utils/num_utils.dart';
import 'activity_leg_spring_stiffness_chart.dart';
class ActivityLegSpringStiffnessWidget extends StatefulWidget {
final Activity activity;
ActivityLegSpringStiffnessWidget({this.activity});
@override
_ActivityLegSpringStiffnessWidgetState createState() => _ActivityLegSpringStiffnessWidgetState();
}
class _ActivityLegSpringStiffnessWidgetState extends State<ActivityLegSpringStiffnessWidget> {
List<Event> records = [];
String avgLegSpringStiffnessString = "Loading ...";
String sdevLegSpringStiffnessString = "Loading ...";
@override
void initState() {
getData();
super.initState();
}
@override
Widget build(context) {
if (records.length > 0) {
var powerValues = records.map((value) => value.db.groundTime).nonZeroDoubles();
if (powerValues.length > 0) {
return ListTileTheme(
iconColor: Colors.deepOrange,
child: ListView(
padding: EdgeInsets.only(left: 25),
children: <Widget>[
ActivityLegSpringStiffnessChart(records: records, activity: widget.activity),
ListTile(
leading: Icon(Icons.ev_station),
title: Text(avgLegSpringStiffnessString),
subtitle: Text("average ground time"),
),
ListTile(
leading: Icon(Icons.unfold_more),
title: Text(sdevLegSpringStiffnessString),
subtitle: Text("standard deviation ground time"),
),
ListTile(
leading: Icon(Icons.playlist_add),
title: Text(records.length.toString()),
subtitle: Text("number of measurements"),
),
],
),
);
} else {
return Center(
child: Text("No ground time data available."),
);
}
} else {
return Center(
child: Text("Loading"),
);
}
}
getData() async {
Activity activity = widget.activity;
records = await activity.records;
double avg = await activity.avgLegSpringStiffness;
setState(() {
avgLegSpringStiffnessString = avg.toStringOrDashes(1) + " ms";
});
double sdev = await activity.sdevLegSpringStiffness;
setState(() {
sdevLegSpringStiffnessString = sdev.toStringOrDashes(2) + " ms";
});
}
}
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