From a2f035ac2ac8ddbe8b5fc3f5cccf94800abc5e92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Pedersen?= Date: Sun, 22 Sep 2024 21:10:40 +0200 Subject: [PATCH] Implemented Top3Avg aggregation in visualization tab and use it as default (#289) --- lib/tabs/visualization.dart | 43 +++++++++++++++++++++++++++++++++++-- lib/widgets/settings.dart | 6 +++++- pubspec.yaml | 2 +- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/lib/tabs/visualization.dart b/lib/tabs/visualization.dart index 504fec1..19f0d79 100644 --- a/lib/tabs/visualization.dart +++ b/lib/tabs/visualization.dart @@ -197,6 +197,45 @@ class _VisualizationTabState extends State { value = totalRepsSets > 0 ? totalWeight / totalRepsSets : 0.0; break; + case 'Top3Avg': + // Sort records by the value of interest in descending order + final sortedRecords = recordsForDay + .map((record) => { + 'weight': + double.tryParse(record['weight'].toString()) ?? 0.0, + 'reps': double.tryParse(record['reps'].toString()) ?? 1.0, + 'sets': double.tryParse(record['sets'].toString()) ?? 1.0, + }) + .toList() + ..sort((a, b) => ((b['weight'] ?? 0.0) * + (b['reps'] ?? 1.0) * + (b['sets'] ?? 1.0)) + .compareTo((a['weight'] ?? 0.0) * + (a['reps'] ?? 1.0) * + (a['sets'] ?? 1.0))); + + // Take the top 3 records + final top3Records = sortedRecords.take(3).toList(); + + // Calculate the weighted average for the top 3 records + double top3TotalWeight = 0.0; + double top3TotalRepsSets = 0.0; + + for (var record in top3Records) { + final weight = record['weight']; + final reps = record['reps']; + final sets = record['sets']; + + top3TotalWeight += + (sets ?? 1.0) * (reps ?? 1.0) * (weight ?? 0.0); + top3TotalRepsSets += (sets ?? 1.0) * (reps ?? 1.0); + } + + value = top3TotalRepsSets > 0 + ? top3TotalWeight / top3TotalRepsSets + : 0.0; + break; + case 'Total': value = recordsForDay.fold(0.0, (sum, record) { final sets = double.tryParse(record['sets'].toString()) ?? 1.0; @@ -317,7 +356,7 @@ class _VisualizationTabState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox( - width: 90, + width: 100, child: _buildAggregationDropdown(theme), ), const SizedBox(height: 16.0), @@ -435,7 +474,7 @@ class _VisualizationTabState extends State { }); } }, - items: ['Max', 'Average', 'Total'].map((method) { + items: ['Max', 'Average', 'Top3Avg', 'Total'].map((method) { return DropdownMenuItem( value: method, child: Text(method, diff --git a/lib/widgets/settings.dart b/lib/widgets/settings.dart index 49cc85b..9c7c288 100644 --- a/lib/widgets/settings.dart +++ b/lib/widgets/settings.dart @@ -35,7 +35,7 @@ class _SettingsModalState extends State { super.initState(); _appTheme = widget.appTheme; _isKg = widget.isKg; - _aggregationMethod = 'Max'; // Default value + _aggregationMethod = 'Top3Avg'; // Default value _plotType = 'Line'; // Default value _appVersion = _getAppVersion(); _loadSettings(); @@ -299,6 +299,10 @@ class _SettingsModalState extends State { value: 'Average', child: Text('Average'), ), + DropdownMenuItem( + value: 'Top3Avg', + child: Text('Top3Avg'), + ), ], onChanged: _handleAggregationMethodChange, ), diff --git a/pubspec.yaml b/pubspec.yaml index a009808..101199d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.7.6+35 +version: 0.8.0+36 environment: sdk: '>=3.4.3 <4.0.0'