OSDN Git Service

Merge branch '201410-StalledPlayer'
[shogi-server/shogi-server.git] / test / benchmark.rb
1 #!/usr/bin/ruby
2
3 require 'logger'
4 require 'socket'
5 require 'thread'
6
7 $logger = nil
8
9 class BenchPlayer
10   def initialize(game_name, name, sente)
11     @game_name = game_name
12     @name = "%s_%s" % [game_name, name]
13     @turn_mark = sente ? "+" : "-"
14     @nmoves = 0
15     @socket = nil
16   end
17   attr_reader :nmoves
18
19   def connect
20     port = 4000
21     @socket = TCPSocket.open("localhost", port)
22     @socket.sync = true
23     @message = ""
24     reader
25   end
26
27   def reader
28     Thread.new do
29       Thread.pass
30       loop do 
31         if r = select([@socket], nil, nil, 300)
32           str = r[0].first.gets
33           if %r!^[\+\-]\d{4}\w{2},T\d+$! =~ str
34             @nmoves += 1
35           end
36           @message << str if str
37         else
38           $logger.warn "Timed out: %s" % [@name]
39         end
40       end
41       $logger.error "Socket error: %s" % [@name]
42     end
43   end
44
45   def wait(reg)
46     loop do 
47       break if reg =~ @message
48       #$logger.debug "WAIT %s: %s" % [reg, @message]
49       sleep 0.001
50       #Thread.pass
51     end
52   end
53
54   def wait_nmoves(n)
55     loop do
56       break if @nmoves == n
57       sleep 0.001
58       #Thread.pass
59     end
60   end
61
62   def login
63     @socket.puts "LOGIN #{@name} dummy x1"
64     wait %r!^##\[LOGIN\] \+OK!
65   end
66
67   def game
68     @socket.puts "%%GAME #{@game_name}-1500-0 #{@turn_mark}"
69   end
70
71   def agree
72     @socket.puts "AGREE"
73   end
74
75   def move(m)
76     @socket.puts m
77   end
78
79   def toryo
80     @socket.puts "%TORYO"
81   end
82
83   def logout
84     @socket.puts "LOGOUT"
85   end
86
87 end
88
89 class BenchGame
90   @@mutex = Mutex.new
91   @@count = 0
92   def initialize(game_name, csa)
93     @game_name = game_name
94     @csa = csa
95     @@mutex.synchronize do 
96       @p1 = BenchPlayer.new(@game_name, "bp#{@@count+=1}", true)
97       @p2 = BenchPlayer.new(@game_name, "bp#{@@count+=1}", false)
98     end
99   end
100
101   def each_player
102     [@p1, @p2].each {|player| yield player}
103   end
104
105   def start
106     $logger.info "Starting... %s" % [@game_name]
107     $logger.debug "Connecting... %s" % [@game_name]
108     each_player {|player| player.connect}
109     $logger.debug "Logging in... %s" % [@game_name]
110     each_player {|player| player.login}
111     $logger.debug "Sending GAME... %s" % [@game_name]
112     each_player {|player| player.game}
113     $logger.debug "Waiting... %s" % [@game_name]
114     each_player {|player| player.wait %r!^END Game_Summary!}
115     $logger.debug "Agreeing... %s" % [@game_name]
116     each_player {|player| player.agree}
117     $logger.debug "AGREE waiting... %s" % [@game_name]
118     each_player {|player| player.wait %r!^START:!}
119     $logger.info "Started %s" % [@game_name]
120     turn = true # black
121     nmoves = 0
122     @csa.each_line do |line|
123       case line
124       when /^\+\d{4}\w{2}/
125         @p1.wait_nmoves nmoves
126         @p1.move $&
127         turn = false
128         nmoves += 1
129       when /^\-\d{4}\w{2}/
130         @p2.wait_nmoves nmoves
131         @p2.move $&
132         turn = true
133         nmoves += 1
134       when /^%TORYO/
135         $logger.debug "Waiting TORYO... %s" % [@game_name]
136         @p1.wait_nmoves nmoves
137         @p2.wait_nmoves nmoves
138         turn ? @p1.toryo : @p2.toryo
139       end
140     end
141     $logger.info "Logging out... %s" % [@game_name]
142     each_player {|player| player.logout}
143     $logger.info "Finished %s" % [@game_name]
144   end
145 end
146
147
148 if __FILE__ == $0
149   filepath = ARGV.shift || File.join(File.dirname(__FILE__), "csa", "wdoor+floodgate-900-0+gps_normal+gps_l+20100507120007.csa")
150   csa = File.open(filepath){|f| f.read} 
151
152   $logger = Logger.new(STDOUT)
153   $logger.level = $DEBUG ? Logger::DEBUG : Logger::INFO  
154
155   nclients = ARGV.shift || 1
156   nclients = nclients.to_i
157   threads = []
158   nclients.times do |i|
159     threads << Thread.new do
160       Thread.pass
161       game = BenchGame.new("b#{i}", csa)
162       game.start
163     end
164   end
165   threads.each {|t| t.join}
166
167 end
168