Skip to content

Commit

Permalink
clean up activity data
Browse files Browse the repository at this point in the history
  • Loading branch information
seesharpguy committed Dec 4, 2024
1 parent ea19196 commit 4c36e2b
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 208 deletions.
31 changes: 4 additions & 27 deletions lib/app/models/activity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,34 +53,11 @@ class ZonePointRecord {
}
}

/// Class representing a calorie burned record.
class CalorieBurnedRecord {
final String uuid;
final double numericValue;
final String unit;
final DateTime dateFrom;
final DateTime dateTo;
final String sourceName;

CalorieBurnedRecord({
required this.uuid,
required this.numericValue,
required this.unit,
required this.dateFrom,
required this.dateTo,
required this.sourceName,
});
class WeightDataRecord {
final String date;
final double weight;

factory CalorieBurnedRecord.fromJson(Map<String, dynamic> json) {
return CalorieBurnedRecord(
uuid: json['uuid'],
numericValue: (json['value']['numericValue'] as num).toDouble(),
unit: json['unit'],
dateFrom: DateTime.parse(json['dateFrom']),
dateTo: DateTime.parse(json['dateTo']),
sourceName: json['sourceName'],
);
}
WeightDataRecord(this.date, this.weight);
}

/// Class representing a step record.
Expand Down
73 changes: 3 additions & 70 deletions lib/app/modules/diary/controllers/activity_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,15 @@ class HealthActivityManager {

// Aggregate records by day and month
final dailyStepRecords = RxList<StepRecord>([]);
final dailyCalorieRecords = RxList<CalorieBurnedRecord>([]);
final dailyZonePointRecords = RxList<ZonePointRecord>([]);
final monthlyStepRecords = RxList<StepRecord>([]);
final monthlyCalorieRecords = RxList<CalorieBurnedRecord>([]);
final monthlyZonePointRecords = RxList<ZonePointRecord>([]);

// Convert statistics to Rx
final totalSteps = 0.obs;
final totalCaloriesBurned = 0.0.obs;
final totalZonePoints = 0.obs;
final multipleCalorieSources = false.obs;
final multipleSourcesExist = false.obs;
final totalWorkoutCalories = 0.0.obs;
final totalActiveZoneMinutes = 0.obs;

Expand Down Expand Up @@ -113,8 +111,7 @@ class HealthActivityManager {
workoutRecords.value = _parseWorkoutData(
activityData.where((data) => data.type == HealthDataType.WORKOUT).toList());

multipleCalorieSources.value =
activityData.map((record) => record.sourceName).toSet().length > 1;
multipleSourcesExist.value = activityData.map((record) => record.sourceName).toSet().length > 1;

// Process heart rate zones
_processHeartRateZones(userAge);
Expand Down Expand Up @@ -143,8 +140,7 @@ class HealthActivityManager {
workoutRecords.value = _parseWorkoutData(
activityData.where((data) => data.type == HealthDataType.WORKOUT).toList());

// multipleCalorieSources.value =
// calorieRecords.map((record) => record.sourceName).toSet().length > 1;
multipleSourcesExist.value = activityData.map((record) => record.sourceName).toSet().length > 1;

// Process steps by day
_processStepsByDayAndMonth();
Expand Down Expand Up @@ -237,60 +233,6 @@ class HealthActivityManager {
..sort((a, b) => a.dateFrom.compareTo(b.dateFrom));
}

// // Add this new method to bucket calories by hour
// void _processCaloriesByHour() {
// if (calorieRecords.isEmpty) return;

// // Create a map to store hourly totals
// Map<DateTime, double> hourlyTotals = {};

// // Get the date from the first record, or use current date if no records
// DateTime firstDate = calorieRecords.isEmpty
// ? DateTime.now()
// : DateTime(
// calorieRecords.first.dateFrom.year,
// calorieRecords.first.dateFrom.month,
// calorieRecords.first.dateFrom.day,
// );

// // Initialize all hours with 0 calories
// for (int hour = 0; hour < 24; hour++) {
// DateTime hourKey = firstDate.add(Duration(hours: hour));
// hourlyTotals[hourKey] = 0;
// }

// // Track processed time ranges to avoid double counting
// Set<String> processedRanges = {};

// // Sum up calories for each hour, avoiding duplicates
// for (var record in calorieRecords) {
// String timeRange = '${record.dateFrom}-${record.dateTo}';
// if (processedRanges.contains(timeRange)) continue;

// DateTime hourKey = DateTime(
// record.dateFrom.year,
// record.dateFrom.month,
// record.dateFrom.day,
// record.dateFrom.hour,
// );
// hourlyTotals[hourKey] = (hourlyTotals[hourKey] ?? 0) + record.numericValue;
// processedRanges.add(timeRange);
// }

// // Convert back to CalorieBurnedRecord list
// hourlyCalorieRecords.value = hourlyTotals.entries.map((entry) {
// return CalorieBurnedRecord(
// numericValue: entry.value,
// dateFrom: entry.key,
// dateTo: entry.key.add(const Duration(hours: 1)),
// sourceName: 'hourly',
// uuid: 'hourly_${entry.key.toString()}',
// unit: 'KILOCALORIE',
// );
// }).toList()
// ..sort((a, b) => a.dateFrom.compareTo(b.dateFrom));
// }

void _processStepsByHour() {
if (stepRecords.isEmpty) return;

Expand Down Expand Up @@ -381,9 +323,7 @@ class HealthActivityManager {
totalActiveZoneMinutes.value = 0;
dailyZonePointRecords.clear();
dailyStepRecords.clear();
dailyCalorieRecords.clear();
monthlyStepRecords.clear();
monthlyCalorieRecords.clear();
monthlyZonePointRecords.clear();
}

Expand All @@ -392,13 +332,6 @@ class HealthActivityManager {
return healthData.map((data) => HeartRateRecord.fromJson(data.toJson())).toList();
}

/// Parses a list of JSON objects into CalorieBurnedRecord instances.
List<CalorieBurnedRecord> parseCalorieData(List<HealthDataPoint> healthData) {
final t = healthData;

return t.map((data) => CalorieBurnedRecord.fromJson(data.toJson())).toList();
}

/// Parses a list of JSON objects into StepRecord instances.
List<StepRecord> _parseStepData(List<HealthDataPoint> healthData) {
return healthData.map((data) => StepRecord.fromJson(data.toJson())).toList();
Expand Down
89 changes: 77 additions & 12 deletions lib/app/modules/track/controllers/track_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class TrackController extends GetxController {
final logger = Get.find<Logger>();
final zone2User = Rxn<Zone2User>();
final userAge = Rxn<int>();
final userWeightData = Rx<List<WeightData>>([]);
final filteredWeightData = Rx<List<WeightData>>([]);
final userWeightData = Rx<List<WeightDataRecord>>([]);
final filteredWeightData = Rx<List<WeightDataRecord>>([]);
final weightDataLoading = false.obs;
final activityDataLoading = false.obs;
final selectedTimeFrame = TimeFrame.week.obs;
Expand Down Expand Up @@ -70,7 +70,7 @@ class TrackController extends GetxController {

// Convert the latest entries to WeightData, converting kg to lbs
final weightEntries = await Future.wait(latestEntries.values.map((dataPoint) async =>
WeightData(
WeightDataRecord(
DateFormat('M/d/yy').format(dataPoint.dateFrom),
// Await the conversion to ensure we get a double value
await healthService.convertWeightUnit(
Expand All @@ -95,8 +95,8 @@ class TrackController extends GetxController {
activityManager.value
.processAggregatedActivityData(activityData: allActivityData, userAge: userAge.value ?? 30);
activityDataLoading.value = false;
getFilteredStepData();
getFilteredZonePointData();
applyStepFilter();
applyZonePointFilter();
update();
}

Expand Down Expand Up @@ -133,7 +133,7 @@ class TrackController extends GetxController {
update();
}

void getFilteredStepData() {
void applyStepFilter() {
DateTime now = DateTime.now();
DateTime startDate;

Expand All @@ -152,13 +152,18 @@ class TrackController extends GetxController {
startDate = DateTime(2000); // Arbitrary early date for all-time data
}

filteredStepData.value = activityManager.value.dailyStepRecords.where((record) {
final records = activityManager.value.dailyStepRecords.where((record) {
return record.dateFrom.isAfter(startDate);
}).toList();

// Calculate average steps per day by month for 1/2 Year and Journey
filteredStepData.value = selectedTimeFrame.value == TimeFrame.allTime
? _calculateMonthlyStepAverages(records)
: records;
update();
}

void getFilteredZonePointData() {
void applyZonePointFilter() {
DateTime now = DateTime.now();
DateTime startDate;

Expand All @@ -177,13 +182,18 @@ class TrackController extends GetxController {
startDate = DateTime(2000); // Arbitrary early date for all-time data
}

filteredZonePointData.value = activityManager.value.dailyZonePointRecords.where((record) {
final records = activityManager.value.dailyZonePointRecords.where((record) {
return record.dateFrom.isAfter(startDate);
}).toList();

// Calculate average steps per day by month for 1/2 Year and Journey
filteredZonePointData.value = selectedTimeFrame.value == TimeFrame.allTime
? _calculateMonthlyZoneAverages(records)
: records;
update();
}

List<WeightData> getTrendLineData() {
List<WeightDataRecord> getTrendLineData() {
if (userWeightData.value.isEmpty) return [];
final journeyStartDate = zone2User.value!.zoneSettings?.journeyStartDate.toDate().toString();
DateTime startDate = DateTime.parse(journeyStartDate ?? DateTime.now().toString());
Expand All @@ -195,8 +205,63 @@ class TrackController extends GetxController {
double targetWeight = 190.0;

return [
WeightData(DateFormat('M/d/yy').format(trendStartDate), startWeight),
WeightData(DateFormat('M/d/yy').format(endDate), targetWeight),
WeightDataRecord(DateFormat('M/d/yy').format(trendStartDate), startWeight),
WeightDataRecord(DateFormat('M/d/yy').format(endDate), targetWeight),
];
}

List<ZonePointRecord> _calculateMonthlyZoneAverages(List<ZonePointRecord> records) {
// Implement logic to calculate average steps per day by month
Map<DateTime, List<ZonePointRecord>> groupedByMonth = {};
for (var record in records) {
DateTime monthKey = DateTime(record.dateFrom.year, record.dateFrom.month);
if (!groupedByMonth.containsKey(monthKey)) {
groupedByMonth[monthKey] = [];
}
groupedByMonth[monthKey]!.add(record);
}

List<ZonePointRecord> averageRecords = [];
groupedByMonth.forEach((month, records) {
double totalSteps = records.fold(0, (sum, record) => sum + record.zonePoints);
double averageSteps = totalSteps / records.length;
averageRecords.add(ZonePointRecord(
dateFrom: month,
zonePoints: averageSteps.toInt(),
uuid: "month_${month.toString()}",
sourceName: 'Zone Points',
dateTo: month.add(const Duration(days: 1)),
));
});

return averageRecords;
}

List<StepRecord> _calculateMonthlyStepAverages(List<StepRecord> records) {
// Implement logic to calculate average steps per day by month
// This is a placeholder implementation
Map<DateTime, List<StepRecord>> groupedByMonth = {};
for (var record in records) {
DateTime monthKey = DateTime(record.dateFrom.year, record.dateFrom.month);
if (!groupedByMonth.containsKey(monthKey)) {
groupedByMonth[monthKey] = [];
}
groupedByMonth[monthKey]!.add(record);
}

List<StepRecord> averageRecords = [];
groupedByMonth.forEach((month, records) {
double totalSteps = records.fold(0, (sum, record) => sum + record.numericValue);
double averageSteps = totalSteps / records.length;
averageRecords.add(StepRecord(
dateFrom: month,
numericValue: averageSteps.toInt(),
uuid: "month_${month.toString()}",
unit: 'COUNT',
dateTo: month.add(const Duration(days: 1)),
));
});

return averageRecords;
}
}
44 changes: 2 additions & 42 deletions lib/app/modules/track/views/step_tab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class StepTab extends GetView<TrackController> {
if (selected) {
controller.selectedTimeFrame.value = entry.value;
// Update the graph data based on the selected time frame
controller.getFilteredStepData();
controller.applyStepFilter();
}
},
);
Expand Down Expand Up @@ -88,11 +88,6 @@ class StepGraph extends GetView<TrackController> {
interval = 1.0;
}

// Calculate average steps per day by month for 1/2 Year and Journey
final averageRecords = controller.selectedTimeFrame.value == TimeFrame.allTime
? _calculateMonthlyAverages(controller.filteredStepData.value)
: controller.filteredStepData.value;

return Skeletonizer(
enabled: controller.activityDataLoading.value,
child: SfCartesianChart(
Expand All @@ -115,7 +110,7 @@ class StepGraph extends GetView<TrackController> {
),
series: <CartesianSeries>[
ColumnSeries<StepRecord, DateTime>(
dataSource: averageRecords,
dataSource: controller.filteredStepData.value,
xValueMapper: (StepRecord record, _) => record.dateFrom,
yValueMapper: (StepRecord record, _) => record.numericValue,
name: 'Steps',
Expand All @@ -140,39 +135,4 @@ class StepGraph extends GetView<TrackController> {
),
);
}

List<StepRecord> _calculateMonthlyAverages(List<StepRecord> records) {
// Implement logic to calculate average steps per day by month
// This is a placeholder implementation
Map<DateTime, List<StepRecord>> groupedByMonth = {};
for (var record in records) {
DateTime monthKey = DateTime(record.dateFrom.year, record.dateFrom.month);
if (!groupedByMonth.containsKey(monthKey)) {
groupedByMonth[monthKey] = [];
}
groupedByMonth[monthKey]!.add(record);
}

List<StepRecord> averageRecords = [];
groupedByMonth.forEach((month, records) {
double totalSteps = records.fold(0, (sum, record) => sum + record.numericValue);
double averageSteps = totalSteps / records.length;
averageRecords.add(StepRecord(
dateFrom: month,
numericValue: averageSteps.toInt(),
uuid: "month_${month.toString()}",
unit: 'COUNT',
dateTo: month.add(const Duration(days: 1)),
));
});

return averageRecords;
}
}

class WeightData {
final String date;
final double weight;

WeightData(this.date, this.weight);
}
Loading

0 comments on commit 4c36e2b

Please sign in to comment.