|
...
|
...
|
@@ -309,6 +309,23 @@ class YearlyHrvReport implements HrvPeriodReport { |
|
|
|
List<HrvDayReport> daysForMonth(int month) =>
|
|
|
|
days.where((day) => day.date.month == month).toList();
|
|
|
|
|
|
|
|
List<HrvDayReport> levelDaysForMonth(int month) =>
|
|
|
|
daysForMonth(month).where((day) => day.level != null).toList();
|
|
|
|
|
|
|
|
int stressedDaysForMonth(int month) {
|
|
|
|
return levelDaysForMonth(month).where((day) {
|
|
|
|
return day.level == HrvStressLevel.attention ||
|
|
|
|
day.level == HrvStressLevel.overload;
|
|
|
|
}).length;
|
|
|
|
}
|
|
|
|
|
|
|
|
int relaxedDaysForMonth(int month) {
|
|
|
|
return levelDaysForMonth(month).where((day) {
|
|
|
|
return day.level == HrvStressLevel.excellent ||
|
|
|
|
day.level == HrvStressLevel.normal;
|
|
|
|
}).length;
|
|
|
|
}
|
|
|
|
|
|
|
|
double? averageForMonth(int month) {
|
|
|
|
final values = daysForMonth(month)
|
|
|
|
.map((day) => day.averageHrv)
|
|
...
|
...
|
@@ -318,11 +335,80 @@ class YearlyHrvReport implements HrvPeriodReport { |
|
|
|
return values.reduce((sum, value) => sum + value) / values.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
HrvStressLevel? levelForMonth(int month) {
|
|
|
|
final levels = daysForMonth(month)
|
|
|
|
.where((day) => day.averageHrv != null)
|
|
|
|
.map((day) => day.level)
|
|
|
|
.whereType<HrvStressLevel>()
|
|
|
|
.toList();
|
|
|
|
if (levels.isEmpty) return null;
|
|
|
|
return levels.first;
|
|
|
|
}
|
|
|
|
|
|
|
|
List<int> get monthsWithAverage => [
|
|
|
|
for (var month = 1; month <= 12; month++)
|
|
|
|
if (averageForMonth(month) != null) month,
|
|
|
|
];
|
|
|
|
|
|
|
|
({List<int> mostStressed, List<int> leastStressed})
|
|
|
|
averageStressExtremeMonths() {
|
|
|
|
final values = [
|
|
|
|
for (final month in monthsWithAverage)
|
|
|
|
if (averageForMonth(month) case final average?)
|
|
|
|
MapEntry(month, average),
|
|
|
|
];
|
|
|
|
values.sort(_compareByStressDescending);
|
|
|
|
|
|
|
|
final mostStressed = <int>[];
|
|
|
|
final leastStressed = <int>[];
|
|
|
|
if (values.isEmpty) {
|
|
|
|
return (mostStressed: mostStressed, leastStressed: leastStressed);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (values.length == 1) {
|
|
|
|
final entry = values.single;
|
|
|
|
if (_isStressedAverage(entry.value)) {
|
|
|
|
mostStressed.add(entry.key);
|
|
|
|
} else {
|
|
|
|
leastStressed.add(entry.key);
|
|
|
|
}
|
|
|
|
return (mostStressed: mostStressed, leastStressed: leastStressed);
|
|
|
|
}
|
|
|
|
|
|
|
|
mostStressed.add(values.first.key);
|
|
|
|
leastStressed.add(values.last.key);
|
|
|
|
|
|
|
|
if (values.length == 3) {
|
|
|
|
final middle = values[1];
|
|
|
|
if (_isStressedAverage(middle.value)) {
|
|
|
|
mostStressed.add(middle.key);
|
|
|
|
} else {
|
|
|
|
leastStressed.add(middle.key);
|
|
|
|
}
|
|
|
|
} else if (values.length >= 4) {
|
|
|
|
mostStressed.add(values[1].key);
|
|
|
|
leastStressed.add(values[values.length - 2].key);
|
|
|
|
}
|
|
|
|
|
|
|
|
mostStressed.sort();
|
|
|
|
leastStressed.sort();
|
|
|
|
return (mostStressed: mostStressed, leastStressed: leastStressed);
|
|
|
|
}
|
|
|
|
|
|
|
|
int _compareByStressDescending(
|
|
|
|
MapEntry<int, double> a,
|
|
|
|
MapEntry<int, double> b,
|
|
|
|
) {
|
|
|
|
final valueComparison = a.value.compareTo(b.value);
|
|
|
|
return valueComparison == 0 ? a.key.compareTo(b.key) : valueComparison;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool _isStressedAverage(double average) {
|
|
|
|
final level = HrvStressLevel.fromAverageHrv(average);
|
|
|
|
return level == HrvStressLevel.attention ||
|
|
|
|
level == HrvStressLevel.overload;
|
|
|
|
}
|
|
|
|
|
|
|
|
List<int> monthsAtExtreme({required bool maximum}) {
|
|
|
|
final values = [
|
|
|
|
for (var month = 1; month <= 12; month++)
|
...
|
...
|
|