424 lines
11 KiB
JavaScript
424 lines
11 KiB
JavaScript
import express from 'express';
|
|
import sqlite3 from 'sqlite3';
|
|
import { open } from 'sqlite';
|
|
import fs from 'fs';
|
|
|
|
// Déclaration de la variable db pour qu'elle soit accessible dans tout le script
|
|
let db;
|
|
|
|
// Fonction pour initialiser la base de données
|
|
async function initializeDatabase() {
|
|
// open the database - SQLite créera automatiquement le fichier s'il n'existe pas
|
|
db = await open({
|
|
filename: './datas/database.db',
|
|
driver: sqlite3.Database
|
|
});
|
|
|
|
// Créer les tables nécessaires si elles n'existent pas
|
|
await db.exec(`
|
|
CREATE TABLE IF NOT EXISTS scores (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
player_name TEXT,
|
|
score INTEGER,
|
|
pathHistory TEXT,
|
|
date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`);
|
|
|
|
console.log('Database initialized');
|
|
}
|
|
|
|
initializeDatabase().catch(err => {
|
|
console.error('Error initializing database:', err);
|
|
});
|
|
|
|
const app = express();
|
|
const port = 3000;
|
|
|
|
app.use(express.static('public'));
|
|
app.use(express.json());
|
|
|
|
app.get('/', (req, res) => {
|
|
res.sendFile('index.html', { root: '.' });
|
|
});
|
|
|
|
const templatePiece = [
|
|
[ // ok
|
|
[3, 0],
|
|
[4, 0],
|
|
[5, 0],
|
|
[6, 0],
|
|
[4.5, 0.5]
|
|
],
|
|
[
|
|
[3, 1],
|
|
[4, 1],
|
|
[5, 1],
|
|
[5, 0],
|
|
[4, 1]
|
|
],
|
|
[ // ok
|
|
[3, 1],
|
|
[4, 1],
|
|
[5, 1],
|
|
[3, 0],
|
|
[4, 1]
|
|
],
|
|
[ // ok
|
|
[3, 0],
|
|
[4, 0],
|
|
[4, 1],
|
|
[5, 1],
|
|
[4, 1]
|
|
],
|
|
[
|
|
[3, 1],
|
|
[4, 1],
|
|
[4, 0],
|
|
[5, 0],
|
|
[4, 1]
|
|
],
|
|
[ // ok
|
|
[3, 0],
|
|
[4, 0],
|
|
[4, 1],
|
|
[5, 0],
|
|
[4, 0]
|
|
],
|
|
[ // ok
|
|
[4, 0],
|
|
[5, 0],
|
|
[4, 1],
|
|
[5, 1],
|
|
[4.5, 0.5]
|
|
]
|
|
];
|
|
|
|
const templateColor = [
|
|
[240, 87, 84, 255],
|
|
[254, 223, 92, 255],
|
|
[27, 148, 118, 255],
|
|
[36, 115, 155, 255],
|
|
[106, 190, 178, 255],
|
|
[164, 199, 218, 255],
|
|
[177, 225, 218, 255]
|
|
];
|
|
|
|
const MOVELEFT = 1;
|
|
const MOVERIGHT = 2;
|
|
const MOVEDOWN = 3;
|
|
const ROTATE = 4;
|
|
const MOVEDOWNFAST = 5;
|
|
const RESPAWN = 6;
|
|
const CHANGENEXTPIECE = 7;
|
|
|
|
function ifPiece(x, y, board) {
|
|
if (x < 0 || x >= 10 || y >= 20) {
|
|
return true;
|
|
}
|
|
|
|
if (y < 0) {
|
|
return false;
|
|
}
|
|
|
|
if (board[x][y][0] == 0 && board[x][y][1] == 0 && board[x][y][2] == 0) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function canMoveTo(x, y, piece, board) {
|
|
for (let i = 0; i < piece.length - 1; i++) {
|
|
if (piece[i][0] + x < 0 || piece[i][0] + x >= 10 || piece[i][1] + y >= 20 || ifPiece(piece[i][0] + x, piece[i][1] + y, board)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function ifRotate(piece, board) {
|
|
for (let i = 0; i < piece.length - 1; i++) {
|
|
if (piece[i][0] < 0 || piece[i][0] >= 10 || piece[i][1] >= 20 || ifPiece(piece[i][0], piece[i][1], board)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function moveDown(piece, board) {
|
|
if (canMoveTo(0, 1, piece, board)) {
|
|
for (let i = 0; i < piece.length; i++) {
|
|
piece[i][1]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
function moveLeft(piece, board) {
|
|
if (canMoveTo(-1, 0, piece, board)) {
|
|
for (let i = 0; i < piece.length; i++) {
|
|
piece[i][0]--;
|
|
}
|
|
}
|
|
}
|
|
|
|
function moveRight(piece, board) {
|
|
if (canMoveTo(1, 0, piece, board)) {
|
|
for (let i = 0; i < piece.length; i++) {
|
|
piece[i][0]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
function rotate(piece, board) {
|
|
if (piece.length == 0) {
|
|
return;
|
|
}
|
|
|
|
let currentPieceCopy = [];
|
|
|
|
for (let i = 0; i < piece.length; i++) {
|
|
currentPieceCopy.push([piece[i][0], piece[i][1]]);
|
|
}
|
|
|
|
const center = currentPieceCopy[currentPieceCopy.length - 1];
|
|
for (let i = 0; i < piece.length - 1; i++) {
|
|
const x = currentPieceCopy[i][0] - center[0];
|
|
const y = currentPieceCopy[i][1] - center[1];
|
|
|
|
currentPieceCopy[i][0] = center[0] - y;
|
|
currentPieceCopy[i][1] = center[1] + x;
|
|
}
|
|
|
|
|
|
if (ifRotate(currentPieceCopy, board)) {
|
|
piece = currentPieceCopy;
|
|
// Don't modify history in verification function
|
|
}
|
|
else {
|
|
for (let x = -1; x <= 1; x++) {
|
|
for (let y = 0; y >= -1; y--) {
|
|
if (canMoveTo(x, y, currentPieceCopy, board)) {
|
|
moveToPiece(x, y, currentPieceCopy);
|
|
piece = currentPieceCopy;
|
|
|
|
x = 2;
|
|
y = -2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function moveToPiece(x, y, piece) {
|
|
for (let i = 0; i < piece.length; i++) {
|
|
piece[i][0] += x;
|
|
piece[i][1] += y;
|
|
}
|
|
}
|
|
|
|
function checkLine(board, scoreObject) {
|
|
let lineFilled = 0;
|
|
let score = 0;
|
|
let lines = 0;
|
|
let level = 0;
|
|
|
|
for (let i = 0; i < 20; i++) {
|
|
let check = true;
|
|
|
|
for (let j = 0; j < 10; j++) {
|
|
if (board[j][i][0] == 0 && board[j][i][1] == 0 && board[j][i][2] == 0) {
|
|
check = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (check) {
|
|
for (let j = i; j > 0; j--) {
|
|
for (let k = 0; k < 10; k++) {
|
|
board[k][j] = board[k][j - 1];
|
|
}
|
|
}
|
|
|
|
for (let k = 0; k < 10; k++) {
|
|
board[k][0] = [0, 0, 0, 255];
|
|
}
|
|
|
|
lineFilled++;
|
|
}
|
|
}
|
|
|
|
if (lineFilled == 1) {
|
|
score += 40;
|
|
}
|
|
else if (lineFilled == 2) {
|
|
score += 100;
|
|
}
|
|
else if (lineFilled == 3) {
|
|
score += 300;
|
|
}
|
|
else if (lineFilled == 4) {
|
|
score += 1200;
|
|
}
|
|
|
|
lines += lineFilled;
|
|
level = Math.floor(lines / 10);
|
|
|
|
scoreObject.score += score;
|
|
scoreObject.lines += lineFilled;
|
|
scoreObject.level = Math.floor(scoreObject.lines / 10);
|
|
}
|
|
|
|
function verifieHystoryAndScore(score, history) {
|
|
let board = [];
|
|
|
|
for (let i = 0; i < 10; i++) {
|
|
board[i] = [];
|
|
for (let j = 0; j < 20; j++) {
|
|
board[i][j] = [0, 0, 0, 255];
|
|
}
|
|
}
|
|
|
|
let piece = [];
|
|
let nextPiece = [];
|
|
let nextIndex = 0;
|
|
|
|
let scoreObject = {
|
|
score: 0,
|
|
lines: 0,
|
|
level: 0
|
|
};
|
|
|
|
for (let i = 0; i < history.length; i++) {
|
|
if (history[i][0] === CHANGENEXTPIECE) {
|
|
// Only place non-fractional coordinates on the board
|
|
for (let j = 0; j < piece.length - 1; j++) {
|
|
if (Number.isInteger(piece[j][0]) && Number.isInteger(piece[j][1]) &&
|
|
piece[j][0] >= 0 && piece[j][0] < 10 &&
|
|
piece[j][1] >= 0 && piece[j][1] < 20) {
|
|
board[piece[j][0]][piece[j][1]] = [templateColor[nextIndex][0], templateColor[nextIndex][1], templateColor[nextIndex][2], templateColor[nextIndex][3]];
|
|
}
|
|
}
|
|
|
|
checkLine(board, scoreObject);
|
|
|
|
nextIndex = history[i][1];
|
|
|
|
// Reset piece and copy from template
|
|
piece = [];
|
|
for (let j = 0; j < templatePiece[nextIndex].length; j++) {
|
|
piece.push([templatePiece[nextIndex][j][0], templatePiece[nextIndex][j][1]]);
|
|
}
|
|
|
|
// Set up next piece
|
|
nextPiece = [];
|
|
let nextNextIndex = (i+1 < history.length && history[i+1][0] === CHANGENEXTPIECE) ? history[i+1][1] : 0;
|
|
for (let j = 0; j < templatePiece[nextNextIndex].length; j++) {
|
|
nextPiece.push([templatePiece[nextNextIndex][j][0], templatePiece[nextNextIndex][j][1]]);
|
|
}
|
|
}
|
|
else if (history[i][0] === MOVEDOWN) {
|
|
moveDown(piece, board);
|
|
}
|
|
else if (history[i][0] === MOVELEFT) {
|
|
moveLeft(piece, board);
|
|
}
|
|
else if (history[i][0] === MOVERIGHT) {
|
|
moveRight(piece, board);
|
|
}
|
|
else if (history[i][0] === ROTATE) {
|
|
rotate(piece, board);
|
|
}
|
|
}
|
|
|
|
console.log("Calculated score:", scoreObject.score, "Submitted score:", score);
|
|
return score === scoreObject.score;
|
|
}
|
|
|
|
app.put('/api/sendScore', (req, res) => {
|
|
|
|
let score = req.body.score;
|
|
let history = req.body.history;
|
|
let playerName = req.body.playerName;
|
|
|
|
// if (score === null || history === null || playerName === null) {
|
|
// return res.status(400).send('Missing required fields');
|
|
// }
|
|
|
|
// if (score < 0) {
|
|
// return res.status(400).send('Score cannot be negative');
|
|
// }
|
|
|
|
// if (history.length === 0) {
|
|
// return res.status(400).send('History cannot be empty');
|
|
// }
|
|
|
|
if (!verifieHystoryAndScore(score, history)) {
|
|
return res.status(400).send('Invalid history or score');
|
|
}
|
|
|
|
// Vérifier si le dossier des historiques existe, le créer si nécessaire
|
|
const historyDir = './datas/histories';
|
|
if (!fs.existsSync(historyDir)) {
|
|
fs.mkdirSync(historyDir, { recursive: true });
|
|
}
|
|
|
|
// Date du jour
|
|
|
|
const date = new Date();
|
|
const dateString = date.toISOString().split('T')[0]; // Format YYYY-MM-DD
|
|
|
|
// Vérifier si un fichier avec ce nom existe déjà et ajouter un chiffre si nécessaire
|
|
let finalPlayerName = playerName + dateString;
|
|
let counter = 0;
|
|
let historyFilePath = `${historyDir}/${finalPlayerName}.json`;
|
|
|
|
while (fs.existsSync(historyFilePath)) {
|
|
counter++;
|
|
finalPlayerName = `${playerName}${dateString}${counter}`;
|
|
historyFilePath = `${historyDir}/${finalPlayerName}.json`;
|
|
}
|
|
|
|
// Écrire l'historique dans le fichier
|
|
try {
|
|
fs.writeFileSync(historyFilePath, JSON.stringify(history));
|
|
console.log(`History written to ${historyFilePath}`);
|
|
} catch (err) {
|
|
console.error('Error writing history file:', err);
|
|
return res.status(500).send('Error writing history file');
|
|
}
|
|
|
|
//
|
|
db.run('INSERT INTO scores (player_name, score, pathHistory) VALUES (?, ?, ?)', [playerName, score, historyFilePath])
|
|
.then(() => {
|
|
console.log(`Score inserted for ${playerName}`);
|
|
})
|
|
.then(() => {
|
|
console.log('History path inserted in database');
|
|
res.status(200).json({
|
|
success: true,
|
|
playerName: playerName,
|
|
message: 'Score and history saved'
|
|
});
|
|
})
|
|
.catch(err => {
|
|
console.error('Database error:', err);
|
|
res.status(500).send('Error inserting data');
|
|
});
|
|
});
|
|
|
|
app.get('/api/getHighScores', async (req, res) => {
|
|
try {
|
|
const scores = await db.all('SELECT player_name, score FROM scores ORDER BY score DESC LIMIT 10');
|
|
res.json(scores);
|
|
} catch (err) {
|
|
console.error('Database error:', err);
|
|
res.status(500).send('Error retrieving high scores');
|
|
}
|
|
}
|
|
);
|
|
|
|
app.listen(port, () => {
|
|
console.log(`Server listening at http://localhost:${port}`);
|
|
});
|