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.
7 # Author:: Daigo Moriwaki <daigo at debian dot org>
8 # Copyright:: Copyright (C) 2006-2012 Daigo Moriwaki <daigo at debian dot org>
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.
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.
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
38 attr_reader :file_name
40 attr_reader :black_name, :white_name
41 attr_reader :black_id, :white_id
42 attr_reader :winner, :loser
44 attr_reader :start_time, :end_time
47 def initialize(file_name, encoding="Shift_JIS:EUC-JP")
48 @file_name = file_name
55 @str = File.open(@file_name, "r:#{@encoding}").read
58 if /^N\+(.*)$/ =~ @str then @black_name = $1.strip end
59 if /^N\-(.*)$/ =~ @str then @white_name = $1.strip end
60 if /^'summary:(.*)$/ =~ @str
61 @state, p1, p2 = $1.split(":").map {|a| a.strip}
62 p1_name, p1_mark = p1.split(" ")
63 p2_name, p2_mark = p2.split(" ")
64 if p1_name == @black_name
65 @black_name, black_mark = p1_name, p1_mark
66 @white_name, white_mark = p2_name, p2_mark
67 elsif p2_name == @black_name
68 @black_name, black_mark = p2_name, p2_mark
69 @white_name, white_mark = p1_name, p1_mark
71 raise "Never reach!: #{black} #{white} #{p3} #{p2}"
74 if /^\$START_TIME:(.*)$/ =~ @str
75 @start_time = Time.parse($1.strip)
77 if /^'\$END_TIME:(.*)$/ =~ @str
78 @end_time = Time.parse($1.strip)
80 if /^'rating:(.*)$/ =~ @str
81 black_id, white_id = $1.split(":").map {|a| a.strip}
82 @black_id = identify_id(black_id)
83 @white_id = identify_id(white_id)
84 if @black_id && @white_id && (@black_id != @white_id) &&
85 @black_mark && @white_mark
86 if black_mark == WIN_MARK && white_mark == LOSS_MARK
87 @winner, @loser = @black_id, @white_id
88 elsif black_mark == LOSS_MARK && white_mark == WIN_MARK
89 @winner, @loser = @white_id, @black_id
90 elsif black_mark == DRAW_MARK && white_mark == DRAW_MARK
91 @winner, @loser = nil, nil
93 raise "Never reached!"
98 @str.each_line do |line|
99 if /^[\+\-]\d{4}[A-Z]{2}/ =~ line
107 @str.gsub(%r!^T(\d+)!) do |match|
114 return "Summary: #{@file_name}\n" +
115 "BlackName #{@black_name}, WhiteName #{@white_name}\n" +
116 "BlackId #{@black_id}, WhiteId #{@white_id}\n" +
117 "Winner #{@winner}, Loser #{@loser}\n" +
118 "Start #{@start_time}, End #{@end_time}\n" +
123 if /@NORATE\+/ =~ id # the player having @NORATE in the name should not be rated
126 id.gsub(/@.*?\+/,"+")
133 puts "Usage: #{$0} [OPTIONS] dir [...]"
135 puts " --players player_a,player_b select games of the player_a vs the player_b"
136 puts " --black player select games of which the player is Black"
137 puts " --white player select games of which the player is White"
143 parser = GetoptLong.new(
144 ['--black', GetoptLong::REQUIRED_ARGUMENT],
145 ['--white', GetoptLong::REQUIRED_ARGUMENT],
146 ['--players', GetoptLong::REQUIRED_ARGUMENT]
149 parser.each_option do |name, arg|
150 eval "$OPT_#{name.sub(/^--/, '').gsub(/-/, '_').upcase} = '#{arg}'"
156 while dir = ARGV.shift
157 Dir.glob(File.join(dir, "**", "*.csa")).each do |file|
158 csa = CsaFileReader.new(file)
160 next unless csa.black_id && csa.white_id
163 players = $OPT_PLAYERS.split(",")
164 unless (csa.black_id.downcase.index(players[0].downcase) == 0 &&
165 csa.white_id.downcase.index(players[1].downcase) == 0) ||
166 (csa.black_id.downcase.index(players[1].downcase) == 0 &&
167 csa.white_id.downcase.index(players[0].downcase) == 0)
173 next unless csa.black_id.downcase.index($OPT_BLACK.downcase) == 0
176 next unless csa.white_id.downcase.index($OPT_WHITE.downcase) == 0