1e51ef7def
- Konzept/, didaktik_geografie/, didaktik_simulation/, v2-modules/, v2-platform/ - 12 code-workspace-Files - STATUS-*.md - viele M/D/R-Änderungen an bereits getrackten Files - .gitignore verstärkt: **/.humaninput/, **/secret_keys.txt Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4.9 KiB
4.9 KiB
V2 Plattform-Bibliotheken
Helfer-Libs für V2-Module, sparen Boilerplate. ESM, keine Build-Step, keine Dependencies.
Verfügbar
| Lib | Zweck |
|---|---|
| telemetry-client.js | Telemetry, Profil, runtime-config, State, Result. Spec-Vollständig. |
TelemetryClient — Quickstart
import { TelemetryClient } from '../../../v2-platform/lib/telemetry-client.js';
// 1. Instanz
const tc = new TelemetryClient({
moduleSlug: 'hallo-welt',
moduleVersion: '1.0.0',
specVersion: '1.0',
});
// 2. Init (holt runtime-config + profile, startet Heartbeat + Stuck-Detection)
await tc.init();
// 3. Profil + Session sind jetzt verfügbar
console.log(tc.profile); // { displayName, avatarUrl, easyLanguage, nachteilsausgleich, levelUnlocks, ... }
console.log(tc.session); // { mode, difficulty, lang, classId, studentId, isMock, ... }
// 4. Phase wechseln (Lehrperson-Dashboard sieht das live)
tc.setPhase('welcome', 'Begrüßung');
// 5. Milestone emittieren
tc.milestone('welcome-shown', 'Begrüßung gesehen', /* scoreDelta */ 1);
// 6. Score aktualisieren (fließt in nächste Heartbeats)
tc.updateScore(42, 100);
// 7. Resume-State speichern (regelmäßig oder bei Milestones)
await tc.saveState({ ...modulInternerState }, 'Tag 3, Level 2');
// 8. Modul abschließen (sendet Result-POST + cleanup)
await tc.complete({
completed: true,
lehrplanCoverage: { 'AT-GW-1.4.2': 'full' },
freeTextAnswers: [],
moduleSpecificData: { /* modul-eigene Kennzahlen */ },
});
// 9. Bei manuellem Abbruch (z.B. ✕-Klick)
tc.exit('user-cancelled');
Was die Lib für dich erledigt
- URL-Param-Parsing —
session_token,mode,difficulty,lang,class_id,student_id,mock=1 - Runtime-Config — Heartbeat-Frequenz wird auf Plattform-Grenzen geclampt (Default 10–30s)
- Heartbeat-Loop — alle X Sekunden automatisch, pausiert bei AFK (>60s ohne Eingabe)
- Stuck-Detection — bei >90s ohne Eingabe wird Stuck-Event gefeuert (Schwellwert aus runtime-config)
- Tab-Close-Beacon — navigator.sendBeacon-Final-Heartbeat
- Fehlertoleranz — Telemetry-Fetches die scheitern blockieren das Modul nicht (silent fail)
- Token-Expired-Handling — bei 401 default Redirect zu
/v2beta/, im iframe wird nur Warnung geloggt - Mock-Erkennung — wenn
?mock=1, geht alles automatisch gegen die Mock-Plattform
Was du selbst tun musst
- Activity-Tracking für
click/touchstart/keydownmacht die Lib automatisch (andocumentregistriert) - A11y-Profil auswerten —
tc.profile.preferences.highContrastetc. → Modul setztbody[data-high-contrast="…"] - Easy-Sprache laden —
tc.session.langzeigt was geladen werden soll - Level-Unlock-Sicht —
tc.profile.levelUnlocks[moduleSlug]für freien Modus - Nachteilsausgleich —
tc.profile.nachteilsausgleich === true→ Level-Wähler statt Auftrags-Vorgabe
API-Referenz
Konstruktor
new TelemetryClient({
moduleSlug: string, // PFLICHT
moduleVersion: string, // PFLICHT
specVersion: string, // PFLICHT
heartbeatPreferenceS?: number, // default 15
onProfileLoaded?: (profile) => void,
onError?: (err) => void,
onTokenExpired?: (reason) => void,
})
Methoden
| Methode | Zweck |
|---|---|
init() |
Async. Holt runtime-config + profile, startet Heartbeat + Stuck-Loop. |
setPhase(phase, label?, step?) |
Phase wechseln; löst sofort einen Heartbeat aus. |
updateScore(score, scoreMax?) |
Score aktualisieren. Wird in nächsten Heartbeats mitgesendet. |
milestone(id, label, scoreDelta?) |
Milestone-Event posten (id muss im Manifest deklariert sein). |
accessibilityBlocker({blockerType, hint}) |
A11y-Blocker melden. |
saveState(state, summary?) |
Resume-State speichern (PUT /api/module/state). |
complete(result) |
Result-POST + Cleanup. Ruft destroy() automatisch. |
exit(reason?) |
Abbruch melden + Cleanup. |
destroy() |
Manueller Cleanup (Timer + Listener entfernen). |
elapsedTotalS(), elapsedPhaseS() |
Hilfs-Getter für Sekunden seit Start / Phase-Start. |
Properties (nach await init())
| Property | Inhalt |
|---|---|
tc.profile |
Schüler*innen-Profil (/api/student/me-Response inkl. Nachteilsausgleich + Level-Unlocks) |
tc.config |
Runtime-Config-Werte (heartbeat, stuck, telemetry, auth) |
tc.session |
URL-Param-Werte (sessionToken, studentId, classId, mode, difficulty, lang, resume, isMock) |
Bekannte Limitierungen
- Token-Auto-Refresh ist Stub. Echte Refresh-Logik kommt mit V2-Login. Aktuell: bei Token-Ablauf (401) → Redirect zu
/v2beta/. onTokenExpiredCallback kann das überschreiben, falls Modul eigene Handhabung will (z.B. iframe-Eltern benachrichtigen).- Mock-Erkennung über
?mock=1-URL-Param. Wenn dein Modul-Wrapper-Pfad nichtv2-modules/<slug>/public/ist, musst duapiBaseselbst überschreiben (nicht in der API vorgesehen — am besten Pfad anpassen).