From 13a823aebe192a11f1feaad5bb0600d2b637c32a Mon Sep 17 00:00:00 2001 From: Daigo Moriwaki Date: Sun, 24 Nov 2013 22:20:19 +0900 Subject: [PATCH] * [shogi-server] - Added a new pairing method, ShogiServer::ExcludeUnratedPlayers, which filters out unrated players. - Enhanced syntax of Floodgate time configuration file. Now it supports "set pairing_factory "; it sets a factory function name generating a pairing method which will be used in a specific Floodgate game. ex. set pairing_factory floodgate_zyunisen --- changelog | 11 ++++++ shogi_server/league/floodgate.rb | 61 ++++++++++++++++++++++++++++---- shogi_server/league/floodgate_thread.rb | 1 - shogi_server/pairing.rb | 25 +++++++++++-- test/TC_floodgate_next_time_generator.rb | 16 +++++++++ test/TC_pairing.rb | 55 ++++++++++++++++++++++++++++ 6 files changed, 160 insertions(+), 9 deletions(-) diff --git a/changelog b/changelog index b8648e3..1790cf0 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,14 @@ +2013-12-05 Daigo Moriwaki + + * [shogi-server] + - Added a new pairing method, ShogiServer::ExcludeUnratedPlayers, + which filters out unrated players. + - Enhanced syntax of Floodgate time configuration file. + Now it supports "set pairing_factory "; it sets a + factory function name generating a pairing method which will be + used in a specific Floodgate game. + ex. set pairing_factory floodgate_zyunisen + 2013-11-24 Daigo Moriwaki * [shogi-server] diff --git a/shogi_server/league/floodgate.rb b/shogi_server/league/floodgate.rb index b308454..a93d30d 100644 --- a/shogi_server/league/floodgate.rb +++ b/shogi_server/league/floodgate.rb @@ -27,11 +27,13 @@ class League # attr_reader :next_time attr_reader :league, :game_name + attr_reader :pairing_factory def initialize(league, hash={}) @league = league @next_time = hash[:next_time] || nil @game_name = hash[:game_name] || "floodgate-900-0" + @pairing_factory = "default_factory" # will be updated by NextTimeGenerator charge if @next_time.nil? end @@ -41,6 +43,7 @@ class League def charge ntg = NextTimeGenerator.factory(@game_name) + @pairing_factory = ntg.pairing_factory if ntg @next_time = ntg.call(Time.now) else @@ -49,12 +52,14 @@ class League end def match_game + log_message("Starting Floodgate games...: %s, %s" % [@game_name, @pairing_factory]) players = @league.find_all_players do |pl| pl.status == "game_waiting" && game_name?(pl.game_name) && pl.sente == nil end - Pairing.match(players) + logics = Pairing.send(@pairing_factory) + Pairing.match(players, logics) end # @@ -80,10 +85,22 @@ class League end end + class AbstructNextTimeGenerator + + attr_reader :pairing_factory + + # Constructor. + # + def initialize + @pairing_factory = "default_factory" + end + end + # Schedule the next time from configuration files. # # Line format: # # This is a comment line + # set # DoW Time # ... # where @@ -97,12 +114,20 @@ class League # Sat 22:00 # Sun 13:00 # - class NextTimeGeneratorConfig + # Set parameters: + # + # * pairing_factory: + # Specifies a factory function name generating a pairing + # method which will be used in a specific Floodgate game. + # ex. floodgate_zyunisen + # + class NextTimeGeneratorConfig < AbstructNextTimeGenerator # Constructor. # Read configuration contents. # def initialize(lines) + super() @lines = lines end @@ -114,7 +139,10 @@ class League # now.cweek 1-53 # now.cwday 1(Monday)-7 @lines.each do |line| - if %r!^\s*(\w+)\s+(\d{1,2}):(\d{1,2})! =~ line + case line + when %r!^\s*set\s+pairing_factory\s+(\w+)! + @pairing_factory = $1 + when %r!^\s*(\w+)\s+(\d{1,2}):(\d{1,2})! dow, hour, minute = $1, $2.to_i, $3.to_i dow_index = ::ShogiServer::parse_dow(dow) next if dow_index.nil? @@ -132,7 +160,14 @@ class League # Schedule the next time for floodgate-900-0: each 30 minutes # - class NextTimeGenerator_Floodgate_900_0 + class NextTimeGenerator_Floodgate_900_0 < AbstructNextTimeGenerator + + # Constructor. + # + def initialize + super + end + def call(now) if now.min < 30 return Time.mktime(now.year, now.month, now.day, now.hour, 30) @@ -144,7 +179,14 @@ class League # Schedule the next time for floodgate-3600-0: each 2 hours (odd hour) # - class NextTimeGenerator_Floodgate_3600_0 + class NextTimeGenerator_Floodgate_3600_0 < AbstructNextTimeGenerator + + # Constructor. + # + def initialize + super + end + def call(now) return Time.mktime(now.year, now.month, now.day, now.hour) + ((now.hour%2)+1)*3600 end @@ -152,7 +194,14 @@ class League # Schedule the next time for debug: each 30 seconds. # - class NextTimeGenerator_Debug + class NextTimeGenerator_Debug < AbstructNextTimeGenerator + + # Constructor. + # + def initialize + super + end + def call(now) if now.sec < 30 return Time.mktime(now.year, now.month, now.day, now.hour, now.min, 30) diff --git a/shogi_server/league/floodgate_thread.rb b/shogi_server/league/floodgate_thread.rb index 4cd9be1..937e47c 100644 --- a/shogi_server/league/floodgate_thread.rb +++ b/shogi_server/league/floodgate_thread.rb @@ -64,7 +64,6 @@ module ShogiServer end def start_games(floodgate) - log_message("Starting Floodgate games...: %s" % [floodgate.game_name]) $league.reload floodgate.match_game end diff --git a/shogi_server/pairing.rb b/shogi_server/pairing.rb index 11f7665..7d70cbb 100644 --- a/shogi_server/pairing.rb +++ b/shogi_server/pairing.rb @@ -60,8 +60,16 @@ module ShogiServer StartGameWithoutHumans.new] end - def match(players) - logics = default_factory + def floodgate_zyunisen + return [LogPlayers.new, + ExcludeUnratedPlayers.new, + ExcludeSacrificeGps500.new, + MakeEven.new, + LeastDiff.new, + StartGameWithoutHumans.new] + end + + def match(players, logics) logics.inject(players) do |result, item| item.match(result) result @@ -499,4 +507,17 @@ module ShogiServer end end + # This pairing method excludes unrated players + # + class ExcludeUnratedPlayers < Pairing + + def match(players) + super + + log_message("Floodgate: Deleting unrated players...") + players.delete_if{|a| a.rate == 0} + log_players(players) + end + end # class ExcludeUnratedPlayers + end # ShogiServer diff --git a/test/TC_floodgate_next_time_generator.rb b/test/TC_floodgate_next_time_generator.rb index 2388634..c91cdfe 100644 --- a/test/TC_floodgate_next_time_generator.rb +++ b/test/TC_floodgate_next_time_generator.rb @@ -202,4 +202,20 @@ class TestNextTimeGeneratorConfig < Test::Unit::TestCase ntc = ShogiServer::League::Floodgate::NextTimeGeneratorConfig.new ["Thu 22:00"] assert_equal Time.parse("17-06-2010 22:00"), ntc.call(now) end + + def test_default_pairing_factory + now = DateTime.new(2010, 6, 10, 21, 59, 59) # Thu + lines = %w(Thu\ 22:00) + ntc = ShogiServer::League::Floodgate::NextTimeGeneratorConfig.new lines + assert_equal Time.parse("10-06-2010 22:00"), ntc.call(now) + assert_equal("default_factory", ntc.pairing_factory) + end + + def test_read_pairing_factory + now = DateTime.new(2010, 6, 10, 21, 59, 59) # Thu + lines = %w(set\ pairing_factory\ least_diff_pairing Thu\ 22:00) + ntc = ShogiServer::League::Floodgate::NextTimeGeneratorConfig.new lines + assert_equal Time.parse("10-06-2010 22:00"), ntc.call(now) + assert_equal("least_diff_pairing", ntc.pairing_factory) + end end diff --git a/test/TC_pairing.rb b/test/TC_pairing.rb index 90cea15..d9871e3 100644 --- a/test/TC_pairing.rb +++ b/test/TC_pairing.rb @@ -571,3 +571,58 @@ class TestLeastDiff < Test::Unit::TestCase end end +class TestExcludeUnratedPlayers < Test::Unit::TestCase + def setup + @pairing= ShogiServer::ExcludeUnratedPlayers.new + @a = ShogiServer::BasicPlayer.new + @a.name = "a" + @a.win = 1 + @a.loss = 2 + @a.rate = 0 + @b = ShogiServer::BasicPlayer.new + @b.name = "b" + @b.win = 10 + @b.loss = 20 + @b.rate = 1500 + @c = ShogiServer::BasicPlayer.new + @c.name = "c" + @c.win = 100 + @c.loss = 200 + @c.rate = 1000 + @d = ShogiServer::BasicPlayer.new + @d.name = "d" + @d.win = 1000 + @d.loss = 2000 + @d.rate = 2000 + end + + def test_match_without_any_players + players = [] + @pairing.match(players) + assert_equal([], players) + end + + def test_match_without_unrated_player_1 + players = [@b, @c, @d] + @pairing.match(players) + assert_equal([@b, @c, @d], players) + end + + def test_match_without_unrated_player_2 + players = [@b] + @pairing.match(players) + assert_equal([@b], players) + end + + def test_match_with_unrated_player_1 + players = [@a, @b, @c, @d] + @pairing.match(players) + assert_equal([@b, @c, @d], players) + end + + def test_match_with_unrated_player_2 + players = [@a] + @pairing.match(players) + assert_equal([], players) + end +end -- 2.11.0