Commit dc191e87c313b897b25bdbc16d272f45d276e993

Authored by 刘宏哲
1 parent 3cbf45f8

feat(app): bug fixed

... ... @@ -178,6 +178,13 @@ class ApiHrvReportDataSource implements HrvReportDataSource {
if (_stressLevelFromApiId(item.hrvLevel) case final level?)
date: level,
};
final dailyStressScoresByDate = <DateTime, double>{
for (final item
in data.dailyDistributionList ?? const <DailyDistributionList>[])
if (_parseApiDate(item.date) case final date?)
if (item.comprehensiveStressScore case final score?)
date: score.toDouble(),
};
final distributionCounts = _distributionCounts(data.hrvDistributionList);
return YearlyHrvReport(
... ... @@ -189,6 +196,7 @@ class ApiHrvReportDataSource implements HrvReportDataSource {
trendsByDate,
levelsByDate,
preferDailyLevel: true,
dailyStressScoresByDate: dailyStressScoresByDate,
),
],
distributionCounts:
... ... @@ -203,6 +211,7 @@ class ApiHrvReportDataSource implements HrvReportDataSource {
Map<DateTime, HrvTrendList> trendsByDate,
Map<DateTime, HrvStressLevel> levelsByDate, {
bool preferDailyLevel = false,
Map<DateTime, double> dailyStressScoresByDate = const {},
}) {
final trend = trendsByDate[date];
final trendLevel = _stressLevelFromApiId(trend?.state);
... ... @@ -215,6 +224,7 @@ class ApiHrvReportDataSource implements HrvReportDataSource {
averageHeartRate: trend?.hrAverage?.round(),
lastRestingHrValue: trend?.lastRestingHrValue,
comprehensiveStressScore: trend?.comprehensiveStressScore?.toDouble(),
dailyComprehensiveStressScore: dailyStressScoresByDate[date],
trendLevel: trendLevel,
level: level,
);
... ... @@ -418,6 +428,16 @@ class MockHrvReportDataSource implements HrvReportDataSource {
if (year == 2025) return YearlyHrvReport.empty(year);
const monthlyValues = [58.0, 82.0, 64.0, 74.0, 31.0, 45.0, 31.0];
const monthlyStressScores = [42.0, 29.0, 48.0, 33.0, 72.0, 86.0, 55.0];
const monthlyTrendLevels = [
HrvStressLevel.normal,
HrvStressLevel.normal,
HrvStressLevel.normal,
HrvStressLevel.normal,
HrvStressLevel.attention,
HrvStressLevel.overload,
HrvStressLevel.normal,
];
final days = <HrvDayReport>[];
var dataIndex = 0;
final levels = <HrvStressLevel>[
... ... @@ -437,10 +457,26 @@ class MockHrvReportDataSource implements HrvReportDataSource {
averageHrv: hasData ? monthlyValues[month - 1] : null,
averageHeartRate: hasData ? 67 : null,
level: level,
comprehensiveStressScore:
day == 1 && month <= monthlyStressScores.length
? monthlyStressScores[month - 1]
: null,
dailyComprehensiveStressScore:
hasData ? _mockDailyStressScore(level!) : null,
trendLevel: day == 1 && month <= monthlyTrendLevels.length
? monthlyTrendLevels[month - 1]
: null,
),
);
}
}
return YearlyHrvReport(year: year, days: days, validDayCount: 133);
}
double _mockDailyStressScore(HrvStressLevel level) => switch (level) {
HrvStressLevel.excellent => 10,
HrvStressLevel.normal => 40,
HrvStressLevel.attention => 70,
HrvStressLevel.overload => 90,
};
}
... ...
... ... @@ -38,6 +38,7 @@ class HrvDayReport {
this.averageHeartRate,
this.lastRestingHrValue,
this.comprehensiveStressScore,
this.dailyComprehensiveStressScore,
this.trendLevel,
this.level,
});
... ... @@ -47,6 +48,7 @@ class HrvDayReport {
final int? averageHeartRate;
final int? lastRestingHrValue;
final double? comprehensiveStressScore;
final double? dailyComprehensiveStressScore;
final HrvStressLevel? trendLevel;
final HrvStressLevel? level;
... ...
... ... @@ -592,51 +592,40 @@ class _DailyDistributionCard extends StatelessWidget {
({List<HrvDayReport> mostStressed, List<HrvDayReport> mostRelaxed})
_dailyStressExtremeDays(YearlyHrvReport report) {
final days = report.days.where((day) => day.level != null).toList()
..sort(_compareByStressDescending);
final mostStressed = <HrvDayReport>[];
final mostRelaxed = <HrvDayReport>[];
if (days.isEmpty) {
return (mostStressed: mostStressed, mostRelaxed: mostRelaxed);
}
if (days.length == 1) {
final day = days.single;
if (_isStressedLevel(day.level!)) {
mostStressed.add(day);
} else {
mostRelaxed.add(day);
}
return (mostStressed: mostStressed, mostRelaxed: mostRelaxed);
}
mostStressed.add(days.first);
mostRelaxed.add(days.last);
if (days.length == 3) {
final middle = days[1];
if (_isStressedLevel(middle.level!)) {
mostStressed.add(middle);
} else {
mostRelaxed.add(middle);
}
} else if (days.length >= 4) {
mostStressed.add(days[1]);
mostRelaxed.add(days[days.length - 2]);
}
final daysWithScore = report.days.where((day) {
return day.level != null && day.dailyComprehensiveStressScore != null;
});
final mostStressed = daysWithScore
.where((day) => _isStressedLevel(day.level!))
.toList()
..sort(_compareByDailyStressDescending);
final mostRelaxed = daysWithScore
.where((day) => !_isStressedLevel(day.level!))
.toList()
..sort(_compareByDailyStressAscending);
return (
mostStressed: _takeTwoAndSortByDate(mostStressed),
mostRelaxed: _takeTwoAndSortByDate(mostRelaxed),
);
}
mostStressed.sort(_compareByDate);
mostRelaxed.sort(_compareByDate);
return (mostStressed: mostStressed, mostRelaxed: mostRelaxed);
int _compareByDailyStressDescending(HrvDayReport a, HrvDayReport b) {
final valueComparison = b.dailyComprehensiveStressScore!
.compareTo(a.dailyComprehensiveStressScore!);
return valueComparison == 0 ? a.date.compareTo(b.date) : valueComparison;
}
int _compareByStressDescending(HrvDayReport a, HrvDayReport b) {
final valueComparison =
_stressRank(b.level!).compareTo(_stressRank(a.level!));
int _compareByDailyStressAscending(HrvDayReport a, HrvDayReport b) {
final valueComparison = a.dailyComprehensiveStressScore!
.compareTo(b.dailyComprehensiveStressScore!);
return valueComparison == 0 ? a.date.compareTo(b.date) : valueComparison;
}
List<HrvDayReport> _takeTwoAndSortByDate(List<HrvDayReport> days) {
return days.take(2).toList()..sort(_compareByDate);
}
int _compareByDate(HrvDayReport a, HrvDayReport b) {
return a.date.compareTo(b.date);
}
... ... @@ -646,14 +635,6 @@ class _DailyDistributionCard extends StatelessWidget {
level == HrvStressLevel.overload;
}
int _stressRank(HrvStressLevel level) {
return switch (level) {
HrvStressLevel.excellent => 0,
HrvStressLevel.normal => 1,
HrvStressLevel.attention => 2,
HrvStressLevel.overload => 3,
};
}
}
class _MonthDots extends StatelessWidget {
... ...
... ... @@ -395,6 +395,7 @@ class LocalHealthDataConvert {
DailyDistributionList(
date: dateKey(item.day),
hrvLevel: item.state,
comprehensiveStressScore: item.comprehensiveStressScore,
),
]
: null,
... ...
... ... @@ -78,20 +78,26 @@ class DailyDistributionList {
DailyDistributionList({
this.date,
this.hrvLevel,
this.comprehensiveStressScore,
});
DailyDistributionList.fromJson(dynamic json) {
date = json['date'] ?? json['time_key'];
hrvLevel = json['hrv_level'] ?? json['stress_state'] ?? json['stress_id'];
comprehensiveStressScore = json['comprehensive_stress_score'];
}
Object? date;
Object? hrvLevel;
num? comprehensiveStressScore;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['date'] = date;
map['hrv_level'] = hrvLevel;
if (comprehensiveStressScore != null) {
map['comprehensive_stress_score'] = comprehensiveStressScore;
}
return map;
}
}
... ...
... ... @@ -724,6 +724,10 @@ void main() {
expect(statistics.dailyDistributionList, hasLength(1));
expect(statistics.dailyDistributionList?.single.date, 20260512);
expect(
statistics.dailyDistributionList?.single.comprehensiveStressScore,
77,
);
expect(
statistics.dailyDistributionList?.map((e) => e.date),
isNot(contains(20260101)),
);
... ...