make case files

This commit is contained in:
Lukas Cremer
2026-01-25 22:09:52 +01:00
parent 2fdc1b0d3e
commit 7da14769b4
4 changed files with 180 additions and 17 deletions

27
cases/bode-museum.json Normal file
View File

@@ -0,0 +1,27 @@
{
"chapter": "🔍 Bode-Museum: Der Big Maple Leaf Raub",
"description": "Am 27. März 2017 wurde aus dem Bode-Museum in Berlin eine der größten Goldmünzen der Welt gestohlen: die 'Big Maple Leaf' mit einem Gewicht von 100 kg. Die Täter drangen nachts in das Museum ein und entwendeten die wertvolle Münze. Die Polizei startete eine großangelegte Fahndung nach den Tätern und der gestohlenen Münze.",
"tasks": [
{
"id": "bode-museum-1",
"question": "🕵️ AKTE: Bode-Museum Berlin, 27.03.2017\n\nGESTOHLEN: 1 Goldmünze (Big Maple Leaf)\nGEWICHT: 100 kg\nGOLDPREIS (Tatzeit): 37.500 €/kg\n\nBerechne den Versicherungsschaden in Euro.",
"answer": 3750000,
"points": 50,
"type": "word-problem"
},
{
"id": "bode-museum-2",
"question": "Die drei Täter verkauften das Gold an einen Hehler. Der Hehler zahlte ihnen 3.200.000 €. Sie teilten das Geld so auf: Der Anführer bekam doppelt so viel wie die anderen beiden. Die anderen beiden bekamen gleich viel. Wie viel Euro bekam jeder der beiden anderen Täter?",
"answer": 800000,
"points": 55,
"type": "word-problem"
},
{
"id": "bode-museum-3",
"question": "📹 ÜBERWACHUNGSVIDEO - Bode-Museum:\n\n03:27 Uhr - Täter betreten das Museum\n03:52 Uhr - Münze wird gestohlen\n04:18 Uhr - Täter verlassen das Gebäude\n05:47 Uhr - Nachtwächter entdeckt den Diebstahl\n\nFragen:\na) Wie viele Minuten waren die Täter im Museum? (von Eintritt bis Verlassen)\nb) Wie viele Minuten vergingen zwischen Diebstahl und Entdeckung?\n\nAntworte mit der Summe beider Zeiten in Minuten.",
"answer": 166,
"points": 50,
"type": "word-problem"
}
]
}

27
cases/steglitz.json Normal file
View File

