http://d.hatena.ne.jp/hs9587/20100719/1279533327の続きというか、ライトニングトークを意識するならやっぱりカウントダウンが良いみたい。ので、そのように改造
LT_timer.rb
#coding:Windows-31J # $Id: LT_timer.rb 3590 2010-12-30 07:00:56Z hs9587 $ # $Date: 2010-12-30 16:00:56 +0900 (譛ィ, 30 12 2010) $ # $Name$ $Author: hs9587 $ $Revision: 3590 $ Version = "0.0 ($Revision: 3590 $)" require 'vr/vruby' require 'vr/vrcontrol' require 'vr/vrtimer' require 'vr/vrlayout' require 'time' Min = Time.parse('00:01')-Time.parse('00:00') class TimerControl < VRPanel include VRTimerFeasible include VRDrawable SrartResetStruct= Struct.new :name, :button, :body StartReset = [ SrartResetStruct.new('start', '!' \ , lambda{@start_time = Time.now; def anchor_time; @start_time; end}), SrartResetStruct.new('reset', '0' \ , lambda{def anchor_time; Time.now; end}), SrartResetStruct.new('close', '.', lambda{exit}), ] attr_writer :time_out, :time_color, :countdown def construct self.caption = 'LTTimer' #addTimer 1000 addTimer 50 @font = @screen.factory.newfont 'MS ゴシック', -72 #@font = @screen.factory.newfont 'HG ゴシックE', -72 #@font = @screen.factory.newfont 'HGS ゴシックE', -72 #@font = @screen.factory.newfont 'Tahoma', -72, 400, 0, 0, 0, 34, 0 #@font = @screen.factory.newfont 'Tahoma', -72 @time_out = 5.0 @time_color = 3.0 end # def construct def self_paint elapse = (Time.now - anchor_time).abs self.textColor = RGB elapsed(elapse), 0, 0 setFont @font mm_ss = mm_ss elapse #p textExtent(mm_ss) drawText mm_ss, 0,0, *textExtent(mm_ss) end # def self_paint def self_timer refresh end StartReset.each do |start_reset| define_method start_reset.name, start_reset.body end # StartReset.each do |start_reset| private def anchor_time Time.now end # def anchor_time def elapsed(sec) case sec when 0 ... Min*@time_color then 0 when Min*@time_color ... Min*@time_out then 256 * (sec - Min*@time_color) / (Min*(@time_out - @time_color)) else sec < 0 ? 0 : 255 end # case sec end # def elapsed(sec) def mm_ss(elapse) if @countdown then Time.at((@time_out*Min - elapse).floor.abs).strftime '%M:%S' else# if @countdown Time.at(elapse).strftime '%M:%S' end # if @countdown end # def mm_ss(elapse) end # class TimerControl < VRPanel class StartResetControl < VRPanel include VRVertLayoutManager include VRStdControlContainer def construct TimerControl::StartReset.each do |start_reset| addControl VRButton, start_reset.name, start_reset.button send_parent start_reset.name, 'clicked' end # TimerControl::StartReset.each do |start_reset| end # def construct end # class StartResetControl < VRPanel module LTTimer attr_reader :timer def construct self.caption = 'LTTimer' move 0,0, 198,104 addControl TimerControl, 'timer', 'Timer', 0,0, 180,72 addControl StartResetControl, 'buttons', 'Buttons', 181,0, 10,72 top 0xffffffff end # def construct TimerControl::StartReset.each do |start_reset| define_method("buttons_#{start_reset.name}_clicked") do @timer.send start_reset.name end # define_method("buttons_#{start_reset.name}_clicked") do end # TimerControl::StartReset.each do |start_reset| end # module LTTimer time_out, time_color, countdown, start = 5, 3, false, false require 'optparse' ARGV.options do |opt| opt.on('-o', '--timeout=VAL', "default: #{time_out}(min)"){|v| time_out = v.to_f} opt.on('-c', '--timecolor=VAL', "default: #{time_color}(min)"){|v| time_color = v.to_f} opt.on('-d', '--[no-]countdown', "default: #{countdown}"){|v| countdown = v} opt.on('-s', '--[no-]start', "default: #{start}"){|v| start = v} opt.banner << "\nLeft upper topmost timer" begin # rescue OptionParser::ParseError => evar opt.parse! rescue OptionParser::ParseError => evar evar.display $stderr; "\n".display $stderr opt.help.display $stderr exit 1 end # rescue OptionParser::ParseError => evar end # ARGV.options do |opt| #VRLocalScreen.start LTTimer lt = VRLocalScreen.showForm LTTimer lt.timer.time_out = time_out lt.timer.time_color = time_color lt.timer.countdown = countdown lt.timer.start if start VRLocalScreen.messageloop
カウントダウン用のオプションを定義した上で、大きな違いは表示分秒文字列をみる mm_ss(elapse)メソッドの所。
def mm_ss(elapse) if @countdown then Time.at((@time_out*Min - elapse).floor.abs).strftime '%M:%S' else# if @countdown Time.at(elapse).strftime '%M:%S' end # if @countdown end # def mm_ss(elapse)
floor注意、こうしないと0秒の前後で 1秒ずれる。
Time.at() の処理は self_paintメソッドでの elapse計算時からこっちに移動した。一方表示色の方は基本的に elapsed()メソッドでの計算の儘、Time.at()処理の移動に伴い .to_i はいらなくなった。
オプションはカウントダウン側をデフォルト動作にしたものかどうか迷い中。
opt.on の事
オプション解析のところなんだけど
opt.on('-s', '--[no-]start', "default: #{start}"){|v| start = v}
とか、同じキーワード(start)が 3回も出てくるのはちょっと気になる。
{:s => :start}.each do |s_opt, l_opt| opt.on("-#{s_opt}", "--[no-]#{l_opt}", "default: #{eval l_opt}"){|v| eval "#{l_opt} = v"} end # {:s => :start}.each do |s_opt, l_opt|
とかするのだろうか。でもロングオプションの引数記法「=VAL」を使う方との切り替えはちょっと何だし、ここで eval はやり過ぎの様な気もする。そもそもオプション値のやりとりにローカル変数を使ってるから eval になるので、ハッシュとか別のコンテナを使えばいいのかも知れない、高が 4つのオプションにそれも大げさな気がする。
追求してると optparse の DSLを作るという話になってしまうのだろうか。儘でいいや。