Skip to content

Commit

Permalink
Complete endpoints using OpenSkill! Thanks chatgpt4
Browse files Browse the repository at this point in the history
  • Loading branch information
geneotech committed Jan 14, 2024
1 parent 1b4d3b2 commit fd9b311
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 39 deletions.
8 changes: 5 additions & 3 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ if (!fs.existsSync(dbPath)) {
db.serialize(() => {
db.run(`
CREATE TABLE IF NOT EXISTS players (
id INTEGER PRIMARY KEY AUTOINCREMENT,
steam_id TEXT UNIQUE,
mmr INTEGER DEFAULT 0,
account_id TEXT UNIQUE,
nickname TEXT,
mmr FLOAT DEFAULT 0,
mu FLOAT DEFAULT 0,
sigma FLOAT DEFAULT 0,
matches_won INTEGER DEFAULT 0,
matches_lost INTEGER DEFAULT 0
)
Expand Down
7 changes: 5 additions & 2 deletions src/leaderboards.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ router.get('/', (req, res) => {
const db = new sqlite3.Database(dbPath);

// Fetch all players and their match counts
db.all('SELECT steam_id, mmr, matches_won, matches_lost FROM players', (err, rows) => {
db.all('SELECT account_id, mmr, mu, sigma, matches_won, matches_lost, nickname FROM players', (err, rows) => {
if (err) {
console.error(err.message);
return res.status(500).json({ error: 'Internal Server Error' });
Expand All @@ -22,8 +22,11 @@ router.get('/', (req, res) => {

// Create a JSON response with players and match counts
const leaderboards = rows.map((row) => ({
steam_id: row.steam_id,
account_id: row.account_id,
nickname: row.nickname,
mmr: row.mmr,
mu: row.mu,
sigma: row.sigma,
matches_won: row.matches_won,
matches_lost: row.matches_lost
}));
Expand Down
72 changes: 40 additions & 32 deletions src/report_match.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,74 @@
const express = require('express');
const sqlite3 = require('sqlite3').verbose();
const Database = require('better-sqlite3');
const { rating, rate, ordinal } = require('openskill');

const router = express.Router();
const dbPath = process.env.DB_PATH;

// Middleware for API key authentication
function apiKeyAuth(req, res, next) {
const apiKey = req.headers["apikey"];

// Check if the API key is valid (replace 'your-api-key' with the actual API key)
if (apiKey && apiKey === process.env.REPORT_MATCH_APIKEY) {
return next();
} else {
return res.status(401).json({ error: 'Unauthorized' });
}
}

router.post('/', apiKeyAuth, async (req, res) => {
router.post('/', apiKeyAuth, (req, res) => {
res.setHeader('Content-Type', 'application/json; charset=utf-8');

const { win_score, lose_score, win_players, lose_players } = req.body;
const { win_score, lose_score, win_players, lose_players, nicknames } = req.body;

// Validate input
if (!win_score || !lose_score || !win_players || !lose_players) {
if (!win_score || !lose_score || !win_players || !lose_players || !nicknames) {
return res.status(400).json({ error: 'Invalid input format' });
}

try {
const db = new sqlite3.Database(dbPath);
const db = new Database(dbPath);

// Start a transaction to handle multiple queries
db.serialize(() => {
const stmtInsertPlayer = db.prepare('INSERT OR IGNORE INTO players (steam_id) VALUES (?)');
const stmtUpdateMatchesWon = db.prepare('UPDATE players SET matches_won = matches_won + 1 WHERE steam_id = ?');
const stmtUpdateMatchesLost = db.prepare('UPDATE players SET matches_lost = matches_lost + 1 WHERE steam_id = ?');
db.transaction(() => {
const allPlayers = win_players.concat(lose_players);
const playerRatings = {};
const default_rating = rating();
const stmt_insert_player = db.prepare('INSERT OR IGNORE INTO players (account_id, mu, sigma) VALUES (?, ?, ?)');
const stmt_get_player = db.prepare('SELECT mu, sigma FROM players WHERE account_id = ?');
const stmt_update_player = db.prepare('UPDATE players SET mu = ?, sigma = ?, mmr = ?, matches_won = matches_won + ?, matches_lost = matches_lost + ?, nickname = ? WHERE account_id = ?');

// Process win players
win_players.forEach((player) => {
// Insert the player if not already exists
stmtInsertPlayer.run(player);
// Insert player entries if they do not exist
allPlayers.forEach(playerId => {
stmt_insert_player.run(playerId, default_rating.mu, default_rating.sigma);
});

// Increment matches_won for the player
stmtUpdateMatchesWon.run(player);
// Read current ratings from the database
allPlayers.forEach(playerId => {
const row = stmt_get_player.get(playerId);
playerRatings[playerId] = rating({ mu: row.mu, sigma: row.sigma });
});

// Process lose players
lose_players.forEach((player) => {
// Insert the player if not already exists
stmtInsertPlayer.run(player);
// Calculate new ratings
const winners = win_players.map(playerId => playerRatings[playerId]);
const losers = lose_players.map(playerId => playerRatings[playerId]);
const updatedRatings = rate([winners, losers]);

// Increment matches_lost for the player
stmtUpdateMatchesLost.run(player);
});
// Update players in the database with new ratings
updatedRatings.forEach((team, index) => {
team.forEach((playerRating, playerIndex) => {
const playerId = index === 0 ? win_players[playerIndex] : lose_players[playerIndex];
const winIncrement = index === 0 ? 1 : 0;
const lossIncrement = index === 1 ? 1 : 0;
const mmr = ordinal(playerRating);
const new_nickname = nicknames[playerId];

// Finalize the statements
stmtInsertPlayer.finalize();
stmtUpdateMatchesWon.finalize();
stmtUpdateMatchesLost.finalize();
});
stmt_update_player.run(playerRating.mu, playerRating.sigma, mmr, winIncrement, lossIncrement, new_nickname, playerId);
});
});
})(); // Execute the transaction

return res.status(200).json({ success: true });
} catch (error) {
res.json({ message: 'Match reported successfully' });
}
catch (error) {
console.error(error.message);
return res.status(500).json({ error: 'Internal Server Error' });
}
Expand Down
8 changes: 6 additions & 2 deletions views/leaderboards.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@
<table class="sortable">
<thead>
<tr>
<th>Steam ID</th>
<th>Nickname</th>
<th>MMR</th>
<th>Mu</th>
<th>Sigma</th>
<th>Matches Won</th>
<th>Matches Lost</th>
</tr>
</thead>
<tbody>
<% leaderboards.forEach(i => { %>
<tr>
<td><%= i.steam_id %></td>
<td><%= i.nickname %></td>
<td><%= i.mmr %></td>
<td><%= i.mu %></td>
<td><%= i.sigma %></td>
<td><%= i.matches_won %></td>
<td><%= i.matches_lost %></td>
</tr>
Expand Down

0 comments on commit fd9b311

Please sign in to comment.