X-Git-Url: http://git.sourceforge.jp/view?p=shogi-server%2Fshogi-server.git;a=blobdiff_plain;f=mk_rate;h=f935acbb97a512a69b10086b8c06c2ac3b4a51f1;hp=5c8dd04aa194d0373482d2bc5bc588871f1527fa;hb=1cb7d05f325c8d6f4790f5ec109969cac86eeae5;hpb=810c0751b2b94f92fd50b4c769fda4ed571f1942 diff --git a/mk_rate b/mk_rate index 5c8dd04..f935acb 100755 --- a/mk_rate +++ b/mk_rate @@ -5,7 +5,7 @@ # Homepage:: http://sourceforge.jp/projects/shogi-server/ # #-- -# Copyright (C) 2006-2008 Daigo Moriwaki +# Copyright (C) 2006-2009 Daigo Moriwaki # # 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 @@ -34,6 +34,9 @@ # DIR:: # CSA files are recursively looked up the directories. # +# --base-date:: +# a base time point for this calicuration (default now). Ex. '2009-10-31' +# # --half-life:: # n [days] (default 60) # @@ -47,6 +50,10 @@ # --fixed-rate:: # rate # +# --skip-draw-games:: +# skip draw games. [default: draw games are counted in as 0.5 win and 0.5 +# lost.] +# # --help:: # show this message # @@ -466,14 +473,19 @@ class WinLossMatrix end ## - # Removes a delete_index'th player and returns a new object. + # Removes players in a rows such as [1,3,5], and then returns a new + # object. # - def delete_row(delete_index) + def delete_rows(rows) + rows = rows.sort.reverse + copied_cols = [] (0...size).each do |i| - next if i == delete_index + next if rows.include?(i) row = @matrix.row(i).clone - row.delete_at(delete_index) + rows.each do |j| + row.delete_at(j) + end copied_cols << row end if copied_cols.size == 0 @@ -481,20 +493,13 @@ class WinLossMatrix else new_matrix = GSL::Matrix[*copied_cols] end - new_keys = @keys.clone - new_keys.delete_at(delete_index) - return WinLossMatrix.new(new_keys, new_matrix) - end - ## - # Removes players in a rows; [1,3,5] - # - def delete_rows(rows) - obj = self - rows.sort.reverse.each do |index| - obj = obj.delete_row(index) + new_keys = @keys.clone + rows.each do |j| + new_keys.delete_at(j) end - obj + + return WinLossMatrix.new(new_keys, new_matrix) end ## @@ -593,13 +598,21 @@ def half_life(days) end def _add_win_loss(winner, loser, time) - how_long_days = (Time.now - time)/(3600*24) + how_long_days = ($options["base-date"] - time)/(3600*24) $players[winner] ||= Hash.new { GSL::Vector[0,0] } $players[loser] ||= Hash.new { GSL::Vector[0,0] } $players[winner][loser] += GSL::Vector[1.0*half_life(how_long_days),0] $players[loser][winner] += GSL::Vector[0,1.0*half_life(how_long_days)] end +def _add_draw(player1, player2, time) + how_long_days = ($options["base-date"] - time)/(3600*24) + $players[player1] ||= Hash.new { GSL::Vector[0,0] } + $players[player2] ||= Hash.new { GSL::Vector[0,0] } + $players[player1][player2] += GSL::Vector[0.5*half_life(how_long_days),0.5*half_life(how_long_days)] + $players[player2][player1] += GSL::Vector[0.5*half_life(how_long_days),0.5*half_life(how_long_days)] +end + def _add_time(player, time) $players_time[player] = time if $players_time[player] < time end @@ -610,7 +623,11 @@ def add(black_mark, black_name, white_name, white_mark, time) elsif black_mark == LOSS_MARK && white_mark == WIN_MARK _add_win_loss(white_name, black_name, time) elsif black_mark == DRAW_MARK && white_mark == DRAW_MARK - return + if $options["skip-draw-games"] + return + else + _add_draw(black_name, white_name, time) + end else raise "Never reached!" end @@ -625,45 +642,26 @@ def identify_id(id) id.gsub(/@.*?\+/,"+") end -def grep(file) - str = File.open(file).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" - p1_name, p1_mark = p1.split(" ") - p2_name, p2_mark = p2.split(" ") - if p1_name == black_name - black_name, black_mark = p1_name, p1_mark - white_name, white_mark = p2_name, p2_mark - elsif p2_name == black_name - black_name, black_mark = p2_name, p2_mark - white_name, white_mark = p1_name, p1_mark - else - raise "Never reach!: #{black} #{white} #{p3} #{p2}" - end - end - if /^'\$END_TIME:(.*)$/ =~ str - time = Time.parse($1.strip) - end - 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) - if black_id && white_id && (black_id != white_id) - add(black_mark, black_id, white_id, white_mark, time) - end +# Parse a game result line +# +def parse(line) + time, state, black_mark, black_id, white_id, white_mark, file = line.split("\t") + unless time && state && black_mark && black_id && + white_id && white_mark && file + $stderr.puts "Failed to parse the line : #{line}" + return end -end -def usage - $stderr.puts <<-EOF -USAGE: #{$0} dir [...] - EOF - exit 1 + return if state == "abnormal" + time = Time.parse(time) + return if $options["base-date"] < time + black_id = identify_id(black_id) + white_id = identify_id(white_id) + + if black_id && white_id && (black_id != white_id) && + black_mark && white_mark + add(black_mark, black_id, white_id, white_mark, time) + end end def validate(yaml) @@ -684,11 +682,14 @@ def usage(io) USAGE: #{$0} [options] DIR.. DIR where CSA files are looked up recursively OPTOINS: + --base-date a base time point for this calicuration (default now). Ex. '2009-10-31' --half-life n [days] (default 60) --half-life-ignore m [days] (default 7) after m days, half-life effect works --fixed-rate-player player whose rate is fixed at the rate --fixed-rate rate + --skip-draw-games skip draw games. [default: draw games are counted in + as 0.5 win and 0.5 lost] --help show this message EOF end @@ -696,11 +697,13 @@ end def main $options = Hash::new parser = GetoptLong.new( + ["--base-date", GetoptLong::REQUIRED_ARGUMENT], ["--half-life", GetoptLong::REQUIRED_ARGUMENT], ["--half-life-ignore", GetoptLong::REQUIRED_ARGUMENT], ["--help", "-h", GetoptLong::NO_ARGUMENT], ["--fixed-rate-player", GetoptLong::REQUIRED_ARGUMENT], - ["--fixed-rate", GetoptLong::REQUIRED_ARGUMENT]) + ["--fixed-rate", GetoptLong::REQUIRED_ARGUMENT], + ["--skip-draw-games", GetoptLong::NO_ARGUMENT]) parser.quiet = true begin parser.each_option do |name, arg| @@ -721,14 +724,29 @@ def main usage($stdout) exit 0 end + if $options["base-date"] + $options["base-date"] = Time::parse $options["base-date"] + else + $options["base-date"] = Time.now + end $options["half-life"] ||= 60 $options["half-life"] = $options["half-life"].to_i $options["half-life-ignore"] ||= 7 $options["half-life-ignore"] = $options["half-life-ignore"].to_i $options["fixed-rate"] = $options["fixed-rate"].to_i if $options["fixed-rate"] - while dir = ARGV.shift do - Dir.glob( File.join(dir, "**", "*.csa") ) {|f| grep(f)} + if ARGV.empty? + while line = $stdin.gets do + parse line.strip + end + else + while file = ARGV.shift do + File.open(file) do |f| + f.each_line do |line| + parse line.strip + end + end + end end yaml = {}