@@ -0,0 +1,27 @@
{
"chapter": "🏦 Berlin-Steglitz: Der Bankeinbruch 2013",
"description": "Im Januar 2013 gruben Täter einen unterirdischen Tunnel von einem leerstehenden Ladenlokal zur Sparkasse in Berlin-Steglitz. Über mehrere Tage arbeiteten sie sich durch den Boden, um unbemerkt in die Tresorräume der Bank zu gelangen. Der Einbruch wurde erst entdeckt, nachdem die Täter bereits mit der Beute geflohen waren.",
"tasks": [
{
"id": "steglitz-1",
"question": "💬 Chat-Protokoll der Täter (von Polizei abgefangen):\n\nNach dem Bankeinbruch in Berlin-Steglitz 2013:\n\nTäter1: 'Wie viel haben wir eigentlich aus den Tresoren geholt?'\nTäter2: 'Ich hab alle Geldscheine gezählt: 847.000 €'\nTäter3: 'Ne, das kann nicht stimmen. Ich komme auf 1.234.000 €'\nTäter1: 'Moment, lass mich nochmal nachzählen...'\n\nBei der späteren Polizeivernehmung stellte sich heraus: Täter2 hatte sich beim Zählen um 387.000 € verzählt.\n\nWie viel wurde tatsächlich aus der Bank gestohlen?",
"answer": 1234000,
"points": 45,
"type": "word-problem"
},
{
"id": "steglitz-2",
"question": "Die Täter gruben einen Tunnel von einem leerstehenden Ladenlokal zur Sparkasse in Berlin-Steglitz. Der Tunnel sollte 47 Meter lang werden.\n\nDrei Täter gruben gemeinsam und schafften zusammen 8 Meter pro Tag.\nNach 2 Tagen kam ein vierter Täter dazu. An diesem Tag gruben alle vier zusammen weitere 15 Meter.\n\nWie viele Meter des Tunnels fehlten noch, bis sie die Bank erreichten?",
"answer": 16,
"points": 50,
"type": "word-problem"
},
{
"id": "steglitz-3",
"question": "📊 POLIZEIBERICHT - Zeitleiste des Bankeinbruchs:\n\nBerlin-Steglitz, Januar 2013:\n\nTag 1, 14:30 Uhr: Täter beginnen Tunnelbau vom leerstehenden Laden\nTag 3, 18:45 Uhr: Tunnel ist fertig, sie erreichen die Bank\nTag 4, 02:15 Uhr: Täter brechen in die Tresorräume ein\nTag 4, 04:37 Uhr: Täter fliehen durch den Tunnel mit der Beute\nTag 5, 11:20 Uhr: Bankangestellte entdecken den Einbruch\n\nBerechne: Wie viele Stunden vergingen vom Beginn des Tunnelbaus bis zur Flucht der Täter? (Antwort in Stunden, runde auf ganze Stunden)",
"answer": 84,
"points": 55,
"type": "word-problem"
}
]
}

143
server.js
View File

