diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2026-07-12 09:33:58 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2026-07-12 09:33:58 +0200 |
| commit | 1a291fb37fdf0e5a1b2a54825e5af7c5e986f00f (patch) | |
| tree | 3349f89ce4412b63c403411045185c80ba50a6bf /js/graduation-common.js | |
| parent | b39d7dd42c75b096aa88ffc07ae78f1445c8e588 (diff) | |
| download | bycs-sol-1a291fb37fdf0e5a1b2a54825e5af7c5e986f00f.tar.gz bycs-sol-1a291fb37fdf0e5a1b2a54825e5af7c5e986f00f.zip | |
implment observation period handling
Diffstat (limited to 'js/graduation-common.js')
| -rw-r--r-- | js/graduation-common.js | 161 |
1 files changed, 132 insertions, 29 deletions
diff --git a/js/graduation-common.js b/js/graduation-common.js index 3ab1fdd..1c68f38 100644 --- a/js/graduation-common.js +++ b/js/graduation-common.js @@ -22,11 +22,15 @@ class GraduationChange { publicDBFields () { return { "change": this.change, + "date": this.date, }; } dbFields () { return { + // We include the date in the json because Moodle reports the timeadded + // locale dependent. + "date": this.date, "change": this.change, "reason": this.reason, "context": this.context, @@ -34,9 +38,25 @@ class GraduationChange { } static fromDBEntry(e) { - const {date, coach, json} = e; + const {coach, json} = e; const change = JSON.parse(json); - return new GraduationChange(new Date(date), change.change, change.reason, coach, change.context); + return new GraduationChange(new Date(change.date), change.change, change.reason, coach, change.context); + } + + static newObservationRequest() { + return new GraduationChange(new Date(), "ObservationRequest", "", "", ""); + } + + static newObservationStart() { + return new GraduationChange(new Date(), "ObservationStart", "", "", ""); + } + + static newObservationEnd(reason, success) { + return new GraduationChange(new Date(), "ObservationEnd", reason, "", JSON.stringify(success)); + } + + static newObservationChange(observation) { + return new GraduationChange(observation.date, "Observation", "", "", JSON.stringify(observation.status)); } static newGreenPointChange(reason, coach) { @@ -53,14 +73,16 @@ class GraduationChange { } class Graduation { - constructor(student, green, orange, red, level, stickers, observation, changes) { + constructor(student, green, orange, red, level, stickers, observationRequested, observation, pastObservations, changes) { this.student = student; this.green = green; this.orange = orange; this.red = red; this.level = level; this.stickers = stickers; + this.observationRequested = observationRequested; this.observation = observation; + this.pastObservations = pastObservations; this.changes = changes; student.graduation = this; @@ -71,41 +93,66 @@ class Graduation { let orange = 0; let red = 0; let level = 1; + let openObservationRequest = null; let observationPeriod = null; let pastObservations = []; let stickers = []; + + // The parsing logic assumes that changes are ordered chronologically + changes.sort((a, b) => a.date - b.date); + for (const change of changes) { switch (change.change) { case "GrĂ¼n": green++; break; + case "Orange": orange++; break; + case "Rot": red++; break; + + case "ObservationRequest": + openObservationRequest = change.date; + break; + case "ObservationStart": - observationPeriod = new ObservationPeriod(change.date, null, []); + console.assert(openObservationRequest, "No request for observation start"); + observationPeriod = new ObservationPeriod(change.date); + openObservationRequest = null; break; + case "ObservationEnd": - observationPeriod.end = change.date; + console.assert(observationPeriod, "No active observation period"); + observationPeriod.finishPeriod(change.context.success); + if (change.context.success) { + level++; + } pastObservations.push(observationPeriod); observationPeriod = null; break; + case "Observation": - const observation = Observation.fromContext(change.context); - if (observationPeriod) { - observationPeriod.addObservation(observation); - } else { - alert(`No active observation period`); - } + console.assert(observationPeriod, "No active observation period"); + const observation = Observation.fromChange(change); + observationPeriod.addObservation(observation); + break; + + case "LevelChange": + level = change.context.level; break; + default: alert(`Unexpected change: ${change}`); } } - return new Graduation(student, green, orange, red, level, stickers, observationPeriod, changes); + return new Graduation(student, green, orange, red, level, + stickers, + openObservationRequest, observationPeriod, pastObservations, + changes); } addChange(change) { @@ -120,7 +167,36 @@ class Graduation { * Request observation */ async requestObservation() { - await addEntryToStudentDatabase(this.student, "submit", {change: "ObservationRequest"}); + const request = GraduationChange.newObservationRequest(); + this.observationRequested = request.date; + await addEntryToStudentDatabase(this.student, "submit", JSON.stringify(request.publicDBFields())); + } + + /** + * Start an observation + */ + async startObservation() { + if (!this.observationRequested) { + console.assert(this.observationRequested, "No observation requested"); + return; + } + this.observationRequested = null; + this.observation = new ObservationPeriod(new Date()); + return submitGraduationChange(this.student, GraduationChange.newObservationStart()); + } + + /** + * End an observation + */ + async endObservation(reason, success) { + if (!this.observation) { + console.assert(this.observation, "No active observation"); + return; + } + this.observation.end = new Date(); + this.pastObservations.push(this.observation); + this.observation = null; + return submitGraduationChange(this.student, GraduationChange.newObservationEnd(reason, success)); } /** @@ -147,10 +223,14 @@ class Graduation { } class ObservationPeriod { - constructor(start, end, observations) { + constructor(start) { this.start = start; - this.end = end; - this.observations = observations; + this.observations = []; + } + + finishPeriod(success) { + this.end = new Date(); + this.success = success; } ended() { @@ -158,18 +238,28 @@ class ObservationPeriod { } ready() { - // TODO(muhq): add time contraint - return this.observations > 10; + if (this.observations.length < 10) + return false; + + // at least 10 observation on different days + let days = new Map(); + for (const observation of this.observations) { + const d = observation.date; + days.set(`${d.getFullYear()}${d.getMonth()}${d.getDate()}`, true); + } + return days.size >= 10; } getObservationsSums() { - let sums = Array(OBSERVATION_TYPES.length).fill({"yes":0, "no":0}); + let sums = Array(OBSERVATION_TYPES.length).fill().map(() => ({"yes":0, "no":0})); for (const observation of this.observations) { for (let i = 0; i < sums.length; i++) { - if (observation.status[i]) - sums[i].yes++; - else - sums[i].no++; + if (observation.status[i]) { + if (observation.status[i] === "yes") + sums[i].yes++; + else + sums[i].no++; + } } } return sums; @@ -192,10 +282,14 @@ const OBSERVATION_TYPES = [ class Observation { constructor(date, status) { - console.assert(status.length != OBSERVATION_TYPES.length, "invalid observation status"); + console.assert(status.length == OBSERVATION_TYPES.length, "invalid observation status"); this.date = date; this.status = status; } + + static fromChange(change) { + return new Observation(change.date, JSON.parse(change.context)) + } } async function fetchGraduationChangesFromDb(student, type) { @@ -206,15 +300,23 @@ async function fetchGraduationChangesFromDb(student, type) { const gradChange = GraduationChange.fromDBEntry(e); changes.push(gradChange); } - return changes; + return changes.flat(); } async function fetchGraduationChanges(student) { - return fetchGraduationChangesFromDb(student, "shadow"); + let changes = await Promise.all([ + fetchGraduationChangesFromDb(student, "shadow"), + fetchGraduationChangesFromDb(student, "submit"), + ]); + return changes.flat(); } async function fetchPublicGraduationChanges(student) { - return fetchGraduationChangesFromDb(student, "public"); + let changes = await Promise.all([ + fetchGraduationChangesFromDb(student, "public"), + fetchGraduationChangesFromDb(student, "submit"), + ]); + return changes.flat(); } async function fetchGraduation(student) { @@ -248,8 +350,9 @@ async function submitGraduationChange(student, change) { } async function submitObservation(student, observation) { - student.graduation.addObservation(observation); - await addEntryToStudentDatabase(student, "shadow", JSON.stringify(observation)); + console.assert(student.graduation.observation, "no active observation"); + student.graduation.observation.addObservation(observation); + await submitGraduationChange(student, GraduationChange.newObservationChange(observation)); } export { |
