/ Published in: PHP
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
<style> div.perfrating { padding: 10px; background-color: #DDD; border: 1px solid #444; } span.rating_change { display: block; padding: 5px; background-color: light-blue; border: 1px solid blue; } </style> <?php // We need even number of participants to do pairing class player { public $strength; public $rating; public $games; /** * Constructor * * @param int $rating Start rating * @return player */ public function player($rating) { $this->rating = $rating; } /** * Calculate K-factor for player * * @return int K-factor */ public function get_k_factor() { $factor = 25; if ($this->games > 30) { $factor = 22; } if ($this->rating > 1700) { $factor = 20; } if ($this->rating > 1900) { $factor = 15; } if ($this->rating > 2100) { $factor = 10; } return $factor; } } function connect() { $host="localhost"; $login="root"; $pass=""; $dname="elo"; // Create the table in case someone wants to check the script "CREATE TABLE IF NOT EXISTS `deltas` ( `value` decimal(11,4) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8;" ); } function random_pairing($pairs) { // Fail if number of items is odd for($i = 0; $i < $pairs * 2; $i++){ $nums[] = $i; } } function play_game($player1, $player2, &$participants2) { global $players; // Fetch ratings $str1 = $players[$player1]->strength; $str2 = $players[$player2]->strength; // Throw a dice here // $points = rand(1, $rating1 + $rating2); if ($str2 <= $str1) { // player 1 won $winner = $player1; $loser = $player2; } else { $winner = $player2; $loser = $player1; } $participants2[] = $winner; echo '' . $player1 . '[' . $players[$player1]->rating . '] vs ' . $player2 . '[' . $players[$player2]->rating . '], winner is <b>' . $winner . '</b><br/>'; $status = 'normal'; // 5% of games end in draw. // User that go in next tier determined by VP $status = 'draw'; } // Add log record 'player1' => $player1, 'player2' => $player2, 'winner' => $winner, 'loser' => $loser, 'status' => $status ); return $log_record; } function play_tier($participants, &$tourlog) { global $players; // Decide the pairing $subtour = 0; // Second round foreach ($pairs as $player1 => $player2) { $tourlog[] = play_game($participants[$player1], $participants[$player2], $participants2); $subtour++; } return $participants2; } /** * Performance Rating is a hypothetical rating that would result from the games * of a single event only. Some chess organizations use the "algorithm of 400" * to calculate performance rating. According to this algorithm, performance rating * for an event is calculated by taking (1) the rating of each player beaten and * adding 400, (2) the rating of each player lost to and subtracting 400, (3) * the rating of each player drawn, and (4) summing these figures and dividing by * the number of games played. * * @param mixed $tourlog * @param mixed $participants */ function display_performance_rating($tourlog, $participants) { global $players; // echo '<div class="perfrating">'; foreach ($participants as $participant) { $Prating = 0; $games_played = 0; // Process tour logs foreach($tourlog as $tour_record) { if ($tour_record['status'] == 'draw' && ($participant == $tour_record['player1'] || $participant == $tour_record['player2']) ) { if ($participant == $tour_record['player1']) { $Prating += $players[$tour_record['player2']]->rating; } else { $Prating += $players[$tour_record['player1']]->rating; } } elseif ($participant == $tour_record['winner']) { $Prating += $players[$tour_record['loser']]->rating + 400; $games_played++; } elseif($participant == $tour_record['loser']) { $Prating += $players[$tour_record['winner']]->rating - 400; $games_played++; } } // Calculate performance ratings: if ($games_played > 0) { // echo 'PerformanceRating of player ' . $participant . ' on event #'. $tour .' is ' . IntVal($perfRating[$participant]) . '<br/>'; } } foreach ($perfRating as $player => $p_rating) { echo ' PerformanceRating of player ' . $player . ' on event is ' . $p_rating . '<br/>'; } echo '</div>'; } function process_ratings($tourlog) { global $players; // Expected scores // Actual scores // Games played foreach ($tourlog as $tour_record) { // Expected scores $exp[$tour_record['player1']] += 1 / (1 + pow(10, (($players[$tour_record['player2']]->rating - $players[$tour_record['player1']]->rating)/400))); $exp[$tour_record['player2']] += 1 / (1 + pow(10, (($players[$tour_record['player1']]->rating - $players[$tour_record['player2']]->rating)/400))); $games_count[$tour_record['player1']]++; $games_count[$tour_record['player2']]++; if ($tour_record['status'] == 'draw') { $s[$tour_record['player1']] += 0.5; $s[$tour_record['player2']] += 0.5; } elseif ($tour_record['winner'] == $tour_record['player1']) { $s[$tour_record['player1']] += 1; // $s[$tour_record['player2']] -= 1; } else { $s[$tour_record['player2']] += 1; // $s[$tour_record['player1']] = 1; } } // Do calculations only for those in the current log foreach ($participants as $player) { $newrating = round($players[$player]->rating + $players[$player]->get_k_factor() * ($s[$player] - $exp[$player])); echo '<div>Player ' . $player . ' have expected score ' . $exp[$player] . ' and actual ' . $s[$player] . '</div>'; if ($players[$player]->rating != $newrating) { echo '<span class="rating_change">Player ' . $player . ' has rating change from <em class="rating">' . $players[$player]->rating . '</em> to <em class="rating">' . $newrating . '</em> (delta is ' . ($s[$player] - $exp[$player]) .' and k-factor is ' . $players[$player]->get_k_factor() . ')</span>'; "INSERT INTO `elo`.`deltas` ( `value` ) VALUES ( '" . ($s[$player] - $exp[$player]). "' );" ); // New rating $players[$player]->rating = $newrating; $players[$player]->games += $games_count[$player]; } } } // BEGIN global $players; // MYSQL connect(); for ($i = 0; $i <= NUM_PLAYERS; $i++){ $players[$i] = new player(START_RATING); // Beginners rating } for ($tour = 1; $tour <= NUM_TOURNAMENTS; $tour++){ echo '<h3>Tournament '. $tour . '</h3>'; // Choose 20 participants at random $participants = array_combine(range(0,NUM_PARTICIPANTS - 1), array_slice($mob, 0, NUM_PARTICIPANTS)); } else { echo 'Too few players'. exit; } // new log every tournament echo '<h4>Tier 0</h4>'; $participants1 = play_tier($participants, $tourlog); // TIER 1 echo '<h4>Tier 1</h4>'; $participants2 = play_tier($participants1, $tourlog); // TIER 2 echo '<h4>Tier 2</h4>'; $participants3 = play_tier($participants2, $tourlog); // TIER 3 echo '<h4>Tier 3</h4>'; $participants4 = play_tier($participants3, $tourlog); // FINALS echo '<h4>Finals</h4>'; $winner = play_tier($participants4, $tourlog); echo '<span>Tour #' . $tour . ' games are ended, tourlog has ' . count($tourlog) .' records</span>'; // RATINGS CALCULATION display_performance_rating($tourlog, $participants); process_ratings($tourlog); } // arsort($players; echo '<table>'; echo '<tr><th>Player</th><th>Rating</th><th>Strength</th></tr>'; foreach ($players as $playerid => $player) { echo '<tr><td>' . $playerid . '</td><td>' . $player->rating . '</td><td>' . $player->strength . '</td></tr>'; } echo '</table>'; ?>
URL: http://en.wikipedia.org/wiki/Elo_rating_system