Skip to content
Snippets Groups Projects
Commit 5405840c authored by Maiko Voigtländer's avatar Maiko Voigtländer
Browse files

Merge branch 'Tutorial-6' into 'main'

Tutorial 6

See merge request maiko--tu-chemnitz.de/chess-project!6
parents a63673bf 69757e98
No related branches found
No related tags found
No related merge requests found
node_modules
\ No newline at end of file
node_modules
server/gameStates
......@@ -13,6 +13,7 @@
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"express": "^4.18.2",
"fs": "^0.0.1-security",
"hbs": "^4.2.0",
"http-errors": "~1.6.3",
"morgan": "~1.9.1",
......@@ -630,6 +631,11 @@
"node": ">= 0.6"
}
},
"node_modules/fs": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
"integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
......
......@@ -11,6 +11,7 @@
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"express": "^4.18.2",
"fs": "^0.0.1-security",
"hbs": "^4.2.0",
"http-errors": "~1.6.3",
"morgan": "~1.9.1",
......
public/images/Chess.png

1.41 MiB

......@@ -111,6 +111,11 @@ async function Play(boardFEN){
return await response.json();
}
/* async function savePreviousBoard(boardFEN){
await fetch(`${window.location.origin}/savePreviousBoard?boardFEN=${encodeURIComponent(boardFEN)}`);
return true;
} */
function removeHighlight(){
let highlightedElements = document.querySelectorAll('.highlighted');
highlightedElements.forEach(function(element) {
......@@ -121,7 +126,17 @@ function removeHighlight(){
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
async function handleComputerMove(boardFEN) {
try {
let PlayResponse = await Play(boardFEN);
let ValidateBotMoveResponse = await ValidateMove(PlayResponse.move_made);
placePieces(ValidateBotMoveResponse.validated_move.board_after_move.fen);
} catch (error) {
console.error('Error:', error);
}
}
export async function clickField(event){
let fromId = event.currentTarget.id;
......@@ -129,21 +144,19 @@ export async function clickField(event){
if (document.getElementById(fromId).classList.contains('highlighted')){ // mögliche Figurposition angeklickt
let element = document.getElementById(fromId);
let validatedMove = await ValidateMove(element.move);
let ValidateMoveResponse = await ValidateMove(element.move);
removeHighlight();
delete board.lastClicked;
placePieces(validatedMove.validated_move.board_after_move.fen);
await timeout(1000); // Warte 1 Sekunde
let PlayResponse = Play(board.FEN);
placePieces(ValidateMoveResponse.validated_move.board_after_move.fen);
PlayResponse.then((result) => {
placePieces(result.move_made.board_after_move.fen);
}).catch((error) => {
console.error('Error:', error);
});
// await savePreviousBoard(ValidateMoveResponse.validated_move.board_before_move.fen);
if (window.location.href.endsWith('/onePlayerGame')) {
await timeout(1000); // Warte 1 Sekunde
await handleComputerMove(board.FEN);
}
}
else if(board.lastClicked == fromId){ // Ausgangsfeld erneut angeklickt
......
import * as chessPieceFunctionality from './chessPieceFunctionality.js'
window.clickField = chessPieceFunctionality.clickField;
window.resetGame = resetGame;
chessPieceFunctionality.placePieces('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
\ No newline at end of file
async function resetGame(){
let response = await fetch(`${window.location.origin}/reset`);
let gameState = await response.json();
chessPieceFunctionality.placePieces(gameState.fen);
}
/* async function undoMove(){
}
*/
chessPieceFunctionality.placePieces(document.getElementById("chessboardElement").dataset.gamestate);
\ No newline at end of file
body {
padding-top: 10px;
padding-left: 50px;
padding-right: 50px;
padding-bottom: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
background-color: #212529 !important;
}
a {
......
var express = require('express');
var router = express.Router();
const chessboard = require('../server/createChessboard.js');
const {createChessboard} = require('../server/createChessboard.js');
const {createGrpcClient} = require('../server/grpcClient.js')
const {withGameState} = require("../server/cookie.js");
let moveGen = createGrpcClient();
......@@ -11,18 +12,29 @@ router.get('/', function(req, res, next) {
res.render('index', { title: 'Schachspiel'});
});
router.get('/game', function(req, res, next) {
router.get('/onePlayerGame', function(req, res, next) {
let pov = 'w';
res.render('game', { title: 'Schachspiel', board: chessboard.createChessboard(pov)});
withGameState(req, res, (gameState, saveState) => {
// Sobald gameState verfügbar ist, führe res.render() aus
res.render('onePlayer', {
title: 'Schachspiel Einzelspieler',
board: createChessboard(pov),
gameState: gameState
});
});
});
router.get('/twoPlayerGame', function(req, res, next) {
let pov = 'w';
res.render('twoPlayer', { title: 'Schachspiel 2 Spieler', board: createChessboard(pov)});
});
router.get('/possibleMoves', function(req, res, next){
let boardFEN = req.query.boardFEN;
let p_from = req.query.from;
let GetPossibleMovesRequest = {
current_board: { fen: boardFEN },
from: p_from
current_board: { fen: req.query.boardFEN },
from: req.query.from
};
moveGen.GetPossibleMoves(GetPossibleMovesRequest, function(error, response) {
......@@ -37,17 +49,45 @@ router.get('/possibleMoves', function(req, res, next){
});
});
router.get('/validate', function(req, res, next){
router.get('/validate', function(req, res, next) {
let ValidateRequest = {move_to_validate: JSON.parse(req.query.move)};
moveGen.Validate(ValidateRequest, function(error, response) {
if(error) res.sendStatus(500);
else {
res.send(response);
if (error) {
res.sendStatus(500);
} else {
withGameState(req, res, (gameState, saveState) => {
// Hier aktualisierst du den Spielstand mit dem neuen FEN
let newState = response.validated_move.board_after_move.fen;
saveState(newState);
// Sende die Antwort nach dem Speichern des neuen Zustands
res.send(response);
});
}
});
});
router.get('/reset', function(req, res, next) {
withGameState(req, res, (gameState, saveState) => {
// Hier aktualisierst du den Spielstand mit dem neuen FEN
saveState('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
// Sende die Antwort nach dem Speichern des neuen Zustands
res.send({fen: 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'});
});
});
/* router.get('/savePreviousBoard', function(req, res, next) {
withGameState(req, res, (gameState, saveState) => {
// Hier aktualisierst du den Spielstand mit dem neuen FEN
console.log(req.query.boardFEN);
saveState(req.query.boardFEN);
// Sende die Antwort nach dem Speichern des neuen Zustands
res.send();
});
});
*/
router.get('/play', function(req, res, next){
let PlayRequest = {current_board: { fen: req.query.boardFEN }};
......
const crypto = require('crypto');
const fs = require('fs');
async function withGameState(req, res, onGameState) {
let gameId = req.cookies['gameId'];
if (!gameId) {
// Schritt 1-4: Neues Spiel und Generieren eines neuen Identifikators
gameId = crypto.randomUUID();
const initialGame = initialGameState();
saveGameState(gameId, initialGame);
res.cookie('gameId', gameId, { httpOnly: true });
onGameState(initialGame, newState => saveGameState(gameId, newState));
return;
}
try {
// Schritt 5: Spielzustand abrufen
const gameState = await getGameState(gameId);
onGameState(gameState, newState => saveGameState(gameId, newState));
} catch (err) {
// Fehlerbehandlung
console.error("Fehler beim Abrufen des Spielzustands:", err);
res.status(500).send("Serverfehler");
}
}
function initialGameState() {
// Diese Funktion gibt den initialen Spielzustand zurück
return 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1';
}
function saveGameState(gameId, gameState) {
// Diese Funktion speichert den Spielzustand.
fs.writeFile(`./server/gameStates/${gameId}.json`, JSON.stringify(gameState), err => {
if (err) {
// Fehlerbehandlung
console.log("saveGameState:", err);
}
// Spielstand gespeichert
});
}
function getGameState(gameId) {
// Diese Funktion holt den Spielzustand basierend auf dem gameId
return new Promise((resolve, reject) => {
fs.readFile(`./server/gameStates/${gameId}.json`, (err, data) => {
if (err) {
console.log("getGameState:", err);
reject(err);
} else {
resolve(JSON.parse(data));
}
});
});
}
module.exports = {withGameState};
\ No newline at end of file
......@@ -25,4 +25,4 @@ function createChessboard(pov){
return HTML;
}
module.exports = {createChessboard};
\ No newline at end of file
module.exports = {createChessboard};
\ No newline at end of file
<div class="container">
<header class="d-flex justify-content-center py-3">
<ul class="nav nav-pills">
<li class="nav-item"><a href="/game" class="nav-link active" aria-current="page">Neues Spiel</a></li>
<li class="nav-item"><a href="#" class="nav-link">Spiel fortstetzen</a></li>
</ul>
</header>
<div class="px-4 pt-1 text-center">
<h1 class="display-4 fw-bold text-body-emphasis">Schachspiel</h1>
<div class="col-lg-6 mx-auto">
<p class="lead mb-3">Bitte wählen Sie den Spielmodus aus.</p>
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center mb-3">
<button type="button" class="btn btn-primary btn-lg px-4 me-sm-3" onclick="window.location.href='/onePlayerGame';">1 Spieler</button>
<button type="button" class="btn btn-primary btn-lg px-4 me-sm-3" onclick="window.location.href='/twoPlayerGame';">2 Spieler</button>
</div>
\ No newline at end of file
</div>
<div class="overflow-hidden">
<div class="container px-5 mb-2">
<img src="/images/Chess.png" class="mx-auto d-block rounded img-fluid" alt="Schachbrett" style="height: 60vmin;" loading="lazy">
</div>
</div>
</div>
\ No newline at end of file
<!DOCTYPE html>
<html>
<html data-bs-theme="dark">
<head>
<title>{{title}}</title>
<link rel='stylesheet' href='/stylesheets/style.css'>
......@@ -8,13 +8,15 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
</head>
<body>
<main>
{{{body}}}
</main>
<footer>
<p>©Copyright 2023 by Maiko Voigtländer. All rights reserved.</p>
</footer>
<div class="container">
<footer class="d-flex flex-wrap justify-content-between align-items-center py-1 my-2 border-top">
<div class="col-md-6 d-flex align-items-center">
<p class="mb-2 mb-md-0 text-body-secondary">©Copyright 2024 by Maiko Voigtländer. All rights reserved.</p>
</div>
</footer>
</div>
</body>
</html>
<div class="container">
<header class="d-flex justify-content-center py-3">
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center mb-3">
<button type="button" class="btn btn-primary btn-sm px-4" onclick="resetGame()">Spiel neustarten</button>
<button type="button" class="btn btn-primary btn-sm px-4" onclick="window.location.href='/';">Spiel beenden</button>
<button type="button" class="btn btn-primary btn-sm px-4">Zug zurücknehmen</button>
<button type="button" class="btn btn-primary btn-sm px-4">Zug vorschlagen</button>
<button type="button" class="btn btn-primary btn-sm px-4">Spiel löschen</button>
</div>
</header>
</div>
<div class="container" id="chessboardElement" data-gamestate="{{gameState}}">{{{board}}}</div>
<script src="javascripts/main.js" type="module"></script>
\ No newline at end of file
<div class="container">
<header class="d-flex justify-content-center py-3">
<ul class="nav nav-pills">
<li class="nav-item"><a href="/game" class="nav-link active" aria-current="page">Neues Spiel</a></li>
<li class="nav-item"><a href="/onePlayerGame" class="nav-link active" aria-current="page">Neues Spiel</a></li>
<li class="nav-item"><a href="/" class="nav-link">Spiel abbrechen</a></li>
<li class="nav-item"><a href="#" class="nav-link">Spiel fortstetzen</a></li>
<li class="nav-item"><a href="#" class="nav-link">Spiel speichern</a></li>
<li class="nav-item"><a href="#" class="nav-link">Spiel löschen</a></li>
</ul>
</header>
</div>
<div id="chessboardElement">{{{board}}}</div>
<script src="javascripts/main.js" type="module"></script>
\ No newline at end of file
<div class="container" id="chessboardElement">{{{board}}}</div>
<script src="javascripts/main.js" type="module"></script>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment