Klimatologiot/lib/core/utils/time_series_mapper.dart

118 lines
3.0 KiB
Dart

class TimeSeriesMapper {
/// =========================
/// 📅 DAILY (24 JAM)
/// =========================
static List<double> toDaily<T>({
required List<T> data,
required DateTime Function(T) getTime,
required double Function(T) getValue,
}) {
final now = DateTime.now();
final sums = List<double>.filled(24, 0.0);
final counts = List<int>.filled(24, 0);
for (final item in data) {
final time = getTime(item);
if (_isSameDay(time, now)) {
final hour = time.hour;
sums[hour] += getValue(item);
counts[hour]++;
}
}
return List.generate(24, (i) {
if (counts[i] == 0) return 0;
return sums[i] / counts[i]; // 🔥 average, bukan overwrite
});
}
/// =========================
/// 📅 WEEKLY (7 HARI)
/// =========================
static List<double> toWeekly<T>({
required List<T> data,
required DateTime Function(T) getTime,
required double Function(T) getValue,
}) {
final now = DateTime.now();
final sums = List<double>.filled(7, 0.0);
final counts = List<int>.filled(7, 0);
DateTime startOfWeek = now.subtract(Duration(days: now.weekday - 1));
startOfWeek =
DateTime(startOfWeek.year, startOfWeek.month, startOfWeek.day);
for (final item in data) {
final time = getTime(item);
if (time.isAfter(startOfWeek)) {
final index = time.weekday - 1;
sums[index] += getValue(item);
counts[index]++;
}
}
return List.generate(7, (i) {
if (counts[i] == 0) return 0;
return sums[i] / counts[i];
});
}
/// =========================
/// 📅 MONTHLY
/// =========================
static List<double> toMonthly<T>({
required List<T> data,
required DateTime Function(T) getTime,
required double Function(T) getValue,
}) {
final now = DateTime.now();
final daysInMonth = DateTime(now.year, now.month + 1, 0).day;
final sums = List<double>.filled(daysInMonth, 0.0);
final counts = List<int>.filled(daysInMonth, 0);
for (final item in data) {
final time = getTime(item);
if (time.month == now.month && time.year == now.year) {
final index = time.day - 1;
sums[index] += getValue(item);
counts[index]++;
}
}
return List.generate(daysInMonth, (i) {
if (counts[i] == 0) return 0;
return sums[i] / counts[i];
});
}
/// =========================
/// 🧠 HELPER
/// =========================
static bool _isSameDay(DateTime a, DateTime b) {
return a.year == b.year && a.month == b.month && a.day == b.day;
}
static List<double> smooth(List<double> data) {
if (data.length < 3) return data;
List<double> result = [];
for (int i = 0; i < data.length; i++) {
if (i == 0 || i == data.length - 1) {
result.add(data[i]);
} else {
final avg = (data[i - 1] + data[i] + data[i + 1]) / 3;
result.add(avg);
}
}
return result;
}
}