#!/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"
]>
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