@@ -5,27 +5,133 @@ const path = require('path');
const app = express();
const PORT = process.env.PORT || 3000;
const TASKS_FILE = path.join(__dirname, 'tasks.json');
const CASES_DIR = path.join(__dirname, 'cases');
// Middleware
app.use(cors());
app.use(express.json());
app.use(express.static('public'));
// Lade Aufgaben
// Lade alle Aufgaben aus dem cases-Ordner
function loadTasks() {
try {
const data = fs.readFileSync(TASKS_FILE, 'utf8');
return JSON.parse(data);
// Erstelle cases-Ordner falls er nicht existiert
if (!fs.existsSync(CASES_DIR)) {
fs.mkdirSync(CASES_DIR, { recursive: true });
console.log('Cases-Ordner erstellt:', CASES_DIR);
return [];
}
const allTasks = [];
const files = fs.readdirSync(CASES_DIR);
files.forEach(file => {
if (file.endsWith('.json')) {
const filePath = path.join(CASES_DIR, file);
const data = fs.readFileSync(filePath, 'utf8');
const caseData = JSON.parse(data);
// Unterstütze sowohl alte Struktur (Array) als auch neue Struktur (Objekt)
if (Array.isArray(caseData)) {
// Alte Struktur: direktes Array von Tasks
allTasks.push(...caseData);
} else if (caseData.tasks && Array.isArray(caseData.tasks)) {
// Neue Struktur: Objekt mit chapter, description, tasks
caseData.tasks.forEach(task => {
// Füge chapter und chapterDescription zu jeder Task hinzu
const taskWithChapter = {
...task,
chapter: caseData.chapter,
chapterDescription: caseData.description
};
allTasks.push(taskWithChapter);
});
}
}
});
return allTasks;
} catch (error) {
console.error('Fehler beim Laden der Aufgaben:', error);
return [];
}
}
// Speichere Aufgaben
function saveTasks(tasks) {
fs.writeFileSync(TASKS_FILE, JSON.stringify(tasks, null, 2));
// Finde die Datei, die eine bestimmte Task-ID enthält
function findTaskFile(taskId) {
try {
if (!fs.existsSync(CASES_DIR)) {
return null;
}
const files = fs.readdirSync(CASES_DIR);
for (const file of files) {
if (file.endsWith('.json')) {
const filePath = path.join(CASES_DIR, file);
const data = fs.readFileSync(filePath, 'utf8');
const caseData = JSON.parse(data);
// Unterstütze sowohl alte Struktur (Array) als auch neue Struktur (Objekt)
let tasks = [];
if (Array.isArray(caseData)) {
tasks = caseData;
} else if (caseData.tasks && Array.isArray(caseData.tasks)) {
tasks = caseData.tasks;
}
if (tasks.some(task => task.id === taskId)) {
return { filePath, caseData };
}
}
}
return null;
} catch (error) {
console.error('Fehler beim Finden der Task-Datei:', error);
return null;
}
}
// Speichere Aufgaben in der entsprechenden Datei
function saveTask(taskId, updatedTask) {
try {
const fileInfo = findTaskFile(taskId);
if (!fileInfo) {
throw new Error(`Datei für Task ${taskId} nicht gefunden`);
}
const { filePath, caseData } = fileInfo;
// Entferne chapter und chapterDescription aus der Task (werden beim Laden wieder hinzugefügt)
const { chapter, chapterDescription, ...taskWithoutChapter } = updatedTask;
// Unterstütze sowohl alte Struktur (Array) als auch neue Struktur (Objekt)
if (Array.isArray(caseData)) {
// Alte Struktur: direktes Array
const taskIndex = caseData.findIndex(t => t.id === taskId);
if (taskIndex === -1) {
throw new Error(`Task ${taskId} nicht in Datei gefunden`);
}
caseData[taskIndex] = updatedTask;
fs.writeFileSync(filePath, JSON.stringify(caseData, null, 2));
} else if (caseData.tasks && Array.isArray(caseData.tasks)) {
// Neue Struktur: Objekt mit chapter, description, tasks
const taskIndex = caseData.tasks.findIndex(t => t.id === taskId);
if (taskIndex === -1) {
throw new Error(`Task ${taskId} nicht in Datei gefunden`);
}
caseData.tasks[taskIndex] = taskWithoutChapter;
fs.writeFileSync(filePath, JSON.stringify(caseData, null, 2));
} else {
throw new Error('Ungültige Dateistruktur');
}
return true;
} catch (error) {
console.error('Fehler beim Speichern der Aufgabe:', error);
return false;
}
}
// API: Hole alle Aufgaben
@@ -44,30 +150,33 @@ app.post('/api/check-answer', (req, res) => {
}
const tasks = loadTasks();
const taskIndex = tasks.findIndex(t => t.id === taskId);
const task = tasks.find(t => t.id === taskId);
if (taskIndex === -1) {
if (!task) {
return res.status(404).json({ error: 'Aufgabe nicht gefunden' });
}
const task = tasks[taskIndex];
const userAnswer = parseInt(answer);
const correctAnswer = parseInt(task.answer);
const isCorrect = userAnswer === correctAnswer;
// Initialisiere attempts Counter falls nicht vorhanden
if (tasks[taskIndex].attempts === undefined) {
tasks[taskIndex].attempts = 0;
if (task.attempts === undefined) {
task.attempts = 0;
}
// Erhöhe Versuchszähler bei jeder Antwortprüfung
tasks[taskIndex].attempts += 1;
task.attempts += 1;
// Speichere Antwort, isCorrect und Timestamp in der Task
tasks[taskIndex].userAnswer = userAnswer;
tasks[taskIndex].isCorrect = isCorrect;
tasks[taskIndex].answerTimestamp = new Date().toISOString();
saveTasks(tasks);
task.userAnswer = userAnswer;
task.isCorrect = isCorrect;
task.answerTimestamp = new Date().toISOString();
// Speichere die aktualisierte Task in der entsprechenden Datei
if (!saveTask(taskId, task)) {
return res.status(500).json({ error: 'Fehler beim Speichern der Antwort' });
}
res.json({
correct: isCorrect,