Bestenliste und Scores gespeichert und beim Ende eines Spiel Rang anzeige
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
const mySql = require("mysql2");
|
const mySql = require("mysql2");
|
||||||
const UserManager = require("./UserManager/UserManager");
|
const UserManager = require("./UserManager/UserManager");
|
||||||
|
const ScoreManager = require("./ScoreManager/ScoreManager");
|
||||||
require("dotenv").config();
|
require("dotenv").config();
|
||||||
|
|
||||||
class DataBaseManager {
|
class DataBaseManager {
|
||||||
@@ -20,6 +21,7 @@ class DataBaseManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.usermanager = new UserManager(this.connection);
|
this.usermanager = new UserManager(this.connection);
|
||||||
|
this.scoremanager = new ScoreManager(this.connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
backend/src/Database/ScoreManager/Score.js
Normal file
12
backend/src/Database/ScoreManager/Score.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
class Score{
|
||||||
|
/** @param {UserManager} usermanager */
|
||||||
|
constructor(scoreJson){
|
||||||
|
this.id = scoreJson.id;
|
||||||
|
this.user1ID = scoreJson.user1;
|
||||||
|
this.user2ID = scoreJson.user2;
|
||||||
|
this.score = scoreJson.score;
|
||||||
|
this.time = new Date(scoreJson.time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Score;
|
||||||
44
backend/src/Database/ScoreManager/ScoreManager.js
Normal file
44
backend/src/Database/ScoreManager/ScoreManager.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
const mySql = require("mysql2");
|
||||||
|
const Score = require("./Score");
|
||||||
|
|
||||||
|
class ScoreManager{
|
||||||
|
/**@param {mySql.Connection} connection*/
|
||||||
|
constructor(connection) {
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllScores(){
|
||||||
|
const response = await this.connection.promise().query("SELECT * FROM scores ORDER BY score DESC");
|
||||||
|
const sortedScores = response[0].map(scoreData => new Score(scoreData));
|
||||||
|
|
||||||
|
return sortedScores;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createScore(newScoreJson){
|
||||||
|
const sql = `INSERT INTO scores (user1, user2, score) VALUES (
|
||||||
|
${newScoreJson.user1}, ${newScoreJson.user2}, ${newScoreJson.score})`;
|
||||||
|
|
||||||
|
const insertResult = await this.connection.promise().query(sql);
|
||||||
|
const insertId = insertResult[0].insertId;
|
||||||
|
|
||||||
|
const selectSql = `SELECT * FROM scores WHERE id = ${insertId}`;
|
||||||
|
const selectResult = await this.connection.promise().query(selectSql);
|
||||||
|
|
||||||
|
return new Score(selectResult[0][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getScoreById(id){
|
||||||
|
const response = await this.connection.promise().query(`SELECT * FROM scores WHERE id = ${id}`);
|
||||||
|
return new Score(response.rows[0][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getScoreRang(id){
|
||||||
|
const allSortetScores = await this.getAllScores();
|
||||||
|
|
||||||
|
const score = allSortetScores.find(score => score.id === id);
|
||||||
|
|
||||||
|
return allSortetScores.indexOf(score) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ScoreManager;
|
||||||
@@ -17,7 +17,7 @@ class ClientHandler {
|
|||||||
this.socket
|
this.socket
|
||||||
);
|
);
|
||||||
|
|
||||||
this.socket.on("disconnect", () => { this.defaultDisconnect() });
|
this.socket.on("disconnect", async () => { await this.defaultDisconnect() });
|
||||||
|
|
||||||
this.joinGame();
|
this.joinGame();
|
||||||
}
|
}
|
||||||
@@ -31,8 +31,8 @@ class ClientHandler {
|
|||||||
this.socket.join(`game-${this.currentGameCode}`);
|
this.socket.join(`game-${this.currentGameCode}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultDisconnect(){
|
async defaultDisconnect(){
|
||||||
this.gameManager.leaveGame(this.user, this.currentGameCode);
|
await this.gameManager.leaveGame(this.user, this.currentGameCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class Snake{
|
|||||||
this.setup(startTiles);
|
this.setup(startTiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(startTiles){
|
async setup(startTiles){
|
||||||
this.player.socket.emit("color", this.color);
|
this.player.socket.emit("color", this.color);
|
||||||
|
|
||||||
const headX = startTiles.x;
|
const headX = startTiles.x;
|
||||||
@@ -66,7 +66,7 @@ class Snake{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkAndDrawTiles();
|
await this.checkAndDrawTiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
movementToAxes(movement){
|
movementToAxes(movement){
|
||||||
@@ -82,7 +82,7 @@ class Snake{
|
|||||||
return {num, axes};
|
return {num, axes};
|
||||||
}
|
}
|
||||||
|
|
||||||
move(){
|
async move(){
|
||||||
// Aktuelles Movement Klonen nicht das es zwischendurch geändert wird
|
// Aktuelles Movement Klonen nicht das es zwischendurch geändert wird
|
||||||
if(
|
if(
|
||||||
this.movementToAxes(this.nextMovement).axes
|
this.movementToAxes(this.nextMovement).axes
|
||||||
@@ -156,7 +156,7 @@ class Snake{
|
|||||||
else if (dy === 1) end.deg = 270;
|
else if (dy === 1) end.deg = 270;
|
||||||
else if (dy === -1) end.deg = 90;
|
else if (dy === -1) end.deg = 90;
|
||||||
|
|
||||||
this.checkAndDrawTiles();
|
await this.checkAndDrawTiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
getBigger(){
|
getBigger(){
|
||||||
@@ -181,22 +181,24 @@ class Snake{
|
|||||||
this.tiles.push(newEnd);
|
this.tiles.push(newEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAndDrawTiles(){
|
async checkAndDrawTiles(){
|
||||||
this.tiles.forEach(tile => {
|
for (const tile of this.tiles) {
|
||||||
const exsitingtile = this.playground.getTile(tile.x, tile.y);
|
const exsitingtile = this.playground.getTile(tile.x, tile.y);
|
||||||
|
|
||||||
// TODO: Klammert man das ein Kann man alleine Spielen, da es keine Kolisionserkennung gibt
|
// TODO: Klammert man das ein Kann man alleine Spielen, da es keine Kolisionserkennung gibt
|
||||||
if(exsitingtile === undefined){
|
if(exsitingtile === undefined){
|
||||||
// End Game weil außerhalb des Spielfeldes
|
// End Game weil außerhalb des Spielfeldes
|
||||||
this.game.endGame(`${this.player.username} hat die Wand berührt!`)
|
await this.game.endGame(`${this.player.username} hat die Wand berührt!`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if(exsitingtile?.class === "Snake"){
|
if(exsitingtile?.class === "Snake"){
|
||||||
// Eng Game weil schon belegt mit anderer oder eigender Schlange
|
// Eng Game weil schon belegt mit anderer oder eigender Schlange
|
||||||
this.game.endGame(`Es gab eine Kollision!`)
|
await this.game.endGame(`Es gab eine Kollision!`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.playground.setTile(tile.x, tile.y, tile);
|
this.playground.setTile(tile.x, tile.y, tile);
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateNextMovement(data){
|
updateNextMovement(data){
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ class Game{
|
|||||||
/**@type {Array<SocketUser>} */
|
/**@type {Array<SocketUser>} */
|
||||||
this.players = [];
|
this.players = [];
|
||||||
|
|
||||||
|
/**@type {Array<SocketUser>} */
|
||||||
|
this.playerIds = [];
|
||||||
|
|
||||||
this.gameLoop = new GameLoop(io, this);
|
this.gameLoop = new GameLoop(io, this);
|
||||||
|
|
||||||
setTimeout(() => { this.waitingForPlayers(true) }, 100);
|
setTimeout(() => { this.waitingForPlayers(true) }, 100);
|
||||||
@@ -35,6 +38,9 @@ class Game{
|
|||||||
|
|
||||||
// 2 Schlangen für die Spieler Instazieren
|
// 2 Schlangen für die Spieler Instazieren
|
||||||
this.players.forEach((player, i) => {
|
this.players.forEach((player, i) => {
|
||||||
|
// id pushen um nachher das Endgame zu beenden
|
||||||
|
this.playerIds.push(player.id);
|
||||||
|
|
||||||
const start = (10 * i + 5) - 1;
|
const start = (10 * i + 5) - 1;
|
||||||
const snake = new Snake(
|
const snake = new Snake(
|
||||||
player,
|
player,
|
||||||
@@ -54,20 +60,29 @@ class Game{
|
|||||||
this.gameLoop.loop();
|
this.gameLoop.loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
endGame(msg){
|
async endGame(msg){
|
||||||
// TODO: Spielende in die Datenbank eintragen
|
// TODO: Spielende in die Datenbank eintragen
|
||||||
|
this.gameStarted = false;
|
||||||
|
|
||||||
|
const scoreDb = await this.gameManager.db.scoremanager.createScore({
|
||||||
|
user1: this.playerIds[0],
|
||||||
|
user2: this.playerIds[1],
|
||||||
|
score: this.score
|
||||||
|
});
|
||||||
|
|
||||||
|
const rang = await this.gameManager.db.scoremanager.getScoreRang(scoreDb.id);
|
||||||
|
|
||||||
this.io.to(`game-${this.code}`).emit("gameEnd", {
|
this.io.to(`game-${this.code}`).emit("gameEnd", {
|
||||||
msg: msg,
|
msg: msg,
|
||||||
score: this.score,
|
score: this.score,
|
||||||
|
rang: rang
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
waitingForPlayers(changeTime = false){
|
async waitingForPlayers(changeTime = false){
|
||||||
if(this.waitingSeconds <= 0){
|
if(this.waitingSeconds <= 0){
|
||||||
if(this.players.length < 2) {
|
if(this.players.length < 2) {
|
||||||
this.endGame("Das Spiel ist zu Ende, da nicht genug Spieler beigetreten sind!");
|
await this.endGame("Das Spiel ist zu Ende, da nicht genug Spieler beigetreten sind!");
|
||||||
this.gameManager.games.delete(this.code);
|
this.gameManager.games.delete(this.code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -108,16 +123,15 @@ class Game{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @param {SocketUser} user */
|
/** @param {SocketUser} user */
|
||||||
leaveUser(user){
|
async leaveUser(user){
|
||||||
this.players.forEach((player, index) => {
|
this.players.forEach((player, index) => {
|
||||||
if(player.id === user.id){
|
if(player.id === user.id){
|
||||||
this.players.splice(index, 1);
|
this.players.splice(index, 1);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if(this.players.length != 2){
|
if(this.players.length != 2){
|
||||||
this.endGame("Das Spiel ist zu Ende, da ein Spieler verlassen hat!");
|
if(this.gameStarted) await this.endGame("Das Spiel ist zu Ende, da ein Spieler verlassen hat!");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,18 +18,20 @@ class GameLoop{
|
|||||||
this.fruitManager = new FruitManager(this.io, this.game, this.playground);
|
this.fruitManager = new FruitManager(this.io, this.game, this.playground);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop(){
|
async loop(){
|
||||||
this.playground.resetPlayground();
|
this.playground.resetPlayground();
|
||||||
|
|
||||||
this.snakes.forEach(snake => { snake.move()});
|
await Promise.all(this.snakes.map(snake => snake.move()));
|
||||||
this.fruitManager.updateFruits();
|
this.fruitManager.updateFruits();
|
||||||
|
|
||||||
this.sendUpdate();
|
this.sendUpdate();
|
||||||
|
|
||||||
|
if(this.game.gameStarted){
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.loop();
|
this.loop();
|
||||||
}, 125);
|
}, 125);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sendUpdate(){
|
sendUpdate(){
|
||||||
this.io.to(`game-${this.game.code}`).emit("loop", {
|
this.io.to(`game-${this.game.code}`).emit("loop", {
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ const socketIO = require("socket.io");
|
|||||||
const SocketUser = require("../Classes/SocketUser");
|
const SocketUser = require("../Classes/SocketUser");
|
||||||
const TemporaryLobby = require("../LobbyManager/Classes/TemporaryLobby");
|
const TemporaryLobby = require("../LobbyManager/Classes/TemporaryLobby");
|
||||||
const LobbyManager = require("../LobbyManager/LobbyManager");
|
const LobbyManager = require("../LobbyManager/LobbyManager");
|
||||||
|
const DataBaseManager = require("../../Database/DataBaseManager");
|
||||||
const Game = require("./Game/Game");
|
const Game = require("./Game/Game");
|
||||||
|
|
||||||
class GameManager {
|
class GameManager {
|
||||||
/** @param {socketIO.Server} io @param {LobbyManager} lobbyManager */
|
/** @param {socketIO.Server} io @param {DataBaseManager} db @param {LobbyManager} lobbyManager */
|
||||||
constructor(io, lobbyManager) {
|
constructor(io, db, lobbyManager) {
|
||||||
this.io = io;
|
this.io = io;
|
||||||
|
this.db = db;
|
||||||
this.lobbyManager = lobbyManager;
|
this.lobbyManager = lobbyManager;
|
||||||
|
|
||||||
/** @type {Map<string, Game>}*/
|
/** @type {Map<string, Game>}*/
|
||||||
@@ -52,11 +54,11 @@ class GameManager {
|
|||||||
return oldLobbySave.gameCode;
|
return oldLobbySave.gameCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
leaveGame(user, code){
|
async leaveGame(user, code){
|
||||||
const game = this.games.get(code);
|
const game = this.games.get(code);
|
||||||
if(!game) return 1;
|
if(!game) return 1;
|
||||||
|
|
||||||
const response = game.leaveUser(user);
|
const response = await game.leaveUser(user);
|
||||||
if(response === 1) this.games.delete(code);
|
if(response === 1) this.games.delete(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class SocketIOManager {
|
|||||||
Der LobbyManager kümmert sich um alle Lobbys
|
Der LobbyManager kümmert sich um alle Lobbys
|
||||||
*/
|
*/
|
||||||
this.lobbyManager = new LobbyManager(this.io);
|
this.lobbyManager = new LobbyManager(this.io);
|
||||||
this.gameManager = new GameManager(this.io, this.lobbyManager);
|
this.gameManager = new GameManager(this.io, this.db, this.lobbyManager);
|
||||||
|
|
||||||
this.io.on("connection", (socket) => { this.sendToRightManager(socket) });
|
this.io.on("connection", (socket) => { this.sendToRightManager(socket) });
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,26 @@ INSERT INTO `users` (`id`, `username`, `email`, `password`, `fullName`, `created
|
|||||||
(2, 'test2', 'test2@gmail.com', '$2b$10$fRrqNkFVA4TIyy61ovgPae83drW6oZOCND94BErwthKmt1MxzgTci', 'Test Person 2', '2025-03-22 19:48:45'),
|
(2, 'test2', 'test2@gmail.com', '$2b$10$fRrqNkFVA4TIyy61ovgPae83drW6oZOCND94BErwthKmt1MxzgTci', 'Test Person 2', '2025-03-22 19:48:45'),
|
||||||
(3, 'test3', NULL, '$2b$10$5QEkQuI/HxnaNovp8XPbnOnkuPpfSLdjwyqXMXKCB5oHZQR3ILTkq', NULL, '2025-03-22 19:48:51');
|
(3, 'test3', NULL, '$2b$10$5QEkQuI/HxnaNovp8XPbnOnkuPpfSLdjwyqXMXKCB5oHZQR3ILTkq', NULL, '2025-03-22 19:48:51');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Tabellenstruktur für Tabelle `scores`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `scores` (
|
||||||
|
`id` int(11) NOT NULL,
|
||||||
|
`user1` int(11) NOT NULL,
|
||||||
|
`user2` int(11) NOT NULL,
|
||||||
|
`score` int(11) NOT NULL,
|
||||||
|
`time` timestamp NOT NULL DEFAULT current_timestamp()
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
|
--
|
||||||
|
-- Daten für Tabelle `scores`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `scores` (`id`, `user1`, `user2`, `score`, `time`) VALUES
|
||||||
|
(1, 1, 2, 100, '2025-03-22 20:00:00'),
|
||||||
|
(2, 2, 3, 150, '2025-03-22 20:15:00'),
|
||||||
|
(3, 1, 3, 200, '2025-03-22 20:30:00');
|
||||||
--
|
--
|
||||||
-- Indizes der exportierten Tabellen
|
-- Indizes der exportierten Tabellen
|
||||||
--
|
--
|
||||||
@@ -58,6 +78,14 @@ ALTER TABLE `users`
|
|||||||
ADD PRIMARY KEY (`id`),
|
ADD PRIMARY KEY (`id`),
|
||||||
ADD UNIQUE KEY `username` (`username`);
|
ADD UNIQUE KEY `username` (`username`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indizes für die Tabelle `scores`
|
||||||
|
--
|
||||||
|
ALTER TABLE `scores`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `user1` (`user1`),
|
||||||
|
ADD KEY `user2` (`user2`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- AUTO_INCREMENT für exportierte Tabellen
|
-- AUTO_INCREMENT für exportierte Tabellen
|
||||||
--
|
--
|
||||||
@@ -67,6 +95,19 @@ ALTER TABLE `users`
|
|||||||
--
|
--
|
||||||
ALTER TABLE `users`
|
ALTER TABLE `users`
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT für Tabelle `scores`
|
||||||
|
--
|
||||||
|
ALTER TABLE `scores`
|
||||||
|
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints der Tabelle `scores`
|
||||||
|
--
|
||||||
|
ALTER TABLE `scores`
|
||||||
|
ADD CONSTRAINT `scores_ibfk_1` FOREIGN KEY (`user1`) REFERENCES `users` (`id`),
|
||||||
|
ADD CONSTRAINT `scores_ibfk_2` FOREIGN KEY (`user2`) REFERENCES `users` (`id`);
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
|
|||||||
@@ -107,6 +107,10 @@ class UIManager{
|
|||||||
const score = document.createElement("h2");
|
const score = document.createElement("h2");
|
||||||
score.innerText = data.score;
|
score.innerText = data.score;
|
||||||
scoreDiv.appendChild(score);
|
scoreDiv.appendChild(score);
|
||||||
|
const rang = document.createElement("h2");
|
||||||
|
rang.innerText = `Bestenliste Platz: ${data.rang}`;
|
||||||
|
rang.style.color = "rgb(255, 223, 0)";
|
||||||
|
scoreDiv.appendChild(rang);
|
||||||
endDiv.appendChild(scoreDiv);
|
endDiv.appendChild(scoreDiv);
|
||||||
|
|
||||||
const dashButton = document.createElement("button");
|
const dashButton = document.createElement("button");
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ img{
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
height: 150px;
|
height: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#scoreEndDiv h3{
|
#scoreEndDiv h3{
|
||||||
|
|||||||
Reference in New Issue
Block a user