aboutsummaryrefslogtreecommitdiff
path: root/src/admin-tools.js
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2026-10-15 19:23:09 +0200
committerFlorian Fischer <florian.fischer@muhq.space>2026-10-15 19:23:09 +0200
commit25d723f829cadb8de1763a9158e53c88fe082f87 (patch)
tree43d7fb9cc1884653af8f4c4fcdf67c3cae762cce /src/admin-tools.js
parent8ec39d9f0bb8a0d2fd6c62604888d51e154a8ec0 (diff)
downloadbycs-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.js74
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") {