forked from firka/firka
141 lines
3.7 KiB
Dart
141 lines
3.7 KiB
Dart
import 'dart:ui';
|
|
|
|
import 'package:firka_common/ui/theme/style.dart';
|
|
import 'package:kreta_api/kreta_api.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;
|
|
}
|
|
|
|
int percentageToGrade(int grade) {
|
|
if (grade < 50) {
|
|
return 1;
|
|
}
|
|
if (grade < 60) {
|
|
return 2;
|
|
}
|
|
if (grade < 70) {
|
|
return 3;
|
|
}
|
|
if (grade < 80) {
|
|
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;
|
|
}
|
|
}
|
|
|
|
(int total, List<int> countsByGrade) getGradeDistribution(List<Grade> grades) {
|
|
final filtered = grades.where((g) {
|
|
final typeName = g.type.name?.toLowerCase() ?? '';
|
|
if (typeName == 'felevi_jegy_ertekeles' ||
|
|
typeName == 'evvegi_jegy_ertekeles') {
|
|
return false;
|
|
}
|
|
|
|
final valueTypeName = g.valueType.name?.toLowerCase() ?? '';
|
|
final isPercentage =
|
|
valueTypeName.contains('szazalek') || valueTypeName.contains('percent');
|
|
if (isPercentage) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}).toList();
|
|
final counts = [0, 0, 0, 0, 0];
|
|
for (final g in filtered) {
|
|
if (g.numericValue == null) continue;
|
|
final value = g.valueType.name == "Szazalekos"
|
|
? percentageToGrade(g.numericValue!.round())
|
|
: g.numericValue!.round().clamp(1, 5);
|
|
counts[value - 1]++;
|
|
}
|
|
return (filtered.length, counts);
|
|
}
|
|
|
|
extension GradeListExtension on List<Grade> {
|
|
double getAverageBySubject(Subject subject) {
|
|
final subjectGrades = where((g) => g.subject.uid == subject.uid).toList();
|
|
if (subjectGrades.isEmpty) return double.nan;
|
|
|
|
final feleviOrEvvegi = subjectGrades.where((g) {
|
|
final typeName = g.type.name?.toLowerCase() ?? '';
|
|
return typeName == 'felevi_jegy_ertekeles' ||
|
|
typeName == 'evvegi_jegy_ertekeles';
|
|
}).toList();
|
|
final hasOtherType = subjectGrades.any((g) {
|
|
final typeName = g.type.name?.toLowerCase() ?? '';
|
|
return typeName != 'felevi_jegy_ertekeles' &&
|
|
typeName != 'evvegi_jegy_ertekeles';
|
|
});
|
|
|
|
if (!hasOtherType && feleviOrEvvegi.isNotEmpty) {
|
|
final withValue = feleviOrEvvegi
|
|
.where((g) => g.numericValue != null && g.numericValue! > 0)
|
|
.toList();
|
|
if (withValue.isEmpty) return double.nan;
|
|
withValue.sort((a, b) => a.recordDate.compareTo(b.recordDate));
|
|
return withValue.last.numericValue!.toDouble();
|
|
}
|
|
|
|
var weightTotal = 0.00;
|
|
var sum = 0.00;
|
|
for (var grade in subjectGrades) {
|
|
final valueTypeName = grade.valueType.name?.toLowerCase() ?? '';
|
|
final isPercentage =
|
|
valueTypeName.contains('szazalek') ||
|
|
valueTypeName.contains('percent');
|
|
final typeName = grade.type.name?.toLowerCase() ?? '';
|
|
final isHalfYear = typeName == 'felevi_jegy_ertekeles';
|
|
final isEndYear = typeName == 'evvegi_jegy_ertekeles';
|
|
if (isPercentage || isHalfYear || isEndYear) continue;
|
|
if (grade.numericValue != null) {
|
|
var weight = (grade.weightPercentage ?? 100) / 100.0;
|
|
weightTotal += weight;
|
|
sum += grade.numericValue! * weight;
|
|
}
|
|
}
|
|
if (weightTotal == 0) return double.nan;
|
|
return sum / weightTotal;
|
|
}
|
|
}
|