second commit

This commit is contained in:
MrKritio 2024-08-17 01:44:20 +02:00
parent 3f86ab488e
commit 0d055b2ce5
6 changed files with 245 additions and 158 deletions

View File

@ -1,35 +0,0 @@
// database.js
const mysql = require('mysql2/promise');
const dbConfig = {
host: "95.217.113.161",
user: "Likima",
password: "27As$r0q1",
database: "jedaiito",
charset: "utf8"
};
const pool = mysql.createPool({
...dbConfig,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
async function updatePlayerElo(player) {
const connection = await pool.getConnection();
try {
const updateQuery = `
UPDATE players
SET elo = ?
WHERE guid = ?
`;
await connection.query(updateQuery, [player.elo, player.guid]);
} finally {
connection.release();
}
}
module.exports = {
updatePlayerElo,
};

10
elo.js
View File

@ -1,10 +0,0 @@
// elo.js
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;
}
module.exports = {
calculateElo,
};

View File

@ -1,54 +0,0 @@
// events.js
const events = require('events');
const { calculateElo } = require('./elo');
const { updatePlayerElo } = require('./database');
class GameEventEmitter extends events.EventEmitter {}
const gameEventEmitter = new GameEventEmitter();
function handleRoundEnd(redScore, blueScore, playerScores, currentPlayers) {
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;
winningPlayers.forEach(async (player) => {
const individualPerformanceFactor = playerScores[player.id] / redScore; // Adjust based on individual contribution
player.elo = calculateElo(player.elo, averageLosingElo, 1 * individualPerformanceFactor, kFactor);
await updatePlayerElo(player);
});
losingPlayers.forEach(async (player) => {
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.");
}
gameEventEmitter.on('RoundEnd', handleRoundEnd);
module.exports = {
gameEventEmitter,
handleRoundEnd,
};

257
main.js
View File

@ -1,46 +1,229 @@
// main.js
const { spawn } = require('child_process');
const { gameEventEmitter } = require('./events');
const { Player } = require('./player');
const mysql = require('mysql2/promise');
const WebSocket = require('ws');
const axios = require('axios');
const events = require('events');
let currentPlayers = [];
let playerScores = {};
// Database configuration
const dbConfig = {
host: "95.217.113.161",
user: "Likima",
password: "27As$r0q1",
database: "jedaiito",
charset: "utf8"
};
function runCommand(command) {
const p = spawn('sh', ['-c', command], { stdio: 'pipe' });
// Create a MySQL connection pool
const pool = mysql.createPool({
...dbConfig,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
p.stderr.on('data', (data) => {
const line = data.toString().trim();
console.log(">>> " + line);
// 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;
}
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, currentPlayers);
playerScores = {}; // Reset playerScores after round end
} 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(' ');
// 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;
}
}
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}`);
// 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'
}
}
});
if (checkLine(line)) {
// Additional event handling can go here
gameEventEmitter.emit('SomeOtherEvent', line);
}
});
const { data } = response;
return data.data.token;
} catch (error) {
console.error('Error requesting new token:', error);
throw error;
}
}
p.on('close', (code) => {
console.log(`Process exited with code ${code}`);
});
// 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) {
@ -55,5 +238,5 @@ function checkLine(line) {
return false;
}
// Running the game command
runCommand("sh start.sh");
// Start the WebSocket connection
startWebSocketConnection();

25
package.json Normal file
View File

@ -0,0 +1,25 @@
{
"name": "game-server-management",
"version": "1.0.0",
"description": "A Node.js application for managing game server events and player Elo ratings.",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"axios": "^1.4.0",
"events": "^3.3.0",
"mysql2": "^3.1.0",
"ws": "^8.12.0"
},
"keywords": [
"game",
"server",
"elo",
"websocket",
"mysql"
],
"author": "Your Name",
"license": "MIT"
}

View File

@ -1,22 +0,0 @@
// player.js
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;
}
}
function removeColorCodes(name) {
return name.replace(/\^\d/g, '');
}
module.exports = {
Player,
removeColorCodes,
};