Add play.js

This commit is contained in:
DST81 2026-05-13 10:22:06 +02:00
parent 184f933a57
commit 90ab402ca6
4 changed files with 333 additions and 74 deletions

View File

@ -3,14 +3,41 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title >Lorem Ipsum - Das Spiel</title>
<title>Lorem Ipsum - Das Spiel</title>
<link rel="icon" type="image/png" href="image/icon_l.png">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="assets/bootstrap-5.3.8-dist/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/custom.css">
<!-- Kleine Korrektur direkt hier, falls Sie custom.css nicht sofort ändern wollen -->
<style>
/* Sicherstellen, dass der Main-Area den ganzen Platz einnimmt */
#main-area {
display: flex;
flex-direction: column;
flex: 1; /* Füllt den verbleibenden Platz im page-wrapper */
}
/* Content soll wachsen, Footer wird nach unten gedrückt */
#main-content {
flex: 1;
}
/* Footer immer unten im Flex-Container */
footer {
margin-top: auto;
}
/* Body Padding entfernen für sauberes Dashboard-Layout */
body {
padding: 0 !important;
overflow-x: hidden; /* Verhindert horizontales Scrollen durch Sidebar */
}
</style>
</head>
<body class="p-4">
<!-- class="p-4" entfernt -->
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
@ -18,7 +45,6 @@
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<!--evtl. weglassen, da es eine Sidebar gibt -->
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class ="nav-item"><a class="nav-link" href="#" id="navbar-messages">Nachrichten</a></li>
@ -27,6 +53,7 @@
</div>
</div>
</nav>
<div id="page-wrapper">
<!-- Sidebar -->
<nav id="sidebar" class="bg-dark text-white p-3">
@ -35,83 +62,68 @@
<li class="nav-item"><a class="nav-link" href="#" id="nav-play">Spiel Starten</a></li>
<li class="nav-item"><a class="nav-link" href="#" id="nav-my-scores">Meine Scores</a></li>
<li class="nav-item"> <a class="nav-link" href="#" id="nav-leaderboard">Leaderboard</a></li>
</ul>
</nav>
<!--Main Area -->
<!-- Main Area: Enthält jetzt Topbar, Content UND Footer -->
<div id="main-area">
<!--Topbar-->
<!-- Topbar -->
<header id="topbar">
<h1 class="text-center mb-4">Dashboard</h1>
</header>
<!-- Content -->
<main class="container mt-4" id="main-content"></main>
</div>
</div>
<main class="container mt-4" id="main-content">
<!-- Hier wird play.html geladen -->
</main>
<!-- Footer & Impressum Section -->
<footer class="bg-dark text-black py-4 mt-auto border-top border-secondary">
<div class="container">
<!-- Oberer Bereich: Slogan & Haupttext -->
<div class="row mb-3">
<div class="col-12">
<h5 class="text-warning">Made with <span class="text-danger"></span> und zu viel Kaffee für das Modul Frontend. Bootstrap 5.3.8 powered.</h5>
<p class="text-black small mb-0 fst-italic">
<em>„Unser Impressum ist länger als der Text, den Sie sich merken müssen.“</em>
</p>
</div>
</div>
<!-- Unterer Bereich: Responsives Impressum -->
<div class="row mt-2">
<div class="col-12">
<!-- Titel Impressum (immer oben) -->
<span class="text-warning fw-bold d-block mb-2" style="font-size: 0.7rem;">Impressum</span>
<!-- Container für die Impressum-Punkte -->
<div class="text-black-50" style="font-size: 0.7rem; line-height: 1.4;">
<div class="row g-1"> <!-- g-1 sorgt für minimalen Abstand zwischen den Spalten -->
<!-- Punkt 1: Betreiber -->
<div class="col-12 col-md-6 col-lg-4">
<strong>Betreiber</strong>:&nbsp;Das Team FAD (Florin, Adi, Daniela)
<!-- Footer: Jetzt INSIDE main-area, damit Flexbox funktioniert -->
<footer class="bg-dark text-black py-4 border-top border-secondary">
<div class="container">
<!-- Oberer Bereich -->
<div class="row mb-3">
<div class="col-12">
<h5 class="text-warning">Made with <span class="text-danger"></span> und zu viel Kaffee für das Modul Frontend. Bootstrap 5.3.8 powered.</h5>
<p class="text-black small mb-0 fst-italic">
<em>„Unser Impressum ist länger als der Text, den Sie sich merken müssen.“</em>
</p>
</div>
</div>
<!-- Punkt 2: Adresse -->
<div class="col-12 col-md-6 col-lg-4">
<strong>Adresse</strong>:&nbsp;Irgendwo im Internet, Schweiz
<!-- Impressum -->
<div class="row mt-2">
<div class="col-12">
<span class="text-warning fw-bold d-block mb-2" style="font-size: 0.7rem;">Impressum</span>
<div class="text-black-50" style="font-size: 0.7rem; line-height: 1.4;">
<div class="row g-1">
<div class="col-12 col-md-6 col-lg-4">
<strong>Betreiber</strong>:&nbsp;Das Team FAD (Florin, Adi, Daniela)
</div>
<div class="col-12 col-md-6 col-lg-4">
<strong>Adresse</strong>:&nbsp;Irgendwo im Internet, Schweiz
</div>
<div class="col-12 col-md-6 col-lg-4">
<strong>Kontakt</strong>:&nbsp;schreibuns@lorem-ipsum-spiel.ch
</div>
<div class="col-12 col-md-6 col-lg-4">
<strong>Inhalt</strong>:&nbsp;Der letzte Committer
</div>
<div class="col-12 col-md-6 col-lg-4">
<strong>Datenschutz</strong>:&nbsp;Wir speichern nur Scores.
</div>
</div>
</div>
<div class="text-center mt-2">
<p class="mb-0 text-black-50" style="font-size: 0.65rem;">
&copy; 2026 Modul Frontend Projekt. Alle Rechte vorbehalten.
</p>
</div>
</div>
<!-- Punkt 3: Kontakt -->
<div class="col-12 col-md-6 col-lg-4">
<strong>Kontakt</strong>:&nbsp;schreibuns@lorem-ipsum-spiel.ch
</div>
<!-- Punkt 4: Inhalt -->
<div class="col-12 col-md-6 col-lg-4">
<strong>Inhalt</strong>:&nbsp;Der letzte Committer
</div>
<!-- Punkt 5: Datenschutz -->
<div class="col-12 col-md-6 col-lg-4">
<strong>Datenschutz</strong>:&nbsp;Wir speichern nur Scores.
</div>
</div>
</div>
<!-- Copyright Zeile (rechtsbündig, ganz unten) -->
<div class="text-center mt-2">
<p class="mb-0 text-black-50" style="font-size: 0.65rem;">
&copy; 2026 Modul Frontend Projekt. Alle Rechte vorbehalten.
</p>
</div>
</div>
</footer>
</div>
</div>
</footer>
<!-- Bootstrap JS Bundle -->
<script src="assets/bootstrap-5.3.8-dist/js/bootstrap.bundle.min.js"></script>
@ -122,7 +134,7 @@
<script src="js/login.js"></script>
<script src="js/leaderboard.js"></script>
<!--Navigation Script -->
<script src="js/play.js"></script>
<script src="js/navigation.js"></script>
</body>
</html>

