changed old subject type to gradesubject

This commit is contained in:
Kima 2023-10-15 12:14:06 +02:00
parent c7c3b421f4
commit 2d5cbe8799
31 changed files with 497 additions and 156 deletions

View File

@ -22,7 +22,8 @@ class SubjectIconData {
}); });
} }
SubjectIconVariants createIcon({required IconData material, required IconData cupertino}) { SubjectIconVariants createIcon(
{required IconData material, required IconData cupertino}) {
return { return {
IconPack.material: material, IconPack.material: material,
IconPack.cupertino: cupertino, IconPack.cupertino: cupertino,
@ -30,88 +31,224 @@ SubjectIconVariants createIcon({required IconData material, required IconData cu
} }
class SubjectIcon { class SubjectIcon {
static String resolveName({Subject? subject, String? subjectName}) => _resolve(subject: subject, subjectName: subjectName).name; static String resolveName({GradeSubject? subject, String? subjectName}) =>
static IconData resolveVariant({Subject? subject, String? subjectName, required BuildContext context}) => _resolve(subject: subject, subjectName: subjectName).name;
_resolve(subject: subject, subjectName: subjectName).data[Provider.of<SettingsProvider>(context, listen: false).iconPack]!; static IconData resolveVariant(
{GradeSubject? subject,
String? subjectName,
required BuildContext context}) =>
_resolve(subject: subject, subjectName: subjectName).data[
Provider.of<SettingsProvider>(context, listen: false).iconPack]!;
static SubjectIconData _resolve({Subject? subject, String? subjectName}) { static SubjectIconData _resolve(
{GradeSubject? subject, String? subjectName}) {
assert(!(subject == null && subjectName == null)); assert(!(subject == null && subjectName == null));
String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim(); String name = (subject?.name ?? subjectName ?? "")
String category = subject?.category.description.toLowerCase().specialChars() ?? ""; .toLowerCase()
.specialChars()
.trim();
String category =
subject?.category.description.toLowerCase().specialChars() ?? "";
// todo: check for categories // todo: check for categories
if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") { if (RegExp("mate(k|matika)").hasMatch(name) || category == "matematika") {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.function, material: Icons.calculate_outlined), name: "function");
} else if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.textformat_alt, material: Icons.spellcheck_outlined), name: "textformat.alt");
} else if (RegExp("irodalom").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.book, material: Icons.menu_book_outlined), name: "book");
} else if (RegExp("tor(i|tenelem)").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.compass, material: Icons.hourglass_empty_outlined), name: "safari");
} else if (RegExp("foldrajz").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.map, material: Icons.public_outlined), name: "map");
} else if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.paintbrush, material: Icons.palette_outlined), name: "paintbrush");
} else if (RegExp("fizika").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.lightbulb, material: Icons.emoji_objects_outlined), name: "lightbulb");
} else if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.music_note, material: Icons.music_note_outlined), name: "music.note");
} else if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.sportscourt, material: Icons.sports_soccer_outlined), name: "sportscourt");
} else if (RegExp("kemia").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.lab_flask, material: Icons.science_outlined), name: "testtube.2");
} else if (RegExp("biologia").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.paw, material: Icons.pets_outlined), name: "pawprint");
} else if (RegExp("kornyezet|termeszet ?(tudomany|ismeret)|hon( es nep)?ismeret").hasMatch(name)) {
return SubjectIconData( return SubjectIconData(
data: createIcon(cupertino: CupertinoIcons.arrow_3_trianglepath, material: Icons.eco_outlined), name: "arrow.3.trianglepath"); data: createIcon(
cupertino: CupertinoIcons.function,
material: Icons.calculate_outlined),
name: "function");
} else if (RegExp("magyar nyelv|nyelvtan").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.textformat_alt,
material: Icons.spellcheck_outlined),
name: "textformat.alt");
} else if (RegExp("irodalom").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.book,
material: Icons.menu_book_outlined),
name: "book");
} else if (RegExp("tor(i|tenelem)").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.compass,
material: Icons.hourglass_empty_outlined),
name: "safari");
} else if (RegExp("foldrajz").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.map, material: Icons.public_outlined),
name: "map");
} else if (RegExp("rajz|muvtori|muveszet|vizualis").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.paintbrush,
material: Icons.palette_outlined),
name: "paintbrush");
} else if (RegExp("fizika").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.lightbulb,
material: Icons.emoji_objects_outlined),
name: "lightbulb");
} else if (RegExp("^enek|zene|szolfezs|zongora|korus").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.music_note,
material: Icons.music_note_outlined),
name: "music.note");
} else if (RegExp("^tes(i|tneveles)|sport").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.sportscourt,
material: Icons.sports_soccer_outlined),
name: "sportscourt");
} else if (RegExp("kemia").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.lab_flask,
material: Icons.science_outlined),
name: "testtube.2");
} else if (RegExp("biologia").hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.paw, material: Icons.pets_outlined),
name: "pawprint");
} else if (RegExp(
"kornyezet|termeszet ?(tudomany|ismeret)|hon( es nep)?ismeret")
.hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.arrow_3_trianglepath,
material: Icons.eco_outlined),
name: "arrow.3.trianglepath");
} else if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) { } else if (RegExp("(hit|erkolcs)tan|vallas|etika").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.heart, material: Icons.favorite_border_outlined), name: "heart"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.heart,
material: Icons.favorite_border_outlined),
name: "heart");
} else if (RegExp("penzugy").hasMatch(name)) { } else if (RegExp("penzugy").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.money_dollar, material: Icons.savings_outlined), name: "dollarsign"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.money_dollar,
material: Icons.savings_outlined),
name: "dollarsign");
} else if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) { } else if (RegExp("informatika|szoftver|iroda|digitalis").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.device_laptop, material: Icons.computer_outlined), name: "laptopcomputer"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.device_laptop,
material: Icons.computer_outlined),
name: "laptopcomputer");
} else if (RegExp("prog").hasMatch(name)) { } else if (RegExp("prog").hasMatch(name)) {
return SubjectIconData( return SubjectIconData(
data: createIcon(cupertino: CupertinoIcons.chevron_left_slash_chevron_right, material: Icons.code_outlined), data: createIcon(
cupertino: CupertinoIcons.chevron_left_slash_chevron_right,
material: Icons.code_outlined),
name: "chevron.left.forwardslash.chevron.right"); name: "chevron.left.forwardslash.chevron.right");
} else if (RegExp("halozat").hasMatch(name)) { } else if (RegExp("halozat").hasMatch(name)) {
return SubjectIconData( return SubjectIconData(
data: createIcon(cupertino: CupertinoIcons.antenna_radiowaves_left_right, material: Icons.wifi_tethering_outlined), data: createIcon(
cupertino: CupertinoIcons.antenna_radiowaves_left_right,
material: Icons.wifi_tethering_outlined),
name: "antenna.radiowaves.left.and.right"); name: "antenna.radiowaves.left.and.right");
} else if (RegExp("szinhaz").hasMatch(name)) { } else if (RegExp("szinhaz").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.hifispeaker, material: Icons.theater_comedy_outlined), name: "hifispeaker"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.hifispeaker,
material: Icons.theater_comedy_outlined),
name: "hifispeaker");
} else if (RegExp("film|media").hasMatch(name)) { } else if (RegExp("film|media").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.film, material: Icons.theaters_outlined), name: "film"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.film,
material: Icons.theaters_outlined),
name: "film");
} else if (RegExp("elektro(tech)?nika").hasMatch(name)) { } else if (RegExp("elektro(tech)?nika").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.bolt, material: Icons.electrical_services_outlined), name: "bolt"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.bolt,
material: Icons.electrical_services_outlined),
name: "bolt");
} else if (RegExp("gepesz|mernok|ipar").hasMatch(name)) { } else if (RegExp("gepesz|mernok|ipar").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.wrench, material: Icons.precision_manufacturing_outlined), name: "wrench"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.wrench,
material: Icons.precision_manufacturing_outlined),
name: "wrench");
} else if (RegExp("technika").hasMatch(name)) { } else if (RegExp("technika").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.hammer, material: Icons.build_outlined), name: "hammer"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.hammer, material: Icons.build_outlined),
name: "hammer");
} else if (RegExp("tanc").hasMatch(name)) { } else if (RegExp("tanc").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.music_mic, material: Icons.speaker_outlined), name: "music.mic"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.music_mic,
material: Icons.speaker_outlined),
name: "music.mic");
} else if (RegExp("filozofia").hasMatch(name)) { } else if (RegExp("filozofia").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.bubble_left, material: Icons.psychology_outlined), name: "bubble.left"); return SubjectIconData(
} else if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) || name == "ofo") { data: createIcon(
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.group, material: Icons.groups_outlined), name: "person.3"); cupertino: CupertinoIcons.bubble_left,
material: Icons.psychology_outlined),
name: "bubble.left");
} else if (RegExp("osztaly(fonoki|kozosseg)").hasMatch(name) ||
name == "ofo") {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.group, material: Icons.groups_outlined),
name: "person.3");
} else if (RegExp("gazdasag").hasMatch(name)) { } else if (RegExp("gazdasag").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.chart_pie, material: Icons.account_balance_outlined), name: "chart.pie"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.chart_pie,
material: Icons.account_balance_outlined),
name: "chart.pie");
} else if (RegExp("szorgalom").hasMatch(name)) { } else if (RegExp("szorgalom").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.checkmark_seal, material: Icons.verified_outlined), name: "checkmark.seal"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.checkmark_seal,
material: Icons.verified_outlined),
name: "checkmark.seal");
} else if (RegExp("magatartas").hasMatch(name)) { } else if (RegExp("magatartas").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.smiley, material: Icons.emoji_people_outlined), name: "face.smiling"); return SubjectIconData(
} else if (RegExp("angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv").hasMatch(name)) { data: createIcon(
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.globe, material: Icons.translate_outlined), name: "globe"); cupertino: CupertinoIcons.smiley,
material: Icons.emoji_people_outlined),
name: "face.smiling");
} else if (RegExp(
"angol|nemet|francia|olasz|orosz|spanyol|latin|kinai|nyelv")
.hasMatch(name)) {
return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.globe,
material: Icons.translate_outlined),
name: "globe");
} else if (RegExp("linux").hasMatch(name)) { } else if (RegExp("linux").hasMatch(name)) {
return SubjectIconData(data: createIcon(material: FilcIcons.linux, cupertino: FilcIcons.linux)); return SubjectIconData(
data: createIcon(
material: FilcIcons.linux, cupertino: FilcIcons.linux));
} else if (RegExp("adatbazis").hasMatch(name)) { } else if (RegExp("adatbazis").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.table_badge_more, material: Icons.table_chart), name: "table.badge.more"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.table_badge_more,
material: Icons.table_chart),
name: "table.badge.more");
} else if (RegExp("asztali alkalmazasok").hasMatch(name)) { } else if (RegExp("asztali alkalmazasok").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.macwindow, material: Icons.desktop_windows_outlined), name: "macwindow"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.macwindow,
material: Icons.desktop_windows_outlined),
name: "macwindow");
} else if (RegExp("projekt").hasMatch(name)) { } else if (RegExp("projekt").hasMatch(name)) {
return SubjectIconData(data: createIcon(cupertino: CupertinoIcons.person_3_fill, material: Icons.groups_3), name: "person.3.fill"); return SubjectIconData(
data: createIcon(
cupertino: CupertinoIcons.person_3_fill,
material: Icons.groups_3),
name: "person.3.fill");
} }
return SubjectIconData(); return SubjectIconData();
@ -119,10 +256,13 @@ class SubjectIcon {
} }
class ShortSubject { class ShortSubject {
static String resolve({Subject? subject, String? subjectName}) { static String resolve({GradeSubject? subject, String? subjectName}) {
assert(!(subject == null && subjectName == null)); assert(!(subject == null && subjectName == null));
String name = (subject?.name ?? subjectName ?? "").toLowerCase().specialChars().trim(); String name = (subject?.name ?? subjectName ?? "")
.toLowerCase()
.specialChars()
.trim();
// String category = subject?.category.description.toLowerCase().specialChars() ?? ""; // String category = subject?.category.description.toLowerCase().specialChars() ?? "";
if (RegExp("magyar irodalom").hasMatch(name)) { if (RegExp("magyar irodalom").hasMatch(name)) {
@ -137,7 +277,9 @@ class ShortSubject {
return "Tesi"; return "Tesi";
} else if (RegExp("tortenelem").hasMatch(name)) { } else if (RegExp("tortenelem").hasMatch(name)) {
return "Töri"; return "Töri";
} else if (RegExp("(angol|nemet|francia|olasz|orosz|spanyol|latin|kinai) nyelv").hasMatch(name)) { } else if (RegExp(
"(angol|nemet|francia|olasz|orosz|spanyol|latin|kinai) nyelv")
.hasMatch(name)) {
return (subject?.name ?? subjectName ?? "?").replaceAll(" nyelv", ""); return (subject?.name ?? subjectName ?? "?").replaceAll(" nyelv", "");
} else if (RegExp("informatika").hasMatch(name)) { } else if (RegExp("informatika").hasMatch(name)) {
return "Infó"; return "Infó";

View File

@ -5,17 +5,21 @@ enum SubjectLessonCountUpdateState { ready, updating }
class SubjectLessonCount { class SubjectLessonCount {
DateTime lastUpdated; DateTime lastUpdated;
Map<Subject, int> subjects; Map<GradeSubject, int> subjects;
SubjectLessonCountUpdateState state; SubjectLessonCountUpdateState state;
SubjectLessonCount({required this.lastUpdated, required this.subjects, this.state = SubjectLessonCountUpdateState.ready}); SubjectLessonCount(
{required this.lastUpdated,
required this.subjects,
this.state = SubjectLessonCountUpdateState.ready});
factory SubjectLessonCount.fromMap(Map json) { factory SubjectLessonCount.fromMap(Map json) {
return SubjectLessonCount( return SubjectLessonCount(
lastUpdated: DateTime.fromMillisecondsSinceEpoch(json["last_updated"] ?? 0), lastUpdated:
DateTime.fromMillisecondsSinceEpoch(json["last_updated"] ?? 0),
subjects: ((json["subjects"] as Map?) ?? {}).map( subjects: ((json["subjects"] as Map?) ?? {}).map(
(key, value) => MapEntry( (key, value) => MapEntry(
Subject(id: key, name: "", category: Category.fromJson({})), GradeSubject(id: key, name: "", category: Category.fromJson({})),
value, value,
), ),
), ),

View File

@ -31,7 +31,7 @@ import 'absences_page.i18n.dart';
enum AbsenceFilter { absences, delays, misses } enum AbsenceFilter { absences, delays, misses }
class SubjectAbsence { class SubjectAbsence {
Subject subject; GradeSubject subject;
List<Absence> absences; List<Absence> absences;
double percentage; double percentage;
@ -56,7 +56,7 @@ class _AbsencesPageState extends State<AbsencesPage>
late String firstName; late String firstName;
late TabController _tabController; late TabController _tabController;
late List<SubjectAbsence> absences = []; late List<SubjectAbsence> absences = [];
final Map<Subject, Lesson> _lessonCount = {}; final Map<GradeSubject, Lesson> _lessonCount = {};
@override @override
void initState() { void initState() {
@ -87,7 +87,7 @@ class _AbsencesPageState extends State<AbsencesPage>
} }
void buildSubjectAbsences() { void buildSubjectAbsences() {
Map<Subject, SubjectAbsence> _absences = {}; Map<GradeSubject, SubjectAbsence> _absences = {};
for (final absence in absenceProvider.absences) { for (final absence in absenceProvider.absences) {
if (absence.delay != 0) continue; if (absence.delay != 0) continue;

View File

@ -32,7 +32,7 @@ class GradeSubjectView extends StatefulWidget {
const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0}) const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0})
: super(key: key); : super(key: key);
final Subject subject; final GradeSubject subject;
final double groupAverage; final double groupAverage;
void push(BuildContext context, {bool root = false}) { void push(BuildContext context, {bool root = false}) {
@ -62,7 +62,7 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
bool gradeCalcMode = false; bool gradeCalcMode = false;
List<Grade> getSubjectGrades(Subject subject) => !gradeCalcMode List<Grade> getSubjectGrades(GradeSubject subject) => !gradeCalcMode
? gradeProvider.grades.where((e) => e.subject == subject).toList() ? gradeProvider.grades.where((e) => e.subject == subject).toList()
: calculatorProvider.grades.where((e) => e.subject == subject).toList(); : calculatorProvider.grades.where((e) => e.subject == subject).toList();

View File

@ -41,7 +41,7 @@ class _GradesPageState extends State<GradesPage> {
int avgDropValue = 0; int avgDropValue = 0;
List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider List<Grade> getSubjectGrades(GradeSubject subject, {int days = 0}) => gradeProvider
.grades .grades
.where((e) => .where((e) =>
e.subject == subject && e.subject == subject &&
@ -51,14 +51,14 @@ class _GradesPageState extends State<GradesPage> {
.toList(); .toList();
void generateTiles() { void generateTiles() {
List<Subject> subjects = gradeProvider.grades List<GradeSubject> subjects = gradeProvider.grades
.map((e) => e.subject) .map((e) => e.subject)
.toSet() .toSet()
.toList() .toList()
..sort((a, b) => a.name.compareTo(b.name)); ..sort((a, b) => a.name.compareTo(b.name));
List<Widget> tiles = []; List<Widget> tiles = [];
Map<Subject, double> subjectAvgs = {}; Map<GradeSubject, double> subjectAvgs = {};
tiles.addAll(subjects.map((subject) { tiles.addAll(subjects.map((subject) {
List<Grade> subjectGrades = getSubjectGrades(subject); List<Grade> subjectGrades = getSubjectGrades(subject);

View File

@ -13,7 +13,7 @@ class Absence {
Category? justification; Category? justification;
Category? type; Category? type;
Category? mode; Category? mode;
Subject subject; GradeSubject subject;
DateTime lessonStart; DateTime lessonStart;
DateTime lessonEnd; DateTime lessonEnd;
int? lessonIndex; int? lessonIndex;
@ -83,7 +83,7 @@ class Absence {
: null, : null,
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null, type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
mode: json["Mod"] != null ? Category.fromJson(json["Mod"]) : null, mode: json["Mod"] != null ? Category.fromJson(json["Mod"]) : null,
subject: Subject.fromJson(json["Tantargy"] ?? {}), subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
lessonStart: lessonStart, lessonStart: lessonStart,
lessonEnd: lessonEnd, lessonEnd: lessonEnd,
lessonIndex: lessonIndex, lessonIndex: lessonIndex,

View File

@ -10,7 +10,7 @@ class Exam {
Category? mode; Category? mode;
// int? subjectIndex; // int? subjectIndex;
// String subjectName; // String subjectName;
Subject subject; GradeSubject subject;
Teacher teacher; Teacher teacher;
String description; String description;
String group; String group;
@ -42,7 +42,7 @@ class Exam {
mode: json["Modja"] != null ? Category.fromJson(json["Modja"]) : null, mode: json["Modja"] != null ? Category.fromJson(json["Modja"]) : null,
// subjectIndex: json["OrarendiOraOraszama"], // subjectIndex: json["OrarendiOraOraszama"],
// subjectName: json["TantargyNeve"] ?? "", // subjectName: json["TantargyNeve"] ?? "",
subject: Subject.fromJson(json["Tantargy"] ?? {}), subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()), teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
description: (json["Temaja"] ?? "").trim(), description: (json["Temaja"] ?? "").trim(),
group: json["OsztalyCsoport"] != null group: json["OsztalyCsoport"] != null

View File

@ -12,7 +12,7 @@ class Grade {
String description; String description;
GradeType type; GradeType type;
String groupId; String groupId;
Subject subject; GradeSubject subject;
Category? gradeType; Category? gradeType;
Category mode; Category mode;
DateTime writeDate; DateTime writeDate;
@ -57,7 +57,7 @@ class Grade {
? Category.getGradeType(json["Tipus"]["Nev"]) ? Category.getGradeType(json["Tipus"]["Nev"])
: GradeType.unknown, : GradeType.unknown,
groupId: (json["OsztalyCsoport"] ?? {})["Uid"] ?? "", groupId: (json["OsztalyCsoport"] ?? {})["Uid"] ?? "",
subject: Subject.fromJson(json["Tantargy"] ?? {}), subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
gradeType: json["ErtekFajta"] != null gradeType: json["ErtekFajta"] != null
? Category.fromJson(json["ErtekFajta"]) ? Category.fromJson(json["ErtekFajta"])
: null, : null,

View File

@ -3,7 +3,7 @@ import 'package:filcnaplo_kreta_api/models/subject.dart';
class GroupAverage { class GroupAverage {
String uid; String uid;
double average; double average;
Subject subject; GradeSubject subject;
Map json; Map json;
GroupAverage({required this.uid, required this.average, required this.subject, this.json = const {}}); GroupAverage({required this.uid, required this.average, required this.subject, this.json = const {}});
@ -12,7 +12,7 @@ class GroupAverage {
return GroupAverage( return GroupAverage(
uid: json["Uid"] ?? "", uid: json["Uid"] ?? "",
average: json["OsztalyCsoportAtlag"] ?? 0, average: json["OsztalyCsoportAtlag"] ?? 0,
subject: Subject.fromJson(json["Tantargy"] ?? {}), subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
json: json, json: json,
); );
} }

View File

@ -12,7 +12,7 @@ class Homework {
bool homeworkEnabled; bool homeworkEnabled;
Teacher teacher; Teacher teacher;
String content; String content;
Subject subject; GradeSubject subject;
String group; String group;
List<HomeworkAttachment> attachments; List<HomeworkAttachment> attachments;
String id; String id;
@ -48,7 +48,7 @@ class Homework {
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false, homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()), teacher: Teacher.fromString((json["RogzitoTanarNeve"] ?? "").trim()),
content: (json["Szoveg"] ?? "").trim(), content: (json["Szoveg"] ?? "").trim(),
subject: Subject.fromJson(json["Tantargy"] ?? {}), subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
group: json["OsztalyCsoport"] != null group: json["OsztalyCsoport"] != null
? json["OsztalyCsoport"]["Uid"] ?? "" ? json["OsztalyCsoport"]["Uid"] ?? ""
: "", : "",

View File

@ -6,7 +6,7 @@ class Lesson {
Map? json; Map? json;
Category? status; Category? status;
DateTime date; DateTime date;
Subject subject; GradeSubject subject;
String lessonIndex; String lessonIndex;
int? lessonYearIndex; int? lessonYearIndex;
Teacher? substituteTeacher; Teacher? substituteTeacher;
@ -68,7 +68,7 @@ class Lesson {
date: json["Datum"] != null date: json["Datum"] != null
? DateTime.parse(json["Datum"]).toLocal() ? DateTime.parse(json["Datum"]).toLocal()
: DateTime(0), : DateTime(0),
subject: Subject.fromJson(json["Tantargy"] ?? {}), subject: GradeSubject.fromJson(json["Tantargy"] ?? {}),
lessonIndex: json["Oraszam"] != null ? json["Oraszam"].toString() : "+", lessonIndex: json["Oraszam"] != null ? json["Oraszam"].toString() : "+",
lessonYearIndex: json["OraEvesSorszama"], lessonYearIndex: json["OraEvesSorszama"],
substituteTeacher: json["HelyettesTanarNeve"] != null substituteTeacher: json["HelyettesTanarNeve"] != null

View File

@ -1,6 +1,6 @@
import 'category.dart'; import 'category.dart';
class Subject { class GradeSubject {
String id; String id;
Category category; Category category;
String name; String name;
@ -8,11 +8,16 @@ class Subject {
bool get isRenamed => renamedTo != null; bool get isRenamed => renamedTo != null;
Subject({required this.id, required this.category, required this.name, this.renamedTo}); GradeSubject({
required this.id,
required this.category,
required this.name,
this.renamedTo,
});
factory Subject.fromJson(Map json) { factory GradeSubject.fromJson(Map json) {
final id = json["Uid"] ?? ""; final id = json["Uid"] ?? "";
return Subject( return GradeSubject(
id: id, id: id,
category: Category.fromJson(json["Kategoria"] ?? {}), category: Category.fromJson(json["Kategoria"] ?? {}),
name: (json["Nev"] ?? "").trim(), name: (json["Nev"] ?? "").trim(),
@ -21,7 +26,7 @@ class Subject {
@override @override
bool operator ==(other) { bool operator ==(other) {
if (other is! Subject) return false; if (other is! GradeSubject) return false;
return id == other.id; return id == other.id;
} }

View File

@ -0,0 +1,165 @@
import 'package:filcnaplo/api/providers/user_provider.dart';
import 'package:filcnaplo/api/providers/database_provider.dart';
import 'package:filcnaplo/models/settings.dart';
import 'package:filcnaplo/models/user.dart';
import 'package:filcnaplo_kreta_api/client/api.dart';
import 'package:filcnaplo_kreta_api/client/client.dart';
import 'package:filcnaplo_kreta_api/models/grade.dart';
import 'package:filcnaplo_kreta_api/models/group_average.dart';
import 'package:filcnaplo_kreta_api/providers/grade_provider.i18n.dart';
import 'package:flutter/material.dart';
class SubjectProvider with ChangeNotifier {
// Private
late List<Grade> _grades;
late DateTime _lastSeen;
late String _groups;
List<GroupAverage> _groupAvg = [];
late final SettingsProvider _settings;
late final UserProvider _user;
late final DatabaseProvider _database;
late final KretaClient _kreta;
// Public
List<Grade> get grades => _grades;
DateTime get lastSeenDate =>
_settings.gradeOpeningFun ? _lastSeen : DateTime(3000);
String get groups => _groups;
List<GroupAverage> get groupAverages => _groupAvg;
SubjectProvider({
List<Grade> initialGrades = const [],
required SettingsProvider settings,
required UserProvider user,
required DatabaseProvider database,
required KretaClient kreta,
}) {
_settings = settings;
_user = user;
_database = database;
_kreta = kreta;
_grades = List.castFrom(initialGrades);
_lastSeen = DateTime.now();
if (_grades.isEmpty) restore();
}
Future<void> seenAll() async {
String? userId = _user.id;
if (userId != null) {
final userStore = _database.userStore;
userStore.storeLastSeenGrade(DateTime.now(), userId: userId);
_lastSeen = DateTime.now();
}
}
Future<void> restore() async {
String? userId = _user.id;
// Load grades from the database
if (userId != null) {
final userQuery = _database.userQuery;
_grades = await userQuery.getGrades(userId: userId);
await convertBySettings();
_groupAvg = await userQuery.getGroupAverages(userId: userId);
notifyListeners();
DateTime lastSeenDB = await userQuery.lastSeenGrade(userId: userId);
if (lastSeenDB.millisecondsSinceEpoch == 0 ||
lastSeenDB.year == 0 ||
!_settings.gradeOpeningFun) {
_lastSeen = DateTime.now();
await seenAll();
} else {
_lastSeen = lastSeenDB;
}
notifyListeners();
}
}
// good student mode, renamed subjects
Future<void> convertBySettings() async {
Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled
? await _database.userQuery.renamedSubjects(userId: _user.user!.id)
: {};
Map<String, String> renamedTeachers = _settings.renamedTeachersEnabled
? await _database.userQuery.renamedTeachers(userId: _user.user!.id)
: {};
for (Grade grade in _grades) {
grade.subject.renamedTo =
renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
grade.teacher.renamedTo =
renamedTeachers.isNotEmpty ? renamedTeachers[grade.teacher.id] : null;
grade.value.value =
_settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
grade.value.valueName = _settings.goodStudent
? "Jeles".i18n
: '${grade.json!["SzovegesErtek"]}'
.replaceAll(RegExp(r'[(]+[12345]?[)]'), '')
.i18n;
grade.value.shortName = _settings.goodStudent
? "Jeles".i18n
: '${grade.json!["SzovegesErtekelesRovidNev"]}' != "null" &&
'${grade.json!["SzovegesErtekelesRovidNev"]}' != "-" &&
'${grade.json!["SzovegesErtekelesRovidNev"]}'
.replaceAll(RegExp(r'[0123456789]+[%]?'), '') !=
""
? '${grade.json!["SzovegesErtekelesRovidNev"]}'.i18n
: grade.value.valueName;
}
notifyListeners();
}
// Fetches Grades from the Kreta API then stores them in the database
Future<void> fetch() async {
User? user = _user.user;
if (user == null) throw "Cannot fetch Grades for User null";
String iss = user.instituteCode;
List? gradesJson = await _kreta.getAPI(KretaAPI.grades(iss));
if (gradesJson == null) throw "Cannot fetch Grades for User ${user.id}";
List<Grade> grades = gradesJson.map((e) => Grade.fromJson(e)).toList();
if (grades.isNotEmpty || _grades.isNotEmpty) await store(grades);
List? groupsJson = await _kreta.getAPI(KretaAPI.groups(iss));
if (groupsJson == null || groupsJson.isEmpty) {
throw "Cannot fetch Groups for User ${user.id}";
}
_groups = (groupsJson[0]["OktatasNevelesiFeladat"] ?? {})["Uid"] ?? "";
List? groupAvgJson =
await _kreta.getAPI(KretaAPI.groupAverages(iss, _groups));
if (groupAvgJson == null) {
throw "Cannot fetch Class Averages for User ${user.id}";
}
final groupAvgs =
groupAvgJson.map((e) => GroupAverage.fromJson(e)).toList();
await storeGroupAvg(groupAvgs);
}
// Stores Grades in the database
Future<void> store(List<Grade> grades) async {
User? user = _user.user;
if (user == null) throw "Cannot store Grades for User null";
String userId = user.id;
await _database.userStore.storeGrades(grades, userId: userId);
_grades = grades;
await convertBySettings();
}
Future<void> storeGroupAvg(List<GroupAverage> groupAvgs) async {
_groupAvg = groupAvgs;
User? user = _user.user;
if (user == null) throw "Cannot store Grades for User null";
String userId = user.id;
await _database.userStore.storeGroupAverages(groupAvgs, userId: userId);
notifyListeners();
}
}

View File

@ -35,12 +35,12 @@ class _PersonalityCardState extends State<PersonalityCard> {
late SettingsProvider settings; late SettingsProvider settings;
late List<int> subjectAvgsList = []; late List<int> subjectAvgsList = [];
late Map<Subject, double> subjectAvgs = {}; late Map<GradeSubject, double> subjectAvgs = {};
late double subjectAvg; late double subjectAvg;
late List<Grade> classWorkGrades; late List<Grade> classWorkGrades;
late Map<int, int> mostCommonGrade; late Map<int, int> mostCommonGrade;
late List<Absence> absences = []; late List<Absence> absences = [];
final Map<Subject, Lesson> _lessonCount = {}; final Map<GradeSubject, Lesson> _lessonCount = {};
late int totalDelays; late int totalDelays;
late int unexcusedAbsences; late int unexcusedAbsences;
@ -48,14 +48,15 @@ class _PersonalityCardState extends State<PersonalityCard> {
bool hold = false; bool hold = false;
List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider List<Grade> getSubjectGrades(GradeSubject subject, {int days = 0}) =>
.grades gradeProvider.grades
.where((e) => .where((e) =>
e.subject == subject && e.subject == subject &&
e.type == GradeType.midYear && e.type == GradeType.midYear &&
(days == 0 || (days == 0 ||
e.date.isBefore(DateTime.now().subtract(Duration(days: days))))) e.date
.toList(); .isBefore(DateTime.now().subtract(Duration(days: days)))))
.toList();
@override @override
void initState() { void initState() {
@ -89,13 +90,13 @@ class _PersonalityCardState extends State<PersonalityCard> {
} }
void getGrades() { void getGrades() {
List<Subject> subjects = gradeProvider.grades List<GradeSubject> subjects = gradeProvider.grades
.map((e) => e.subject) .map((e) => e.subject)
.toSet() .toSet()
.toList() .toList()
..sort((a, b) => a.name.compareTo(b.name)); ..sort((a, b) => a.name.compareTo(b.name));
for (Subject subject in subjects) { for (GradeSubject subject in subjects) {
List<Grade> subjectGrades = getSubjectGrades(subject); List<Grade> subjectGrades = getSubjectGrades(subject);
double avg = AverageHelper.averageEvals(subjectGrades); double avg = AverageHelper.averageEvals(subjectGrades);

View File

@ -8,10 +8,16 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class AbsenceSubjectTile extends StatelessWidget { class AbsenceSubjectTile extends StatelessWidget {
const AbsenceSubjectTile(this.subject, {Key? key, this.percentage = 0.0, this.excused = 0, this.unexcused = 0, this.pending = 0, this.onTap}) const AbsenceSubjectTile(this.subject,
{Key? key,
this.percentage = 0.0,
this.excused = 0,
this.unexcused = 0,
this.pending = 0,
this.onTap})
: super(key: key); : super(key: key);
final Subject subject; final GradeSubject subject;
final void Function()? onTap; final void Function()? onTap;
final double percentage; final double percentage;
@ -31,12 +37,20 @@ class AbsenceSubjectTile extends StatelessWidget {
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
visualDensity: VisualDensity.compact, visualDensity: VisualDensity.compact,
onTap: onTap, onTap: onTap,
leading: Icon(SubjectIcon.resolveVariant(subject: subject, context: context), size: 32.0), leading: Icon(
SubjectIcon.resolveVariant(subject: subject, context: context),
size: 32.0),
title: Text( title: Text(
subject.renamedTo ?? subject.name.capital(), subject.renamedTo ?? subject.name.capital(),
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15.0, fontStyle: subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null), style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 15.0,
fontStyle:
subject.isRenamed && settingsProvider.renamedSubjectsItalics
? FontStyle.italic
: null),
), ),
subtitle: AbsenceDisplay(excused, unexcused, pending), subtitle: AbsenceDisplay(excused, unexcused, pending),
trailing: Row( trailing: Row(
@ -47,7 +61,10 @@ class AbsenceSubjectTile extends StatelessWidget {
Stack( Stack(
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
children: [ children: [
const Opacity(child: Text("100%", style: TextStyle(fontFamily: "monospace")), opacity: 0), const Opacity(
child: Text("100%",
style: TextStyle(fontFamily: "monospace")),
opacity: 0),
Text( Text(
percentage.round().toString() + "%", percentage.round().toString() + "%",
style: TextStyle( style: TextStyle(

View File

@ -16,7 +16,7 @@ class GradeSubjectTile extends StatelessWidget {
this.averageBefore = 0.0}) this.averageBefore = 0.0})
: super(key: key); : super(key: key);
final Subject subject; final GradeSubject subject;
final void Function()? onTap; final void Function()? onTap;
final double average; final double average;
final double groupAverage; final double groupAverage;
@ -56,7 +56,10 @@ class GradeSubjectTile extends StatelessWidget {
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 14.0, fontSize: 14.0,
color: textColor, color: textColor,
fontStyle: settingsProvider.renamedSubjectsItalics && subject.isRenamed ? FontStyle.italic : null), fontStyle:
settingsProvider.renamedSubjectsItalics && subject.isRenamed
? FontStyle.italic
: null),
), ),
trailing: Row( trailing: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,

View File

@ -22,10 +22,10 @@ class AbsenceSubjectView extends StatelessWidget {
const AbsenceSubjectView(this.subject, {Key? key, this.absences = const []}) const AbsenceSubjectView(this.subject, {Key? key, this.absences = const []})
: super(key: key); : super(key: key);
final Subject subject; final GradeSubject subject;
final List<Absence> absences; final List<Absence> absences;
static void show(Subject subject, List<Absence> absences, static void show(GradeSubject subject, List<Absence> absences,
{required BuildContext context}) { {required BuildContext context}) {
Navigator.of(context, rootNavigator: true) Navigator.of(context, rootNavigator: true)
.push<Absence>(CupertinoPageRoute( .push<Absence>(CupertinoPageRoute(

View File

@ -33,7 +33,7 @@ import 'absences_page.i18n.dart';
enum AbsenceFilter { absences, delays, misses } enum AbsenceFilter { absences, delays, misses }
class SubjectAbsence { class SubjectAbsence {
Subject subject; GradeSubject subject;
List<Absence> absences; List<Absence> absences;
double percentage; double percentage;
@ -58,7 +58,7 @@ class _AbsencesPageState extends State<AbsencesPage>
late String firstName; late String firstName;
late TabController _tabController; late TabController _tabController;
late List<SubjectAbsence> absences = []; late List<SubjectAbsence> absences = [];
final Map<Subject, Lesson> _lessonCount = {}; final Map<GradeSubject, Lesson> _lessonCount = {};
@override @override
void initState() { void initState() {
@ -90,7 +90,7 @@ class _AbsencesPageState extends State<AbsencesPage>
} }
void buildSubjectAbsences() { void buildSubjectAbsences() {
Map<Subject, SubjectAbsence> _absences = {}; Map<GradeSubject, SubjectAbsence> _absences = {};
for (final absence in absenceProvider.absences) { for (final absence in absenceProvider.absences) {
if (absence.delay != 0) continue; if (absence.delay != 0) continue;

View File

@ -16,7 +16,7 @@ import 'grade_calculator.i18n.dart';
class GradeCalculator extends StatefulWidget { class GradeCalculator extends StatefulWidget {
const GradeCalculator(this.subject, {Key? key}) : super(key: key); const GradeCalculator(this.subject, {Key? key}) : super(key: key);
final Subject subject; final GradeSubject subject;
@override @override
_GradeCalculatorState createState() => _GradeCalculatorState(); _GradeCalculatorState createState() => _GradeCalculatorState();

View File

@ -7,7 +7,7 @@ import 'grades_page.i18n.dart';
class FailWarning extends StatelessWidget { class FailWarning extends StatelessWidget {
const FailWarning({Key? key, required this.subjectAvgs}) : super(key: key); const FailWarning({Key? key, required this.subjectAvgs}) : super(key: key);
final Map<Subject, double> subjectAvgs; final Map<GradeSubject, double> subjectAvgs;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -42,7 +42,7 @@ class GradeSubjectView extends StatefulWidget {
const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0}) const GradeSubjectView(this.subject, {Key? key, this.groupAverage = 0.0})
: super(key: key); : super(key: key);
final Subject subject; final GradeSubject subject;
final double groupAverage; final double groupAverage;
void push(BuildContext context, {bool root = false}) { void push(BuildContext context, {bool root = false}) {
@ -77,7 +77,7 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
String plan = ''; String plan = '';
List<Grade> getSubjectGrades(Subject subject) => !gradeCalcMode List<Grade> getSubjectGrades(GradeSubject subject) => !gradeCalcMode
? gradeProvider.grades.where((e) => e.subject == subject).toList() ? gradeProvider.grades.where((e) => e.subject == subject).toList()
: calculatorProvider.grades.where((e) => e.subject == subject).toList(); : calculatorProvider.grades.where((e) => e.subject == subject).toList();

View File

@ -48,24 +48,25 @@ class _GradesPageState extends State<GradesPage> {
int avgDropValue = 0; int avgDropValue = 0;
List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider List<Grade> getSubjectGrades(GradeSubject subject, {int days = 0}) =>
.grades gradeProvider.grades
.where((e) => .where((e) =>
e.subject == subject && e.subject == subject &&
e.type == GradeType.midYear && e.type == GradeType.midYear &&
(days == 0 || (days == 0 ||
e.date.isBefore(DateTime.now().subtract(Duration(days: days))))) e.date
.toList(); .isBefore(DateTime.now().subtract(Duration(days: days)))))
.toList();
void generateTiles() { void generateTiles() {
List<Subject> subjects = gradeProvider.grades List<GradeSubject> subjects = gradeProvider.grades
.map((e) => e.subject) .map((e) => e.subject)
.toSet() .toSet()
.toList() .toList()
..sort((a, b) => a.name.compareTo(b.name)); ..sort((a, b) => a.name.compareTo(b.name));
List<Widget> tiles = []; List<Widget> tiles = [];
Map<Subject, double> subjectAvgs = {}; Map<GradeSubject, double> subjectAvgs = {};
tiles.addAll(subjects.map((subject) { tiles.addAll(subjects.map((subject) {
List<Grade> subjectGrades = getSubjectGrades(subject); List<Grade> subjectGrades = getSubjectGrades(subject);

View File

@ -30,7 +30,7 @@ class _AllSumBodyState extends State<AllSumBody> {
int avgDropValue = 0; int avgDropValue = 0;
bool animation = false; bool animation = false;
List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider List<Grade> getSubjectGrades(GradeSubject subject, {int days = 0}) => gradeProvider
.grades .grades
.where((e) => .where((e) =>
e.subject == subject && e.subject == subject &&

View File

@ -50,14 +50,15 @@ class _GradesBodyState extends State<GradesBody> {
int avgDropValue = 0; int avgDropValue = 0;
bool animation = false; bool animation = false;
List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider List<Grade> getSubjectGrades(GradeSubject subject, {int days = 0}) =>
.grades gradeProvider.grades
.where((e) => .where((e) =>
e.subject == subject && e.subject == subject &&
e.type == GradeType.midYear && e.type == GradeType.midYear &&
(days == 0 || (days == 0 ||
e.date.isBefore(DateTime.now().subtract(Duration(days: days))))) e.date
.toList(); .isBefore(DateTime.now().subtract(Duration(days: days)))))
.toList();
@override @override
void initState() { void initState() {
@ -74,18 +75,18 @@ class _GradesBodyState extends State<GradesBody> {
} }
void generateTiles({required int filter}) { void generateTiles({required int filter}) {
List<Subject> subjects = gradeProvider.grades List<GradeSubject> subjects = gradeProvider.grades
.map((e) => e.subject) .map((e) => e.subject)
.toSet() .toSet()
.toList() .toList()
..sort((a, b) => a.name.compareTo(b.name)); ..sort((a, b) => a.name.compareTo(b.name));
List<Widget> tiles = []; List<Widget> tiles = [];
Map<Subject, double> subjectAvgs = {}; Map<GradeSubject, double> subjectAvgs = {};
var count = 1; var count = 1;
for (Subject subject in subjects) { for (GradeSubject subject in subjects) {
List<Grade> subjectGrades = getSubjectGrades(subject); List<Grade> subjectGrades = getSubjectGrades(subject);
double avg = AverageHelper.averageEvals(subjectGrades); double avg = AverageHelper.averageEvals(subjectGrades);

View File

@ -28,7 +28,7 @@ List<String> faces = [
]; ];
class SubjectAbsence { class SubjectAbsence {
Subject subject; GradeSubject subject;
List<Absence> absences; List<Absence> absences;
double percentage; double percentage;
@ -52,7 +52,7 @@ class _LessonsBodyState extends State<LessonsBody> {
late List<SubjectAbsence> absences = []; late List<SubjectAbsence> absences = [];
late List<Widget> lessons = []; late List<Widget> lessons = [];
late List<Absence> delays = []; late List<Absence> delays = [];
final Map<Subject, Lesson> _lessonCount = {}; final Map<GradeSubject, Lesson> _lessonCount = {};
@override @override
void initState() { void initState() {
@ -85,7 +85,7 @@ class _LessonsBodyState extends State<LessonsBody> {
} }
void buildSubjectAbsences() { void buildSubjectAbsences() {
Map<Subject, SubjectAbsence> _absences = {}; Map<GradeSubject, SubjectAbsence> _absences = {};
for (final absence in absenceProvider.absences) { for (final absence in absenceProvider.absences) {
if (absence.delay != 0) continue; if (absence.delay != 0) continue;

View File

@ -9,10 +9,10 @@ class GoalProvider extends ChangeNotifier {
final UserProvider _user; final UserProvider _user;
late bool _done = false; late bool _done = false;
late Subject? _doneSubject; late GradeSubject? _doneSubject;
bool get hasDoneGoals => _done; bool get hasDoneGoals => _done;
Subject? get doneSubject => _doneSubject; GradeSubject? get doneSubject => _doneSubject;
GoalProvider({ GoalProvider({
required DatabaseProvider database, required DatabaseProvider database,
@ -24,7 +24,7 @@ class GoalProvider extends ChangeNotifier {
var goalAvgs = await _db.userQuery.subjectGoalAverages(userId: _user.id!); var goalAvgs = await _db.userQuery.subjectGoalAverages(userId: _user.id!);
var beforeAvgs = await _db.userQuery.subjectGoalBefores(userId: _user.id!); var beforeAvgs = await _db.userQuery.subjectGoalBefores(userId: _user.id!);
List<Subject> subjects = gradeProvider.grades List<GradeSubject> subjects = gradeProvider.grades
.map((e) => e.subject) .map((e) => e.subject)
.toSet() .toSet()
.toList() .toList()
@ -45,7 +45,7 @@ class GoalProvider extends ChangeNotifier {
_doneSubject = null; _doneSubject = null;
} }
Future<void> clearGoal(Subject subject) async { Future<void> clearGoal(GradeSubject subject) async {
final goalPlans = await _db.userQuery.subjectGoalPlans(userId: _user.id!); final goalPlans = await _db.userQuery.subjectGoalPlans(userId: _user.id!);
final goalAvgs = await _db.userQuery.subjectGoalAverages(userId: _user.id!); final goalAvgs = await _db.userQuery.subjectGoalAverages(userId: _user.id!);
final goalBeforeGrades = final goalBeforeGrades =

View File

@ -20,7 +20,7 @@ class GoalCompleteModal extends StatelessWidget {
final UserProvider user; final UserProvider user;
final DatabaseProvider database; final DatabaseProvider database;
final Subject subject; final GradeSubject subject;
final double goalAverage; final double goalAverage;
final double beforeAverage; final double beforeAverage;
@ -218,7 +218,7 @@ class GoalCompleteModal extends StatelessWidget {
} }
static Future<T?> show<T>( static Future<T?> show<T>(
Subject subject, { GradeSubject subject, {
required BuildContext context, required BuildContext context,
}) async { }) async {
UserProvider user = Provider.of<UserProvider>(context, listen: false); UserProvider user = Provider.of<UserProvider>(context, listen: false);

View File

@ -64,7 +64,7 @@ class GoalPlanner {
form: '', form: '',
groupId: '', groupId: '',
type: GradeType.midYear, type: GradeType.midYear,
subject: Subject.fromJson({}), subject: GradeSubject.fromJson({}),
mode: Category.fromJson({}), mode: Category.fromJson({}),
seenDate: DateTime(0), seenDate: DateTime(0),
writeDate: DateTime(0), writeDate: DateTime(0),

View File

@ -25,7 +25,7 @@ enum PlanResult {
} }
class GoalPlannerScreen extends StatefulWidget { class GoalPlannerScreen extends StatefulWidget {
final Subject subject; final GradeSubject subject;
const GoalPlannerScreen({Key? key, required this.subject}) : super(key: key); const GoalPlannerScreen({Key? key, required this.subject}) : super(key: key);
@ -42,7 +42,7 @@ class _GoalPlannerScreenState extends State<GoalPlannerScreen> {
bool gradeCalcMode = false; bool gradeCalcMode = false;
List<Grade> getSubjectGrades(Subject subject) => !gradeCalcMode List<Grade> getSubjectGrades(GradeSubject subject) => !gradeCalcMode
? gradeProvider.grades.where((e) => e.subject == subject).toList() ? gradeProvider.grades.where((e) => e.subject == subject).toList()
: calculatorProvider.grades.where((e) => e.subject == subject).toList(); : calculatorProvider.grades.where((e) => e.subject == subject).toList();

View File

@ -22,7 +22,7 @@ import 'goal_planner_screen.dart';
import 'graph.dart'; import 'graph.dart';
class GoalStateScreen extends StatefulWidget { class GoalStateScreen extends StatefulWidget {
final Subject subject; final GradeSubject subject;
const GoalStateScreen({Key? key, required this.subject}) : super(key: key); const GoalStateScreen({Key? key, required this.subject}) : super(key: key);
@ -77,10 +77,10 @@ class _GoalStateScreenState extends State<GoalStateScreen> {
setState(() {}); setState(() {});
} }
List<Grade> getSubjectGrades(Subject subject) => List<Grade> getSubjectGrades(GradeSubject subject) =>
gradeProvider.grades.where((e) => (e.subject == subject)).toList(); gradeProvider.grades.where((e) => (e.subject == subject)).toList();
List<Grade> getAfterGoalGrades(Subject subject) => gradeProvider.grades List<Grade> getAfterGoalGrades(GradeSubject subject) => gradeProvider.grades
.where((e) => (e.subject == subject && e.date.isAfter(goalPinDate))) .where((e) => (e.subject == subject && e.date.isAfter(goalPinDate)))
.toList(); .toList();

View File

@ -91,7 +91,7 @@ class _ModifySubjectNamesState extends State<ModifySubjectNames> {
final _subjectName = TextEditingController(); final _subjectName = TextEditingController();
String? selectedSubjectId; String? selectedSubjectId;
late List<Subject> subjects; late List<GradeSubject> subjects;
late UserProvider user; late UserProvider user;
late DatabaseProvider dbProvider; late DatabaseProvider dbProvider;
late SettingsProvider settings; late SettingsProvider settings;
@ -294,9 +294,11 @@ class _ModifySubjectNamesState extends State<ModifySubjectNames> {
children: [ children: [
Panel( Panel(
child: SwitchListTile( child: SwitchListTile(
title: Text("italics_toggle".i18n), title: Text("italics_toggle".i18n),
onChanged: (value) => settings.update(renamedSubjectsItalics: value), onChanged: (value) =>
value: settings.renamedSubjectsItalics,), settings.update(renamedSubjectsItalics: value),
value: settings.renamedSubjectsItalics,
),
), ),
const SizedBox( const SizedBox(
height: 20, height: 20,
@ -339,7 +341,7 @@ class _ModifySubjectNamesState extends State<ModifySubjectNames> {
child: Column( child: Column(
children: snapshot.data!.keys.map( children: snapshot.data!.keys.map(
(key) { (key) {
Subject? subject = subjects GradeSubject? subject = subjects
.firstWhere((element) => key == element.id); .firstWhere((element) => key == element.id);
String renameTo = snapshot.data![key]!; String renameTo = snapshot.data![key]!;
return RenamedSubjectItem( return RenamedSubjectItem(
@ -385,7 +387,7 @@ class RenamedSubjectItem extends StatelessWidget {
required this.removeCallback, required this.removeCallback,
}) : super(key: key); }) : super(key: key);
final Subject subject; final GradeSubject subject;
final String renamedTo; final String renamedTo;
final void Function() modifyCallback; final void Function() modifyCallback;
final void Function() removeCallback; final void Function() removeCallback;