From 1a2f563ca8dc0f4e79b4746ee797b5375f9d2eaa Mon Sep 17 00:00:00 2001 From: Paolo Capriotti Date: Mon, 22 Jun 2009 17:48:12 +0200 Subject: [PATCH] Implemented clock logic. Implemented clock ticking, increment and byo-yomi. --- lib/clock.rb | 94 +++++++++++++++++++++++++++++++++++++++++++++ test/test_clock.rb | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 lib/clock.rb create mode 100644 test/test_clock.rb diff --git a/lib/clock.rb b/lib/clock.rb new file mode 100644 index 0000000..461d215 --- /dev/null +++ b/lib/clock.rb @@ -0,0 +1,94 @@ +class Clock + include Observable + ByoYomi = Struct.new(:time, :periods) + + # main = allotted time + # increment = increment per move + # byoyomi.time = time per move after main is elapsed + # byoyomi.periods = number of times byoyomi.time has to elapse + # for the byoyomi to end + # + # byoyomi and increment don't work together + # + # all times are in seconds + # + def initialize(main, increment, byoyomi, timer_class = Qt::Timer) + @main = main + @increment = increment + if byoyomi + @byoyomi = byoyomi.dup + @byoyomi_time = @byoyomi.time + end + + @timer = timer_class.new + @timer.single_shot = true + @timer.on(:timeout) { tick } + end + + def start + @count = 0 + @elapsed = 0 + @time = Qt::Time.new + + @time.start + @timer.start(100) + end + + def stop + @elapsed += @time.elapsed + @timer.stop + + @main += @increment + + fire :timer => { :main => @main } + end + + def resume + # milliseconds for the next tick + delta = (@count + 1) * 100 - @elapsed + @time.start + @timer.start(delta) + end + + def tick + # update counter + @count += 1 + elapsed = false + + # update clock state + if @count % 10 == 0 + if @main <= 0 + # if we get here, there must be + # a byoyomi, otherwise the timer would + # be stopped + @byoyomi.time -= 1 + if @byoyomi.time <= 0 + @byoyomi.periods -= 1 + @byoyomi.time = @byoyomi_time + if @byoyomi.periods <= 0 + elapsed = true + end + end + else + @main -= 1 + if @main <= 0 and (not @byoyomi) + elapsed = true + end + end + + if elapsed + fire :elapsed + elsif @main > 0 + fire :timer => { :main => @main } + else + fire :timer => { :byoyomi => @byoyomi.dup } + end + end + + if not elapsed + # schedule next tick + delta = (@count + 1) * 100 - @elapsed - @time.elapsed + @timer.start(delta) + end + end +end \ No newline at end of file diff --git a/test/test_clock.rb b/test/test_clock.rb new file mode 100644 index 0000000..01e07b6 --- /dev/null +++ b/test/test_clock.rb @@ -0,0 +1,111 @@ +require 'test/unit' +require 'clock' + +class TestClock < Test::Unit::TestCase + class FakeTimer + def on(*args) + end + + def single_shot=(val) + end + + def start(ms) + end + + def stop + end + end + + def test_main + elapsed = false + timer = nil + + # 2 seconds main time + clock = Clock.new(2, 0, nil, FakeTimer) + clock.observe(:timer) {|timer|} + clock.observe(:elapsed) { elapsed = true } + clock.start + + clock.tick + assert ! elapsed + assert_nil timer + + 8.times { clock.tick } + assert ! elapsed + assert_nil timer + + clock.tick + assert ! elapsed + assert_equal({ :main => 1 }, timer) + timer = nil + + 9.times { clock.tick } + assert ! elapsed + assert_nil timer + + clock.tick + assert elapsed + assert_nil timer + end + + def test_increment + elapsed = false + timer = nil + + # 10 seconds main time, 1 second increment + clock = Clock.new(10, 1, nil, FakeTimer) + clock.observe(:timer) {|timer|} + clock.observe(:elapsed) { elapsed = true } + clock.start + + 80.times { clock.tick } + assert ! elapsed + assert_equal({:main => 2}, timer) + timer = nil + + clock.stop + assert ! elapsed + assert_equal({:main => 3}, timer) + clock.resume + + 15.times { clock.tick } + assert ! elapsed + assert_equal({:main => 2}, timer) + timer = nil + + 14.times { clock.tick } + assert ! elapsed + assert_equal({:main => 1}, timer) + timer = nil + + clock.tick + assert elapsed + assert_nil timer + end + + def test_byoyomi + elapsed = false + timer = nil + + # 10 seconds main time, 1 second byoyomi, 2 periods + clock = Clock.new(10, 0, Clock::ByoYomi.new(1, 2), FakeTimer) + clock.observe(:timer) {|timer|} + clock.observe(:elapsed) { elapsed = true } + clock.start + + 80.times { clock.tick } + assert ! elapsed + assert_equal({:main => 2}, timer) + + 25.times { clock.tick } + assert ! elapsed + assert_equal({:byoyomi => Clock::ByoYomi.new(1, 2)}, timer) + + 10.times { clock.tick } + assert ! elapsed + assert_equal({:byoyomi => Clock::ByoYomi.new(1, 1) }, timer) + + 5.times { clock.tick } + assert elapsed + end +end -- 2.11.4.GIT