diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2026-10-15 19:23:09 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2026-10-15 19:23:09 +0200 |
| commit | 25d723f829cadb8de1763a9158e53c88fe082f87 (patch) | |
| tree | 43d7fb9cc1884653af8f4c4fcdf67c3cae762cce /src/admin-tools.js | |
| parent | 8ec39d9f0bb8a0d2fd6c62604888d51e154a8ec0 (diff) | |
| download | bycs-sol-25d723f829cadb8de1763a9158e53c88fe082f87.tar.gz bycs-sol-25d723f829cadb8de1763a9158e53c88fe082f87.zip | |
admin-tools: add find duplicate and student id tool
Diffstat (limited to 'src/admin-tools.js')
| -rw-r--r-- | src/admin-tools.js | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/src/admin-tools.js b/src/admin-tools.js index 54c8d26..116b5ee 100644 --- a/src/admin-tools.js +++ b/src/admin-tools.js @@ -1,7 +1,8 @@ import { GraduationChange, submitGraduationChange } from "./graduation-ENV.ts"; import { fetchStudent, fetchStudents } from "./student-ENV.ts"; import { fetchCourses } from "./moodle-ENV.ts"; -import { getCourseId } from "./utils-ENV.js"; +import { DB } from "./database-ENV.ts"; +import { DATETIME_FMT } from "./utils-common.ts"; let outputNode; function output(msg) { @@ -58,7 +59,7 @@ async function updateActivities(course) { return Promise.all(promises); } -export async function updateCourses() { +async function updateCourses() { output("loading courses ..."); const courses = await fetchCourses("SOL Graduierung"); output(`updating ${courses.length} courses ... `); @@ -76,6 +77,70 @@ export async function updateCourses() { }); } +async function findDuplicates(course) { + const dbActivity = await course.getActivity("Graduation"); + const db = new DB(dbActivity.id); + const entries = await db.fetchEntries(); + const changes = entries.map((e) => GraduationChange.fromDBEntry(e)); + + const searched = new Set(); + const duplicates = []; + for (const change of changes) { + if (searched.has(change)) continue; + searched.add(change); + + const curDuplicates = [change]; + for (const other of changes) { + if (other === change) continue; + + let same = true; + for (const key in change) { + switch (key) { + case "changeId": + continue; + case "date": + same = same && change.date.getTime() === other.date.getTime(); + break; + case "context": + same = same && JSON.stringify(change.context) === JSON.stringify(other.context); + break; + default: + same = same && change[key] === other[key]; + } + if (!same) break; + } + + if (same) { + curDuplicates.push(other); + searched.add(other); + } + } + + if (curDuplicates.length > 1) { + duplicates.push(curDuplicates); + } + } + + if (duplicates.length === 0) return; + + let msg = `${course.title} Duplikate:<br>`; + for (const d of duplicates) { + const ids = d.map((e) => e.changeId); + const c = d[0]; + msg += `- ${DATETIME_FMT.format(c.date)} ${c.coach} ${c.studentId} ${c.change} ${JSON.stringify(c.context)} ids: ${ids}<br>`; + } + output(msg + "\n"); +} + +async function findAllDuplicates() { + output("loading courses ..."); + const courses = await fetchCourses("SOL Graduierung"); + output(`searching in ${courses.length} courses ... `); + for (const course of courses) { + findDuplicates(course); + } +} + async function init() { outputNode = document.getElementById("admin-tools-output"); output("Admin tools ready."); @@ -83,6 +148,11 @@ async function init() { .getElementById("admin-tools-coach-import-submit") .addEventListener("click", coachAssignmentImport); document.getElementById("activity-update-submit").addEventListener("click", updateCourses); + document.getElementById("print-ids").addEventListener("click", async function () { + const students = await fetchStudents(); + output(JSON.stringify(students.map((s) => s.id))); + }); + document.getElementById("find-duplicates").addEventListener("click", findAllDuplicates); } if (document.readyState === "loading") { |
