Commit 6c6d1c70 authored by Administrator's avatar Administrator

calculate interval

parent 8115683b
......@@ -111,6 +111,7 @@ class Event {
double get positionLat => _db.positionLat;
double get positionLong => _db.positionLong;
double get speed => _db.speed;
double get cadence => _db.cadence;
double get strydCadence => _db.strydCadence;
double get verticalOscillation => _db.verticalOscillation;
int get formPower => _db.formPower;
......
......@@ -22,19 +22,23 @@ class Ftp {
return backlog;
}
static Future<void> calculate({List<Activity> backlog}) async {
static Future<void> catchUp({List<Activity> backlog}) async {
for (final Activity activity in backlog) {
print('calculating ftp for ${activity.name} ...');
final List<Event> records = await activity.records;
final List<Event> powerRecords = records
.where((Event value) => value.power != null && value.power > 100)
.toList();
final PowerDuration powerDuration = PowerDuration(records: powerRecords);
final PowerDuration ftpCurve = powerDuration.normalize();
final double ftp = ftpCurve.powerMap.values.toList().reduce(max);
activity.ftp = ftp;
activity.ftp = calculate(records: powerRecords);
activity.save();
print('ftp calculated');
}
}
static double calculate({List<Event> records}) {
final PowerDuration powerDuration = PowerDuration(records: records);
final PowerDuration ftpCurve = powerDuration.normalize();
final double ftp = ftpCurve.powerMap.values.toList().reduce(max);
return ftp;
}
}
import 'package:encrateia/model/model.dart' show DbEvent, DbInterval;
import 'package:encrateia/models/record_list.dart';
import 'package:encrateia/models/event.dart';
import 'package:encrateia/models/ftp.dart';
import 'package:encrateia/models/activity.dart';
import 'package:sqfentity_gen/sqfentity_gen.dart';
......@@ -58,7 +59,7 @@ class Interval {
int get lastRecordId => _db.lastRecordId;
int get avgHeartRate => _db.avgHeartRate;
int get distance => _db.distance;
int get duration => _db.duration;
Duration get duration => Duration(seconds: _db.duration ?? 0);
int get maxFormPower => _db.maxFormPower;
int get maxHeartRate => _db.maxHeartRate;
int get maxPower => _db.maxPower;
......@@ -70,6 +71,11 @@ class Interval {
set firstRecordId(int value) => _db.firstRecordId = value;
set lastRecordId(int value) => _db.lastRecordId = value;
set athletesId(int value) => _db.athletesId = value;
set activitiesId(int value) => _db.activitiesId = value;
set distance(int value) => _db.distance = value;
set duration(Duration value) => _db.duration = value.inSeconds;
set ftp(double value) => _db.ftp = value;
Future<BoolResult> delete() async => await _db.delete();
Future<int> save() async => await _db.save();
......@@ -92,17 +98,34 @@ class Interval {
..maxSpeed = recordList.maxSpeed()
..avgGroundTime = recordList.avgGroundTime()
..sdevGroundTime = recordList.sdevGroundTime()
..minGroundTime = recordList.minGroundTime()
..maxGroundTime = recordList.maxGroundTime()
..avgStrydCadence = recordList.avgStrydCadence()
..sdevStrydCadence = recordList.sdevStrydCadence()
..minStrydCadence = recordList.minStrydCadence()
..maxStrydCadence = recordList.maxStrydCadence()
..avgCadence = recordList.avgStrydCadence()
..sdevCadence = recordList.sdevStrydCadence()
..minCadence = recordList.minCadence()
..maxCadence = recordList.maxCadence()
..avgLegSpringStiffness = recordList.avgLegSpringStiffness()
..sdevLegSpringStiffness = recordList.sdevLegSpringStiffness()
..minLegSpringStiffness = recordList.minLegSpringStiffness()
..maxLegSpringStiffness = recordList.maxLegSpringStiffness()
..avgVerticalOscillation = recordList.avgVerticalOscillation()
..sdevVerticalOscillation = recordList.sdevVerticalOscillation()
..minVerticalOscillation = recordList.minVerticalOscillation()
..maxVerticalOscillation = recordList.maxVerticalOscillation()
..avgFormPower = recordList.avgFormPower()
..sdevFormPower = recordList.sdevFormPower();
..sdevFormPower = recordList.sdevFormPower()
..minFormPower = recordList.minFormPower()
..maxFormPower = recordList.maxFormPower();
await save();
}
// totalAscent => _db.totalAscent;
// totalDescent => _db.totalDescent;
Future<List<Event>> get records async {
final List<DbEvent> dbEvents = await DbEvent()
.select()
......@@ -118,7 +141,10 @@ class Interval {
}
Future<void> calculateAndSave({RecordList<Event> records}) async {
distance = (records.last.distance - records.first.distance).round();
duration = records.last.timeStamp.difference(records.first.timeStamp);
ftp = Ftp.calculate(records: records);
await setAverages();
}
static Interval exDb(DbInterval db) => Interval._fromDb(db);
......
......@@ -118,6 +118,18 @@ class RecordList<E> extends DelegatingList<E> {
double sdevGroundTime() =>
_records.map((Event record) => record.groundTime).nonZeros().sdev();
double minGroundTime() {
final List<double> groundTimes =
_records.map((Event record) => record.groundTime).nonZeros().cast<double>();
return groundTimes.isNotEmpty ? groundTimes.min() as double : 0;
}
double maxGroundTime() {
final List<double> groundTimes =
_records.map((Event record) => record.groundTime).nonZeros().cast<double>();
return groundTimes.isNotEmpty ? groundTimes.max() as double : 0;
}
// Stryd Cadence
double avgStrydCadence() {
final List<double> strydCadences = _records
......@@ -131,6 +143,43 @@ class RecordList<E> extends DelegatingList<E> {
.nonZeros()
.sdev();
double minStrydCadence() {
final List<double> strydCadences =
_records.map((Event record) => record.strydCadence).nonZeros().cast<double>();
return strydCadences.isNotEmpty ? strydCadences.min() as double : 0;
}
double maxStrydCadence() {
final List<double> strydCadences =
_records.map((Event record) => record.strydCadence).nonZeros().cast<double>();
return strydCadences.isNotEmpty ? strydCadences.max() as double : 0;
}
// Cadence
double avgCadence() {
final List<double> cadences = _records
.map((Event record) => record.cadence ?? 0.0 * 2)
.nonZeros().cast<double>();
return cadences.isNotEmpty ? cadences.mean() : -1;
}
double sdevCadence() => _records
.map((Event record) => record.cadence ?? 0.0 * 2)
.nonZeros()
.sdev();
double minCadence() {
final List<double> cadences =
_records.map((Event record) => record.cadence).nonZeros().cast<double>();
return cadences.isNotEmpty ? cadences.min() as double : 0;
}
double maxCadence() {
final List<double> cadences =
_records.map((Event record) => record.cadence).nonZeros().cast<double>();
return cadences.isNotEmpty ? cadences.max() as double : 0;
}
// Leg Spring Stiffness
double avgLegSpringStiffness() {
final List<double> legSpringStiffnesses = _records
......@@ -144,6 +193,18 @@ class RecordList<E> extends DelegatingList<E> {
.nonZeros()
.sdev();
double minLegSpringStiffness() {
final List<double> legSpringStiffnesses =
_records.map((Event record) => record.legSpringStiffness).nonZeros().cast<double>();
return legSpringStiffnesses.isNotEmpty ? legSpringStiffnesses.min() as double : 0;
}
double maxLegSpringStiffness() {
final List<double> legSpringStiffnesses =
_records.map((Event record) => record.legSpringStiffness).nonZeros().cast<double>();
return legSpringStiffnesses.isNotEmpty ? legSpringStiffnesses.max() as double : 0;
}
// Vertical Oscillation
double avgVerticalOscillation() {
final List<double> verticalOscillation = _records
......@@ -157,6 +218,18 @@ class RecordList<E> extends DelegatingList<E> {
.nonZeros()
.sdev();
double minVerticalOscillation() {
final List<double> verticalOscillations =
_records.map((Event record) => record.verticalOscillation).nonZeros().cast<double>();
return verticalOscillations.isNotEmpty ? verticalOscillations.min() as double : 0;
}
double maxVerticalOscillation() {
final List<double> verticalOscillations =
_records.map((Event record) => record.verticalOscillation).nonZeros().cast<double>();
return verticalOscillations.isNotEmpty ? verticalOscillations.max() as double : 0;
}
// Form Power
double avgFormPower() {
final Iterable<int> formPowers = _records
......@@ -172,6 +245,18 @@ class RecordList<E> extends DelegatingList<E> {
.map((Event record) => record.formPower)
.sdev();
int minFormPower() {
final List<int> formPowers =
_records.map((Event record) => record.formPower).nonZeros().cast<int>();
return formPowers.isNotEmpty ? formPowers.min() as int : 0;
}
int maxFormPower() {
final List<int> formPowers =
_records.map((Event record) => record.formPower).nonZeros().cast<int>();
return formPowers.isNotEmpty ? formPowers.max() as int : 0;
}
// Power Ratio
double avgPowerRatio() {
final Iterable<double> powerRatios = _records
......@@ -229,6 +314,15 @@ class RecordList<E> extends DelegatingList<E> {
record.strydCadence /
record.verticalOscillation)
.sdev();
// Ascend and descend
double totalAscend() {
final List<double> verticalOscillation = _records
.map((Event record) => record.verticalOscillation)
.nonZeros().cast<double>();
return verticalOscillation.isNotEmpty ? verticalOscillation.mean() : -1;
}
// END OF AVERAGES
List<IntPlotPoint> toIntDataPoints({
......
......@@ -69,7 +69,7 @@ class _AthleteFtpWidgetState extends State<AthleteFtpWidget> {
MyButton.activity(
child: const Text('Calculate missing FTP'),
onPressed: () async {
await Ftp.calculate(backlog: backlog);
await Ftp.catchUp(backlog: backlog);
getData();
}),
const SizedBox(width: 20),
......@@ -87,7 +87,7 @@ class _AthleteFtpWidgetState extends State<AthleteFtpWidget> {
MyButton.activity(
child: const Text('Calculate FTP'),
onPressed: () async {
Ftp.calculate(backlog: backlog);
Ftp.catchUp(backlog: backlog);
setState(() {});
}),
const SizedBox(width: 20),
......
......@@ -318,6 +318,8 @@ class _ActivityIntervalsChartState extends State<ActivityIntervalsChart> {
Future<void> getData() async {
laps = await widget.activity.laps;
interval.athletesId = widget.athlete.id;
interval.activitiesId = widget.activity.id;
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