OSDN Git Service

Added a tool to investicate statistics of csa kifu files
authorbeatles <beatles@b8c68f68-1e22-0410-b08e-880e1f8202b4>
Wed, 25 Nov 2009 09:00:59 +0000 (09:00 +0000)
committerbeatles <beatles@b8c68f68-1e22-0410-b08e-880e1f8202b4>
Wed, 25 Nov 2009 09:00:59 +0000 (09:00 +0000)
utils/csa-filter.rb
utils/statistics.rb [new file with mode: 0755]

index a87e44f..b393bcd 100755 (executable)
@@ -28,6 +28,7 @@
 require 'time'
 require 'pathname'
 require 'getoptlong'
 require 'time'
 require 'pathname'
 require 'getoptlong'
+require 'nkf'
 
 class CsaFileReader
   WIN_MARK  = "win"
 
 class CsaFileReader
   WIN_MARK  = "win"
@@ -35,9 +36,11 @@ class CsaFileReader
   DRAW_MARK = "draw"
 
   attr_reader :file_name
   DRAW_MARK = "draw"
 
   attr_reader :file_name
+  attr_reader :str
   attr_reader :black_name, :white_name
   attr_reader :black_id, :white_id
   attr_reader :winner, :loser
   attr_reader :black_name, :white_name
   attr_reader :black_id, :white_id
   attr_reader :winner, :loser
+  attr_reader :state
   attr_reader :start_time, :end_time
 
   def initialize(file_name)
   attr_reader :start_time, :end_time
 
   def initialize(file_name)
@@ -46,13 +49,14 @@ class CsaFileReader
   end
 
   def grep
   end
 
   def grep
-    str = File.open(@file_name).read
+    @str = File.open(@file_name, "r:Shift_JIS:EUC-JP").read
 
 
-    if /^N\+(.*)$/ =~ str then @black_name = $1.strip end
-    if /^N\-(.*)$/ =~ str then @white_name = $1.strip end
-    if /^'summary:(.*)$/ =~ str
-      state, p1, p2 = $1.split(":").map {|a| a.strip}    
-      return if state == "abnormal"
+
+    if /^N\+(.*)$/ =~ @str then @black_name = $1.strip end
+    if /^N\-(.*)$/ =~ @str then @white_name = $1.strip end
+    if /^'summary:(.*)$/ =~ @str
+      @state, p1, p2 = $1.split(":").map {|a| a.strip}    
+      return if @state == "abnormal"
       p1_name, p1_mark = p1.split(" ")
       p2_name, p2_mark = p2.split(" ")
       if p1_name == @black_name
       p1_name, p1_mark = p1.split(" ")
       p2_name, p2_mark = p2.split(" ")
       if p1_name == @black_name
@@ -65,13 +69,13 @@ class CsaFileReader
         raise "Never reach!: #{black} #{white} #{p3} #{p2}"
       end
     end
         raise "Never reach!: #{black} #{white} #{p3} #{p2}"
       end
     end
-    if /^\$START_TIME:(.*)$/ =~ str
+    if /^\$START_TIME:(.*)$/ =~ @str
       @start_time = Time.parse($1.strip)
     end
       @start_time = Time.parse($1.strip)
     end
-    if /^'\$END_TIME:(.*)$/ =~ str
+    if /^'\$END_TIME:(.*)$/ =~ @str
       @end_time = Time.parse($1.strip)
     end
       @end_time = Time.parse($1.strip)
     end
-    if /^'rating:(.*)$/ =~ str
+    if /^'rating:(.*)$/ =~ @str
       black_id, white_id = $1.split(":").map {|a| a.strip}
       @black_id = identify_id(black_id)
       @white_id = identify_id(white_id)
       black_id, white_id = $1.split(":").map {|a| a.strip}
       @black_id = identify_id(black_id)
       @white_id = identify_id(white_id)
@@ -90,6 +94,14 @@ class CsaFileReader
     end
   end
 
     end
   end
 
+  def movetimes
+    ret = []
+    @str.gsub(%r!^T(\d+)!) do |match|
+      ret << $1.to_i
+    end
+    return ret
+  end
+
   def to_s
     return "Summary: #{@file_name}\n" +
            "BlackName #{@black_name}, WhiteName #{@white_name}\n" +
   def to_s
     return "Summary: #{@file_name}\n" +
            "BlackName #{@black_name}, WhiteName #{@white_name}\n" +
