X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=utils%2Feval_graph.rb;h=fbf42fe056fb5c5c62f9d0f01de44d44a73eeeac;hb=04d3404e19f33232638e2ea7b7e08476833f3a8b;hp=8f212f6cd8a625ef727fcece2db469039aafd2d9;hpb=4a23a155dc322a8247214ed28b43d55c423775ca;p=shogi-server%2Fshogi-server.git diff --git a/utils/eval_graph.rb b/utils/eval_graph.rb index 8f212f6..fbf42fe 100755 --- a/utils/eval_graph.rb +++ b/utils/eval_graph.rb @@ -1,29 +1,32 @@ -#!/usr/bin/env ruby -# This generates graphs of evaluation values from comments in CSA files. -# Ruby libraries that are required: -# - RubyGems: http://rubyforge.org/projects/rubygems/ -# - rgplot: http://rubyforge.org/projects/rgplot/ -# OS librariles that is required: -# - Gnuplot: http://www.gnuplot.info/ -# On Debian, $ sudo apt-get install gnuplot -# -# Copyright (C) 2006 Daigo Moriwaki +#!/usr/bin/ruby +# This generates graphs of evaluation values from comments in CSA files. +# Ruby libraries that are required: +# * RubyGems: http://rubyforge.org/projects/rubygems/ +# * rgplot: http://rubyforge.org/projects/rgplot/ +# OS librariles that is required: +# * Gnuplot: http://www.gnuplot.info/ +# * On Debian, $ sudo apt-get install gnuplot # -# Version: $Id$ +# Author:: Daigo Moriwaki +# Copyright:: Copyright (C) 2006-2008 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 -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. +# $Id$ # -# 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. +#-- +# 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. # -# 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 +# 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 +#++ require 'pathname' require 'getoptlong' @@ -36,10 +39,18 @@ end def reformat_svg(str) str.gsub(%r!!m, <<-END) - - END + +END +end + +# Parse play time from the game_name, then return it. If the game_name is +# not valid, return 0. +# +def play_time(game_name) + if /.*?\+.*?\-(\d*?)\-/ =~ game_name + return $1.to_i + end + return 0 end module EvalGraph @@ -59,11 +70,15 @@ module EvalGraph attr_accessor :theOther attr_reader :name, :comments, :start_time + # type is '+' or '-' def initialize(type) - @comments = [] + @comments = [] + @times = [] @type = type - @regexp_move = Regexp.new("^\\#{@type}\\d{4}\\w{2}") - @regexp_name = Regexp.new("^N\\#{@type}(.*)") + @regexp_move = Regexp.new("^\\#{@type}\\d{4}\\w{2}") + @regexp_name = Regexp.new("^N\\#{@type}(.*)") + @regexp_time = Regexp.new(/^T(\d+)/) + @regexp_comment = Regexp.new(/^'\*\*(.*)/) @flag = false @name = nil end @@ -80,7 +95,11 @@ module EvalGraph when @regexp_move @flag = true @theOther.reset - when /^'\*\*(.*)/ + when @regexp_time + if @flag + @times << $1.to_i + end + when @regexp_comment if @flag @comments << EvalGraph::parse_comment($1) @flag = false @@ -92,7 +111,26 @@ module EvalGraph end end - end + # Return times for each move which the player played. + # return[0] is the initial play_time. + # + def time_values(y_max, play_time) + consume = play_time + values = [] + values << 1.0*y_max/play_time*consume + @times.each do |t| + if consume == 0 + break + end + consume -= t + if consume < 0 + consume = 0 + end + values << 1.0*y_max/play_time*consume + end + return values + end + end # Player class Black < Player def name @@ -104,12 +142,26 @@ module EvalGraph def eval_values moves = [] comments.each_with_index do |c, i| - moves << i*2 + 1 if c + moves << i*2 if c end moves.unshift 0 [moves, comments.compact.unshift(0)] end - end + + # Return moves and times. For example, [[0,1,3], [900, 899, 898]] + def time_values(y_max, play_time) + values = super + moves = [0] + return [moves, values] if values.size <= 1 + + i = 1 + values[1, values.size-1].each do |v| + moves << i + i += 2 + end + return [moves, values] + end + end # Black class White < Player def name @@ -119,12 +171,25 @@ module EvalGraph def eval_values moves = [] comments.each_with_index do |c, i| - moves << i*2 if c + moves << i*2+1 if c end moves.unshift 0 [moves, comments.compact.unshift(0)] end - end + + def time_values(y_max, play_time) + values = super + moves = [0] + return [moves, values] if values.size <= 1 + + i = 2 + values[1, values.size-1].each do |v| + moves << i + i += 2 + end + return [moves, values] + end + end # White def create_players @@ -135,14 +200,14 @@ module EvalGraph return black,white end module_function :create_players -end +end # module EvalGraph -def plot(csa_file, title, black, white) +def plot(csa_file, title, black, white, a_play_time) width = [black.comments.size, white.comments.size].max * 2 + 1 Gnuplot.open do |gp| Gnuplot::Plot.new( gp ) do |plot| - plot.terminal "svg" # or png + plot.terminal "svg size 800 500 fixed" # or png plot.output to_svg_file(csa_file) plot.title title @@ -159,24 +224,46 @@ def plot(csa_file, title, black, white) plot.size "0.9,0.9" plot.key "left" + plot.style "line 1 linewidth 5 linetype 0 linecolor rgbcolor \"red\"" + plot.style "line 2 linewidth 4 linetype 0 linecolor rgbcolor \"dark-green\"" + plot.data << Gnuplot::DataSet.new( black.eval_values ) do |ds| - ds.with = "lines" + ds.with = "lines ls 1" ds.title = black.name end plot.data << Gnuplot::DataSet.new( white.eval_values ) do |ds| - ds.with = "lines" + ds.with = "lines ls 2" ds.title = white.name end - + + if a_play_time > 0 + plot.style "line 5 linewidth 1 linetype 0 linecolor rgbcolor \"red\"" + plot.style "line 6 linewidth 1 linetype 0 linecolor rgbcolor \"green\"" + plot.style "fill solid 0.25 noborder" + + plot.data << Gnuplot::DataSet.new( black.time_values(3000, a_play_time) ) do |ds| + ds.with = "boxes notitle ls 5" + end + + plot.data << Gnuplot::DataSet.new( white.time_values(-3000, a_play_time) ) do |ds| + ds.with = "boxes notitle ls 6" + end + end # if + end end end - -def read(lines, file_name) +# Read kifu, a record of moves, to generate a graph file. +# lines are contents of the kifu. +# file is a file name of a genrating image file. +# original_file_name is a file name of the csa file. +# +def read(lines, file_name, original_file_name=nil) lines.map! {|l| l.strip} + original_file_name ||= file_name black,white = EvalGraph.create_players while l = lines.shift do @@ -185,7 +272,8 @@ def read(lines, file_name) end title = "#{file_name}" - plot(file_name, title, black, white) + a_play_time = play_time(original_file_name) + plot(file_name, title, black, white, a_play_time) end