OSDN Git Service

Remove a debug message
[shogi-server/shogi-server.git] / utils / statistics.rb
1 #!/usr/bin/ruby
2 # This program shows statistics of CSA kifu files like following: 
3 #   - Monthly #games and #players
4 #   - Game results
5 #   - Time of each move
6 #   - Time of each game
7 #   - Moves of each game
8 #
9 # Sample command line:
10 #   $ ./statistics.rb /dev/shm/floodgate
11 #
12 # Author::    Daigo Moriwaki <daigo at debian dot org>
13 # Copyright:: Copyright (C) 2009-2012 Daigo Moriwaki <daigo at debian dot org>
14 #
15 # $Id$
16 #
17 #--
18 # This program is free software; you can redistribute it and/or modify
19 # it under the terms of the GNU General Public License as published by
20 # the Free Software Foundation; either version 2 of the License, or
21 # (at your option) any later version.
22 #
23 # This program is distributed in the hope that it will be useful,
24 # but WITHOUT ANY WARRANTY; without even the implied warranty of
25 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26 # GNU General Public License for more details.
27 #
28 # You should have received a copy of the GNU General Public License
29 # along with this program; if not, write to the Free Software
30 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
31 #++
32
33 $:.unshift File.dirname(__FILE__)
34 require 'csa-filter'
35 require 'set'
36
37 class Monthly
38   def initialize
39     @games = Hash.new {|hash,key| hash[key] = 0}
40     @players = Hash.new {|hash,key| hash[key] = Set.new}
41   end
42
43   def add(csa)
44     st = csa.start_time
45     month = st.strftime("%Y%m")
46
47     @games[month] += 1
48
49     [csa.black_id, csa.white_id].each do |player|
50       @players[month].add(player)
51     end
52   end
53
54   def print
55     puts "YYYYMM\t#games\t#players"
56     @games.sort {|a,b| a[0] <=> b[0]}.each do |key,value|
57       puts "%s\t% 6d\t% 2d" % [key, value, @players[key].size]
58     end
59   end
60 end
61
62 class Values
63   def initialize
64     @v = []
65   end
66
67   def add(value)
68     case value
69     when Array 
70      @v.concat value
71     else
72       @v << value
73     end
74   end
75
76   def print(file)
77     total = @v.inject(0){|sum, item| sum+item}
78     avg   = 1.0*total/@v.size
79     puts "avg: %f sec (size: %d)" % [avg, @v.size]
80
81     File.open(file, "w") do |f|
82       @v.each {|v| f.puts v}
83     end
84   end
85 end
86
87 class State
88   def initialize
89     @hash = Hash.new {|hash,key| hash[key] = 0}
90   end
91
92   def add(value)
93     if value.nil? || value.empty?
94       value = "error"
95     end
96     @hash[value] += 1
97   end
98
99   def print
100     puts "status\t#games"
101     @hash.sort {|a,b| b[1] <=> a[1]}.each do |key, value|
102       puts "%s\t% 6d" % [key, value]
103     end
104   end
105 end
106
107 $monthly  = Monthly.new
108 $gametime = Values.new
109 $movetime = Values.new
110 $moves    = Values.new
111 $states   = State.new
112
113 def do_file(file)
114   $OPT_REPEAT -= 1 if $OPT_REPEAT > 0
115   csa = CsaFileReader.new(file, "EUC-JP")
116
117   # Want to see completed games only
118   $states.add csa.state
119   return unless csa.state == "toryo"
120
121   # 1. Process monthly
122   $monthly.add(csa)
123
124   # 2. Process gametime
125   duration = (csa.end_time - csa.start_time).to_i
126   $gametime.add duration.to_i
127
128   # 3. Process movetime
129   values = csa.movetimes
130   $movetime.add values
131
132   # 4. Process moves
133   $moves.add values.size
134
135 rescue => ex
136   $stderr.puts "ERROR: %s" % [file]
137   throw ex
138 end
139
140 if $0 == __FILE__
141   def usage
142     puts "Usage: #{$0} [OPTIONS] dir [...]"
143     puts "Options:"
144     exit 1
145   end
146
147   usage if ARGV.empty?
148
149   parser = GetoptLong.new(
150              ['--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT]
151            )
152   begin
153     parser.each_option do |name, arg|
154       eval "$OPT_#{name.sub(/^--/, '').gsub(/-/, '_').upcase} = '#{arg}'"
155     end
156   rescue
157     usage
158   end
159
160   $OPT_REPEAT = $OPT_REPEAT.to_i
161   if $OPT_REPEAT == 0
162     $OPT_REPEAT = -1
163   end
164
165   while (cmd = ARGV.shift)
166
167     if FileTest.directory?(cmd)
168       Dir.glob(File.join(cmd, "**", "*.csa")).each do |file|
169         break if $OPT_REPEAT == 0
170         do_file(file)
171       end
172     elsif FileTest.file?(cmd)
173       break if $OPT_REPEAT == 0
174       do_file(cmd)
175     else
176       throw "Unknown file or directory: #{cmd}"
177     end
178
179     puts "States"
180     puts "------"
181     $states.print
182     puts
183     puts "=== Toryo Games ==="
184     puts
185     puts "Montly"
186     puts "------"
187     $monthly.print
188     puts
189     puts "Play Time"
190     puts "---------"
191     $gametime.print("gametime.dat")
192     puts
193     puts "Move Time"
194     puts "---------"
195     $movetime.print("movetime.dat")
196     puts
197     puts "Moves"
198     puts "-----"
199     $moves.print("moves.dat")
200   end
201 end
202