diff --git a/index.html b/index.html index 5dd4a8e..c59810b 100644 --- a/index.html +++ b/index.html @@ -136,9 +136,9 @@ - + - + diff --git a/js/messages.js b/js/messages.js index 255e38d..a16a24f 100644 --- a/js/messages.js +++ b/js/messages.js @@ -4,11 +4,97 @@ const MESSAGE_POLL_INTERVAL_MS = 30000; const ACTIVE_CHALLENGE_STORAGE_KEY = "loremIpsumActiveChallenge"; const CHALLENGE_DATA_PREFIX = "[[loremIpsumChallenge:"; + const CHALLENGE_TEXT_PARTS = { + subjects: [ + "Der flinke Entwickler", + "Die neugierige Studentin", + "Ein mueder Professor", + "Das kleine Frontend", + "Der mutige Browser", + "Eine schlaue Funktion", + "Der vergessliche Server", + "Die kreative Gruppe", + ], + actions: [ + "sortiert leise", + "debuggt geduldig", + "vergleicht heimlich", + "speichert vorsichtig", + "rendert ploetzlich", + "zaehlt konzentriert", + "testet neugierig", + "kompiliert langsam", + ], + objects: [ + "sieben blaue Buttons", + "drei lange Variablen", + "neun goldene Woerter", + "vier kaputte Formulare", + "acht schnelle Requests", + "zwei leuchtende Karten", + "fuenf stille Fehlermeldungen", + "sechs winzige Icons", + ], + places: [ + "im hellen Dashboard", + "unter dem dunklen Navbar", + "neben dem alten Footer", + "zwischen Login und Leaderboard", + "vor dem ersten Kaffee", + "waehrend der Lernphase", + "hinter dem lokalen Server", + "mitten im Semesterprojekt", + ], + endings: [ + "Danach lacht der Code, weil alles endlich funktioniert.", + "Am Ende merkt sich niemand die Semikolons, aber alle die Punkte.", + "Kurz darauf blinkt die Konsole und behauptet, sie sei unschuldig.", + "Spaeter landet der Score im Ranking und wartet auf Applaus.", + "Dabei bleibt die Seite ruhig, obwohl der Timer dramatisch tickt.", + "Zum Schluss gewinnt, wer die Woerter sauber in Reihenfolge bringt.", + ], + }; let currentMessages = []; let currentUsers = []; let messagePollingInterval = null; + function getRandomChallengeTextPart(items) { + return items[Math.floor(Math.random() * items.length)]; + } + + function generateChallengeText() { + const firstSentence = + [ + getRandomChallengeTextPart(CHALLENGE_TEXT_PARTS.subjects), + getRandomChallengeTextPart(CHALLENGE_TEXT_PARTS.actions), + getRandomChallengeTextPart(CHALLENGE_TEXT_PARTS.objects), + getRandomChallengeTextPart(CHALLENGE_TEXT_PARTS.places), + ].join(" ") + "."; + + const secondSentence = + [ + getRandomChallengeTextPart(CHALLENGE_TEXT_PARTS.subjects), + getRandomChallengeTextPart(CHALLENGE_TEXT_PARTS.actions), + getRandomChallengeTextPart(CHALLENGE_TEXT_PARTS.objects), + getRandomChallengeTextPart(CHALLENGE_TEXT_PARTS.places), + ].join(" ") + "."; + + return firstSentence + + " " + + secondSentence + + " " + + getRandomChallengeTextPart(CHALLENGE_TEXT_PARTS.endings); + } + + function buildEmbeddedChallengeText(challengeData, displayText) { + return CHALLENGE_DATA_PREFIX + + JSON.stringify(challengeData) + + "]]" + + "\n" + + displayText; + } + function getAuth() { if (!window.AppAuth || typeof window.AppAuth.getAuth !== "function") { return null; @@ -53,12 +139,24 @@ function normalizeMessage(message) { // Das Backend und unser Nachrichten-Fallback liefern Challenge-Daten leicht unterschiedlich. // Hier werden beide Formen in ein einheitliches Message-Objekt gebracht. - const embeddedChallenge = extractEmbeddedChallenge(message.text ?? ""); + const textCandidates = [ + message.text, + message.content, + message.message, + message.challenge?.text, + message.result?.text, + ]; + const rawText = textCandidates.find((value) => String(value ?? "").includes(CHALLENGE_DATA_PREFIX)) + ?? textCandidates.find((value) => value !== null && value !== undefined) + ?? ""; + const embeddedChallenge = extractEmbeddedChallenge(rawText); const type = message.type ?? MESSAGE_TYPE_CHALLENGE; - const challenge = message.challenge + const backendChallenge = message.challenge ?? message.result - ?? embeddedChallenge.challenge ?? (type === MESSAGE_TYPE_CHALLENGE || type === MESSAGE_TYPE_CHALLENGE_RESULT ? message : null); + const challenge = embeddedChallenge.challenge + ? { ...(backendChallenge ?? {}), ...embeddedChallenge.challenge } + : backendChallenge; return { id: message.id, @@ -76,14 +174,15 @@ // Fallback fuer Challenge-Daten, die im Nachrichtentext mitgesendet werden. // So koennen wir bestehende Message-Endpunkte nutzen, ohne neue Backend-Felder zu verlangen. const rawText = String(text ?? ""); - if (!rawText.startsWith(CHALLENGE_DATA_PREFIX)) { + const startIndex = rawText.indexOf(CHALLENGE_DATA_PREFIX); + if (startIndex === -1) { return { text: rawText, challenge: null, }; } - const endIndex = rawText.indexOf("]]"); + const endIndex = rawText.indexOf("]]", startIndex); if (endIndex === -1) { return { text: rawText, @@ -91,8 +190,11 @@ }; } - const json = rawText.slice(CHALLENGE_DATA_PREFIX.length, endIndex); - const displayText = rawText.slice(endIndex + 2).trim(); + const json = rawText.slice(startIndex + CHALLENGE_DATA_PREFIX.length, endIndex); + const displayText = ( + rawText.slice(0, startIndex) + + rawText.slice(endIndex + 2) + ).trim(); try { return { @@ -137,6 +239,13 @@ ?? null; } + function getChallengeText(challenge) { + return challenge?.challengeText + ?? challenge?.roundText + ?? challenge?.textToRemember + ?? null; + } + function hasScore(value) { return value !== null && value !== undefined && value !== ""; } @@ -254,6 +363,7 @@ challenger: challenger, opponent: otherUser, opponentScore: role === "challenger" ? getOpponentScore(challenge) : null, + challengeText: getChallengeText(challenge), ownUsername: auth?.username ?? "", }), ); @@ -767,11 +877,17 @@ return; } + const challengeText = generateChallengeText(); + const challengeMessage = buildEmbeddedChallengeText( + { challengeText: challengeText }, + text, + ); + const result = await challengeService.postChallenge( auth.username, auth.password, recipient, - text, + challengeMessage, ); if (!result.ok) { diff --git a/js/play.js b/js/play.js index 21550e9..3f73a25 100644 --- a/js/play.js +++ b/js/play.js @@ -135,7 +135,7 @@ gameStatus.style.color = "#1b1b2f"; } - currentGameText = generateGameText(); + currentGameText = getRoundText(); if (targetTextDisplay) targetTextDisplay.textContent = currentGameText; // Nach Ablauf des Timers wird automatisch zur Eingabe gewechselt. @@ -318,6 +318,27 @@ return hasActiveChallenge() && activeChallenge.role === "opponent"; } + function writeActiveChallenge(challenge) { + sessionStorage.setItem(ACTIVE_CHALLENGE_STORAGE_KEY, JSON.stringify(challenge)); + } + + function getRoundText() { + // Bei Challenges spielen beide User mit demselben Text aus dem Challenge-Kontext. + // Falls alte Challenges diesen Text noch nicht haben, gibt es weiterhin einen lokalen Fallback. + if (!activeChallenge) { + return generateGameText(); + } + + if (typeof activeChallenge.challengeText === "string" && activeChallenge.challengeText.trim()) { + return activeChallenge.challengeText; + } + + const generatedText = generateGameText(); + activeChallenge.challengeText = generatedText; + writeActiveChallenge(activeChallenge); + return generatedText; + } + function showScoreSaveFeedback(message, type) { if (!scoreSaveFeedback) return; @@ -534,6 +555,7 @@ challenger: activeChallenge.challenger, opponent: auth.username, opponentScore: scoreData.score, + challengeText: scoreData.text, }; const messageText = @@ -617,6 +639,7 @@ opponent: activeChallenge.opponent, challengerScore: scoreData.score, opponentScore: opponentScore, + challengeText: scoreData.text, winner: winner, };