aboutsummaryrefslogtreecommitdiff
path: root/src/graduation-common.ts
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2026-08-10 14:20:42 +0200
committerFlorian Fischer <florian.fischer@muhq.space>2026-08-10 14:20:42 +0200
commit2c78bd116108cbf6843d75fa2570fb457918df20 (patch)
tree72a9072335d2db41bc38a4ec6a08aa918db85283 /src/graduation-common.ts
parent44bbb1f70d9663fc5015561118fa922dac3aed76 (diff)
downloadbycs-sol-2c78bd116108cbf6843d75fa2570fb457918df20.tar.gz
bycs-sol-2c78bd116108cbf6843d75fa2570fb457918df20.zip
graduation: support change deletion, coach assignment
Also reset points after a level change.
Diffstat (limited to 'src/graduation-common.ts')
-rw-r--r--src/graduation-common.ts180
1 files changed, 117 insertions, 63 deletions
diff --git a/src/graduation-common.ts b/src/graduation-common.ts
index b43b4af..ca4efde 100644
--- a/src/graduation-common.ts
+++ b/src/graduation-common.ts
@@ -15,7 +15,14 @@ const LEVEL_IMAGES = [
new URL(PioneerPng),
];
+interface CoachMapping {
+ [studentId: number]: string;
+}
+
class GraduationChange {
+ static COACH_ASSIGNMENT_ID = -2;
+
+ changeId: number;
date: Date;
studentId: number;
change: string;
@@ -24,6 +31,7 @@ class GraduationChange {
context: any;
constructor(
+ changeId: number,
date: Date,
studentId: number,
change: string,
@@ -31,6 +39,7 @@ class GraduationChange {
coach: string,
context?: any,
) {
+ this.changeId = changeId;
this.date = date;
this.studentId = studentId;
this.change = change;
@@ -49,9 +58,10 @@ class GraduationChange {
}
static fromDBEntry(e: DatabaseEntry) {
- const { date, coach, json } = e;
+ const { changeId, date, coach, json } = e;
const change = JSON.parse(json);
return new GraduationChange(
+ Number(changeId),
new Date(date),
Number(change.studentId),
change.change,
@@ -63,100 +73,131 @@ class GraduationChange {
static newLevelChange(level: number, reason?: string, coach?: string) {
const ctx = { level: level };
- return new GraduationChange(new Date(), -1, "LevelChange", reason || "", coach || "", ctx);
+ return new GraduationChange(
+ -1,
+ new Date(),
+ -1,
+ "LevelÄnderung",
+ reason || "",
+ coach || "",
+ ctx,
+ );
}
static newGreenPointChange(mandatory: boolean, reason?: string, coach?: string) {
const ctx = { mandatory: mandatory };
- return new GraduationChange(new Date(), -1, "Grün", reason || "", coach || "", ctx);
+ return new GraduationChange(-1, new Date(), -1, "Grün", reason || "", coach || "", ctx);
}
static newOrangePointChange(mandatory: boolean, reason?: string, coach?: string) {
const ctx = { mandatory: mandatory };
- return new GraduationChange(new Date(), -1, "Orange", reason || "", coach || "", ctx);
+ return new GraduationChange(-1, new Date(), -1, "Orange", reason || "", coach || "", ctx);
}
static newRedPointChange(mandatory: boolean, reason?: string, coach?: string) {
const ctx = { mandatory: mandatory };
- return new GraduationChange(new Date(), -1, "Rot", reason || "", coach || "", ctx);
+ return new GraduationChange(-1, new Date(), -1, "Rot", reason || "", coach || "", ctx);
+ }
+
+ static newCoachAssignmentChange(assignments: CoachMapping, coach?: string) {
+ const ctx = { zuweisungen: assignments };
+ return new GraduationChange(
+ GraduationChange.COACH_ASSIGNMENT_ID,
+ new Date(),
+ -1,
+ "CoachZuweisung",
+ "",
+ coach || "",
+ ctx,
+ );
}
}
class Graduation {
student: Student;
- green: number;
- orange: number;
- red: number;
- mandatory: number;
- level: number;
- changes: Array<GraduationChange>;
-
- constructor(
- student: Student,
- green: number,
- orange: number,
- red: number,
- mandatory: number,
- level: number,
- changes: Array<GraduationChange>,
- ) {
+ coach: string = "";
+ green: number = 0;
+ orange: number = 0;
+ red: number = 0;
+ mandatory: number = 0;
+ level: number = 1;
+ changes: Array<GraduationChange> = [];
+
+ constructor(student: Student) {
this.student = student;
- this.green = green;
- this.orange = orange;
- this.red = red;
- this.level = level;
- this.mandatory = mandatory;
- this.changes = changes;
student.graduation = this;
}
static from(student: Student, changes: Array<GraduationChange>) {
- let green = 0;
- let orange = 0;
- let red = 0;
- let mandatory = 0;
- let level = 1;
+ const grad = new Graduation(student);
// The parsing logic assumes that changes are ordered chronologically
changes.sort((a, b) => a.date.valueOf() - b.date.valueOf());
for (const change of changes) {
- switch (change.change) {
- case "Grün":
- green++;
- break;
-
- case "Orange":
- orange++;
- break;
-
- case "Rot":
- red++;
- break;
-
- case "LevelChange":
- level = Number(change.context.level);
- break;
-
- default:
- throw new Error(`Unexpected change: ${change}`);
- }
-
- if (change.context.mandatory) {
- mandatory++;
- }
+ grad.addChange(change);
}
- return new Graduation(student, green, orange, red, mandatory, level, changes);
+ return grad;
}
addChange(change: GraduationChange) {
change.studentId = this.student.id;
- // TODO(muhq): Implement incremental addition
- let changes = this.changes;
- changes.push(change);
- // This updates the student.graduation reference as well
- Graduation.from(this.student, changes);
+
+ switch (change.change) {
+ case "Grün":
+ this.green++;
+ break;
+
+ case "Orange":
+ this.orange++;
+ break;
+
+ case "Rot":
+ this.red++;
+ break;
+
+ case "LevelÄnderung":
+ this.level = Number(change.context.level);
+ // Reset the effective marks
+ this.green = 0;
+ this.orange = 0;
+ this.red = 0;
+ break;
+
+ case "CoachZuweisung":
+ // Reset the effective marks
+ if (this.student.id in change.context.zuweisungen)
+ this.coach = change.context.zuweisungen[this.student.id];
+ break;
+
+ default:
+ throw new Error(`Unexpected change: ${change}`);
+ }
+
+ if (change.context.mandatory) {
+ this.mandatory++;
+ }
+
+ this.changes.push(change);
+ }
+
+ removeChange(change: GraduationChange) {
+ let changes: Array<GraduationChange> = this.changes;
+ // Reset the graduation
+ this.coach = "";
+ this.green = 0;
+ this.orange = 0;
+ this.red = 0;
+ this.mandatory = 0;
+ this.level = 1;
+ this.changes = [];
+
+ for (const toAdd of changes.filter(function (el) {
+ return el.changeId !== -1 ? el.changeId != change.changeId : el.date != change.date;
+ })) {
+ this.addChange(toAdd);
+ }
}
/**
@@ -187,4 +228,17 @@ async function submitGraduationChange(graduation: Graduation, change: Graduation
return db.saveEntry(JSON.stringify(change.dbFields()));
}
-export { LEVEL_NAMES, LEVEL_IMAGES, GraduationChange, Graduation, submitGraduationChange };
+async function deleteGraduationChange(graduation: Graduation, change: GraduationChange) {
+ graduation.removeChange(change);
+ const db = await getGraduationDb();
+ return db.deleteEntries([change.changeId]);
+}
+
+export {
+ LEVEL_NAMES,
+ LEVEL_IMAGES,
+ GraduationChange,
+ Graduation,
+ submitGraduationChange,
+ deleteGraduationChange,
+};