+2013-12-05 Daigo Moriwaki <daigo at debian dot org>
+
+ * [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 <function_name>"; 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 <daigo at debian dot org>
* [shogi-server]
#
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
def charge
ntg = NextTimeGenerator.factory(@game_name)
+ @pairing_factory = ntg.pairing_factory
if ntg
@next_time = ntg.call(Time.now)
else
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
#
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 <parameter_name> <value>
# DoW Time
# ...
# where
# 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
# 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?
# 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)
# 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
# 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)
end
def start_games(floodgate)
- log_message("Starting Floodgate games...: %s" % [floodgate.game_name])
$league.reload
floodgate.match_game
end
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
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
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
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