diff --git a/utils/statistics.rb b/utils/statistics.rb
new file mode 100755 (executable)
index 0000000..f9ab9d8
--- /dev/null
@@ -0,0 +1,205 @@
+#!/usr/bin/ruby1.9.1
+# This program filters CSA files. For example, if you want only CSA files
+# played by GPS vs Bonanza,
+#   $ ./csa-filter.rb --players gps-l,bonanza some_dir
+# you will see such files under the some_dir directory.
+#
+# Author::    Daigo Moriwaki <daigo at debian dot org>
+# Copyright:: Copyright (C) 2006-2008  Daigo Moriwaki <daigo at debian dot org>
+#
+# $Id$
+#
+#--
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+#++
+
+$:.unshift File.dirname(__FILE__)
+require 'csa-filter'
+require 'set'
+
+class Monthly
+  def initialize
+    @games = Hash.new {|hash,key| hash[key] = 0}
+    @players = Hash.new {|hash,key| hash[key] = Set.new}
+  end
+
+  def add(csa)
+    st = csa.start_time
+    month = st.strftime("%Y%m")
+
+    @games[month] += 1
+
+    [csa.black_id, csa.white_id].each do |player|
+      @players[month].add(player)
+    end
+  end
+
+  def print
+    puts "YYYYMM\t#games\t#players"
+    @games.sort {|a,b| a[0] <=> b[0]}.each do |key,value|
+      puts "%s\t% 6d\t% 2d" % [key, value, @players[key].size]
+    end
+  end
+end
+
+class Values
+  def initialize
+    @v = []
+  end
+
+  def add(value)
+    case value
+    when Array 
+     @v.concat value
+    else
+      @v << value
+    end
+  end
+
+  def print(file)
+    total = @v.inject(0){|sum, item| sum+item}
+    avg   = 1.0*total/@v.size
+    puts "avg: %f sec (size: %d)" % [avg, @v.size]
+
+    File.open(file, "w") do |f|
+      @v.each {|v| f.puts v}
+    end
+  end
+end
+
+class State
+  def initialize
+    @hash = Hash.new {|hash,key| hash[key] = 0}
+  end
+
+  def add(value)
+    if value.nil? || value.empty?
+      value = "error"
+    end
+    @hash[value] += 1
+  end
+
+  def print
+    puts "status\t#games"
+    @hash.sort {|a,b| b[1] <=> a[1]}.each do |key, value|
+      puts "%s\t% 6d" % [key, value]
+    end
+  end
+end
+
+$monthly  = Monthly.new
+$gametime = Values.new
+$movetime = Values.new
+$moves    = Values.new
+$states   = State.new
+
+def do_file(file)
+  $OPT_REPEAT -= 1 if $OPT_REPEAT > 0
+  csa = CsaFileReader.new(file)
+
+  # Want to see complete games
+  $states.add csa.state
+  return unless csa.state == "toryo"
+
+  # See games between 2008/03 to 2009/07
+  return if csa.start_time <  Time.parse("2008/03/01") ||
+            csa.start_time >= Time.parse("2009/08/01")
+
+  # Process monthly
+  $monthly.add(csa)
+
+  # Process gametime
+  duration = (csa.end_time - csa.start_time).to_i
+  if duration > 2200
+    $stderr.puts "Too long game: #{file}"
+    return
+  end
+  $gametime.add duration.to_i
+
+  # Process movetime
+  values = csa.movetimes
+  $movetime.add values
+
+  #Process moves
+  $moves.add values.size
+
+rescue => ex
+  $stderr.puts "ERROR: %s" % [file]
+  throw ex
+end
+
+if $0 == __FILE__
+  def usage
+    puts "Usage: #{$0} [OPTIONS] dir [...]"
+    puts "Options:"
+    exit 1
+  end
+
+  usage if ARGV.empty?
+
+  parser = GetoptLong.new(
+             ['--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT]
+           )
+  begin
+    parser.each_option do |name, arg|
+      eval "$OPT_#{name.sub(/^--/, '').gsub(/-/, '_').upcase} = '#{arg}'"
+    end
+  rescue
+    usage
+  end
+
+  $OPT_REPEAT = $OPT_REPEAT.to_i
+  if $OPT_REPEAT == 0
+    $OPT_REPEAT = -1
+  end
+
+  while (cmd = ARGV.shift)
+
+    if FileTest.directory?(cmd)
+      Dir.glob(File.join(cmd, "**", "*.csa")).each do |file|
+        break if $OPT_REPEAT == 0
+        do_file(file)
+      end
+    elsif FileTest.file?(cmd)
+      break if $OPT_REPEAT == 0
+      do_file(cmd)
+    else
+      throw "Unknown file or directory: #{cmd}"
+    end
+
+    puts "States"
+    puts "------"
+    $states.print
+    puts
+    puts "=== Toryo Games ==="
+    puts
+    puts "Montly"
+    puts "------"
+    $monthly.print
+    puts
+    puts "Play Time"
+    puts "---------"
+    $gametime.print("gametime.dat")
+    puts
+    puts "Move Time"
+    puts "---------"
+    $movetime.print("movetime.dat")
+    puts
+    puts "Moves"
+    puts "-----"
+    $moves.print("moves.dat")
+  end
+end
+