it-praxisportal/assets/ihk_tools/trace_table_trainer.js

188 lines
7 KiB
JavaScript

/**
* 📝 IHK TRACE-TABELLEN-TRAINER 📝
* =================================
* Interaktiver Wertetabellen-Trainer für AP1 (Lernfeld 5 Programmierung):
* - Schrittweiser Algorithmen-Durchlauf
* - Zeilenweises Befüllen der Variablenzustände
* - Automatische Validierung & Erklärungen
*/
class TraceTableTrainer {
constructor(containerId) {
this.container = document.getElementById(containerId);
this.currentExerciseIndex = 0;
this.exercises = [
{
title: "Aufgabe 1: Schleifenakkumulator mit Bedingung",
code: `GANZZAHL a = 3
GANZZAHL b = 10
GANZZAHL summe = 0
SOLANGE a < b TUE
WENN a MOD 2 == 1 DANN
summe = summe + a
ENDE_WENN
a = a + 2
ENDE_SOLANGE
AUSGABE summe`,
variables: ["Durchlauf", "Bedingung (a < b)", "a", "b", "summe"],
rows: [
{ Durchlauf: "Start", "Bedingung (a < b)": "-", a: "3", b: "10", summe: "0" },
{ Durchlauf: "1", "Bedingung (a < b)": "wahr", a: "5", b: "10", summe: "3" },
{ Durchlauf: "2", "Bedingung (a < b)": "wahr", a: "7", b: "10", summe: "8" },
{ Durchlauf: "3", "Bedingung (a < b)": "wahr", a: "9", b: "10", summe: "15" },
{ Durchlauf: "4", "Bedingung (a < b)": "wahr", a: "11", b: "10", summe: "24" },
{ Durchlauf: "Ende", "Bedingung (a < b)": "falsch", a: "11", b: "10", summe: "24" }
],
finalOutput: "24"
},
{
title: "Aufgabe 2: Lineare Maximum-Suche im Array",
code: `FELD zahlen = [12, 45, 8, 92, 34]
GANZZAHL max = zahlen[0]
GANZZAHL i = 1
SOLANGE i < 5 TUE
WENN zahlen[i] > max DANN
max = zahlen[i]
ENDE_WENN
i = i + 1
ENDE_SOLANGE
AUSGABE max`,
variables: ["Schritt i", "zahlen[i]", "Vergleich (> max)", "max"],
rows: [
{ "Schritt i": "Start", "zahlen[i]": "-", "Vergleich (> max)": "-", max: "12" },
{ "Schritt i": "1", "zahlen[i]": "45", "Vergleich (> max)": "wahr", max: "45" },
{ "Schritt i": "2", "zahlen[i]": "8", "Vergleich (> max)": "falsch", max: "45" },
{ "Schritt i": "3", "zahlen[i]": "92", "Vergleich (> max)": "wahr", max: "92" },
{ "Schritt i": "4", "zahlen[i]": "34", "Vergleich (> max)": "falsch", max: "92" }
],
finalOutput: "92"
}
];
this.init();
}
init() {
if (!this.container) return;
this.render();
}
render() {
const ex = this.exercises[this.currentExerciseIndex];
this.container.innerHTML = `
<div class="ihk-tool-card">
<div class="ihk-tool-header">
<div class="ihk-tool-title">
<span>📝</span> IHK Trace-Tabellen Trainer (LF 5)
</div>
<div>
<span class="ihk-badge">${ex.title}</span>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 20px; margin-bottom: 20px;">
<div>
<label style="font-weight: 600; color: #94a3b8; font-size: 0.85rem;">IHK-Pseudocode:</label>
<pre style="background: #0f172a; padding: 16px; border-radius: 8px; border: 1px solid #334155; font-family: monospace; font-size: 0.9rem; color: #38bdf8; line-height: 1.5; overflow-x: auto;"><code>${ex.code}</code></pre>
</div>
<div>
<label style="font-weight: 600; color: #94a3b8; font-size: 0.85rem;">Trage die Werte für jeden Durchlauf ein:</label>
<div style="overflow-x: auto;">
<table class="ihk-table" id="trace-table-inputs">
<thead>
<tr>
${ex.variables.map(v => `<th>${v}</th>`).join('')}
</tr>
</thead>
<tbody>
${ex.rows.map((row, rIdx) => `
<tr>
${ex.variables.map((v, cIdx) => {
if (cIdx === 0) {
return `<td style="font-weight: bold; color: #94a3b8;">${row[v]}</td>`;
}
return `
<td>
<input type="text" class="ihk-input trace-cell" data-row="${rIdx}" data-var="${v}" style="padding: 6px 10px; font-size: 0.85rem; font-family: monospace;">
</td>
`;
}).join('')}
</tr>
`).join('')}
</tbody>
</table>
</div>
</div>
</div>
<div style="display: flex; gap: 12px; flex-wrap: wrap;">
<button class="ihk-btn ihk-btn-success" id="btn-check-trace">✓ Trace-Tabelle prüfen</button>
<button class="ihk-btn ihk-btn-secondary" id="btn-next-trace">Nächste Übungsaufgabe →</button>
<button class="ihk-btn ihk-btn-secondary" id="btn-solve-trace">Lösung aufdecken</button>
</div>
<div id="trace-result" class="ihk-result-box"></div>
</div>
`;
document.getElementById("btn-check-trace").addEventListener("click", () => this.check());
document.getElementById("btn-next-trace").addEventListener("click", () => {
this.currentExerciseIndex = (this.currentExerciseIndex + 1) % this.exercises.length;
this.render();
});
document.getElementById("btn-solve-trace").addEventListener("click", () => this.solve());
}
check() {
const ex = this.exercises[this.currentExerciseIndex];
let totalCells = 0;
let correctCells = 0;
const inputs = this.container.querySelectorAll(".trace-cell");
inputs.forEach(input => {
const rIdx = parseInt(input.dataset.row, 10);
const varName = input.dataset.var;
const expected = ex.rows[rIdx][varName].toString().toLowerCase().trim();
const userVal = input.value.toString().toLowerCase().trim();
totalCells++;
if (userVal === expected) {
correctCells++;
input.style.borderColor = "#4ade80";
input.style.background = "rgba(34, 197, 94, 0.1)";
} else {
input.style.borderColor = "#f87171";
input.style.background = "rgba(239, 68, 68, 0.1)";
}
});
const resBox = document.getElementById("trace-result");
const allRight = correctCells === totalCells;
resBox.innerHTML = `
<h4 style="color: ${allRight ? '#4ade80' : '#f87171'}; margin-top: 0;">
${allRight ? '🎉 Perfekt ausgefüllt!' : `Ergebnis: ${correctCells} von ${totalCells} Zellen richtig.`}
</h4>
<p style="color: #94a3b8; font-size: 0.9rem;">
Endgültige Bildschirmausgabe nach dem Durchlauf: <strong style="color: #38bdf8">${ex.finalOutput}</strong>
</p>
`;
resBox.classList.add("active");
}
solve() {
const ex = this.exercises[this.currentExerciseIndex];
const inputs = this.container.querySelectorAll(".trace-cell");
inputs.forEach(input => {
const rIdx = parseInt(input.dataset.row, 10);
const varName = input.dataset.var;
input.value = ex.rows[rIdx][varName];
input.style.borderColor = "#38bdf8";
input.style.background = "rgba(56, 189, 248, 0.1)";
});
}
}
window.TraceTableTrainer = TraceTableTrainer;