157
js/play.js Normal file
View File

@ -0,0 +1,157 @@
(function() {
// --- Konfiguration ---
const GAME_TEXT = "Der schnelle braune Fuchs springt über den faulen Hund. Programmieren ist wie Zaubern, nur mit mehr Kaffee und weniger Magie. Wer rastet, der rostet, aber wer codet, der lebt.";
const MEMORIZE_TIME_SECONDS = 15;
let timerInterval;
let currentTime = 0;
// --- DOM Elemente holen ---
const phaseStart = document.getElementById('phaseStart');
const phaseMemorize = document.getElementById('phaseMemorize');
const phaseInput = document.getElementById('phaseInput');
const phaseResult = document.getElementById('phaseResult');
const targetTextDisplay = document.getElementById('targetTextDisplay');
const timerDisplay = document.getElementById('timerDisplay');
const userTextInput = document.getElementById('userTextInput');
const resultScore = document.getElementById('resultScore');
const resultOriginal = document.getElementById('resultOriginal');
const resultInput = document.getElementById('resultInput');
const gameStatus = document.getElementById('gameStatus');
// Buttons
const btnStart = document.getElementById('btnStartGame');
const btnSubmit = document.getElementById('btnSubmitScore');
const btnRestart = document.getElementById('btnRestart');
const btnLeaderboard = document.getElementById('btnLeaderboard');
// --- Event Listener registrieren ---
if (btnStart) btnStart.addEventListener('click', startGame);
if (btnSubmit) btnSubmit.addEventListener('click', submitScore);
if (btnRestart) btnRestart.addEventListener('click', () => location.reload());
if (btnLeaderboard) btnLeaderboard.addEventListener('click', () => {
const navLink = document.getElementById('nav-leaderboard');
if (navLink) {
navLink.click(); // Simuliert Klick auf Sidebar-Link
} else {
console.warn("Sidebar Link #nav-leaderboard nicht gefunden.");
}
});
// --- Funktionen ---
function startGame() {
if (!phaseStart || !phaseMemorize) return;
// UI umschalten
phaseStart.classList.add('d-none');
phaseMemorize.classList.remove('d-none');
if(gameStatus) {
gameStatus.textContent = "Lernphase";
gameStatus.className = "badge fs-6 px-3 py-2";
gameStatus.style.backgroundColor = "#ffd166";
gameStatus.style.color = "#1b1b2f";
}
if(targetTextDisplay) targetTextDisplay.textContent = GAME_TEXT;
// Timer starten
currentTime = MEMORIZE_TIME_SECONDS;
if(timerDisplay) timerDisplay.textContent = currentTime;
timerInterval = setInterval(() => {
currentTime--;
if(timerDisplay) timerDisplay.textContent = currentTime;
if (currentTime <= 0) {
endMemorizePhase();
}
}, 1000);
}
function endMemorizePhase() {
clearInterval(timerInterval);
if (!phaseMemorize || !phaseInput) return;
// UI umschalten
phaseMemorize.classList.add('d-none');
phaseInput.classList.remove('d-none');
if(gameStatus) {
gameStatus.textContent = "Eingabe";
gameStatus.className = "badge fs-6 px-3 py-2";
gameStatus.style.backgroundColor = "#4a6fa5";
gameStatus.style.color = "#fff";
}
if(userTextInput) {
userTextInput.value = "";
userTextInput.focus();
}
}
function calculateScore(original, input) {
if (!original || !input) return 0;
// Bereinigung: Kleinbuchstaben, Satzzeichen entfernen, in Arrays aufteilen
const cleanOriginal = original.toLowerCase().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g,"").split(/\s+/).filter(w => w.length > 0);
const cleanInput = input.toLowerCase().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g,"").split(/\s+/).filter(w => w.length > 0);
let correctWords = 0;
const limit = Math.min(cleanOriginal.length, cleanInput.length);
for (let i = 0; i < limit; i++) {
if (cleanInput[i] === cleanOriginal[i]) {
correctWords++;
}
}
return correctWords;
}
function submitScore() {
if (!userTextInput) return;
const userInput = userTextInput.value.trim();
if (!userInput) {
alert("Bitte geben Sie einen Text ein.");
return;
}
const score = calculateScore(GAME_TEXT, userInput);
// Ergebnis anzeigen
if (phaseInput) phaseInput.classList.add('d-none');
if (phaseResult) phaseResult.classList.remove('d-none');
if(gameStatus) {
gameStatus.textContent = "Abgeschlossen";
gameStatus.className = "badge fs-6 px-3 py-2";
gameStatus.style.backgroundColor = "#28a745";
gameStatus.style.color = "#fff";
}
if (resultScore) resultScore.textContent = score;
if (resultOriginal) resultOriginal.textContent = GAME_TEXT;
if (resultInput) resultInput.textContent = userInput;
// --- API Aufruf vorbereiten ---
const scoreData = {
score: score,
time: MEMORIZE_TIME_SECONDS,
text: GAME_TEXT,
userWrittenText: userInput
};
console.log("Score bereit zum Senden:", scoreData);
// HIER Ihren Service Aufruf einfügen, z.B.:
// if (typeof window.ScoreService !== 'undefined') {
// window.ScoreService.post(scoreData);
// }
}
})();

