Files
geograsim/App/php/api/logistik-sessions.php
Adminator 1e51ef7def Nachtrag: alle bisher untracked Ordner + hängende Änderungen mit-committen
- 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>
2026-07-08 02:27:02 +02:00

141 lines
4.9 KiB
PHP

<?php
/**
* API: Logistik-Sessions (Durchgangs-Tracking)
*
* POST /api/logistik-sessions {action: "start", levelId: 2}
* -> legt einen aktiven Durchgang an, liefert attempt_id zurueck
*
* POST /api/logistik-sessions {action: "end", attemptId, finalBalance, success, stats}
* -> schliesst den Durchgang ab
*
* GET /api/logistik-sessions?action=status
* -> liefert aktiven Durchgang der aktuellen Schueler-Session (oder null)
*
* Persistenz: nutzt game_saves (save_key = "logistik:active-attempt" +
* "logistik:history") — keine eigene Tabelle noetig.
*
* Security: Session-ID aus Cookie wird gegen student_sessions validiert.
*/
$method = $_SERVER['REQUEST_METHOD'];
$db = Database::get();
/** Student-Session validieren (nicht nur Cookie-Praesenz, sondern DB-Existenz). */
function lg_requireValidStudent(): string {
$sid = Session::requireStudent();
$db = Database::get();
$row = $db->fetchOne('SELECT id FROM student_sessions WHERE id = ?', [$sid]);
if (!$row) {
http_response_code(401);
echo json_encode(['error' => 'Session ungueltig']);
exit;
}
return $sid;
}
function lg_uuid(): string {
return sprintf('%s-%s-%s-%s-%s',
bin2hex(random_bytes(4)),
bin2hex(random_bytes(2)),
bin2hex(random_bytes(2)),
bin2hex(random_bytes(2)),
bin2hex(random_bytes(6))
);
}
if ($method === 'GET') {
$action = $_GET['action'] ?? 'status';
if ($action !== 'status') Response::error('Unbekannte Aktion', 400);
$sid = lg_requireValidStudent();
$row = $db->fetchOne(
'SELECT save_data FROM game_saves WHERE session_id = ? AND save_key = ?',
[$sid, 'logistik:active-attempt']
);
if (!$row) Response::ok(['active' => null]);
$payload = json_decode($row['save_data'], true);
Response::ok(['active' => $payload]);
}
if ($method === 'POST') {
$body = json_decode(file_get_contents('php://input'), true);
if (!is_array($body)) Response::error('Body fehlt oder kein JSON', 400);
$action = $body['action'] ?? '';
$sid = lg_requireValidStudent();
if ($action === 'start') {
$levelId = (int)($body['levelId'] ?? 0);
if ($levelId < 1) Response::error('levelId fehlt oder ungueltig', 400);
$attemptId = lg_uuid();
$payload = [
'attemptId' => $attemptId,
'levelId' => $levelId,
'startedAt' => gmdate('c'),
'status' => 'active',
];
$db->execute(
'INSERT INTO game_saves (session_id, save_key, save_data, save_version)
VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE save_data = VALUES(save_data), save_version = VALUES(save_version)',
[$sid, 'logistik:active-attempt', json_encode($payload), 1]
);
Response::ok(['attemptId' => $attemptId, 'levelId' => $levelId]);
}
if ($action === 'end') {
$attemptId = trim($body['attemptId'] ?? '');
if (strlen($attemptId) < 8) Response::error('attemptId fehlt', 400);
$row = $db->fetchOne(
'SELECT save_data FROM game_saves WHERE session_id = ? AND save_key = ?',
[$sid, 'logistik:active-attempt']
);
if (!$row) Response::error('Kein aktiver Durchgang', 404);
$active = json_decode($row['save_data'], true);
if (($active['attemptId'] ?? null) !== $attemptId) {
Response::error('attemptId passt nicht zum aktiven Durchgang', 409);
}
$finalBalance = (int)($body['finalBalance'] ?? 0);
$success = (bool)($body['success'] ?? false);
$stats = is_array($body['stats'] ?? null) ? $body['stats'] : [];
$closed = array_merge($active, [
'status' => $success ? 'success' : 'fail',
'finalBalance' => $finalBalance,
'endedAt' => gmdate('c'),
'stats' => $stats,
]);
// Aktiven Slot leeren, Historie anhaengen (letzte 20 Durchgaenge)
$db->execute(
'DELETE FROM game_saves WHERE session_id = ? AND save_key = ?',
[$sid, 'logistik:active-attempt']
);
$hist = $db->fetchOne(
'SELECT save_data FROM game_saves WHERE session_id = ? AND save_key = ?',
[$sid, 'logistik:history']
);
$list = $hist ? (json_decode($hist['save_data'], true) ?: []) : [];
$list[] = $closed;
if (count($list) > 20) $list = array_slice($list, -20);
$db->execute(
'INSERT INTO game_saves (session_id, save_key, save_data, save_version)
VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE save_data = VALUES(save_data), save_version = VALUES(save_version)',
[$sid, 'logistik:history', json_encode($list), 1]
);
Response::ok(['closed' => $closed]);
}
Response::error('Unbekannte Aktion', 400);
}
Response::error('Methode nicht erlaubt', 405);