Make progress data-driven and build Knowledge Core
mindflux-ci / build (push) Successful in 23s

This commit is contained in:
AliceDarkest
2026-07-13 22:31:57 +02:00
parent b0d8dd48db
commit d718a09561
15 changed files with 205 additions and 56 deletions
+18 -14
View File
@@ -81,22 +81,23 @@
</div>
<div class="mf-panel">
<div class="prog-top"><h4 style="margin:0"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 17l6-6 4 4 8-8"/></svg> Dein Fortschritt</h4><span class="pill">Woche ▾</span></div>
<div class="op" style="color:var(--muted);font-size:.72rem;margin:.2rem 0">Gesamtfortschritt</div>
<div class="prog-big"><b>65<span>%</span></b><span class="xpbadge">+120 XP</span></div>
<div class="chart">
<svg viewBox="0 0 240 74" preserveAspectRatio="none">
<defs><linearGradient id="ar" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="var(--accent)" stop-opacity=".35"/><stop offset="1" stop-color="var(--accent)" stop-opacity="0"/></linearGradient></defs>
<path d="M0 60 L34 50 L70 56 L104 38 L140 44 L176 24 L210 30 L240 14 L240 74 L0 74 Z" fill="url(#ar)"/>
<path d="M0 60 L34 50 L70 56 L104 38 L140 44 L176 24 L210 30 L240 14" fill="none" stroke="var(--accent)" stroke-width="2" style="filter:drop-shadow(0 0 5px var(--glow-s))"/>
<circle cx="176" cy="24" r="3.5" fill="var(--accent)"/>
</svg>
<div class="prog-top"><h4 style="margin:0"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 17l6-6 4 4 8-8"/></svg> Dein Fortschritt</h4><span class="pill">Diese Woche</span></div>
<div class="op" style="color:var(--muted);font-size:.72rem;margin:.2rem 0">Zum nächsten Level</div>
<div class="prog-big"><b th:text="${overall.progressPercent}">0</b><span style="color:var(--muted);font-size:1rem">%</span><span class="xpbadge" th:text="'+' + ${weekly.totalXp} + ' XP'">+0 XP</span></div>
<div class="chart" id="weeklyXpChart" th:attr="data-values=${weekly.xp}">
<svg viewBox="0 0 240 74" preserveAspectRatio="none"></svg>
<div class="days"><span>Mo</span><span>Di</span><span>Mi</span><span>Do</span><span>Fr</span><span>Sa</span><span>So</span></div>
</div>
</div>
<div class="mf-panel" id="cats">
<h4><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2l3 6 6 .5-4.5 4 1.5 6.5L12 16l-6 3 1.5-6.5L3 8.5 9 8z"/></svg> Top Kategorien</h4>
<h4><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2l3 6 6 .5-4.5 4 1.5 6.5L12 16l-6 3 1.5-6.5L3 8.5 9 8z"/></svg> Top Spiele</h4>
<p th:if="${#lists.isEmpty(topGames)}" style="color:var(--muted);font-size:.78rem;line-height:1.45">Noch keine abgeschlossene Runde. Starte ein Spiel, dann erscheinen hier echte Highscores.</p>
<div class="cat" th:each="game : ${topGames}">
<span class="nm" th:text="${game.name}">MindMatch</span>
<span class="cbar"><i th:style="'width:' + ${game.progressPercent} + '%'"/></span>
<span class="pct" th:text="${game.highscore} + ' XP'">0 XP</span>
</div>
</div>
<div class="mf-panel accent challenge">
@@ -148,9 +149,12 @@
<span class="mf-play">SPIEL STARTEN <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14M13 6l6 6-6 6"/></svg></span>
</a>`).join('');
const SVG={globe:'<circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 3 3 15 0 18M12 3c-3 3-3 15 0 18"/>',chart:'<path d="M4 20V10M10 20V4M16 20v-8M22 20H2"/>',lock:'<rect x="5" y="11" width="14" height="9" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/>',grid:'<rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/>',code:'<path d="M8 7l-5 5 5 5M16 7l5 5-5 5"/>'};
const CATS=[['Netzwerk','globe',85],['Datenbanken','chart',78],['IT-Sicherheit','lock',72],['Hardware','grid',66],['Programmierung','code',60]];
document.getElementById('cats').innerHTML += CATS.map(([n,i,p])=>`<div class="cat"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${SVG[i]}</svg><span class="nm">${n}</span><span class="cbar"><i style="width:${p}%"></i></span><span class="pct">${p}%</span></div>`).join('');
const weekChart = document.getElementById('weeklyXpChart');
const values = JSON.parse(weekChart.dataset.values || '[0,0,0,0,0,0,0]');
const max = Math.max(...values, 1);
const points = values.map((value, index) => `${Math.round(index * 40)} ${64 - Math.round(value / max * 54)}`);
const line = `M${points.join(' L')}`;
weekChart.querySelector('svg').innerHTML = `<defs><linearGradient id="ar" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="var(--accent)" stop-opacity=".35"/><stop offset="1" stop-color="var(--accent)" stop-opacity="0"/></linearGradient></defs><path d="${line} L240 74 L0 74 Z" fill="url(#ar)"/><path d="${line}" fill="none" stroke="var(--accent)" stroke-width="2" style="filter:drop-shadow(0 0 5px var(--glow-s))"/>`;
</script>
</body>
</html>
+25 -26
View File
@@ -3,42 +3,41 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mindflux – Knowledge Center</title>
<title>Knowledge Core – Mindflux</title>
<link rel="stylesheet" href="/css/theme.css">
<script src="/js/theme.js"></script>
<style>
.mf-footer { text-align:center; color:var(--muted); font-size:.82rem; padding:1.6rem 1rem; }
.mf-footer a { color:var(--muted); text-decoration:none; margin:0 .15rem; }
.mf-footer a:hover { color:var(--accent); }
.kc-intro{max-width:720px;color:var(--muted);line-height:1.6}.kc-stats,.kc-routes{display:grid;gap:1rem}.kc-stats{grid-template-columns:repeat(3,1fr);margin:1.2rem 0}.kc-stat{padding:1rem;border:1px solid var(--border);border-radius:10px;background:var(--surface-2)}.kc-stat span,.kc-route small{display:block;color:var(--muted);font-size:.74rem}.kc-stat b{display:block;margin-top:.25rem;color:var(--heading);font-size:1.35rem}.kc-routes{grid-template-columns:repeat(3,1fr)}.kc-route{display:flex;flex-direction:column;gap:.7rem;padding:1.2rem;border:1px solid var(--border);border-radius:12px;background:var(--surface)}.kc-route h2{color:var(--heading);font-size:1.05rem;margin:0}.kc-route p{color:var(--muted);font-size:.86rem;line-height:1.5;flex:1;margin:0}.kc-links{display:flex;flex-wrap:wrap;gap:.5rem}.kc-links a{color:var(--accent);font-size:.76rem;text-decoration:none;border:1px solid var(--border-accent);border-radius:7px;padding:.42rem .55rem}.kc-links a:hover{background:var(--accent);color:var(--accent-ink)}.kc-history{margin-top:1rem}.kc-history li{display:flex;justify-content:space-between;gap:1rem;padding:.65rem 0;border-bottom:1px solid var(--border);color:var(--text)}.kc-history li span{color:var(--muted);font-size:.82rem}.mf-footer{text-align:center;color:var(--muted);font-size:.82rem;padding:1.6rem 1rem}.mf-footer a{color:var(--muted);text-decoration:none;margin:0 .15rem}.mf-footer a:hover{color:var(--accent)}@media(max-width:720px){.kc-stats,.kc-routes{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="mf-theme-float"><button class="mf-theme"></button></div>
<div class="mf-container">
<div class="mf-page-head">
<a th:href="@{/dashboard}" class="mf-back">⟵ Zurück zum Dashboard</a>
</div>
<main class="mf-container">
<div class="mf-page-head"><a th:href="@{/dashboard}" class="mf-back">⟵ Zurück zum Dashboard</a></div>
<span class="mf-eyebrow">Knowledge Core</span>
<h1 style="color:var(--heading);font-size:2.1rem;margin:.3rem 0 .45rem;">Deine Lernzentrale</h1>
<p class="kc-intro">Wähle einen Prüfungsweg oder vertiefe ein Spielmodul. Der Status hier basiert auf deinen gespeicherten XP und abgeschlossenen Runden.</p>
<div class="mf-panel accent" style="text-align:center; padding:2.5rem 1.5rem;">
<h1 style="color:var(--heading); font-size:1.7rem; font-weight:800; margin-bottom:.7rem;">Welcome to the Knowledge Center!</h1>
<p style="color:var(--text);">Hier entsteht dein cooles Modul 📚🧠</p>
</div>
<section class="kc-stats" aria-label="Dein Lernstatus">
<div class="kc-stat"><span>Aktuelles Level</span><b th:text="${overall.userLevel}">1</b></div>
<div class="kc-stat"><span>XP diese Woche</span><b th:text="${weekly.totalXp}">0</b></div>
<div class="kc-stat"><span>Gemessene Spielzeit</span><b th:text="${weekly.totalMinutes} + ' Min.'">0 Min.</b></div>
</section>
</div>
<!-- Footer -->
<footer class="mf-footer">
<a href="#">Support</a>
<a href="#">Feedback</a>
<a href="/nutzungsbedingungen">Nutzungsbedingungen</a>
<a href="/richtlinien">Richtlinien</a>
<a href="/datenschutz">Datenschutz</a>
<a href="/impressum">Impressum</a>
</footer>
<section class="kc-routes" aria-label="Lernwege">
<article class="kc-route"><small>PRÜFUNGSGRUNDLAGEN</small><h2>AP1 kompakt</h2><p>Grundlagen, Zahlensysteme, Datenschutz und Projektarbeit strukturiert wiederholen.</p><div class="kc-links"><a href="/finalflux">FinalFlux öffnen</a><a href="/finalflux/ap1/ip-berechnung.html">IP-Berechnung</a></div></article>
<article class="kc-route"><small>SYSTEMINTEGRATION</small><h2>Netzwerke verstehen</h2><p>Topologien und Adressierung erst festigen, dann die Konfiguration in NetWorker trainieren.</p><div class="kc-links"><a href="/networker">NetWorker spielen</a><a href="/finalflux/systemintegration/osi.html">OSI-Modell</a></div></article>
<article class="kc-route"><small>ENTWICKLUNG &amp; SECURITY</small><h2>Fehler sicher lesen</h2><p>Debugging-Fälle lösen, Zugänge absichern und die Muster danach im Lernstoff nachschlagen.</p><div class="kc-links"><a href="/bughunter">BugHunter spielen</a><a href="/codeescape">SystemEscape spielen</a></div></article>
</section>
<section class="mf-panel kc-history">
<h2 class="mf-section-title">Deine stärksten Spiele</h2>
<p th:if="${#lists.isEmpty(topGames)}" style="color:var(--muted);font-size:.86rem;">Noch keine abgeschlossene Runde – dein erster Highscore erscheint hier.</p>
<ul th:unless="${#lists.isEmpty(topGames)}" style="list-style:none;padding:0;margin:0;">
<li th:each="game : ${topGames}"><b th:text="${game.name}">MindMatch</b><span th:text="${game.highscore} + ' XP · ' + ${game.plays} + ' Runden'">0 XP · 0 Runden</span></li>
</ul>
</section>
</main>
<footer class="mf-footer"><a href="#">Support</a><a href="#">Feedback</a><a href="/nutzungsbedingungen">Nutzungsbedingungen</a><a href="/richtlinien">Richtlinien</a><a href="/datenschutz">Datenschutz</a><a href="/impressum">Impressum</a></footer>
</body>
</html>
+1 -1
View File
@@ -1 +1 @@
<!doctype html><html lang="de" data-theme="dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>NetWorker · Mindflux</title><link rel="stylesheet" href="/css/theme.css"><link rel="stylesheet" href="/css/networker.css?v=1"><script src="/js/theme.js"></script></head><body><main class="nw-app"><header class="nw-top"><a href="/dashboard" class="nw-back">← Dashboard</a><div class="nw-brand"><b>NETWORKER</b><span>NETZPLAN · DIAGNOSE</span></div><span class="mf-a11y-host"></span></header><section id="nwView" class="nw-view"><div class="nw-loading">NETZWERKPLÄNE WERDEN KALIBRIERT …</div></section></main><script src="/js/networker.js?v=1"></script></body></html>
<!doctype html><html lang="de" data-theme="dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>NetWorker · Mindflux</title><link rel="stylesheet" href="/css/theme.css"><link rel="stylesheet" href="/css/networker.css?v=1"><script src="/js/theme.js"></script></head><body><main class="nw-app"><header class="nw-top"><a href="/dashboard" class="nw-back">← Dashboard</a><div class="nw-brand"><b>NetWorker</b><span>NETZPLAN · DIAGNOSE</span></div><span class="mf-a11y-host"></span></header><section id="nwView" class="nw-view"><div class="nw-loading">NETZWERKPLÄNE WERDEN KALIBRIERT …</div></section></main><script src="/js/networker.js?v=1"></script></body></html>
+12 -13
View File
@@ -49,28 +49,27 @@
<p class="mf-percentage" th:text="${xpPercentage + '%'}">78%</p>
</div>
<div class="mf-progress-info">
<p><strong>Korrekte Antworten:</strong> <span th:text="${correctAnswers}">432</span></p>
<p><strong>Level:</strong> <span th:text="${userLevel}">5</span></p>
<p><strong>Erfasste Spielaktionen:</strong> <span th:text="${correctAnswers}">432</span></p>
<p><strong>Level (XP):</strong> <span th:text="${userLevel}">5</span></p>
<div class="mf-bar" style="margin:.6rem 0 .4rem;"><i th:style="'width:' + ${xpPercentage} + '%'"></i></div>
<p><span th:text="${currentXp}">2400</span> / <span th:text="${xpForNextLevel}">3000</span> XP</p>
</div>
</div>
</section>
<!-- Lernzeit pro Woche -->
<!-- Tatsächlich gemessene Spielzeit pro Woche -->
<section class="mf-panel" style="margin-bottom:1.2rem;">
<h2 class="mf-section-title">Lernzeit – Diese Woche</h2>
<h2 class="mf-section-title">Spielzeit – Diese Woche</h2>
<p style="color:var(--muted);font-size:.82rem;margin:-.35rem 0 .9rem;">Nur die Dauer abgeschlossener, zeitgemessener Runden.</p>
<canvas id="learnTimeChart" width="600" height="180"></canvas>
</section>
<!-- Fortschritt pro Spiel -->
<!-- Echte Spielstatistiken -->
<section class="mf-panel" th:if="${gameProgress != null}" style="margin-bottom:1.2rem;">
<h2 class="mf-section-title">Spiel-Fortschritte</h2>
<h2 class="mf-section-title">Spiel-Statistiken</h2>
<div class="mf-game-grid">
<div class="mf-game-card" th:each="game : ${gameProgress}">
<h3 th:text="${game.name}">Hangman</h3>
<p>Fortschritt: <span th:text="${game.progressPercent}">65</span>%</p>
<div class="mf-bar" style="margin:.4rem 0;"><i th:style="'width:' + ${game.progressPercent} + '%'"></i></div>
<p>Beste Punktzahl: <span th:text="${game.highscore}">1200</span></p>
<p>Gespielt: <span th:text="${game.plays}">15</span>×</p>
<p>Letzter Zugriff: <span th:text="${game.lastPlayed}">14.04.2025</span></p>
@@ -81,7 +80,7 @@
</div>
<!-- Diagramme -->
<script th:inline="none">
<script th:inline="javascript">
// Theme-Tokens auslesen, damit die Charts in Dark (Grün) & Light (Magenta) passen
const css = getComputedStyle(document.documentElement);
const accent = css.getPropertyValue('--accent').trim() || '#2bd96a';
@@ -95,7 +94,7 @@
type: 'doughnut',
data: {
datasets: [{
data: [78, 22], // Achtung: Dummywerte, kannst du später dynamisch machen
data: [/*[[${xpPercentage}]]*/ 0, 100 - /*[[${xpPercentage}]]*/ 0],
backgroundColor: [accent, track],
borderWidth: 0
}]
@@ -108,15 +107,15 @@
}
});
// Lernzeit-Balkendiagramm
// Spielzeit-Balkendiagramm
const learnCtx = document.getElementById('learnTimeChart').getContext('2d');
new Chart(learnCtx, {
type: 'bar',
data: {
labels: ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'],
datasets: [{
label: 'Lernzeit (Minuten)',
data: [30, 45, 20, 60, 50, 0, 10], // Beispielwerte
label: 'Spielzeit (Minuten)',
data: /*[[${weekly.minutes}]]*/ [0, 0, 0, 0, 0, 0, 0],
backgroundColor: accent,
borderRadius: 6
}]