OSDN Git Service

Bump up the revision to 20160409.
[shogi-server/shogi-server.git] / shogi_server / time_clock.rb
index 08258de..6b0ee46 100644 (file)
@@ -24,35 +24,47 @@ module ShogiServer # for a namespace
 class TimeClock
 
   def TimeClock.factory(least_time_per_move, game_name)
-    total_time_str = nil
-    byoyomi_str = nil
-    if (game_name =~ /-(\d+)-(\d+)$/)
-      total_time_str = $1
-      byoyomi_str    = $2
-    end
-    total_time = total_time_str.to_i
-    byoyomi    = byoyomi_str.to_i
-    if (byoyomi_str == "060")
-      @time_clock = StopWatchClock.new(least_time_per_move, total_time, byoyomi)
+    time_map = Game.parse_time game_name
+
+    if time_map[:stop_watch]
+      @time_clock = StopWatchClock.new(least_time_per_move, time_map[:total_time], time_map[:byoyomi])
     else
-      @time_clock = ChessClock.new(least_time_per_move, total_time, byoyomi)
+      if least_time_per_move == 0
+        @time_clock = ChessClockWithLeastZero.new(least_time_per_move,
+                                                  time_map[:total_time],
+                                                  time_map[:byoyomi],
+                                                  time_map[:fischer])
+      else
+        @time_clock = ChessClock.new(least_time_per_move,
+                                     time_map[:total_time],
+                                     time_map[:byoyomi],
+                                     time_map[:fischer])
+      end
     end
+
+    @time_clock
   end
 
-  def initialize(least_time_per_move, total_time, byoyomi)
+  def initialize(least_time_per_move, total_time, byoyomi, fischer=0)
     @least_time_per_move = least_time_per_move
     @total_time = total_time
-    @byoyomi     = byoyomi
+    @byoyomi    = byoyomi
+    @fischer    = fischer
   end
 
   # Returns thinking time duration
   #
-  def time_duration(start_time, end_time)
+  def time_duration(mytime, start_time, end_time)
     # implement this
     return 9999999
   end
 
+  # Returns what "Time_Unit:" in CSA protocol should provide.
+  #
+  def time_unit
+    return "1sec"
+  end
+
   # If thinking time runs out, returns true; false otherwise.
   #
   def timeout?(player, start_time, end_time)
@@ -63,8 +75,9 @@ class TimeClock
   # Updates a player's remaining time and returns thinking time.
   #
   def process_time(player, start_time, end_time)
-    t = time_duration(start_time, end_time)
-    
+    t = time_duration(player.mytime, start_time, end_time)
+
+    player.mytime += @fischer
     player.mytime -= t
     if (player.mytime < 0)
       player.mytime = 0
@@ -77,19 +90,19 @@ end
 # Calculates thinking time with chess clock.
 #
 class ChessClock < TimeClock
-  def initialize(least_time_per_move, total_time, byoyomi)
+  def initialize(least_time_per_move, total_time, byoyomi, fischer=0)
     super
   end
 
-  def time_duration(start_time, end_time)
+  def time_duration(mytime, start_time, end_time)
     return [(end_time - start_time).floor, @least_time_per_move].max
   end
 
   def timeout?(player, start_time, end_time)
-    t = time_duration(start_time, end_time)
+    t = time_duration(player.mytime, start_time, end_time)
 
-    if ((player.mytime - t <= -@byoyomi) && 
-        ((@total_time > 0) || (@byoyomi > 0)))
+    if ((player.mytime - t + @byoyomi + @fischer <= 0) &&
+        ((@total_time > 0) || (@byoyomi > 0) || (@fischer > 0)))
       return true
     else
       return false
@@ -97,22 +110,49 @@ class ChessClock < TimeClock
   end
 
   def to_s
-    return "ChessClock: LeastTimePerMove %d; TotalTime %d; Byoyomi %d" % [@least_time_per_move, @total_time, @byoyomi]
+    return "ChessClock: LeastTimePerMove %d; TotalTime %d; Byoyomi %d; Fischer" %
+      [@least_time_per_move, @total_time, @byoyomi, @fischer]
   end
 end
 
+# Calculates thinking time with chess clock, truncating decimal seconds for
+# thinking time. This is a new rule that CSA introduced in November 2014.
+#
+# least_time_per_move should be 0.
+# byoyomi should be more than 0.
+#
+class ChessClockWithLeastZero < ChessClock
+  def initialize(least_time_per_move, total_time, byoyomi, fischer=0)
+    if least_time_per_move != 0
+      raise ArgumentError, "least_time_per_move #{least_time_per_move} should be 0."
+    end
+    super
+  end
+
+  def to_s
+    return "ChessClockWithLeastZero: LeastTimePerMove %d; TotalTime %d; Byoyomi %d; Fischer %d" %
+      [@least_time_per_move, @total_time, @byoyomi, @fischer]
+  end
+end
+
+# StopWatchClock does not support Fischer time.
+#
 class StopWatchClock < TimeClock
   def initialize(least_time_per_move, total_time, byoyomi)
-    super
+    super least_time_per_move, total_time, byoyomi, 0
+  end
+
+  def time_unit
+    return "1min"
   end
 
-  def time_duration(start_time, end_time)
+  def time_duration(mytime, start_time, end_time)
     t = [(end_time - start_time).floor, @least_time_per_move].max
     return (t / @byoyomi) * @byoyomi
   end
 
   def timeout?(player, start_time, end_time)
-    t = time_duration(start_time, end_time)
+    t = time_duration(player.mytime, start_time, end_time)
 
     if (player.mytime <= t)
       return true