This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // For each player simulate the player answering series of questions and observe rating changes | |
| export default function simulateGames( | |
| ratingSystem: RatingSystem, | |
| players: Player[], | |
| questions: Question[], | |
| numQuestionsPerPlayer: number, | |
| ratingRange: number | |
| ): Result[] { | |
| const results: Result[] = [] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Create players | |
| const initialRating = 1000 | |
| const numPlayers = 10 | |
| const playerTiers = 5 | |
| const playerRatingRange = 6000 - initialRating | |
| const playerSegmentSize = Math.floor(numPlayers / playerTiers) | |
| const playerIncrementAmount = Math.floor(playerRatingRange / playerTiers) | |
| const playerGeneration = { | |
| total: numPlayers, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const symmetricRatingSystem = createRatingSystem() | |
| const playerKFactor = 32 | |
| const questionKFactor = 4 | |
| const asymmetricKFactorFn: KFactorFunctionWithPlayers = (rating, playerIndex) => { | |
| let kFactor = playerIndex === 0 | |
| ? playerKFactor | |
| : questionKFactor | |
| if (rating > 6000) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export type KFactorOption = | |
| | KFactorFunctionWithPlayers | |
| | KFactorFunction | |
| | number | |
| export function createRatingSystem(kFactor: KFactorOption = 32, exponentDenominator: number = 400, exponentBase: number = 10): RatingSystem { | |
| let resolvedKFactor: KFactorFunctionWithPlayers | |
| if (typeof kFactor === 'number') { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const { | |
| playerAProbability, | |
| playerBProbability, | |
| nextPlayerARating, | |
| playerARatingDiff, | |
| nextPlayerBRating, | |
| playerBRatingDiff | |
| } = rating.getNextRatings(playerARating, playerBRating, actualScore) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function createNextRatingsFn( | |
| getExpectedPlayerProbabilities: ExpectedProbabilitiesFn, | |
| getNextARating: NextRatingFn, | |
| getNextBRating: NextRatingFn | |
| ): NextRatingsFn { | |
| const nextRatingsFn = (playerARating: number, playerBRating: number, playerAScore: number) => { | |
| const [expectedPlayerAProbability, expectedPlayerBProbability] = getExpectedPlayerProbabilities(playerARating, playerBRating) | |
| const aProbability = playerAScore | |
| const bProbability = 1 - playerAScore |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import createRatingSystem from '@sc2/rating' | |
| // Defaults to K 32, Scale 400, Base 10 | |
| const ratingSystem = createRatingSystem() | |
| // get two players | |
| const playerA = { | |
| id: 'playerA', | |
| rating: 1000, | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export function createRatingSystem(kFactor = 32, exponentDenominator = 400, exponentBase = 10): RatingSystem { | |
| // Standard Elo implementation with symmetric kfactor functions for each player | |
| // This would be a true zero-sum game where A(-x) = B(+x) | |
| const getPlayerProbabilities = createPlayerProbabilitiesFn(exponentBase, exponentDenominator) | |
| const getNextRating = createNextRatingFn(kFactor) | |
| return { | |
| getPlayerProbabilities, | |
| getNextRating | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type NextRatingFn = (rating: number, actualPoints: number, expectedPoints: number) => [nextRating: number, ratingChange: number] | |
| type KFactorFunction = (rating: number) => number | |
| function createNextRatingFn(kFactor: number | KFactorFunction): NextRatingFn { | |
| const kFactorFn: KFactorFunction = typeof kFactor === 'number' | |
| ? () => kFactor | |
| : kFactor | |
| return (rating: number, actualPoints: number, expectedPoints: number): [number, number] => { | |
| const change = Math.round(kFactorFn(rating) * (actualPoints - expectedPoints)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type ExpectedProbabilitiesFn = (playerARating: number, playerBRating: number) => | |
| [ | |
| playerAProbability: number, | |
| playerBProbability: number, | |
| ratingADifference: number, | |
| ratingBDifference: number | |
| ] | |
| function createPlayerProbabilitiesFn(exponentBase: number, exponentDenominator: number): ExpectedProbabilitiesFn { | |
| const expectedPlayerProbabilityFn = createBaseExpectedPlayerProbabilityFn(exponentBase, exponentDenominator) |