View File

@ -1,8 +1,8 @@
<div class="card">
<h2>Willkommen beim Lorem Ipsum Game</h2>
<p>Teste deine Fähigkeiten im Umgang mit Lorem Ipsum Texten! Je schneller und genauer du bist, desto höher ist dein Score.
<h4 class="card-title mb-3">Willkommen beim Lorem Ipsum Game</h2>
<p class="card-text text-uted fs-6 mb-4">Teste deine Fähigkeiten im Umgang mit Lorem Ipsum Texten! Je schneller und genauer du bist, desto höher ist dein Score.
Viel Spaß beim Spielen!</p>
<p> Wähle eine Option aus der Navigation, um zu starten.</p>
<img id="logo_img" src="image/Logo_loremIpsum.png" alt="Lorem Ipsum Game" class="img-fluid mt-3 d-block mx-auto">
<p class="card-text fs-6"> Wähle eine Option aus der Navigation, um zu starten.</p>
<img id="logo_img" src="image/Logo_loremIpsum.png" alt="Lorem Ipsum Game" class="img-fluid w-50 mt-3 d-block mx-auto">
</div>

View File

@ -1,7 +1,97 @@
<div class= "card">
<h2 class="mb-3">Spiel Starten</h2>
<p class="mt-2">Hier kannst du das Spiel starten. Viel Erfolg!</p>
<!-- Spiel-Wrapper -->
<div class="game-container">
<!-- Header Bereich -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h2 class="fw-bold mb-1">Memorize Challenge</h2>
<p class="text-muted mb-0">Merken Sie sich den Text so gut wie möglich.</p>
</div>
<div id="gameStatus" class="badge bg-secondary fs-6 px-3 py-2">
Bereit
</div>
</div>
<!-- Phase 1: Start -->
<div id="phaseStart" class="card">
<div class="card-body text-center py-5">
<h3 class="mb-3">Sind Sie bereit?</h3>
<p class="mb-4" style="max-width: 600px; margin: 0 auto; font-size: 1.1rem;">
Sie sehen gleich einen Text für <strong style="color: #4a6fa5;">15 Sekunden</strong>.<br>
Versuchen Sie, sich so viele Wörter wie möglich zu merken!
</p>
<button id="btnStartGame" class="btn btn-lg px-5">
Spiel Starten
</button>
</div>
</div>
<!-- Phase 2: Lernphase -->
<div id="phaseMemorize" class="d-none">
<div class="card border-warning" style="border-left: 5px solid #ffd166; background-color: #fffbf0;">
<div class="card-body text-center py-4">
<h4 class="text-warning-emphasis mb-3" style="color: #b58900;">Lernphase läuft...</h4>
<p id="targetTextDisplay" class="lead fw-bold mb-4 fst-italic" style="color: #1b1b2f; font-size: 1.4rem; line-height: 1.6;">
<!-- Text wird per JS eingefügt -->
</p>
<div class="mt-3">
<span class="badge bg-danger fs-6 px-3 py-2 blink-animation">
Verbleibende Zeit: <span id="timerDisplay">15</span>s
</span>
</div>
</div>
</div>
</div>
<!-- Phase 3: Eingabe -->
<div id="phaseInput" class="d-none">
<div class="card">
<div class="card-body">
<label for="userTextInput" class="form-label fw-bold mb-2">Geben Sie den Text aus dem Gedächtnis ein:</label>
<textarea id="userTextInput" class="form-control mb-3" rows="8" placeholder="Tippen Sie hier den gemerkten Text ein..."></textarea>
<div class="d-grid">
<button id="btnSubmitScore" class="btn btn-success btn-lg" style="background-color: #28a745; border: none;">
Auswerten & Absenden
</button>
</div>
</div>
</div>
</div>
<!-- Phase 4: Ergebnis -->
<div id="phaseResult" class="d-none">
<div class="card text-center" style="border-top: 5px solid #28a745;">
<div class="card-body py-5">
<h3 class="text-success mb-2">Ergebnis</h3>
<div class="display-1 fw-bold my-4" id="resultScore" style="color: #4a6fa5;">0</div>
<p class="text-muted mb-5">Punkte (korrekte Wörter an der richtigen Position)</p>
<div class="row g-4 text-start mb-5">
<div class="col-md-6">
<div class="p-3 h-100" style="background: #f8f9fa; border-radius: 8px;">
<small class="text-muted d-block mb-2 text-uppercase fw-bold" style="font-size: 0.75rem;">Originaltext</small>
<p class="mb-0 fst-italic" id="resultOriginal" style="font-size: 0.95rem; line-height: 1.5;"></p>
</div>
</div>
<div class="col-md-6">
<div class="p-3 h-100" style="background: #f8f9fa; border-radius: 8px;">
<small class="text-muted d-block mb-2 text-uppercase fw-bold" style="font-size: 0.75rem;">Ihre Eingabe</small>
<p class="mb-0 fst-italic" id="resultInput" style="font-size: 0.95rem; line-height: 1.5;"></p>
</div>
</div>
</div>
<div class="d-flex justify-content-center gap-3">
<button id="btnRestart" class="btn px-4">
Nochmal spielen
</button>
<button id="btnLeaderboard" class="btn px-4" style="background-color: #4a6fa5;">
Zum Leaderboard
</button>
</div>
</div>
</div>
</div>
</div>
<button class="btn btn-primary mt-3">Spiel starten</button>
<!-- Hier könnte der eigentliche Spielinhalt eingebunden werden -->
</div>