forked from firka/firka
161 lines
3.5 KiB
Dart
161 lines
3.5 KiB
Dart
import 'package:kreta_api/kreta_api.dart';
|
|
|
|
import 'dart:ui';
|
|
|
|
import 'package:firka_common/ui/theme/style.dart';
|
|
|
|
int roundGrade(
|
|
num grade, {
|
|
double t1 = 1,
|
|
double t2 = 0.5,
|
|
double t3 = 0.5,
|
|
double t4 = 0.5,
|
|
}) {
|
|
if (grade < 1 + t1) {
|
|
return 1;
|
|
}
|
|
if (grade < 2 + t2) {
|
|
return 2;
|
|
}
|
|
if (grade < 3 + t3) {
|
|
return 3;
|
|
}
|
|
if (grade < 4 + t4) {
|
|
return 4;
|
|
}
|
|
|
|
return 5;
|
|
}
|
|
|
|
Color getGradeColor(
|
|
num grade, {
|
|
double t1 = 1,
|
|
double t2 = 0.5,
|
|
double t3 = 0.5,
|
|
double t4 = 0.5,
|
|
}) {
|
|
switch (roundGrade(grade, t1: t1, t2: t2, t3: t3, t4: t4)) {
|
|
case 2:
|
|
return appStyle.colors.grade2;
|
|
case 3:
|
|
return appStyle.colors.grade3;
|
|
case 4:
|
|
return appStyle.colors.grade4;
|
|
case 5:
|
|
return appStyle.colors.grade5;
|
|
default:
|
|
return appStyle.colors.grade1;
|
|
}
|
|
}
|
|
|
|
extension GradeListExtension on Iterable<Grade> {
|
|
(int total, List<int> countsByGrade) getGradeDistribution() {
|
|
final filtered = where((g) => g.shouldIncludeInAverage());
|
|
final counts = [0, 0, 0, 0, 0];
|
|
for (final g in filtered) {
|
|
counts[g.numericValue! - 1]++;
|
|
}
|
|
return (filtered.length, counts);
|
|
}
|
|
|
|
double? _getAverageBySubject(String uid, {bool halfYearFallback = true}) {
|
|
return where(
|
|
(g) => g.subject.uid == uid,
|
|
).getAverage(halfYearFallback: halfYearFallback);
|
|
}
|
|
|
|
double? getAverageBySubject(Subject subject, {bool halfYearFallback = true}) {
|
|
return _getAverageBySubject(
|
|
subject.uid,
|
|
halfYearFallback: halfYearFallback,
|
|
);
|
|
}
|
|
|
|
double? getRoundedSubjectAverage({
|
|
bool halfYearFallback = true,
|
|
double t1 = 1,
|
|
double t2 = 0.5,
|
|
double t3 = 0.5,
|
|
double t4 = 0.5,
|
|
}) {
|
|
final averages = map((g) => g.subject).toSet().map((subject) {
|
|
final average = getAverageBySubject(
|
|
subject,
|
|
halfYearFallback: halfYearFallback,
|
|
);
|
|
if (average == null) {
|
|
return null;
|
|
}
|
|
return roundGrade(average, t1: t1, t2: t2, t3: t3, t4: t4);
|
|
}).nonNulls;
|
|
|
|
if (averages.isEmpty) {
|
|
return null;
|
|
}
|
|
|
|
return averages.reduce((sum, avg) => sum + avg) / averages.length;
|
|
}
|
|
|
|
double? getSubjectAverage({bool halfYearFallback = true}) {
|
|
final averages = where((g) => g.hasClassicValue())
|
|
.map((g) => g.subject.uid)
|
|
.toSet()
|
|
.map(
|
|
(uid) =>
|
|
_getAverageBySubject(uid, halfYearFallback: halfYearFallback),
|
|
)
|
|
.nonNulls;
|
|
|
|
if (averages.isEmpty) {
|
|
return null;
|
|
}
|
|
|
|
return averages.reduce((sum, avg) => sum + avg) / averages.length;
|
|
}
|
|
|
|
double? getAverage({bool halfYearFallback = true}) {
|
|
if (isEmpty) {
|
|
return null;
|
|
}
|
|
|
|
double weightTotal = 0;
|
|
double sum = 0;
|
|
int? fallback;
|
|
for (Grade grade in this) {
|
|
if (grade.hasClassicValue() && halfYearFallback) {
|
|
fallback = grade.numericValue!;
|
|
}
|
|
|
|
if (!grade.shouldIncludeInAverage()) {
|
|
continue;
|
|
}
|
|
|
|
double weight = grade.weightPercentage! / 100.0;
|
|
weightTotal += weight;
|
|
sum += grade.numericValue! * weight;
|
|
}
|
|
|
|
if (sum == 0) {
|
|
// use classification exam results or half-year evaluations
|
|
return fallback?.toDouble();
|
|
}
|
|
|
|
return sum / weightTotal;
|
|
}
|
|
}
|
|
|
|
extension GradeExtension on Grade {
|
|
bool isInPercentage() {
|
|
return valueType.name == 'Szazalekos';
|
|
}
|
|
|
|
bool hasClassicValue() {
|
|
return valueType.name == "Osztalyzat";
|
|
}
|
|
|
|
// https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=2426172
|
|
bool shouldIncludeInAverage() {
|
|
return weightPercentage != null && hasClassicValue();
|
|
}
|
|
}
|