darkmaria / templates /index.html
Docfile's picture
Update templates/index.html
44bedb5 verified
raw
history blame
9.52 kB
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jeu d'Échecs</title>
<!-- Tailwind CSS via CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* Pour une meilleure interaction avec le SVG */
.chess-board svg {
cursor: default; /* Ou 'pointer' sur les pièces si on gère les clics SVG */
}
.square { /* Styles pour les cases si on n'utilise pas SVG pour le rendu cliquable */
width: 40px; height: 40px;
display: flex; align-items: center; justify-content: center;
border: 1px solid #ccc;
}
.selected-square {
background-color: rgba(255, 255, 0, 0.5) !important;
}
</style>
</head>
<body class="bg-gray-100 flex flex-col items-center justify-center min-h-screen p-4">
<div class="bg-white p-6 rounded-lg shadow-xl w-full max-w-3xl">
<h1 class="text-3xl font-bold text-center text-gray-700 mb-6">Jeu d'Échecs</h1>
<div class="controls mb-4 flex flex-wrap gap-2 justify-center">
<button id="newGameHuman" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Nouvelle Partie (Humain vs Humain)
</button>
<button id="newGameAIWhite" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
Nouvelle Partie (Jouer Blancs vs IA)
</button>
<button id="newGameAIBlack" class="bg-gray-700 hover:bg-gray-900 text-white font-bold py-2 px-4 rounded">
Nouvelle Partie (Jouer Noirs vs IA)
</button>
</div>
<div class="game-area flex flex-col md:flex-row gap-4 items-start">
<!-- Échiquier (rendu par chess.svg) -->
<div id="boardDisplay" class="chess-board mx-auto md:mx-0 border-2 border-gray-500" style="width: 350px; height: 350px;">
<!-- Le SVG de l'échiquier sera injecté ici -->
{{ initial_board_svg|safe if initial_board_svg else "Chargement de l'échiquier..." }}
</div>
<!-- Informations et contrôles de la partie -->
<div class="info-panel flex-grow p-4 bg-gray-50 rounded-md shadow">
<h2 class="text-xl font-semibold mb-2">Informations</h2>
<p id="turnInfo" class="mb-1">Tour: Chargement...</p>
<p id="statusInfo" class="mb-3 font-medium">Statut: Chargement...</p>
<h3 class="text-lg font-semibold mb-1">Jouer un coup (ex: e2e4):</h3>
<div class="move-input flex gap-2 mb-3">
<input type="text" id="moveInput" placeholder="e.g., e2e4"
class="flex-grow p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500">
<button id="submitMove" class="bg-indigo-500 hover:bg-indigo-700 text-white font-bold py-2 px-3 rounded">
Jouer
</button>
</div>
<p class="text-xs text-gray-500 mb-3">
Alternative: cliquez sur la case de départ puis la case d'arrivée sur un échiquier interactif (non implémenté ici, utilisez l'input).
</p>
<h3 class="text-lg font-semibold mb-1">Derniers coups:</h3>
<p id="playerMoveInfo" class="text-sm"></p>
<p id="aiMoveInfo" class="text-sm"></p>
</div>
</div>
</div>
<script>
const boardDisplay = document.getElementById('boardDisplay');
const turnInfo = document.getElementById('turnInfo');
const statusInfo = document.getElementById('statusInfo');
const moveInput = document.getElementById('moveInput');
const playerMoveInfo = document.getElementById('playerMoveInfo');
const aiMoveInfo = document.getElementById('aiMoveInfo');
let currentFen = "{{ initial_fen }}"; // FEN initial passé par Flask
let selectedSquare = null; // Pour une interaction de clic sur le plateau (non implémenté visuellement ici)
async function updateBoard(data) {
if (data.error) {
statusInfo.textContent = `Erreur: ${data.error}`;
if (data.board_svg) boardDisplay.innerHTML = data.board_svg; // Mettre à jour même en cas d'erreur de coup
return;
}
currentFen = data.fen;
boardDisplay.innerHTML = data.board_svg; // chess.svg fournit le plateau
turnInfo.textContent = `Tour: ${data.turn}`;
statusInfo.textContent = `Statut: ${data.status}`;
moveInput.value = '';
playerMoveInfo.textContent = data.player_move_san ? `Votre coup: ${data.player_move_san}` : "";
aiMoveInfo.textContent = data.ai_move_san ? `Coup IA: ${data.ai_move_san}` : "";
if (data.game_over) {
moveInput.disabled = true;
document.getElementById('submitMove').disabled = true;
// On pourrait ajouter une alerte ou un modal
setTimeout(() => alert(`Partie terminée ! ${data.status}`), 100);
} else {
moveInput.disabled = false;
document.getElementById('submitMove').disabled = false;
}
}
async function submitMove() {
const move = moveInput.value.trim().toLowerCase();
if (!move.match(/^[a-h][1-8][a-h][1-8]([qrbn])?$/)) { // Validation basique du format UCI
statusInfo.textContent = "Format de coup invalide (ex: e2e4, e7e8q).";
return;
}
playerMoveInfo.textContent = ""; // Clear previous move info
aiMoveInfo.textContent = "";
try {
const response = await fetch('/move', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ move: move })
});
const data = await response.json();
updateBoard(data);
} catch (error) {
console.error('Erreur lors de la soumission du coup:', error);
statusInfo.textContent = 'Erreur de communication avec le serveur.';
}
}
async function startNewGame(mode, playerPlaysWhite = true) {
playerMoveInfo.textContent = "";
aiMoveInfo.textContent = "";
try {
const response = await fetch('/new_game', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ mode: mode, player_color_white: playerPlaysWhite})
});
const data = await response.json();
updateBoard(data);
statusInfo.textContent = `Nouvelle partie commencée. ${mode === 'ai' ? (playerPlaysWhite ? 'Vous jouez les Blancs.' : 'L\'IA joue les Blancs.') : 'Humain vs Humain.'}`;
} catch (error) {
console.error('Erreur lors du démarrage de la nouvelle partie:', error);
statusInfo.textContent = 'Erreur de communication avec le serveur.';
}
}
document.getElementById('submitMove').addEventListener('click', submitMove);
moveInput.addEventListener('keypress', function(event) {
if (event.key === 'Enter') {
submitMove();
}
});
document.getElementById('newGameHuman').addEventListener('click', () => startNewGame('human'));
document.getElementById('newGameAIWhite').addEventListener('click', () => startNewGame('ai', true));
document.getElementById('newGameAIBlack').addEventListener('click', () => startNewGame('ai', false));
// Initialiser l'état au chargement de la page (si une partie est en cours via session)
async function initializeBoardState() {
if (boardDisplay.innerHTML.includes("Chargement")) { // Si le SVG n'a pas été injecté par le serveur
try {
const response = await fetch('/get_board_state');
const data = await response.json();
updateBoard(data);
} catch (error) {
console.error('Erreur de récupération de l\'état initial:', error);
statusInfo.textContent = 'Erreur de chargement de la partie.';
}
} else { // Le SVG est déjà là, il faut juste mettre à jour les infos de statut
try {
const response = await fetch('/get_board_state'); // Récupérer le statut actuel
const data = await response.json();
turnInfo.textContent = `Tour: ${data.turn}`;
statusInfo.textContent = `Statut: ${data.status}`;
if (data.game_over) {
moveInput.disabled = true;
document.getElementById('submitMove').disabled = true;
}
} catch (error) {
console.error('Erreur de récupération de l\'état initial (infos):', error);
}
}
}
window.onload = initializeBoardState;
</script>
</body>
</html>