* [shogi-server]
- shogi_server/pairing.rb, player.rb:
Simplify estimated rate of unrated players (less memory).
+ - Enhanced syntax of Floodgate time configuration file.
+ Now it supports "set sacrifice <player_id>"; it sets a
+ sacrificed player for a specific Floodgate game.
+ ex. set sacrifice gps500+e293220e3f8a3e59f79f6b0efffaa931
2013-12-05 Daigo Moriwaki <daigo at debian dot org>
Sat 22:00
Sun 13:00
+ PAREMETER SETTING
+
+ In addition, this configuration file allows to set parameters
+ for the specific Floodaget group. A list of parameters is the
+ following:
+
+ * pairing_factory:
+ Specifies a factory function name generating a pairing
+ method which will be used in a specific Floodgate game.
+ ex. set pairing_factory floodgate_zyunisen
+ * sacrifice:
+ Specifies a sacrificed player.
+ ex. set sacrifice gps500+e293220e3f8a3e59f79f6b0efffaa931
+
LICENSE
GPL versoin 2 or later
attr_reader :next_time
attr_reader :league, :game_name
attr_reader :pairing_factory
+ attr_reader :options
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
+ # Options will be updated by NextTimeGenerator
+ @options = {:sacrifice => "gps500+e293220e3f8a3e59f79f6b0efffaa931"}
charge if @next_time.nil?
end
def charge
ntg = NextTimeGenerator.factory(@game_name)
@pairing_factory = ntg.pairing_factory
+ @options[:sacrifice] = ntg.sacrifice
if ntg
@next_time = ntg.call(Time.now)
else
game_name?(pl.game_name) &&
pl.sente == nil
end
- logics = Pairing.send(@pairing_factory)
+ logics = Pairing.send(@pairing_factory, @options)
Pairing.match(players, logics)
end
class AbstructNextTimeGenerator
attr_reader :pairing_factory
+ attr_reader :sacrifice
# Constructor.
#
def initialize
@pairing_factory = "default_factory"
+ @sacrifice = "gps500+e293220e3f8a3e59f79f6b0efffaa931"
end
end
# * pairing_factory:
# Specifies a factory function name generating a pairing
# method which will be used in a specific Floodgate game.
- # ex. floodgate_zyunisen
+ # ex. set pairing_factory floodgate_zyunisen
+ # * sacrifice:
+ # Specifies a sacrificed player.
+ # ex. set sacrifice gps500+e293220e3f8a3e59f79f6b0efffaa931
#
class NextTimeGeneratorConfig < AbstructNextTimeGenerator
case line
when %r!^\s*set\s+pairing_factory\s+(\w+)!
@pairing_factory = $1
+ when %r!^\s*set\s+sacrifice\s+(.*)!
+ @sacrifice = $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)
time = DateTime::commercial(now.cwyear, now.cweek, dow_index, hour, minute) rescue next
time += 7 if time <= now
candidates << time
+ when %r!^\s*#!
+ # Skip comment line
+ when %r!^\s*$!
+ # Skip empty line
+ else
+ log_warning("Floodgate: Unsupported syntax in a next time generator config file: %s" % [line])
end
end
candidates.map! {|dt| ::ShogiServer::datetime2time(dt)}
class Pairing
class << self
- def default_factory
- return least_diff_pairing
+ def default_factory(options)
+ return least_diff_pairing(options)
end
- def sort_by_rate_with_randomness
+ def sort_by_rate_with_randomness(options)
return [LogPlayers.new,
- ExcludeSacrificeGps500.new,
+ ExcludeSacrifice.new(options[:sacrifice]),
MakeEven.new,
SortByRateWithRandomness.new(1200, 2400),
StartGameWithoutHumans.new]
end
- def random_pairing
+ def random_pairing(options)
return [LogPlayers.new,
- ExcludeSacrificeGps500.new,
+ ExcludeSacrifice.new(options[:sacrifice]),
MakeEven.new,
Randomize.new,
StartGameWithoutHumans.new]
end
- def swiss_pairing
+ def swiss_pairing(options)
return [LogPlayers.new,
- ExcludeSacrificeGps500.new,
+ ExcludeSacrifice.new(options[:sacrifice]),
MakeEven.new,
Swiss.new,
StartGameWithoutHumans.new]
end
- def least_diff_pairing
+ def least_diff_pairing(options)
return [LogPlayers.new,
- ExcludeSacrificeGps500.new,
+ ExcludeSacrifice.new(options[:sacrifice]),
MakeEven.new,
LeastDiff.new,
StartGameWithoutHumans.new]
end
- def floodgate_zyunisen
+ def floodgate_zyunisen(options)
return [LogPlayers.new,
ExcludeUnratedPlayers.new,
- ExcludeSacrificeGps500.new,
+ ExcludeSacrifice.new(options[:sacrifice]),
MakeEven.new,
LeastDiff.new,
StartGameWithoutHumans.new]
# @sacrifice a player id to be eliminated
def initialize(sacrifice)
super()
- @sacrifice = sacrifice
+ @sacrifice = sacrifice || "gps500+e293220e3f8a3e59f79f6b0efffaa931"
end
def match(players)
require 'shogi_server'
require 'shogi_server/league/floodgate'
require 'fileutils'
+require 'test/mock_log_message'
$topdir = File.expand_path File.dirname(__FILE__)
def setup
end
+ def test_comment
+ now = DateTime.new(2010, 6, 10, 21, 59, 59) # Thu
+ lines = %w(#\ comment1 Thu\ 22:00 #\ comment2)
+ ntc = ShogiServer::League::Floodgate::NextTimeGeneratorConfig.new lines
+ assert_equal Time.parse("10-06-2010 22:00"), ntc.call(now)
+ end
+
+ def test_empty_line
+ now = DateTime.new(2010, 6, 10, 21, 59, 59) # Thu
+ lines = %w(\ Thu\ 22:00 \ hoge)
+ ntc = ShogiServer::League::Floodgate::NextTimeGeneratorConfig.new lines
+ assert_equal Time.parse("10-06-2010 22:00"), ntc.call(now)
+ end
+
def test_read
now = DateTime.new(2010, 6, 10, 21, 20, 15) # Thu
assert_equal DateTime.parse("10-06-2010 21:20:15"), now
assert_equal Time.parse("10-06-2010 22:00"), ntc.call(now)
assert_equal("least_diff_pairing", ntc.pairing_factory)
end
+
+ def test_default_sacrifice
+ 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("gps500+e293220e3f8a3e59f79f6b0efffaa931", ntc.sacrifice)
+ end
+
+ def test_read_sacrifice
+ now = DateTime.new(2010, 6, 10, 21, 59, 59) # Thu
+ lines = %w(set\ sacrifice\ yowai_gps+95908f6c18338f5340371f71523fc5e3 Thu\ 22:00)
+ ntc = ShogiServer::League::Floodgate::NextTimeGeneratorConfig.new lines
+ assert_equal Time.parse("10-06-2010 22:00"), ntc.call(now)
+ assert_equal("yowai_gps+95908f6c18338f5340371f71523fc5e3", ntc.sacrifice)
+ end
end