• R/O
  • SSH
  • HTTPS

shogi-server: Commit


Commit MetaInfo

Révision371 (tree)
l'heure2009-12-26 10:40:20
Auteurbeatles

Message de Log

* [shogi-server]

- The server can now provide multiple floodgate modes such as
floodgate-900-0 and floodgate-3600-0.

Change Summary

Modification

--- shogi-server/trunk/shogi_server/util.rb (revision 370)
+++ shogi-server/trunk/shogi_server/util.rb (revision 371)
@@ -17,6 +17,9 @@
1717 ## along with this program; if not, write to the Free Software
1818 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1919
20+require 'fileutils'
21+require 'pathname'
22+
2023 module ShogiServer
2124
2225 # Generate a random number such as i<=n<max
@@ -37,4 +40,31 @@
3740 end
3841 module_function :shuffle
3942
43+ # See if the file is writable. The file will be created if it does not exist
44+ # yet.
45+ # Return true if the file is writable, otherwise false.
46+ #
47+ def is_writable_file?(file)
48+ if String === file
49+ file = Pathname.new file
50+ end
51+ if file.exist?
52+ if file.file?
53+ return file.writable_real?
54+ else
55+ return false
56+ end
57+ end
58+
59+ begin
60+ file.open("w") {|fh| }
61+ file.delete
62+ rescue
63+ return false
64+ end
65+
66+ return true
67+ end
68+ module_function :is_writable_file?
69+
4070 end
--- shogi-server/trunk/shogi_server/league/floodgate.rb (revision 370)
+++ shogi-server/trunk/shogi_server/league/floodgate.rb (revision 371)
@@ -7,15 +7,22 @@
77 class League
88 class Floodgate
99 class << self
10- # "floodgate-900-0"
10+ # ex. "floodgate-900-0"
1111 #
1212 def game_name?(str)
1313 return /^floodgate\-\d+\-\d+$/.match(str) ? true : false
1414 end
15- end
1615
17- attr_reader :next_time, :league
16+ def history_file_path(gamename)
17+ return nil unless game_name?(gamename)
18+ filename = "floodgate_history_%s.yaml" % [gamename.gsub("floodgate-", "").gsub("-","_")]
19+ file = File.join($topdir, filename)
20+ return Pathname.new(file)
21+ end
22+ end # class method
1823
24+ attr_reader :next_time, :league, :game_name
25+
1926 def initialize(league, hash={})
2027 @league = league
2128 @next_time = hash[:next_time] || nil
@@ -28,21 +35,11 @@
2835 end
2936
3037 def charge
31- now = Time.now
32- unless $DEBUG
33- # each 30 minutes
34- if now.min < 30
35- @next_time = Time.mktime(now.year, now.month, now.day, now.hour, 30)
36- else
37- @next_time = Time.mktime(now.year, now.month, now.day, now.hour) + 3600
38- end
38+ ntg = NextTimeGenerator.factory(@game_name)
39+ if ntg
40+ @next_time = ntg.call(Time.now)
3941 else
40- # for test, each 30 seconds
41- if now.sec < 30
42- @next_time = Time.mktime(now.year, now.month, now.day, now.hour, now.min, 30)
43- else
44- @next_time = Time.mktime(now.year, now.month, now.day, now.hour, now.min) + 60
45- end
42+ @next_time = nil
4643 end
4744 end
4845
@@ -54,8 +51,54 @@
5451 end
5552 Pairing.match(players)
5653 end
54+
55+ #
56+ #
57+ class NextTimeGenerator
58+ class << self
59+ def factory(game_name)
60+ ret = nil
61+ if $DEBUG
62+ ret = NextTimeGenerator_Debug.new
63+ elsif game_name == "floodgate-900-0"
64+ ret = NextTimeGenerator_Floodgate_900_0.new
65+ elsif game_name == "floodgate-3600-0"
66+ ret = NextTimeGenerator_Floodgate_3600_0.new
67+ end
68+ return ret
69+ end
70+ end
71+ end
5772
73+ class NextTimeGenerator_Floodgate_900_0
74+ def call(now)
75+ # each 30 minutes
76+ if now.min < 30
77+ return Time.mktime(now.year, now.month, now.day, now.hour, 30)
78+ else
79+ return Time.mktime(now.year, now.month, now.day, now.hour) + 3600
80+ end
81+ end
82+ end
5883
84+ class NextTimeGenerator_Floodgate_3600_0
85+ def call(now)
86+ # each 2 hours (odd hour)
87+ return Time.mktime(now.year, now.month, now.day, now.hour) + ((now.hour%2)+1)*3600
88+ end
89+ end
90+
91+ class NextTimeGenerator_Debug
92+ def call(now)
93+ # for test, each 30 seconds
94+ if now.sec < 30
95+ return Time.mktime(now.year, now.month, now.day, now.hour, now.min, 30)
96+ else
97+ return Time.mktime(now.year, now.month, now.day, now.hour, now.min) + 60
98+ end
99+ end
100+ end
101+
59102 #
60103 #
61104 class History
@@ -62,9 +105,12 @@
62105 @@mutex = Mutex.new
63106
64107 class << self
65- def factory
66- file = Pathname.new $options["floodgate-history"]
67- history = History.new file
108+ def factory(pathname)
109+ unless ShogiServer::is_writable_file?(pathname.to_s)
110+ log_error("Failed to write a history file: %s" % [pathname])
111+ return nil
112+ end
113+ history = History.new pathname
68114 history.load
69115 return history
70116 end
--- shogi-server/trunk/shogi_server/game_result.rb (revision 370)
+++ shogi-server/trunk/shogi_server/game_result.rb (revision 371)
@@ -109,10 +109,10 @@
109109 add_observer LoggingObserver.new
110110
111111 if League::Floodgate.game_name?(@game.game_name) &&
112- @game.sente.player_id &&
113- @game.gote.player_id &&
114- $options["floodgate-history"]
115- add_observer League::Floodgate::History.factory
112+ @game.sente.player_id && @game.gote.player_id
113+ path = League::Floodgate.history_file_path(@game.game_name)
114+ history = League::Floodgate::History.factory(path)
115+ add_observer history if history
116116 end
117117 end
118118
--- shogi-server/trunk/shogi_server/pairing.rb (revision 370)
+++ shogi-server/trunk/shogi_server/pairing.rb (revision 371)
@@ -45,11 +45,10 @@
4545 end
4646
4747 def swiss_pairing
48- history = ShogiServer::League::Floodgate::History.factory
4948 return [LogPlayers.new,
5049 ExcludeSacrificeGps500.new,
5150 MakeEven.new,
52- Swiss.new(history),
51+ Swiss.new,
5352 StartGameWithoutHumans.new]
5453 end
5554
@@ -251,16 +250,22 @@
251250 end
252251
253252 class Swiss < Pairing
254- def initialize(history)
255- super()
256- @history = history
257- end
258-
259253 def match(players)
260254 super
261- winners = players.find_all {|pl| @history.last_win?(pl.player_id)}
262- rest = players - winners
255+ if players.size < 3
256+ log_message("Floodgate: players are small enough to skip Swiss pairing: %d" % [players.size])
257+ return
258+ end
263259
260+ path = ShogiServer::League::Floodgate.history_file_path(players.first.game_name)
261+ history = ShogiServer::League::Floodgate::History.factory(path)
262+
263+ winners = []
264+ if history
265+ winners = players.find_all {|pl| history.last_win?(pl.player_id)}
266+ end
267+ rest = players - winners
268+
264269 log_message("Floodgate: Ordering %d winners..." % [winners.size])
265270 sbrwr_winners = SortByRateWithRandomness.new(800, 2500)
266271 sbrwr_winners.match(winners, true)
--- shogi-server/trunk/test/TC_floodgate.rb (revision 370)
+++ shogi-server/trunk/test/TC_floodgate.rb (revision 371)
@@ -5,15 +5,20 @@
55 require 'shogi_server/pairing'
66 require 'shogi_server/league/floodgate'
77
8+$topdir = File.expand_path File.dirname(__FILE__)
9+
810 class MockLogger
911 def debug(str)
12+ #puts str
1013 end
1114 def info(str)
1215 #puts str
1316 end
1417 def warn(str)
18+ puts str
1519 end
1620 def error(str)
21+ puts str
1722 end
1823 end
1924
@@ -26,6 +31,10 @@
2631 $logger.warn(msg)
2732 end
2833
34+def log_error(msg)
35+ $logger.error(msg)
36+end
37+
2938 class TestFloodgate < Test::Unit::TestCase
3039 def setup
3140 @fg = ShogiServer::League::Floodgate.new(nil)
@@ -268,22 +277,26 @@
268277 @a = ShogiServer::BasicPlayer.new
269278 @a.player_id = "a"
270279 @a.rate = 0
280+ @a.game_name = "floodgate-900-0"
271281 @b = ShogiServer::BasicPlayer.new
272282 @b.player_id = "b"
273283 @b.rate = 1000
284+ @b.game_name = "floodgate-900-0"
274285 @c = ShogiServer::BasicPlayer.new
275286 @c.player_id = "c"
276287 @c.rate = 1500
288+ @c.game_name = "floodgate-900-0"
277289 @d = ShogiServer::BasicPlayer.new
278290 @d.player_id = "d"
279291 @d.rate = 2000
292+ @d.game_name = "floodgate-900-0"
280293
281294 @players = [@a, @b, @c, @d]
282295
283- @file = Pathname.new(File.join(File.dirname(__FILE__), "floodgate_history.yaml"))
284- @history = ShogiServer::League::Floodgate::History.new @file
296+ @file = Pathname.new(File.join(File.dirname(__FILE__), "floodgate_history_900_0.yaml"))
297+ @history = ShogiServer::League::Floodgate::History.factory @file
285298
286- @swiss = ShogiServer::Swiss.new @history
299+ @swiss = ShogiServer::Swiss.new
287300 end
288301
289302 def teardown
@@ -290,9 +303,17 @@
290303 @file.delete if @file.exist?
291304 end
292305
306+ def test_none
307+ players = []
308+ @swiss.match players
309+ assert(players.empty?)
310+ end
311+
293312 def test_all_win
294- def @history.last_win?(player_id)
295- true
313+ ShogiServer::League::Floodgate::History.class_eval do
314+ def last_win?(player_id)
315+ true
316+ end
296317 end
297318 @swiss.match @players
298319 assert_equal([@d, @c, @b, @a], @players)
@@ -299,8 +320,10 @@
299320 end
300321
301322 def test_all_lose
302- def @history.last_win?(player_id)
303- false
323+ ShogiServer::League::Floodgate::History.class_eval do
324+ def last_win?(player_id)
325+ false
326+ end
304327 end
305328 @swiss.match @players
306329 assert_equal([@d, @c, @b, @a], @players)
@@ -307,11 +330,13 @@
307330 end
308331
309332 def test_one_win
310- def @history.last_win?(player_id)
311- if player_id == "a"
312- true
313- else
314- false
333+ ShogiServer::League::Floodgate::History.class_eval do
334+ def last_win?(player_id)
335+ if player_id == "a"
336+ true
337+ else
338+ false
339+ end
315340 end
316341 end
317342 @swiss.match @players
@@ -319,11 +344,13 @@
319344 end
320345
321346 def test_two_win
322- def @history.last_win?(player_id)
323- if player_id == "a" || player_id == "d"
324- true
325- else
326- false
347+ ShogiServer::League::Floodgate::History.class_eval do
348+ def last_win?(player_id)
349+ if player_id == "a" || player_id == "d"
350+ true
351+ else
352+ false
353+ end
327354 end
328355 end
329356 @swiss.match @players
--- shogi-server/trunk/test/TC_ALL.rb (revision 370)
+++ shogi-server/trunk/test/TC_ALL.rb (revision 371)
@@ -7,6 +7,7 @@
77 require 'TC_config'
88 require 'TC_floodgate'
99 require 'TC_floodgate_history'
10+require 'TC_floodgate_next_time_generator'
1011 require 'TC_functional'
1112 require 'TC_game'
1213 require 'TC_game_result'
--- shogi-server/trunk/test/TC_floodgate_next_time_generator.rb (nonexistent)
+++ shogi-server/trunk/test/TC_floodgate_next_time_generator.rb (revision 371)
@@ -0,0 +1,89 @@
1+$:.unshift File.join(File.dirname(__FILE__), "..")
2+require 'test/unit'
3+require 'shogi_server'
4+require 'shogi_server/league/floodgate'
5+
6+$topdir = File.expand_path File.dirname(__FILE__)
7+
8+class TestNextTimeGenerator_900_0 < Test::Unit::TestCase
9+ def setup
10+ @next = ShogiServer::League::Floodgate::NextTimeGenerator_Floodgate_900_0.new
11+ end
12+
13+ def test_0_min
14+ now = Time.mktime(2009,12,25,22,0)
15+ assert_equal(Time.mktime(2009,12,25,22,30), @next.call(now))
16+ end
17+
18+ def test_20_min
19+ now = Time.mktime(2009,12,25,22,20)
20+ assert_equal(Time.mktime(2009,12,25,22,30), @next.call(now))
21+ end
22+
23+ def test_30_min
24+ now = Time.mktime(2009,12,25,22,30)
25+ assert_equal(Time.mktime(2009,12,25,23,00), @next.call(now))
26+ end
27+
28+ def test_50_min
29+ now = Time.mktime(2009,12,25,22,50)
30+ assert_equal(Time.mktime(2009,12,25,23,00), @next.call(now))
31+ end
32+
33+ def test_50_min_next_day
34+ now = Time.mktime(2009,12,25,23,50)
35+ assert_equal(Time.mktime(2009,12,26,0,0), @next.call(now))
36+ end
37+
38+ def test_50_min_next_month
39+ now = Time.mktime(2009,11,30,23,50)
40+ assert_equal(Time.mktime(2009,12,1,0,0), @next.call(now))
41+ end
42+
43+ def test_50_min_next_year
44+ now = Time.mktime(2009,12,31,23,50)
45+ assert_equal(Time.mktime(2010,1,1,0,0), @next.call(now))
46+ end
47+end
48+
49+class TestNextTimeGenerator_3600_0 < Test::Unit::TestCase
50+ def setup
51+ @next = ShogiServer::League::Floodgate::NextTimeGenerator_Floodgate_3600_0.new
52+ end
53+
54+ def test_22_00
55+ now = Time.mktime(2009,12,25,22,0)
56+ assert_equal(Time.mktime(2009,12,25,23,0), @next.call(now))
57+ end
58+
59+ def test_22_30
60+ now = Time.mktime(2009,12,25,22,0)
61+ assert_equal(Time.mktime(2009,12,25,23,0), @next.call(now))
62+ end
63+
64+ def test_23_00
65+ now = Time.mktime(2009,12,25,23,0)
66+ assert_equal(Time.mktime(2009,12,26,1,0), @next.call(now))
67+ end
68+
69+ def test_23_30
70+ now = Time.mktime(2009,12,25,23,30)
71+ assert_equal(Time.mktime(2009,12,26,1,0), @next.call(now))
72+ end
73+
74+ def test_00_00
75+ now = Time.mktime(2009,12,26,0,0)
76+ assert_equal(Time.mktime(2009,12,26,1,0), @next.call(now))
77+ end
78+
79+ def test_23_30_next_month
80+ now = Time.mktime(2009,11,30,23,30)
81+ assert_equal(Time.mktime(2009,12,1,1,0), @next.call(now))
82+ end
83+
84+ def test_23_30_next_year
85+ now = Time.mktime(2009,12,31,23,30)
86+ assert_equal(Time.mktime(2010,1,1,1,0), @next.call(now))
87+ end
88+end
89+
Afficher sur ancien navigateur de dépôt.