Files
acht-damen-tuerme-problem/app/templates/dashboard.html
T

277 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/dashboard.css') }}">
</head>
<body>
<nav class="navbar">
<div class="nav-left">♛ 8-Queens App</div>
<div class="nav-right">
<a href="{{ url_for('main.dashboard') }}">Dashboard</a>
<a href="{{ url_for('login.login_settings') }}">Login settings</a>
<form action="{{ url_for('login.logout') }}" method="post" class="nav-logout-form">
<button class="nav-link-button" type="submit">Logout</button>
</form>
</div>
</nav>
<div class="container">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<div class="flash-stack">
{% for category, message in messages %}
<p class="flash-message {{ category }}">{{ message }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<div class="card">
<h2>👋 Willkommen, {{ current_user.username }}</h2>
<div class="user-info">
<p><strong>ID:</strong> {{ current_user.id }}</p>
<p><strong>Username:</strong> {{ current_user.username }}</p>
<p><strong>2FA:</strong> {% if current_user.two_factor_enabled %}Authenticator app enabled{% else %}Disabled{% endif %}</p>
<p><strong>Erstellt:</strong> {{ current_user.created_at }}</p>
</div>
<div class="inline-actions">
<a class="btn secondary" href="{{ url_for('login.login_settings') }}">Open login settings</a>
<form action="{{ url_for('login.logout') }}" method="post">
<button class="btn danger" type="submit">Logout</button>
</form>
</div>
</div>
<div class="mode-switch">
<button class="btn active" onclick="setMode('queens')" id="btnQueens">♛ Damen</button>
<button class="btn secondary" onclick="setMode('rooks')" id="btnRooks">♜ Türme</button>
<button class="btn secondary" onclick="toggleSidebar()" id="btnSidebar">Board Settings</button>
</div>
<div class="card game-card">
<div class="game-card-header">
<h2>♟️ Damen- und Tuerme-Spiel</h2>
<button class="info-button" id="infoButton" onclick="toggleInfoModal(true)" type="button"
aria-label="Spielanleitung und Erklaerung anzeigen">i</button>
</div>
<p class="board-size-info">Aktuelle Brettgroesse: <span id="boardSizeValue">8</span> x <span
id="boardSizeValueMirror">8</span></p>
<div class="game-stats" aria-label="Spielstatus">
<article class="game-stat-card">
<p class="game-stat-label">Schritte</p>
<p class="game-stat-value" id="stepCounterValue">0</p>
</article>
<article class="game-stat-card">
<p class="game-stat-label">Zeit</p>
<p class="game-stat-value" id="timerValue">00:00:00</p>
</article>
<article class="game-stat-card">
<p class="game-stat-label">Status</p>
<p class="game-stat-value game-stat-status" id="gameProgressState">Laeuft</p>
</article>
</div>
<p id="statusMessage"></p>
<div class="board" id="board"></div>
<div class="solver-panel">
<div class="solver-panel-header">
<div>
<h3>Solver-Ablauf</h3>
<p class="solver-message" id="solverMessage">Bereite einen Ablauf vor und spiele ihn Schritt fuer Schritt ab.</p>
</div>
<p class="solver-step-info" id="solverStepInfo">Schritt 0 / 0</p>
</div>
<div class="solver-controls">
<button class="btn" onclick="prepareSolutionTrace()" id="btnPrepareSolve" type="button">Solve Step-by-Step</button>
<button class="btn secondary" onclick="instantSolve()" id="btnInstantSolve" type="button">Instant Solve</button>
<button class="btn secondary" onclick="nextSolverStep()" id="btnNextStep" type="button">Next Step</button>
<button class="btn secondary" onclick="toggleSolverPlayback()" id="btnPlayPause" type="button">Play Animation</button>
</div>
<div class="solver-speed">
<label class="solver-speed-label" for="solverSpeedInput">Speed</label>
<input id="solverSpeedInput" type="range" min="80" max="900" step="20" value="320"
oninput="updateSolverSpeed(this.value)">
<span class="solver-speed-value" id="solverSpeedValue">320 ms</span>
</div>
</div>
<div class="controls">
<button class="btn" onclick="checkSolution()">Check</button>
<button class="btn secondary" onclick="resetBoard()">Reset</button>
<button class="btn" onclick="openSavePanel()">💾 Save</button>
<button class="btn" onclick="openSavePointsPanel()">📂 Load</button>
</div>
</div>
<div class="card">
<h3>📋 Figuren Positionen</h3>
<ul id="queenList"></ul>
</div>
<div class="card">
<div class="history-header">
<div>
<h3>⏱️ Bisherige Zeiten</h3>
<p class="history-subtitle">Die Tabelle zeigt gespeicherte Save-Points mit Zeit und Schritten.</p>
</div>
<button class="btn secondary" onclick="refreshTimeHistory()" type="button">Aktualisieren</button>
</div>
<div class="history-table-wrapper">
<table class="history-table">
<thead>
<tr>
<th>Save-Point</th>
<th>Modus</th>
<th>Brett</th>
<th>Schritte</th>
<th>Zeit</th>
<th>Status</th>
<th>Gespeichert</th>
</tr>
</thead>
<tbody id="timeHistoryTableBody">
<tr>
<td colspan="7" class="history-empty">Noch keine gespeicherten Zeiten vorhanden.</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<aside class="sidebar" id="settingsSidebar" aria-hidden="true">
<div class="sidebar-header">
<h3>Brettgroesse</h3>
<button class="btn secondary sidebar-close" onclick="toggleSidebar(false)" type="button">Schliessen</button>
</div>
<p>Wähle eine Grösse zwischen 4 und 13.</p>
<label class="sidebar-label" for="boardSizeInput">Groesse</label>
<input id="boardSizeInput" type="range" min="4" max="13" value="8" oninput="previewBoardSize(this.value)">
<div class="sidebar-size-row">
<strong><span id="sidebarBoardSizeValue">8</span> x <span id="sidebarBoardSizeValueMirror">8</span></strong>
</div>
<button class="btn" onclick="applyBoardSize()" type="button">Apply Size</button>
<p class="sidebar-hint">Das Brett wird beim Ändern zur Sicherheit zurückgesetzt.</p>
</aside>
<aside class="sidebar save-sidebar" id="saveSidebar" aria-hidden="true">
<div class="sidebar-header">
<h3>Speicherpunkt</h3>
<button class="btn secondary sidebar-close" onclick="toggleSavePanel(false)" type="button">Schliessen</button>
</div>
<p>Gib dem Spielstand einen klaren Namen und optional eine kurze Notiz.</p>
<label class="sidebar-label" for="saveNameInput">Name</label>
<input class="sidebar-input" id="saveNameInput" type="text" maxlength="80" placeholder="z. B. Fast geloeste Dame 8x8">
<label class="sidebar-label" for="saveNoteInput">Notiz</label>
<textarea class="sidebar-input sidebar-textarea" id="saveNoteInput" rows="4" maxlength="240"
placeholder="z. B. Gute Startposition fuer Tuermetest"></textarea>
<label class="sidebar-checkbox">
<input id="saveFavoriteInput" type="checkbox">
Als Favorit markieren
</label>
<button class="btn" onclick="saveGame()" type="button">Jetzt speichern</button>
</aside>
<aside class="sidebar save-points-sidebar" id="savePointsSidebar" aria-hidden="true">
<div class="sidebar-header">
<h3>Save Points</h3>
<button class="btn secondary sidebar-close" onclick="toggleSavePointsPanel(false)" type="button">Schliessen</button>
</div>
<p>Waehle einen Speicherstand aus der Liste.</p>
<div class="save-point-filters">
<label class="sidebar-label" for="savePointModeFilter">Modus</label>
<select class="sidebar-input" id="savePointModeFilter" onchange="refreshSavePoints()">
<option value="all">Alle</option>
<option value="queens">Damen</option>
<option value="rooks">Tuerme</option>
</select>
<label class="sidebar-label" for="savePointSizeFilter">Brettgroesse</label>
<select class="sidebar-input" id="savePointSizeFilter" onchange="refreshSavePoints()">
<option value="all">Alle</option>
{% for board_size in range(4, 14) %}
<option value="{{ board_size }}">{{ board_size }} x {{ board_size }}</option>
{% endfor %}
</select>
<label class="sidebar-label" for="savePointSortFilter">Sortierung</label>
<select class="sidebar-input" id="savePointSortFilter" onchange="refreshSavePoints()">
<option value="newest">Neueste zuerst</option>
<option value="oldest">Aelteste zuerst</option>
<option value="updated">Zuletzt bearbeitet</option>
<option value="favorites">Favoriten zuerst</option>
</select>
<label class="sidebar-checkbox">
<input id="savePointFavoritesOnly" type="checkbox" onchange="refreshSavePoints()">
Nur Favoriten anzeigen
</label>
</div>
<div class="save-points-list" id="savePointsList">
<p class="sidebar-hint">Noch keine Speicherstaende gefunden.</p>
</div>
</aside>
<div class="sidebar-backdrop" id="sidebarBackdrop" onclick="toggleSidebar(false)"></div>
<div class="sidebar-backdrop" id="saveBackdrop" onclick="toggleSavePanel(false)"></div>
<div class="sidebar-backdrop" id="savePointsBackdrop" onclick="toggleSavePointsPanel(false)"></div>
<div class="modal-backdrop" id="infoModalBackdrop" onclick="toggleInfoModal(false)"></div>
<section class="modal" id="infoModal" aria-hidden="true" aria-labelledby="infoModalTitle">
<div class="modal-header">
<h3 id="infoModalTitle">Spielanleitung und Acht-Damen-Problem</h3>
<button class="btn secondary sidebar-close" onclick="toggleInfoModal(false)" type="button">Schliessen</button>
</div>
<div class="modal-content">
<p>Setze pro Reihe genau eine Figur auf das Brett. Eine gueltige Loesung hat keine Konflikte.</p>
<h4>So funktioniert das Spiel</h4>
<p>Im Damen-Modus duerfen sich Damen weder in derselben Spalte noch diagonal angreifen. Im Tuerme-Modus
zaehlen nur Spalten-Konflikte. Mit einem Klick setzt oder entfernst du eine Figur.</p>
<h4>Was ist das Acht-Damen-Problem?</h4>
<p>Das klassische Acht-Damen-Problem fragt nach einer Anordnung von acht Damen auf einem 8x8-Brett, bei
der sich keine zwei Damen schlagen. Es ist ein bekanntes Beispiel fuer kombinatorische Suche und
Backtracking.</p>
<h4>Was zeigen Zeit und Schritte?</h4>
<p>Der Schrittzaehler erfasst deine Zuege auf dem Brett. Die Zeit laeuft fuer das aktuelle Spiel weiter,
auch wenn du die Seite neu laedst. Beim Speichern werden Zeit und Schritte zusammen mit dem Save-Point
abgelegt.</p>
</div>
</section>
<script src="{{ url_for('static', filename='js/dashboard.js') }}"></script>
</body>
</html>