OSDN Git Service

Improved stability of test results.
[shogi-server/shogi-server.git] / test / benchmark.rb
1 #!/usr/bin/ruby
2
3 require 'socket'
4
5 class BenchPlayer
6   def initialize(game_name, name, sente)
7     @game_name = game_name
8     @name = "%s_%s" % [game_name, name]
9     @turn_mark = sente ? "+" : "-"
10     @nmoves = 0
11   end
12   attr_reader :nmoves
13
14   def connect
15     port = 4000
16     @socket = TCPSocket.open("localhost", port)
17     @socket.sync = true
18     @message = ""
19     reader
20   end
21
22   def reader
23     Thread.new do
24       loop do 
25         if r = select([@socket], nil, nil, 10)
26           str = r[0].first.gets
27           if %r!^[\+\-]\d{4}\w{2},T\d+$! =~ str
28             @nmoves += 1
29           end
30           @message << str
31         else
32           raise "timed out"
33         end
34       end
35     end
36   end
37
38   def wait(reg)
39     loop do 
40       break if reg =~ @message
41       sleep 0.1
42     end
43   end
44
45   def wait_nmoves(n)
46     loop do
47       break if @nmoves == n
48       sleep 0.01
49     end
50   end
51
52   def login
53     @socket.puts "LOGIN #{@name} dummy x1"
54     wait %r!^LOGIN!
55   end
56
57   def game
58     @socket.puts "%%GAME #{@game_name}-1500-0 #{@turn_mark}"
59   end
60
61   def agree
62     @socket.puts "AGREE"
63   end
64
65   def move(m)
66     @socket.puts m
67   end
68
69   def toryo
70     @socket.puts "%TORYO"
71   end
72
73   def logout
74     @socket.puts "LOGOUT"
75   end
76
77 end
78
79 class BenchGame
80   def initialize(game_name, csa)
81     @game_name = game_name
82     @csa = csa
83     @p1 = BenchPlayer.new(@game_name, "bp1", true)
84     @p2 = BenchPlayer.new(@game_name, "bp2", false)
85   end
86
87   def each_player
88     [@p1, @p2].each {|player| yield player}
89   end
90
91   def start
92     each_player {|player| player.connect}
93     each_player {|player| player.login}
94     each_player {|player| player.game}
95     each_player {|player| player.wait %r!^END Game_Summary!}
96     each_player {|player| player.agree}
97     each_player {|player| player.wait %r!^START:!}
98     turn = true # black
99     nmoves = 0
100     @csa.each_line do |line|
101       case line
102       when /^\+\d{4}\w{2}/
103         @p1.wait_nmoves nmoves
104         @p1.move $&
105         turn = false
106         nmoves += 1
107       when /^\-\d{4}\w{2}/
108         @p2.wait_nmoves nmoves
109         @p2.move $&
110         turn = true
111         nmoves += 1
112       when /^%TORYO/
113         turn ? @p1.toryo : @p2.toryo
114       end
115     end
116     each_player {|player| player.logout}
117   end
118 end
119
120
121 if __FILE__ == $0
122   filepath = ARGV.shift || File.join(File.dirname(__FILE__), "csa", "wdoor+floodgate-900-0+gps_normal+gps_l+20100507120007.csa")
123   csa = File.open(filepath){|f| f.read} 
124
125   nclients = ARGV.shift || 1
126   nclients = nclients.to_i
127   threads = []
128   nclients.times do |i|
129     threads << Thread.new do
130       game = BenchGame.new("b#{i}", csa)
131       game.start
132     end
133   end
134   threads.each {|t| t.join}
135
136 end
137