Last active
January 19, 2016 12:47
-
-
Save shawn-simon/d01c1433a96841c8fe06 to your computer and use it in GitHub Desktop.
Dota MMR simulator
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
'use strict' | |
// to run- install node.js, save this to a folder, and then run: | |
// npm install median | |
// node dota.js | |
let median = require('median'); | |
// defaults (change these to fit your taste) | |
let start_mmr = 4400; | |
let final_mmr = 5000; | |
let true_mmr = 5100; | |
const simulation_count = 10000; | |
const max_games_to_play = 2000; // max games to play before giving up on reaching an mmr | |
const game_ruiner_rate = .02; // percentage of players who are intentional feeders & griefers, abandoners. | |
const avg_player_variance_mmr = 800; // amount of variance in a players mmr, from game to game (due to picks, smurfs, account buyers, drunk people); | |
const player_variance_mmr = 100; // your variance in mmr from game to game. (+/-n) | |
function play_game(true_mmr, current_mmr) { | |
let enemy_score = 0; | |
for (let i = 0; i < 5; i++) { | |
enemy_score += player_score(current_mmr, avg_player_variance_mmr); | |
} | |
let allied_score = 0; | |
for (let i = 0; i < 4; i++) { | |
allied_score += player_score(current_mmr, avg_player_variance_mmr); | |
} | |
allied_score += player_score(true_mmr, player_variance_mmr, true); | |
if (enemy_score === allied_score) return Math.random() >= .5; | |
else return allied_score > enemy_score; | |
} | |
function player_score(mmr, variance, disable_ruiners) { | |
if (!disable_ruiners && Math.random() < game_ruiner_rate) return 0; | |
let calculated_variance = Math.floor(Math.random() * 2 * variance); | |
mmr = mmr - variance + calculated_variance; | |
return mmr; | |
} | |
function play_games_until_mmr_reached(start_mmr, final_mmr, true_mmr) { | |
let current_mmr = start_mmr; | |
let games_played = 0; | |
let result = { | |
game_count_by_bracket: {} | |
}; | |
while (current_mmr <= final_mmr) { | |
if (games_played >= max_games_to_play) | |
{ | |
result.status = 'max_games_played_reached'; | |
break; | |
} | |
if (current_mmr >= final_mmr) | |
{ | |
result.status = 'mmr_reached'; | |
break; | |
} | |
let bracket = Math.floor(current_mmr / 1000) + 'k'; | |
if (!result.game_count_by_bracket[bracket]) result.game_count_by_bracket[bracket] = 0; | |
result.game_count_by_bracket[bracket]++; | |
let game_result = play_game(true_mmr, current_mmr, game_ruiner_rate) | |
current_mmr += game_result ? 25 : -25; | |
if (current_mmr < 1) current_mmr = 1; | |
games_played++; | |
} | |
result.games_played = games_played; | |
result.mmr = current_mmr; | |
return result; | |
} | |
let min_played = max_games_to_play; | |
let max_played = 0; | |
let games_played_per_simulation = []; | |
for (let i = 0; i < simulation_count; i++) { | |
let result = play_games_until_mmr_reached(start_mmr, final_mmr, true_mmr); | |
games_played_per_simulation.push(result.games_played); | |
if (result.games_played > max_played) max_played = result.games_played; | |
if (result.games_played < min_played) min_played = result.games_played; | |
} | |
let median_played = median(games_played_per_simulation); | |
console.log('** Results **') | |
console.log('Min games played to reach MMR: ' + min_played) | |
console.log('Max games played to reach MMR: ' + max_played) | |
console.log('Median games played to reach MMR: ' + median_played) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment