aboutsummaryrefslogtreecommitdiff
path: root/src/graduation-common.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/graduation-common.js')
-rw-r--r--src/graduation-common.js396
1 files changed, 0 insertions, 396 deletions
diff --git a/src/graduation-common.js b/src/graduation-common.js
deleted file mode 100644
index 0c28465..0000000
--- a/src/graduation-common.js
+++ /dev/null
@@ -1,396 +0,0 @@
-import { getSubmitDb, loadFromStudentDatabase, addEntryToStudentDatabase } from "./database.js"
-
-import NeulingPng from "../assets/Neuling.png";
-import EntdeckerPng from "../assets/Entdecker.png";
-import NavigatorPng from "../assets/Navigator.png";
-import PioneerPng from "../assets/Pioneer.png";
-
-const LEVEL_NAMES = ["Neuling", "Entdecker", "Navigator", "Pionieer"];
-
-const LEVEL_IMAGES = [
- new URL(NeulingPng),
- new URL(EntdeckerPng),
- new URL(NavigatorPng),
- new URL(PioneerPng),
-];
-
-class GraduationChange {
- constructor(date, change, reason, coach, context) {
- this.date = date;
- this.change = change;
- this.reason = reason;
- this.coach = coach;
- this.context = context;
- }
-
- isPublic() {
- return [
- "Grün", "Orange", "Rot",
- "ObservationStart", "ObservationEnd",
- "LevelChange"
- ].includes(this.change);
- }
-
- 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,
- };
- }
-
- static fromDBEntry(e) {
- const {coach, json} = e;
- const change = JSON.parse(json);
- 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) {
- return new GraduationChange(new Date(), "Grün", reason, coach, "");
- }
-
- static newOrangePointChange(reason, coach) {
- return new GraduationChange(new Date(), "Orange", reason, coach, "");
- }
-
- static newRedPointChange(reason, coach) {
- return new GraduationChange(new Date(), "Rot", reason, coach, "");
- }
-}
-
-class Graduation {
- 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;
- }
-
- static from(student, changes) {
- let green = 0;
- 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":
- console.assert(openObservationRequest, "No request for observation start");
- observationPeriod = new ObservationPeriod(change.date);
- openObservationRequest = null;
- break;
-
- case "ObservationEnd":
- 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":
- 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,
- openObservationRequest, observationPeriod, pastObservations,
- changes);
- }
-
- addChange(change) {
- // 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);
- }
-
- /**
- * Request observation
- */
- async requestObservation() {
- 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));
- }
-
- /**
- * Return if the student is in observation.
- */
- isObserved() {
- return Boolean(this.observation);
- }
-
- /**
- * Return the URI of the icon representing the graduation level.
- */
- getIcon() {
- return LEVEL_IMAGES[this.level - 1];
- }
-
- /**
- * Return the name of the current graduation level.
- * @return {String} The name of the current level.
- */
- getLevelName() {
- return LEVEL_NAMES[this.level - 1];
- }
-}
-
-class ObservationPeriod {
- constructor(start) {
- this.start = start;
- this.observations = [];
- }
-
- finishPeriod(success) {
- this.end = new Date();
- this.success = success;
- }
-
- ended() {
- return Boolean(this.end);
- }
-
- ready() {
- 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().map(() => ({"yes":0, "no":0}));
- for (const observation of this.observations) {
- for (let i = 0; i < sums.length; i++) {
- if (observation.status[i]) {
- if (observation.status[i] === "yes")
- sums[i].yes++;
- else
- sums[i].no++;
- }
- }
- }
- return sums;
- }
-
- addObservation(observation) {
- this.observations.push(observation);
- }
-}
-
-const OBSERVATION_TYPES = [
- "Arbeitet konzentriert an Aufgaben",
- "Arbeitet zunehmend selbstständig",
- "Führt das Logbuch zuverlässig",
- "Bringt Material mit",
- "Hält Regeln ein",
- "Geht verantwortungsvoll mit Materialien und LernRaum um",
- "Nimmt Rückmeldungen an und setzt sie um",
-];
-
-class Observation {
- constructor(date, 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))
- }
-}
-
-function changesFromDbEntries(entries) {
- let changes = [];
- for (const e of entries) {
- const gradChange = GraduationChange.fromDBEntry(e);
- changes.push(gradChange);
- }
- return changes;
-}
-
-async function fetchGraduationChangesFromDb(student, type) {
- const data = await loadFromStudentDatabase(student, type);
- return changesFromDbEntries(data);
-}
-
-const submitEntriesPromise = async function() {
- const db = await getSubmitDb();
- const entries = await db.fetchEntries();
- return changesFromDbEntries(entries);
-}();
-
-async function addSubmittedChanges(student, changes) {
- let submitEntries = await submitEntriesPromise;
- for (const e of submitEntries.filter( (c) => c.coach === student.name )) {
- changes.push(e);
- }
- return changes;
-}
-
-async function fetchGraduationChanges(student) {
- let changes = await fetchGraduationChangesFromDb(student, "shadow");
- return addSubmittedChanges(student, changes);
-}
-
-async function fetchPublicGraduationChanges(student) {
- let changes = await fetchGraduationChangesFromDb(student, "public");
- return addSubmittedChanges(student, changes);
-}
-
-async function fetchGraduation(student) {
- const changes = await fetchGraduationChanges(student);
- return Graduation.from(student, changes);
-}
-
-async function fetchPublicGraduation(student) {
- const changes = await fetchPublicGraduationChanges(student);
- return Graduation.from(student, changes);
-}
-
-async function submitGraduationChange(student, change) {
- student.graduation.addChange(change);
-
- // Submit changes concurrently
- let promises = [];
-
- if (change.isPublic()) {
- promises.push(
- // TODO(muhq): strip non public fields from changes
- addEntryToStudentDatabase(student, "public", JSON.stringify(change.publicDBFields()))
- );
- }
-
- promises.push(
- addEntryToStudentDatabase(student, "shadow", JSON.stringify(change.dbFields()))
- );
-
- await Promise.all(promises);
-}
-
-async function submitObservation(student, observation) {
- console.assert(student.graduation.observation, "no active observation");
- student.graduation.observation.addObservation(observation);
- await submitGraduationChange(student, GraduationChange.newObservationChange(observation));
-}
-
-export {
- LEVEL_NAMES,
- LEVEL_IMAGES,
- GraduationChange,
- Graduation,
- fetchGraduation,
- fetchPublicGraduation,
- fetchGraduationChanges,
- fetchPublicGraduationChanges,
- submitGraduationChange,
- submitObservation,
-
- OBSERVATION_TYPES,
- Observation,
- ObservationPeriod,
-};