From: Daigo Moriwaki Date: Sat, 7 Dec 2013 09:50:19 +0000 (+0900) Subject: Simplify estimated rate of unrated players (less memory). X-Git-Tag: 20170902~37^2~4 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=f8dc7d8ab76bf939f4dee30b401cbb2ec1f19ff9;hp=13a823aebe192a11f1feaad5bb0600d2b637c32a;p=shogi-server%2Fshogi-server.git Simplify estimated rate of unrated players (less memory). * [shogi-server] - pairing.rb, player.rb: Simplify estimated rate of unrated players (less memory). --- diff --git a/changelog b/changelog index 1790cf0..109f434 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,9 @@ +2013-12-07 Daigo Moriwaki + + * [shogi-server] + - shogi_server/pairing.rb, player.rb: + Simplify estimated rate of unrated players (less memory). + 2013-12-05 Daigo Moriwaki * [shogi-server] diff --git a/shogi_server/pairing.rb b/shogi_server/pairing.rb index 7d70cbb..6d62891 100644 --- a/shogi_server/pairing.rb +++ b/shogi_server/pairing.rb @@ -396,43 +396,74 @@ module ShogiServer players.shuffle end - # Returns a player's rate value. + # Update estimated rate of a player. # 1. If it has a valid rate, return the rate. - # 2. If it has no valid rate, return average of the following values: - # a. For games it won, the opponent's rate + 100 - # b. For games it lost, the opponent's rate - 100 - # (if the opponent has no valid rate, count out the game) - # (if there are not such games, return 2150 (default value) + # 2. If it has no valid rate, return: + # a. If it won the last game, the opponent's rate + 200 + # b. If it lost the last game, the opponent's rate - 200 + # c. otherwise, return 2150 (default value) # - def get_player_rate(player, history) - return player.rate if player.rate != 0 - return 2150 unless history - - count = 0 - sum = 0 - - history.win_games(player.player_id).each do |g| - next unless g[:loser] - name = g[:loser].split("+")[0] - p = $league.find(name) - if p && p.rate != 0 - count += 1 - sum += p.rate + 100 - end + def estimate_rate(player, history) + player.estimated_rate = 2150 # default value + + unless history + log_message("Floodgate: Without game history, estimated %s's rate: %d" % [player.name, player.estimated_rate]) + return end - history.loss_games(player.player_id).each do |g| - next unless g[:winner] - name = g[:winner].split("+")[0] - p = $league.find(name) - if p && p.rate != 0 - count += 1 - sum += p.rate - 100 - end + + g = history.last_valid_game(player.player_id) + unless g + log_message("Floodgate: Without any valid games in history, estimated %s's rate: %d" % [player.name, player.estimated_rate]) + return end - estimate = (count == 0 ? 2150 : sum/count) - log_message("Floodgate: Estimated rate of %s is %d" % [player.name, estimate]) - return estimate + opponent_id = nil + win = true + case player.player_id + when g[:winner] + opponent_id = g[:loser] + win = true + when g[:loser] + opponent_id = g[:winner] + win = false + else + log_warning("Floodgate: The last valid game is invalid for %s!" % [player.name]) + log_message("Floodgate: Estimated %s's rate: %d" % [player.name, player.estimated_rate]) + return + end + + opponent_name = opponent_id.split("+")[0] + p = $league.find(opponent_name) + unless p + log_message("Floodgate: No active opponent found. Estimated %s's rate: %d" % [player.name, player.estimated_rate]) + return + end + + opponent_rate = 0 + if p.rate != 0 + opponent_rate = p.rate + elsif p.estimated_rate != 0 + opponent_rate = p.estimated_rate + end + + if opponent_rate != 0 + player.estimated_rate = opponent_rate + (win ? 200 : -200) + end + + log_message("Floodgate: Estimated %s's rate: %d" % [player.name, player.estimated_rate]) + end + + # Return a player's rate based on its actual rate or estimated rate. + # + def get_player_rate(player, history) + if player.rate != 0 + return player.rate + elsif player.estimated_rate != 0 + return player.estimated_rate + else + estimate_rate(player, history) + return player.estimated_rate + end end def calculate_diff_with_penalty(players, history) @@ -475,6 +506,9 @@ module ShogiServer return players end + # Reset estimated rate + players.each {|p| p.estimated_rate = 0} + # 10 trials matches = [] scores = [] diff --git a/shogi_server/player.rb b/shogi_server/player.rb index b6b60f5..471119b 100644 --- a/shogi_server/player.rb +++ b/shogi_server/player.rb @@ -27,6 +27,7 @@ class BasicPlayer @name = nil @password = nil @rate = 0 + @estimated_rate = 0 @win = 0 @loss = 0 @last_game_win = false @@ -48,6 +49,10 @@ class BasicPlayer # Score in the rating sysem attr_accessor :rate + # Estimated rate for unrated player (rate == 0) + # But this value is not persisted and cleared when player logs off. + attr_accessor :estimated_rate + # Number of games for win and loss in the rating system attr_accessor :win, :loss diff --git a/test/TC_pairing.rb b/test/TC_pairing.rb index d9871e3..30f353e 100644 --- a/test/TC_pairing.rb +++ b/test/TC_pairing.rb @@ -551,6 +551,7 @@ class TestLeastDiff < Test::Unit::TestCase def test_get_player_rate_0 assert_equal(2150, @pairing.get_player_rate(@x, @history)) + @x.estimated_rate = 0 dummy = nil def @history.make_record(game_result) {:game_id => "wdoor+floodgate-900-0-x-a-1", @@ -558,8 +559,9 @@ class TestLeastDiff < Test::Unit::TestCase :winner => "x", :loser => "a"} end @history.update(dummy) - assert_equal(@a.rate+100, @pairing.get_player_rate(@x, @history)) + assert_equal(@a.rate+200, @pairing.get_player_rate(@x, @history)) + @x.estimated_rate = 0 def @history.make_record(game_result) {:game_id => "wdoor+floodgate-900-0-x-b-1", :black => "x", :white => "b", @@ -567,7 +569,7 @@ class TestLeastDiff < Test::Unit::TestCase end @history.update(dummy) - assert_equal((@a.rate+100+@b.rate-100)/2, @pairing.get_player_rate(@x, @history)) + assert_equal(@b.rate-200, @pairing.get_player_rate(@x, @history)) end end