const mysql = require('mysql2/promise'); const WebSocket = require('ws'); const axios = require('axios'); const events = require('events'); // Database configuration const dbConfig = { host: "95.217.113.161", user: "Likima", password: "27As$r0q1", database: "jedaiito", charset: "utf8" }; // Create a MySQL connection pool const pool = mysql.createPool({ ...dbConfig, waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); // Elo Rating Calculation function calculateElo(currentRating, opponentRating, actualScore, kFactor = 32) { const expectedScore = 1 / (1 + Math.pow(10, (opponentRating - currentRating) / 400)); const newRating = currentRating + kFactor * (actualScore - expectedScore); return newRating; } // Simplified Player class class Player { constructor(id, ip, name, guid, elo = 1000, score = 0, team = '') { this.id = id; this.ip = ip; this.name = name; this.guid = guid; this.elo = elo; this.score = score; this.team = team; this.is_alive = true; } } // Utility function to remove color codes function removeColorCodes(name) { return name.replace(/\^\d/g, ''); } // Update Elo ratings in the database async function updatePlayerElo(player) { const connection = await pool.getConnection(); try { const updateQuery = ` UPDATE jedaii_comp SET elo = ? WHERE guid = ? `; await connection.query(updateQuery, [player.elo, player.guid]); } finally { connection.release(); } } // Event handling class GameEventEmitter extends events.EventEmitter {} const gameEventEmitter = new GameEventEmitter(); // Player lists const currentPlayers = []; const playerQueue = []; // Handle round end event gameEventEmitter.on('RoundEnd', async (redScore, blueScore, playerScores) => { console.log(`Round ended. Red: ${redScore}, Blue: ${blueScore}`); let winningTeam, losingTeam; if (redScore > blueScore) { winningTeam = 'red'; losingTeam = 'blue'; } else if (blueScore > redScore) { winningTeam = 'blue'; losingTeam = 'red'; } else { console.log("It's a draw. No Elo change."); return; } const kFactor = 32; // You can adjust this as needed const winningPlayers = currentPlayers.filter(player => player.team === winningTeam); const losingPlayers = currentPlayers.filter(player => player.team === losingTeam); const averageWinningElo = winningPlayers.reduce((acc, player) => acc + player.elo, 0) / winningPlayers.length; const averageLosingElo = losingPlayers.reduce((acc, player) => acc + player.elo, 0) / losingPlayers.length; for (const player of winningPlayers) { const individualPerformanceFactor = playerScores[player.id] / redScore; // Adjust based on individual contribution player.elo = calculateElo(player.elo, averageLosingElo, 1 * individualPerformanceFactor, kFactor); await updatePlayerElo(player); } for (const player of losingPlayers) { const individualPerformanceFactor = playerScores[player.id] / blueScore; // Adjust based on individual contribution player.elo = calculateElo(player.elo, averageWinningElo, 0 * individualPerformanceFactor, kFactor); await updatePlayerElo(player); } console.log("Elo ratings updated."); }); // Function to request a new token async function requestNewToken() { const API_URL = 'https://panel.pineriver.net/api/client/servers/68f7edce/websocket'; // Corrected API endpoint const API_KEY = 'Bearer ptlc_uohTuXbtbTmVaSAhwtD16R2oDynhQgTWBZKN2m5lWdh'; // Your actual API key try { const response = await axios.get(API_URL, { headers: { 'Authorization': API_KEY, 'Accept': 'application/json', 'Content-Type': 'application/json' } }); const { data } = response; return data.data.token; } catch (error) { console.error('Error requesting new token:', error); throw error; } } // Main function to start WebSocket connection and handle console output async function startWebSocketConnection() { try { const API_URL = 'https://panel.pineriver.net/api/client/servers/68f7edce/websocket'; const API_KEY = 'Bearer ptlc_uohTuXbtbTmVaSAhwtD16R2oDynhQgTWBZKN2m5lWdh'; // Request the token and WebSocket URL const response = await axios.get(API_URL, { headers: { 'Authorization': API_KEY, 'Accept': 'application/json', 'Content-Type': 'application/json' } }); const { token, socket } = response.data.data; // Create WebSocket connection const ws = new WebSocket(socket); ws.on('open', () => { ws.send(JSON.stringify({ event: 'auth', args: [token] })); console.log('WebSocket connection established and authenticated'); }); ws.on('message', async (message) => { const parsedMessage = JSON.parse(message); if (parsedMessage.event === 'console output') { const consoleOutput = parsedMessage.args[0]; handleConsoleOutput(consoleOutput); } if (parsedMessage.event === 'token expiring') { console.log('Token is expiring soon, requesting a new token...'); const newToken = await requestNewToken(); ws.send(JSON.stringify({ event: 'auth', args: [newToken] })); console.log('WebSocket re-authenticated with new token'); } if (parsedMessage.event === 'token expired') { console.log('Token has expired, reconnecting with a new token...'); ws.close(); // Close the current WebSocket connection startWebSocketConnection(); // Start a new WebSocket connection } }); ws.on('close', () => { console.log('WebSocket connection closed'); }); ws.on('error', (error) => { console.error('WebSocket error:', error); }); } catch (error) { console.error('Error starting WebSocket connection:', error); } } // Handle console output received via WebSocket function handleConsoleOutput(line) { const playerScores = {}; if (line.startsWith('>>> red:') && line.includes(' blue:')) { const redScore = parseInt(line.split('red:')[1].split(' ')[0]); const blueScore = parseInt(line.split('blue:')[1]); gameEventEmitter.emit('RoundEnd', redScore, blueScore, playerScores); } else if (line.startsWith('>>> score:')) { const parts = line.split(' '); const score = parseInt(parts[2]); const clientId = parseInt(parts[6]); const playerName = parts.slice(7).join(' '); const player = currentPlayers.find(p => p.id === clientId); if (player) { player.score = score; playerScores[clientId] = score; console.log(`Player ${playerName} (ID: ${clientId}) has a score of ${score}`); } } if (checkLine(line)) { // Additional event handling can go here gameEventEmitter.emit('SomeOtherEvent', line); } } function checkLine(line) { if (line.startsWith("Pl")) return true; if (line.startsWith("Shut")) return true; if (line.startsWith("ClientConne")) return true; if (line.startsWith("ClientDisconn")) return true; if (line.startsWith("Kill")) return true; if (line.includes("say:")) return true; if (line.startsWith("ClientUser")) return true; if (line.startsWith("broadcast")) return true; return false; } // Start the WebSocket connection startWebSocketConnection();