You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fluffychat/lib/pangea/models/chart_analytics_model.dart

141 lines
3.5 KiB
Dart

import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:fluffychat/pangea/enum/time_span.dart';
import 'package:fluffychat/pangea/models/student_analytics_summary_model.dart';
import '../enum/use_type.dart';
class TimeSeriesTotals {
int ta;
int ga;
int wa;
int un;
int get all => ta + ga + wa + un;
TimeSeriesTotals({
required this.ta,
required this.ga,
required this.wa,
required this.un,
});
Map<String, dynamic> toJson() => {
UseType.ta.string: ta,
UseType.ga.string: ga,
UseType.wa.string: wa,
UseType.un.string: un,
};
factory TimeSeriesTotals.fromJson(json) => TimeSeriesTotals(
ta: json[UseType.ta.string],
ga: json[UseType.ga.string],
wa: json[UseType.wa.string],
un: json[UseType.un.string],
);
static get empty => TimeSeriesTotals(ta: 0, ga: 0, wa: 0, un: 0);
int get taPercent => all != 0 ? (ta / all * 100).round() : 0;
int get gaPercent => all != 0 ? (ga / all * 100).round() : 0;
int get waPercent => all != 0 ? (wa / all * 100).round() : 0;
int get unPercent => all != 0 ? (un / all * 100).round() : 0;
void increment(RecentMessageRecord msg) {
switch (msg.useType) {
case UseType.ta:
ta += 1;
break;
case UseType.wa:
wa += 1;
break;
case UseType.ga:
ga += 1;
break;
case UseType.un:
un += 1;
break;
default:
debugger(when: kDebugMode);
debugPrint("message with bad type ${msg.toJson()}");
}
}
}
class TimeSeriesInterval {
DateTime start;
DateTime end;
TimeSeriesTotals totals;
TimeSeriesInterval({
required this.start,
required this.end,
required this.totals,
});
Map<String, dynamic> toJson() => {
"strt": start.toIso8601String(),
"end": end.toIso8601String(),
"totals": totals.toJson(),
};
factory TimeSeriesInterval.fromJson(json) => TimeSeriesInterval(
start: DateTime.parse(json["strt"]),
end: DateTime.parse(json["end"]),
totals: TimeSeriesTotals.fromJson(json["totals"]),
);
}
class ChartAnalyticsModel {
final TimeSpan timeSpan;
final TimeSeriesTotals totals = TimeSeriesTotals.empty;
final List<RecentMessageRecord> msgs;
final String? chatId;
late DateTime fetchedAt;
late List<TimeSeriesInterval> timeSeries;
DateTime? lastMessage;
ChartAnalyticsModel({
required this.timeSpan,
required this.msgs,
this.chatId,
}) {
fetchedAt = DateTime.now();
calculate();
}
bool get isEmpty => (totals.ga + totals.ta + totals.wa == 0);
void calculate() {
final Map<String, TimeSeriesInterval> intervals = timeSpan.emptyIntervals;
final DateTime cutOff = timeSpan.cutOffDate;
final filtered = msgs.where(
(msg) =>
(chatId == null || msg.chatId == chatId) && msg.time.isAfter(cutOff),
);
//remove msgs with duplicate ids
final Map<String, RecentMessageRecord> unique = {};
for (final msg in filtered) {
if (unique[msg.eventId] == null) {
unique[msg.eventId] = msg;
}
}
for (final msg in unique.values) {
final String key = timeSpan.getMapKey(msg.time);
if (intervals[key] == null) {
debugger(when: kDebugMode);
} else {
intervals[key]!.totals.increment(msg);
totals.increment(msg);
lastMessage = msg.time;
}
}
timeSeries = intervals.values.toList().reversed.toList();
}
}