nextjs-rewrite (#5)

Reviewed-on: #5
Co-authored-by: David Gwilliam <dhgwilliam@gmail.com>
Co-committed-by: David Gwilliam <dhgwilliam@gmail.com>
This commit was merged in pull request #5.
This commit is contained in:
2026-03-30 02:30:13 +00:00
committed by david
parent 1a9b3496e1
commit 123df671f5
160 changed files with 19293 additions and 1180 deletions
+152
View File
@@ -0,0 +1,152 @@
/**
* Elo Rating Utilities
*
* Provides functions for calculating Elo ratings and changes
* Based on the standard Elo rating system
*/
/**
* Calculate the expected score for a player based on rating difference
* @param ratingA Player A's rating
* @param ratingB Player B's rating
* @returns Expected score (0-1) for Player A
*/
export function calculateExpectedScore(ratingA: number, ratingB: number): number {
const ratingDiff = ratingA - ratingB;
return 1 / (1 + Math.pow(10, -ratingDiff / 400));
}
/**
* Calculate Elo rating change for a single game
* @param rating Player's current rating
* @param opponentRating Opponent's rating
* @param actualScore Actual score (1 = win, 0.5 = draw, 0 = loss)
* @param kFactor K-factor (how much ratings change per game)
* @returns Elo rating change (positive or negative)
*/
export function calculateEloChange(
rating: number,
opponentRating: number,
actualScore: number,
kFactor: number = 32
): number {
const expectedScore = calculateExpectedScore(rating, opponentRating);
return kFactor * (actualScore - expectedScore);
}
/**
* Calculate team Elo rating as average of individual ratings
* @param rating1 Rating of player 1
* @param rating2 Rating of player 2
* @returns Team rating
*/
export function calculateTeamElo(rating1: number, rating2: number): number {
return (rating1 + rating2) / 2;
}
/**
* Update player statistics after a match
* @param currentRating Current player rating
* @param currentGamesPlayed Current games played count
* @param currentWins Current wins count
* @param eloChange Elo rating change
* @param won Whether the player won
* @returns Updated statistics
*/
export function updatePlayerStats(
currentRating: number,
currentGamesPlayed: number,
currentWins: number,
eloChange: number,
won: boolean
): {
newRating: number;
newGamesPlayed: number;
newWins: number;
newLosses: number;
winRate: number;
} {
const newRating = currentRating + Math.round(eloChange);
const newGamesPlayed = currentGamesPlayed + 1;
const newWins = currentWins + (won ? 1 : 0);
const newLosses = newGamesPlayed - newWins;
const winRate = newGamesPlayed > 0 ? newWins / newGamesPlayed : 0;
return {
newRating,
newGamesPlayed,
newWins,
newLosses,
winRate,
};
}
/**
* Calculate new rating after a match
* @param currentRating Current rating
* @param opponentRating Opponent's rating
* @param won Whether the player won
* @param kFactor K-factor (default 32)
* @returns New rating
*/
export function calculateNewRating(
currentRating: number,
opponentRating: number,
won: boolean,
kFactor: number = 32
): number {
const actualScore = won ? 1 : 0;
const eloChange = calculateEloChange(currentRating, opponentRating, actualScore, kFactor);
return Math.round(currentRating + eloChange);
}
/**
* Validate rating is within reasonable bounds
* @param rating Rating to validate
* @returns Whether the rating is valid
*/
export function isValidRating(rating: number): boolean {
return rating >= 100 && rating <= 3000;
}
/**
* Get rating tier name based on rating
* @param rating Player rating
* @returns Tier name
*/
export function getRatingTier(rating: number): string {
if (rating < 1100) return 'Beginner';
if (rating < 1300) return 'Novice';
if (rating < 1500) return 'Intermediate';
if (rating < 1700) return 'Advanced';
if (rating < 1900) return 'Expert';
if (rating < 2100) return 'Master';
return 'Grandmaster';
}
/**
* Calculate expected score for a team match
* @param team1Rating Average rating of team 1
* @param team2Rating Average rating of team 2
* @returns Expected score for team 1
*/
export function calculateExpectedTeamScore(team1Rating: number, team2Rating: number): number {
return calculateExpectedScore(team1Rating, team2Rating);
}
/**
* Calculate Elo change for team match
* @param team1Rating Average rating of team 1
* @param team2Rating Average rating of team 2
* @param team1Score Actual score for team 1 (1 = win, 0.5 = draw, 0 = loss)
* @param kFactor K-factor (default 32)
* @returns Elo change for team 1
*/
export function calculateTeamEloChange(
team1Rating: number,
team2Rating: number,
team1Score: number,
kFactor: number = 32
): number {
return calculateEloChange(team1Rating, team2Rating, team1Score, kFactor);
}