• R/O
  • SSH
  • HTTPS

shogi-server: Commit


Commit MetaInfo

Revision363 (tree)
Time2009-11-25 18:00:59
Authorbeatles

Log Message

Added a tool to investicate statistics of csa kifu files

Change Summary

Incremental Difference

--- shogi-server/trunk/utils/csa-filter.rb (revision 362)
+++ shogi-server/trunk/utils/csa-filter.rb (revision 363)
@@ -28,6 +28,7 @@
2828 require 'time'
2929 require 'pathname'
3030 require 'getoptlong'
31+require 'nkf'
3132
3233 class CsaFileReader
3334 WIN_MARK = "win"
@@ -35,9 +36,11 @@
3536 DRAW_MARK = "draw"
3637
3738 attr_reader :file_name
39+ attr_reader :str
3840 attr_reader :black_name, :white_name
3941 attr_reader :black_id, :white_id
4042 attr_reader :winner, :loser
43+ attr_reader :state
4144 attr_reader :start_time, :end_time
4245
4346 def initialize(file_name)
@@ -46,13 +49,14 @@
4649 end
4750
4851 def grep
49- str = File.open(@file_name).read
52+ @str = File.open(@file_name, "r:Shift_JIS:EUC-JP").read
5053
51- if /^N\+(.*)$/ =~ str then @black_name = $1.strip end
52- if /^N\-(.*)$/ =~ str then @white_name = $1.strip end
53- if /^'summary:(.*)$/ =~ str
54- state, p1, p2 = $1.split(":").map {|a| a.strip}
55- return if state == "abnormal"
54+
55+ if /^N\+(.*)$/ =~ @str then @black_name = $1.strip end
56+ if /^N\-(.*)$/ =~ @str then @white_name = $1.strip end
57+ if /^'summary:(.*)$/ =~ @str
58+ @state, p1, p2 = $1.split(":").map {|a| a.strip}
59+ return if @state == "abnormal"
5660 p1_name, p1_mark = p1.split(" ")
5761 p2_name, p2_mark = p2.split(" ")
5862 if p1_name == @black_name
@@ -65,13 +69,13 @@
6569 raise "Never reach!: #{black} #{white} #{p3} #{p2}"
6670 end
6771 end
68- if /^\$START_TIME:(.*)$/ =~ str
72+ if /^\$START_TIME:(.*)$/ =~ @str
6973 @start_time = Time.parse($1.strip)
7074 end
71- if /^'\$END_TIME:(.*)$/ =~ str
75+ if /^'\$END_TIME:(.*)$/ =~ @str
7276 @end_time = Time.parse($1.strip)
7377 end
74- if /^'rating:(.*)$/ =~ str
78+ if /^'rating:(.*)$/ =~ @str
7579 black_id, white_id = $1.split(":").map {|a| a.strip}
7680 @black_id = identify_id(black_id)
7781 @white_id = identify_id(white_id)
@@ -90,6 +94,14 @@
9094 end
9195 end
9296
97+ def movetimes
98+ ret = []
99+ @str.gsub(%r!^T(\d+)!) do |match|
100+ ret << $1.to_i
101+ end
102+ return ret
103+ end
104+
93105 def to_s
94106 return "Summary: #{@file_name}\n" +
95107 "BlackName #{@black_name}, WhiteName #{@white_name}\n" +
--- shogi-server/trunk/utils/statistics.rb (nonexistent)
+++ shogi-server/trunk/utils/statistics.rb (revision 363)
@@ -0,0 +1,205 @@
1+#!/usr/bin/ruby1.9.1
2+# This program filters CSA files. For example, if you want only CSA files
3+# played by GPS vs Bonanza,
4+# $ ./csa-filter.rb --players gps-l,bonanza some_dir
5+# you will see such files under the some_dir directory.
6+#
7+# Author:: Daigo Moriwaki <daigo at debian dot org>
8+# Copyright:: Copyright (C) 2006-2008 Daigo Moriwaki <daigo at debian dot org>
9+#
10+# $Id$
11+#
12+#--
13+# This program is free software; you can redistribute it and/or modify
14+# it under the terms of the GNU General Public License as published by
15+# the Free Software Foundation; either version 2 of the License, or
16+# (at your option) any later version.
17+#
18+# This program is distributed in the hope that it will be useful,
19+# but WITHOUT ANY WARRANTY; without even the implied warranty of
20+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21+# GNU General Public License for more details.
22+#
23+# You should have received a copy of the GNU General Public License
24+# along with this program; if not, write to the Free Software
25+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26+#++
27+
28+$:.unshift File.dirname(__FILE__)
29+require 'csa-filter'
30+require 'set'
31+
32+class Monthly
33+ def initialize
34+ @games = Hash.new {|hash,key| hash[key] = 0}
35+ @players = Hash.new {|hash,key| hash[key] = Set.new}
36+ end
37+
38+ def add(csa)
39+ st = csa.start_time
40+ month = st.strftime("%Y%m")
41+
42+ @games[month] += 1
43+
44+ [csa.black_id, csa.white_id].each do |player|
45+ @players[month].add(player)
46+ end
47+ end
48+
49+ def print
50+ puts "YYYYMM\t#games\t#players"
51+ @games.sort {|a,b| a[0] <=> b[0]}.each do |key,value|
52+ puts "%s\t% 6d\t% 2d" % [key, value, @players[key].size]
53+ end
54+ end
55+end
56+
57+class Values
58+ def initialize
59+ @v = []
60+ end
61+
62+ def add(value)
63+ case value
64+ when Array
65+ @v.concat value
66+ else
67+ @v << value
68+ end
69+ end
70+
71+ def print(file)
72+ total = @v.inject(0){|sum, item| sum+item}
73+ avg = 1.0*total/@v.size
74+ puts "avg: %f sec (size: %d)" % [avg, @v.size]
75+
76+ File.open(file, "w") do |f|
77+ @v.each {|v| f.puts v}
78+ end
79+ end
80+end
81+
82+class State
83+ def initialize
84+ @hash = Hash.new {|hash,key| hash[key] = 0}
85+ end
86+
87+ def add(value)
88+ if value.nil? || value.empty?
89+ value = "error"
90+ end
91+ @hash[value] += 1
92+ end
93+
94+ def print
95+ puts "status\t#games"
96+ @hash.sort {|a,b| b[1] <=> a[1]}.each do |key, value|
97+ puts "%s\t% 6d" % [key, value]
98+ end
99+ end
100+end
101+
102+$monthly = Monthly.new
103+$gametime = Values.new
104+$movetime = Values.new
105+$moves = Values.new
106+$states = State.new
107+
108+def do_file(file)
109+ $OPT_REPEAT -= 1 if $OPT_REPEAT > 0
110+ csa = CsaFileReader.new(file)
111+
112+ # Want to see complete games
113+ $states.add csa.state
114+ return unless csa.state == "toryo"
115+
116+ # See games between 2008/03 to 2009/07
117+ return if csa.start_time < Time.parse("2008/03/01") ||
118+ csa.start_time >= Time.parse("2009/08/01")
119+
120+ # Process monthly
121+ $monthly.add(csa)
122+
123+ # Process gametime
124+ duration = (csa.end_time - csa.start_time).to_i
125+ if duration > 2200
126+ $stderr.puts "Too long game: #{file}"
127+ return
128+ end
129+ $gametime.add duration.to_i
130+
131+ # Process movetime
132+ values = csa.movetimes
133+ $movetime.add values
134+
135+ #Process moves
136+ $moves.add values.size
137+
138+rescue => ex
139+ $stderr.puts "ERROR: %s" % [file]
140+ throw ex
141+end
142+
143+if $0 == __FILE__
144+ def usage
145+ puts "Usage: #{$0} [OPTIONS] dir [...]"
146+ puts "Options:"
147+ exit 1
148+ end
149+
150+ usage if ARGV.empty?
151+
152+ parser = GetoptLong.new(
153+ ['--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT]
154+ )
155+ begin
156+ parser.each_option do |name, arg|
157+ eval "$OPT_#{name.sub(/^--/, '').gsub(/-/, '_').upcase} = '#{arg}'"
158+ end
159+ rescue
160+ usage
161+ end
162+
163+ $OPT_REPEAT = $OPT_REPEAT.to_i
164+ if $OPT_REPEAT == 0
165+ $OPT_REPEAT = -1
166+ end
167+
168+ while (cmd = ARGV.shift)
169+
170+ if FileTest.directory?(cmd)
171+ Dir.glob(File.join(cmd, "**", "*.csa")).each do |file|
172+ break if $OPT_REPEAT == 0
173+ do_file(file)
174+ end
175+ elsif FileTest.file?(cmd)
176+ break if $OPT_REPEAT == 0
177+ do_file(cmd)
178+ else
179+ throw "Unknown file or directory: #{cmd}"
180+ end
181+
182+ puts "States"
183+ puts "------"
184+ $states.print
185+ puts
186+ puts "=== Toryo Games ==="
187+ puts
188+ puts "Montly"
189+ puts "------"
190+ $monthly.print
191+ puts
192+ puts "Play Time"
193+ puts "---------"
194+ $gametime.print("gametime.dat")
195+ puts
196+ puts "Move Time"
197+ puts "---------"
198+ $movetime.print("movetime.dat")
199+ puts
200+ puts "Moves"
201+ puts "-----"
202+ $moves.print("moves.dat")
203+ end
204+end
205+
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Show on old repository browser