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