172 lines
8.9 KiB
JavaScript
172 lines
8.9 KiB
JavaScript
/**
|
|
* 🎮 GAMIFICATION ENGINE FÜR DAS PYTHON LERNPORTAL 🎮
|
|
* ====================================================
|
|
* Funktioniert 100% lokal ohne Server (file://) via gamification_data.js & localStorage!
|
|
*/
|
|
|
|
(function () {
|
|
const DEFAULT_LEVELS = [
|
|
{ level: 1, min_xp: 0, max_xp: 150, titel: "Junior IT-Trainee I: Syntax & Basistypen", rang: "Stufe 1" },
|
|
{ level: 2, min_xp: 151, max_xp: 400, titel: "Junior IT-Trainee II: Kontrollfluss & Logik", rang: "Stufe 2" },
|
|
{ level: 3, min_xp: 401, max_xp: 800, titel: "IT-Specialist: Funktionen & Datenstrukturen", rang: "Stufe 3" },
|
|
{ level: 4, min_xp: 801, max_xp: 1300, titel: "Software Developer: OOP-Modellierung", rang: "Stufe 4" },
|
|
{ level: 5, min_xp: 1301, max_xp: 2000, titel: "DevOps Engineer: Versionskontrolle & Tooling", rang: "Stufe 5" },
|
|
{ level: 6, min_xp: 2001, max_xp: 2900, titel: "Quality Engineer: Test-Driven Development (TDD)", rang: "Stufe 6" },
|
|
{ level: 7, min_xp: 2901, max_xp: 4000, titel: "Advanced Engineer: Entwurfsmuster & Polymorphie", rang: "Stufe 7" },
|
|
{ level: 8, min_xp: 4001, max_xp: 5300, titel: "Systems Engineer: Security & Error Handling", rang: "Stufe 8" },
|
|
{ level: 9, min_xp: 5301, max_xp: 6800, titel: "Application Engineer: Schnittstellen & UI", rang: "Stufe 9" },
|
|
{ level: 10, min_xp: 6801, max_xp: 99999, titel: "Certified IT Systems Professional (IHK AP2)", rang: "Master-Stufe" }
|
|
];
|
|
|
|
const DEFAULT_BADGES = {
|
|
rechenkonegin: { icon: "🧮", name: "Zertifikat: Numerische Typen & Arithmetik", desc: "Grundlagen G01 & G02 abgeschlossen (Zahlen, Operatoren & Typen gemeistert)." },
|
|
dialog_profi: { icon: "💬", name: "Zertifikat: Interaktive I/O & String-Interpolation", desc: "Grundlagen G03 abgeschlossen (Interaktive Ein-/Ausgabe mit f-Strings)." },
|
|
weichenstellerin: { icon: "🚦", name: "Zertifikat: Verzweigungslogik & Boolesche Algebra", desc: "Grundlagen G04 abgeschlossen (Bedingungslogik & Kontrollfluss gemeistert)." },
|
|
schleifen_dompteurin: { icon: "🎡", name: "Zertifikat: Iterationslogik & Sequenzverarbeitung", desc: "Grundlagen G05 abgeschlossen (While- & For-Schleifen gemeistert)." },
|
|
funktions_zauberin: { icon: "📐", name: "Zertifikat: Modulare Funktionsarchitektur", desc: "Grundlagen G06 abgeschlossen (Modulare Funktionen & Parameterübergabe)." },
|
|
listen_archivarin: { icon: "📋", name: "Zertifikat: Datenstrukturen: Listen & Slicing", desc: "Grundlagen G07 & G08 abgeschlossen (Sequenzen, Listen & Slicing analysiert)." },
|
|
daten_strategin: { icon: "🗃️", name: "Zertifikat: Assoziative Arrays: Dicts & Sets", desc: "Grundlagen G09 & G10 abgeschlossen (Dicts, Sets & Hash-Lookup O(1))." },
|
|
bug_jaegerin: { icon: "🔍", name: "Zertifikat: Systematisches Code-Debugging", desc: "Warm-up abgeschlossen (Fehleranalyse & Traceback-Debugging)." },
|
|
erste_architektin: { icon: "🏗️", name: "Zertifikat: OOP-Grundlagen: Klassen & Kapselung", desc: "OOP 01 bis 03 gelöst (Klassendefinition, Konstruktoren & Instanzmethoden)." },
|
|
zeit_reisende: { icon: "🌿", name: "Zertifikat: String-Repräsentation & Dunder-Methoden", desc: "OOP 04 gelöst (Spezielle Methoden __str__, __repr__ implementiert)." },
|
|
tamagotchi_mama: { icon: "📦", name: "Zertifikat: State-Machine & Domänenmodellierung", desc: "OOP Mini-Projekt abgeschlossen (Zustandsverwaltung & Objektinteraktion)." },
|
|
qualitaets_garantin: { icon: "🧪", name: "Zertifikat: Automatisierte Testsuites & TDD", desc: "OOP 09 abgeschlossen (Eigene professionelle Unit Tests mit Assertions)." },
|
|
oop_grossmeisterin: { icon: "🧬", name: "Zertifikat: Fortgeschrittene OOP & Robustes Error-Handling", desc: "OOP 10 bis 12 abgeschlossen (Vererbung, Polymorphie & Exceptions)." },
|
|
software_architektin: { icon: "🏆", name: "Zertifikat: Master-Projekt Software Engineering", desc: "Master-Projekt abgeschlossen & vollwertige Anwendungsarchitektur gebaut!" }
|
|
};
|
|
|
|
function getGamificationData() {
|
|
if (window.GAMIFICATION_DATA) {
|
|
return window.GAMIFICATION_DATA;
|
|
}
|
|
const saved = localStorage.getItem("python_gamification_state");
|
|
if (saved) {
|
|
try { return JSON.parse(saved); } catch (e) { }
|
|
}
|
|
return {
|
|
spieler_name: "Python-Entwickler",
|
|
xp: 0,
|
|
level: 1,
|
|
titel: "Junior IT-Trainee I: Syntax & Basistypen",
|
|
rang: "Stufe 1",
|
|
geloeste_kapitel: [],
|
|
bestandene_tests: 0,
|
|
freigeschaltete_badges: [],
|
|
streak_tage: 1
|
|
};
|
|
}
|
|
|
|
function saveGamificationData(data) {
|
|
window.GAMIFICATION_DATA = data;
|
|
localStorage.setItem("python_gamification_state", JSON.stringify(data));
|
|
}
|
|
|
|
// Globaler XP-Zuwachs & Levelberechnung
|
|
window.addXP = function (amount, chapterId = "") {
|
|
const data = getGamificationData();
|
|
data.xp = (data.xp || 0) + amount;
|
|
|
|
if (chapterId && !data.geloeste_kapitel.includes(chapterId)) {
|
|
data.geloeste_kapitel.push(chapterId);
|
|
}
|
|
|
|
// Level prüfen
|
|
for (let i = DEFAULT_LEVELS.length - 1; i >= 0; i--) {
|
|
if (data.xp >= DEFAULT_LEVELS[i].min_xp) {
|
|
data.level = DEFAULT_LEVELS[i].level;
|
|
data.titel = DEFAULT_LEVELS[i].titel;
|
|
data.rang = DEFAULT_LEVELS[i].rang;
|
|
break;
|
|
}
|
|
}
|
|
|
|
saveGamificationData(data);
|
|
window.renderGamificationHUD();
|
|
return data;
|
|
};
|
|
|
|
window.renderGamificationHUD = function () {
|
|
const data = getGamificationData();
|
|
const levels = (window.GAMIFICATION_DATA && window.GAMIFICATION_DATA.levels) ? window.GAMIFICATION_DATA.levels : DEFAULT_LEVELS;
|
|
const badges = (window.GAMIFICATION_DATA && window.GAMIFICATION_DATA.badges) ? window.GAMIFICATION_DATA.badges : DEFAULT_BADGES;
|
|
|
|
const currentLevelObj = levels.find((l) => l.level === data.level) || levels[0];
|
|
const nextLevelObj = levels.find((l) => l.level === data.level + 1);
|
|
|
|
let progressPercent = 100;
|
|
let xpNeeded = "Max Level";
|
|
if (nextLevelObj) {
|
|
const xpInCurrentLevel = data.xp - currentLevelObj.min_xp;
|
|
const levelSpan = nextLevelObj.min_xp - currentLevelObj.min_xp;
|
|
progressPercent = Math.min(100, Math.max(0, Math.round((xpInCurrentLevel / levelSpan) * 100)));
|
|
xpNeeded = `${data.xp} / ${nextLevelObj.min_xp} XP`;
|
|
}
|
|
|
|
// Update Topbar / Sidebar Indicators
|
|
const sbLevel = document.getElementById("sidebar-level-text");
|
|
const sbXP = document.getElementById("sidebar-xp-text");
|
|
if (sbLevel) sbLevel.innerText = `⭐ Level ${data.level}`;
|
|
if (sbXP) sbXP.innerText = `${data.xp} XP`;
|
|
|
|
// Update HUD Widget if present
|
|
const hud = document.getElementById("gamification-hud");
|
|
if (!hud) return;
|
|
|
|
const avatarIcons = ["💻", "🔍", "⚙️", "🏗️", "🌿", "🧪", "🧬", "🛡️", "🖥️", "🏆"];
|
|
const avatarIcon = avatarIcons[data.level - 1] || "💻";
|
|
const solvedCount = (data.geloeste_kapitel || []).length;
|
|
const totalChapters = 27;
|
|
|
|
const nameEl = document.getElementById("hud-user-name");
|
|
const titleEl = document.getElementById("hud-user-title");
|
|
const rankEl = document.getElementById("hud-user-rank");
|
|
const levelEl = document.getElementById("hud-stat-level");
|
|
const xpEl = document.getElementById("hud-stat-xp");
|
|
const solvedEl = document.getElementById("hud-stat-solved");
|
|
const streakEl = document.getElementById("hud-stat-streak");
|
|
const barEl = document.getElementById("hud-progress-bar");
|
|
const progressTextEl = document.getElementById("hud-progress-text");
|
|
const avatarEl = document.getElementById("hud-avatar-icon");
|
|
|
|
if (nameEl) nameEl.innerText = data.spieler_name || "Entwickler-Pass";
|
|
if (titleEl) titleEl.innerText = currentLevelObj.titel;
|
|
if (rankEl) rankEl.innerText = `Rang: ${currentLevelObj.rang}`;
|
|
if (levelEl) levelEl.innerText = data.level;
|
|
if (xpEl) xpEl.innerText = `${data.xp} XP`;
|
|
if (solvedEl) solvedEl.innerText = `${solvedCount} / ${totalChapters}`;
|
|
if (streakEl) streakEl.innerText = `🔥 ${data.streak_tage || 1} Tag${(data.streak_tage || 1) > 1 ? "e" : ""}`;
|
|
if (barEl) barEl.style.width = `${progressPercent}%`;
|
|
if (progressTextEl) progressTextEl.innerText = xpNeeded;
|
|
if (avatarEl) avatarEl.innerText = avatarIcon;
|
|
};
|
|
|
|
function initTaskCheckboxes() {
|
|
const checkboxes = document.querySelectorAll(".task-checkbox");
|
|
if (!checkboxes.length) return;
|
|
|
|
const pageKey = "task_progress_" + window.location.pathname;
|
|
const savedStates = JSON.parse(localStorage.getItem(pageKey) || "{}");
|
|
|
|
checkboxes.forEach((cb) => {
|
|
const id = cb.id;
|
|
if (id && savedStates[id]) {
|
|
cb.checked = true;
|
|
}
|
|
cb.addEventListener("change", function () {
|
|
const states = JSON.parse(localStorage.getItem(pageKey) || "{}");
|
|
states[id] = cb.checked;
|
|
localStorage.setItem(pageKey, JSON.stringify(states));
|
|
});
|
|
});
|
|
}
|
|
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
window.renderGamificationHUD();
|
|
initTaskCheckboxes();
|
|
});
|
|
} else {
|
|
window.renderGamificationHUD();
|
|
initTaskCheckboxes();
|
|
}
|
|
})();
|