Skip to content

Instantly share code, notes, and snippets.

@shawn-simon
Last active January 19, 2016 12:47
Show Gist options
  • Save shawn-simon/d01c1433a96841c8fe06 to your computer and use it in GitHub Desktop.
Save shawn-simon/d01c1433a96841c8fe06 to your computer and use it in GitHub Desktop.
Dota MMR simulator
'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