diff --git a/game.js b/game.js index ed3c441..aee1a81 100644 --- a/game.js +++ b/game.js @@ -1,6 +1,6 @@ import { capitalize } from './utils.js'; -import { updateUserCoins, getUser, insertLog } from './init_database.js' +import {updateUserCoins, getUser, insertLog, insertGame, getUserElo, insertElos, updateElo} from './init_database.js' const messagesTimestamps = new Map(); @@ -139,4 +139,82 @@ export async function slowmodesHandler(msg, activeSlowmodes) { authorSlowmode.lastMessage = Date.now() } return false +} + +export async function eloHandler(p1, p2, p1score, p2score, type) { + const p1DB = getUser.get(p1) + const p2DB = getUser.get(p2) + + if (!p1DB || !p2DB) return + + let p1elo = await getUserElo.get({ id: p1 }) + let p2elo = await getUserElo.get({ id: p2 }) + + if (!p1elo) { + await insertElos.run({ + id: p1.toString(), + elo: 100, + }) + p1elo = await getUserElo.get({ id: p1 }) + } + if (!p2elo) { + await insertElos.run({ + id: p2.toString(), + elo: 100, + }) + p2elo = await getUserElo.get({ id: p2 }) + } + + if (p1score === p2score) { + insertGame.run({ + id: p1.toString() + '-' + p2.toString() + '-' + Date.now().toString(), + p1: p1, + p2: p2, + p1_score: p1score, + p2_score: p2score, + p1_elo: p1elo.elo, + p2_elo: p2elo.elo, + p1_new_elo: p1elo.elo, + p2_new_elo: p2elo.elo, + type: type, + timestamp: Date.now(), + }) + return + } + + let diff = 5; + + if (p1elo.elo > p2elo.elo) { + if (p1score > p2score) { + diff = Math.max(Math.floor(5 * (p2elo.elo/p1elo.elo)), 1) + } else { + diff = Math.max(Math.floor(5 * (1 + (p2elo.elo/p1elo.elo))), 1) + } + } else if (p1elo.elo < p2elo.elo) { + if (p1score < p2score) { + diff = Math.max(Math.floor(5 * (p1elo.elo/p2elo.elo)), 1) + } else { + diff = Math.max(Math.floor(5 * (1 + (p1elo.elo/p2elo.elo))), 1) + } + } + const p1newElo = Math.max(p1elo.elo + (p1score > p2score ? diff : -diff), 0) + const p2newElo = Math.max(p2elo.elo + (p1score > p2score ? -diff : diff), 0) + console.log(`${p1} elo update : ${p1elo.elo} -> ${p1newElo}`) + console.log(`${p2} elo update : ${p2elo.elo} -> ${p2newElo}`) + updateElo.run({ id: p1, elo: p1newElo }) + updateElo.run({ id: p2, elo: p2newElo }) + + insertGame.run({ + id: p1.toString() + '-' + p2.toString() + '-' + Date.now().toString(), + p1: p1, + p2: p2, + p1_score: p1score, + p2_score: p2score, + p1_elo: p1elo.elo, + p2_elo: p2elo.elo, + p1_new_elo: p1newElo, + p2_new_elo: p2newElo, + type: type, + timestamp: Date.now(), + }) } \ No newline at end of file diff --git a/index.js b/index.js index 25d8e34..e5edff1 100644 --- a/index.js +++ b/index.js @@ -18,7 +18,7 @@ import { getAPOUsers, postAPOBuy } from './utils.js'; -import { channelPointsHandler, slowmodesHandler } from './game.js'; +import {channelPointsHandler, eloHandler, slowmodesHandler} from './game.js'; import { Client, GatewayIntentBits, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js'; import cron from 'node-cron'; import Database from "better-sqlite3"; @@ -42,7 +42,7 @@ import { getUserInventory, getTopSkins, updateUserCoins, insertLog, stmtLogs, - getLogs, getUserLogs, + getLogs, getUserLogs, getUserElo, getUserGames, } from './init_database.js'; import { getValorantSkins, getSkinTiers } from './valo.js'; import {sleep} from "openai/core"; @@ -573,6 +573,20 @@ client.on('messageCreate', async (message) => { }) }); } + else if (message.content.startsWith('flopo:sql')) { + let sqlCommand = message.content.replace('flopo:sql ', '') + try { + if (sqlCommand.startsWith('SELECT')) { + const stmt = flopoDB.prepare(`${sqlCommand}`).all(); + console.log(stmt) + } else { + const stmt = flopoDB.prepare(`${sqlCommand}`).run(); + console.log(stmt) + } + } catch (e) { + console.log(e) + } + } } } }); @@ -2673,6 +2687,54 @@ app.get('/user/:id/sparkline', async (req, res) => { } }) +app.get('/user/:id/elo', async (req, res) => { + try { + const userId = req.params.id + + const user = getUser.get(userId) + + if (!user) return res.status(404).send({ message: 'Utilisateur introuvable'}) + + const userElo = getUserElo.get({ id: userId }) + + if (!userElo) return res.status(200).json({ elo: null }) + + return res.status(200).json({ elo: userElo.elo }) + } catch (e) { + return res.status(500).send({ message: 'erreur'}) + } +}) + +app.get('/user/:id/elo-graph', async (req, res) => { + try { + const userId = req.params.id + + const user = getUser.get(userId) + + if (!user) return res.status(404).send({ message: 'Utilisateur introuvable'}) + + + const games = getUserGames.all({ user_id: userId }); + + if (!games) return res.status(404).send({ message: 'Aucune partie'}) + + let array = [] + games.forEach((game, index) => { + if (game.p1 === userId) { + array.push(game.p1_elo) + if (index === games.length - 1) array.push(game.p1_new_elo) + } else if (game.p2 === userId) { + array.push(game.p2_elo) + if (index === games.length - 1) array.push(game.p2_new_elo) + } + }) + + return res.status(200).json({ elo_graph: array }) + } catch (e) { + return res.status(500).send({ message: 'erreur'}) + } +}) + // Get user's inventory app.get('/user/:id/inventory', async (req, res) => { try { @@ -3394,7 +3456,10 @@ io.on('connection', (socket) => { socket.on('tictactoequeue', async (e) => { console.log(`tictactoequeue: ${e.playerId}`); - queue.push(e.playerId) + + if (!queue.find(obj => obj === e.playerId)) { + queue.push(e.playerId) + } if (queue.length >= 2) { let p1 = await client.users.fetch(queue[0]) @@ -3459,7 +3524,16 @@ io.on('connection', (socket) => { io.emit('tictactoeplaying', { allPlayers: playingArray }) }) - socket.on('tictactoegameOver', (e) => { + socket.on('tictactoegameOver', async (e) => { + const winner = e.winner + const game = playingArray.find(obj => obj.p1.id === e.playerId) + if (game) { + if (winner === null) { + await eloHandler(game.p1.id, game.p2.id, 0, 0, 'TICTACTOE') + } else { + await eloHandler(game.p1.id, game.p2.id, game.p1.id === winner ? 1 : 0, game.p2.id === winner ? 1 : 0, 'TICTACTOE') + } + } playingArray = playingArray.filter(obj => obj.p1.id !== e.playerId) }) }); diff --git a/init_database.js b/init_database.js index 19515ea..9904ff5 100644 --- a/init_database.js +++ b/init_database.js @@ -78,4 +78,40 @@ stmtLogs.run() export const insertLog = flopoDB.prepare('INSERT INTO logs (id, user_id, action, target_user_id, coins_amount, user_new_amount) VALUES (@id, @user_id, @action, @target_user_id, @coins_amount, @user_new_amount)'); export const getLogs = flopoDB.prepare('SELECT * FROM logs'); -export const getUserLogs = flopoDB.prepare('SELECT * FROM logs WHERE user_id = @user_id'); \ No newline at end of file +export const getUserLogs = flopoDB.prepare('SELECT * FROM logs WHERE user_id = @user_id'); + + +export const stmtGames = flopoDB.prepare(` + CREATE TABLE IF NOT EXISTS games ( + id PRIMARY KEY, + p1 TEXT REFERENCES users, + p2 TEXT REFERENCES users, + p1_score INTEGER, + p2_score INTEGER, + p1_elo INTEGER, + p2_elo INTEGER, + p1_new_elo INTEGER, + p2_new_elo INTEGER, + type TEXT, + timestamp TIMESTAMP + ) +`); +stmtGames.run() + +export const insertGame = flopoDB.prepare('INSERT INTO games (id, p1, p2, p1_score, p2_score, p1_elo, p2_elo, p1_new_elo, p2_new_elo, type, timestamp) VALUES (@id, @p1, @p2, @p1_score, @p2_score, @p1_elo, @p2_elo, @p1_new_elo, @p2_new_elo, @type, @timestamp)'); +export const getGames = flopoDB.prepare('SELECT * FROM games'); +export const getUserGames = flopoDB.prepare('SELECT * FROM games WHERE p1 = @user_id OR p2 = @user_id'); + + +export const stmtElos = flopoDB.prepare(` + CREATE TABLE IF NOT EXISTS elos ( + id PRIMARY KEY REFERENCES users, + elo INTEGER + ) +`); +stmtElos.run() + +export const insertElos = flopoDB.prepare(`INSERT INTO elos (id, elo) VALUES (@id, @elo)`); +export const getElos = flopoDB.prepare(`SELECT * FROM elos`); +export const getUserElo = flopoDB.prepare(`SELECT * FROM elos WHERE id = @id`); +export const updateElo = flopoDB.prepare('UPDATE elos SET elo = @elo WHERE id = @id') \ No newline at end of file