Massive feature update: Solo session recovery, immediate result saving, image proxy, player reconnection (Live), and UI/UX refinements

This commit is contained in:
2026-04-16 17:53:12 +02:00
parent 247cca0803
commit 4b6e43ba65
8 changed files with 625 additions and 436 deletions
+3 -16
View File
@@ -1,7 +1,3 @@
/**
* Normalize text for freitext comparison.
* "Villingen-Schwenningen" == "villingen schwenningen" == "villingenschwenningen"
*/
function normalizeText(text) {
if (!text) return '';
return text
@@ -14,10 +10,6 @@ function normalizeText(text) {
.trim();
}
/**
* Extract the string value from a Baserow Single Select field.
* Baserow returns { id: 6, value: "MC", color: "..." } for Single Select.
*/
function extractFieldValue(field, fallback) {
if (!field) return fallback || '';
if (typeof field === 'string') return field;
@@ -61,9 +53,6 @@ function shuffleArray(arr) {
return a;
}
/**
* Calculate score for an answer.
*/
function calculateScore(question, selected, timeRemaining, totalTime, scoringMode) {
if (!selected || selected.length === 0) return { points: 0, correct: false };
@@ -104,9 +93,6 @@ function calculateScore(question, selected, timeRemaining, totalTime, scoringMod
return { points, correct: fullyCorrect };
}
/**
* Strip the correct answer and shuffle options before sending to participants.
*/
function sanitizeQuestion(question) {
const typ = getTyp(question);
const sanitized = {
@@ -118,9 +104,10 @@ function sanitizeQuestion(question) {
kategorie: extractFieldValue(question['Kategorie'], ''),
};
// Rewrite image URL to use proxy
const bild = question['Bild'];
if (bild && Array.isArray(bild) && bild.length > 0) {
sanitized.bild = bild[0].url;
if (bild && Array.isArray(bild) && bild.length > 0 && bild[0].url) {
sanitized.bild = `/api/img?url=${encodeURIComponent(bild[0].url)}`;
}
if (typ !== 'freitext') {