#!/usr/local/bin/ruby -w #REK_TITLE: class Bowling 2004-03-15版 #FILENAME: Bowling.rb =begin BowlliardsまたはBowlingのスコアシートをsvgに変換するためのクラスを定義 したファイルです。 Bowling::Result クラス 倒したピンの数の配列を引数にとります。スプリットの場合は+10して下さい。 ストライクは10、ガターやミスは0とします。配列の要素はすべて整数値です。 ファールは扱いません。 得点の計算とsvg出力のための準備をします。 Bowling::ScoreSheet クラス svgで出力するためのクラスです。一枚のシートに複数ゲームのスコアをおさ めることができます。 使い方は...サンプルを参照して下さい。 2004/03/15 くりまれいじ reiji@kurima.net 2004-03-15 sampleを用意 2004-03-11 10フレの処理を修正 2004-03-09 Bowling::stats なんて追加してみたり =end module Bowling class Result attr_reader :pts, :name, :namesize, :cont, :split_frame attr_reader :n_strike, :n_spare def initialize(_ary, param={}) @split_frame = [] @name = param.fetch("name",'') @namesize = param.fetch("namesize", 50) @namesize = 0 if @name == '' @name = '' if @namesize == 0 ary = _ary.dup @pts = 0 @n_strike = 0 @n_spare = 0 @cont = [] (1..12).each do |fnum| next if ary.size == 0 if ary[0] > 10 @split_frame << fnum ary[0] -= 10 end @pts += ary[0] ex1 = ( ary[1] != nil ? ary[1] : 0) ex2 = ( ary[2] != nil ? ary[2] : 0) ex1 = ( ex1 > 10 ? ex1 - 10 : ex1 ) ex2 = ( ex2 > 10 ? ex2 - 10 : ex2 ) if ary[0] == 10 @pts = @pts + ex1 + ex2 @cont << [nil, "X", @pts] @n_strike += 1 elsif ary[0] + ex1 == 10 @pts = @pts + ex1 + ex2 ary[0] = "G" if ary[0] == 0 @cont << [ary[0], "/", @pts] @n_spare += 1 else @pts += ex1 ary[0] = "G" if ary[0] == 0 ary[1] = "-" if ary[1] == 0 @cont << [ary[0], ary[1], @pts] end ary.shift if ary[0] != 10 ary.shift end if @cont.size != 10 ## @cont << [nil,nil,0] a = [@cont[9][0,2],@cont[10][0,2],@cont[11][0,2]].flatten.compact @pts = @cont[9][-1] @cont[9] = [a[0], a[1], @pts, a[2]] end end end ## class Result TEMPLATE=<<"END" ]> {{ var name=svg_defs}} {{ var name=scoresheet}} END class ScoreSheet def initialize @results = [] end def add(bwres) @results << bwres end def svg_def_frame(fx, fy) hx = fx * .5; hy = fy * .5 pdata = ["M", hx, 0, "l",0,hy, "l",hx,0, "l",0,-hy, "l", -fx, 0, "l",0,fy, "l",fx,0, "l",0,-hy] s = [%Q!!] s << %Q! ! s << %Q!! return s end def svg_def_frame10(fx, fy) hx = fx * .5; hy = fy * .5 pdata = ["M", hx ,0, "l",0,hy, "l",hx,0, "l",0,-hy, "l", -fx, 0, "l",0,fy, "l",hx * 3,0, "l",0,-fy, "l",-hx,0, "l",0,hy, "l",hx,0]; s = [%Q!!] s << %Q! ! s << %Q!! return s end def svg_def_strike(fx,fy) hx = fx * .5; qx = fx * .25 hy = fy * .5; qy = fy * .25 s = [%Q!!] s << %Q! ! s << %Q!! return s end def svg_def_spare(fx,fy) hx = fx * .5; qx = fx * .25 hy = fy * .5; qy = fy * .25 s = [%Q!!] s << %Q! ! s << %Q!! return s end def svg_def_split(r) s = [%Q!!] s << %Q! ! s << %Q!! return s end def addobj(obj, x, y) s = [%Q! !] case obj when "X" s << %Q! ! when "/" s << %Q! ! else s << %Q! #{obj}! end s << %Q! ! return s end def to_svg(param = {}, template = '') if template == '' template = TEMPLATE.dup end fx = param.fetch('fx',30).to_i fy = param.fetch('fy',30).to_i hx = fx * .5; qx = fx * .25 hy = fy * .5; qy = fy * .25 svg_x = param.fetch('svg_x',0).to_i svg_y = param.fetch('svg_y',0).to_i if svg_y == 0 svg_y = fy + 10 svg_y += (@results.size - 1) * (fy + 5) end if svg_x == 0 svg_x = 10 + fx * 10.5 svg_x = svg_x + @results[-1].namesize end param["svg_x"] = svg_x param["svg_y"] = svg_y svg_defs = [] svg_defs << svg_def_frame(fx, fy) svg_defs << svg_def_frame10(fx, fy) svg_defs << svg_def_strike(fx,fy) svg_defs << svg_def_spare(fx,fy) svg_defs << svg_def_split((qx > qy ? qy : qx) * .9) param["svg_defs"] = svg_defs.join("\n") ## scoresheet svg_sheet = [] @results.each_with_index do |bw,idx| svg_sheet << %Q!! svg_sheet << %Q!! svg_sheet << %Q!#{bw.name}! svg_sheet << %Q!! ## normal frames (1..9).each do |fnum| a = bw.cont[fnum - 1] svg_sheet << %Q!! svg_sheet << %Q! ! [[qx, qy],[qx * 3, qy],[hx , qy * 3]].each_with_index do |xy,i| next if a[i] == nil svg_sheet << addobj(a[i], *xy) end if bw.split_frame.index(fnum) svg_sheet << %Q! ! svg_sheet << %Q! ! svg_sheet << %Q! ! end svg_sheet << %Q!! end ### 10th frame [10].each do |fnum| a = bw.cont[fnum - 1] svg_sheet << %Q!! svg_sheet << %Q! ! [[qx,qy],[qx * 3, qy],[qx * 3, qy * 3]].each_with_index do |xy,i| svg_sheet << addobj(a[i], *xy) end if a.size == 4 ## upper right svg_sheet << addobj(a[3], qx * 5, qy) end (10..12).each do |i| if bw.split_frame.index(i) j = (i - 10) * 2 + 1 svg_sheet << %Q! ! svg_sheet << %Q! ! svg_sheet << %Q! ! end end svg_sheet << %Q!! end ## [10].each do |fnum| svg_sheet << %Q!! end param["scoresheet"] = svg_sheet.join("\n") svgtempl = template.dup template.scan(/(\{\{ *?var name=(.*?) *?\}\})/).each do |ss| svgtempl.sub!(Regexp.escape(ss[0]), param.fetch(ss[1],'UNDEF').to_s) end return svgtempl end end ## class ScoreSheet module_function def stats(results) points = results.collect{|res| res.pts} rstats = {} rstats["games"] = points.size rstats["max"] = points.max rstats["min"] = points.min sum = 0 n_strike = 0 n_spare = 0 results.each do |res| sum += res.pts n_strike += res.n_strike n_spare += res.n_spare end rstats["ave"] = sum / points.size.to_f rstats["n_strike"] = n_strike rstats["n_spare"] = n_spare rstats["history"] = points return rstats end end if __FILE__ == $0 results = [] ## results << [10,10,10,10,10,10,10,10,10,10,10,10] results << [9,1,18,0,0,10,10,7,2,9,1,17,0,10,7,2,10,10,18] results << [9,1,18,0,0,10,10,7,2,9,1,17,0,10,7,2,10,10,0] results << [9,1,18,0,0,10,10,7,2,9,1,17,0,10,7,3,10,0,0] results << [9,1,18,0,0,10,10,7,2,9,1,17,0,10,10,10,18,2] results << [9,1,18,0,0,10,10,7,2,9,1,17,0,10,7,2,18,2,0] results << [9,1,18,0,0,10,10,7,2,9,1,17,0,10,7,2,0,10,10] results << [9,1,18,0,0,10,10,7,2,9,1,17,0,10,7,2,8,1] results << [9,1,18,0,0,10,10,7,2,9,1,17,0,10,7,2,7,0] myresults = [] sheet = Bowling::ScoreSheet.new results.each do |ary| res = Bowling::Result.new(ary) sheet.add(res) myresults << res end stats = Bowling::stats(myresults) #p stats #open("/share/hoge.svg","w") do |fp| # fp.puts sheet.to_svg #end puts sheet.to_svg end