OSDN Git Service

a87e44fac9fda4953208e344e200d13ec6af11b5
[shogi-server/shogi-server.git] / utils / csa-filter.rb
1 #!/usr/bin/ruby
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 require 'time'
29 require 'pathname'
30 require 'getoptlong'
31
32 class CsaFileReader
33   WIN_MARK  = "win"
34   LOSS_MARK = "lose"
35   DRAW_MARK = "draw"
36
37   attr_reader :file_name
38   attr_reader :black_name, :white_name
39   attr_reader :black_id, :white_id
40   attr_reader :winner, :loser
41   attr_reader :start_time, :end_time
42
43   def initialize(file_name)
44     @file_name = file_name
45     grep
46   end
47
48   def grep
49     str = File.open(@file_name).read
50
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"
56       p1_name, p1_mark = p1.split(" ")
57       p2_name, p2_mark = p2.split(" ")
58       if p1_name == @black_name
59         @black_name, black_mark = p1_name, p1_mark
60         @white_name, white_mark = p2_name, p2_mark
61       elsif p2_name == @black_name
62         @black_name, black_mark = p2_name, p2_mark
63         @white_name, white_mark = p1_name, p1_mark
64       else
65         raise "Never reach!: #{black} #{white} #{p3} #{p2}"
66       end
67     end
68     if /^\$START_TIME:(.*)$/ =~ str
69       @start_time = Time.parse($1.strip)
70     end
71     if /^'\$END_TIME:(.*)$/ =~ str
72       @end_time = Time.parse($1.strip)
73     end
74     if /^'rating:(.*)$/ =~ str
75       black_id, white_id = $1.split(":").map {|a| a.strip}
76       @black_id = identify_id(black_id)
77       @white_id = identify_id(white_id)
78       if @black_id && @white_id && (@black_id != @white_id) &&
79          @black_mark && @white_mark
80         if black_mark == WIN_MARK && white_mark == LOSS_MARK
81           @winner, @loser = @black_id, @white_id
82         elsif black_mark == LOSS_MARK && white_mark == WIN_MARK
83           @winner, @loser = @white_id, @black_id
84         elsif black_mark == DRAW_MARK && white_mark == DRAW_MARK
85           @winner, @loser = nil, nil
86         else
87           raise "Never reached!"
88         end
89       end
90     end
91   end
92
93   def to_s
94     return "Summary: #{@file_name}\n" +
95            "BlackName #{@black_name}, WhiteName #{@white_name}\n" +
96            "BlackId #{@black_id}, WhiteId #{@white_id}\n" +
97            "Winner #{@winner}, Loser #{@loser}\n"    +
98            "Start #{@start_time}, End #{@end_time}\n"
99   end
100
101   def identify_id(id)
102     if /@NORATE\+/ =~ id # the player having @NORATE in the name should not be rated
103       return nil
104     end
105     id.gsub(/@.*?\+/,"+")
106   end
107 end
108
109
110 if $0 == __FILE__
111   def usage
112     puts "Usage: #{$0} [OPTIONS] dir [...]"
113     puts "Options:"
114     puts "  --players player_a,player_b  select games of the player_a vs the player_b"
115     puts "  --black player               select games of which the player is Black"
116     puts "  --white player               select games of which the player is White"
117     exit 1
118   end
119
120   usage if ARGV.empty?
121
122   parser = GetoptLong.new(
123              ['--black',   GetoptLong::REQUIRED_ARGUMENT],
124              ['--white',   GetoptLong::REQUIRED_ARGUMENT],
125              ['--players', GetoptLong::REQUIRED_ARGUMENT]
126            )
127   begin
128     parser.each_option do |name, arg|
129       eval "$OPT_#{name.sub(/^--/, '').gsub(/-/, '_').upcase} = '#{arg}'"
130     end
131   rescue
132     usage
133   end
134   
135   while dir = ARGV.shift
136     Dir.glob(File.join(dir, "**", "*.csa")).each do |file|
137       csa = CsaFileReader.new(file)
138
139       next unless csa.black_id && csa.white_id
140
141       if $OPT_PLAYERS
142         players = $OPT_PLAYERS.split(",")
143         unless (csa.black_id.downcase.index(players[0].downcase) == 0 &&
144                 csa.white_id.downcase.index(players[1].downcase) == 0) ||
145                (csa.black_id.downcase.index(players[1].downcase) == 0 &&
146                 csa.white_id.downcase.index(players[0].downcase) == 0)
147           next
148         end
149       end
150       
151       if $OPT_BLACK
152         next unless csa.black_id.downcase.index($OPT_BLACK.downcase) == 0
153       end
154       if $OPT_WHITE
155         next unless csa.white_id.downcase.index($OPT_WHITE.downcase) == 0
156       end
157       puts csa.file_name
158     end
159   end
160 end