#!/usr/bin/env python
"""Go timer.
This module defines a UI that combines game clock with automatic game recording.
When player presses the clock, an image of the board is taken. The sequence of
images can later be analysed by Imago to produce a game record in abstract
notation.
"""
import os
import sys
import time
import argparse
import subprocess
import pygame
[docs]class Timer:
"""Keeps track of time remaining one player."""
def __init__(self, main_time, byop, byot):
self._last = 0
self._elapsed = 0.
self._main_t = main_time
self.byost = "main time"
self._byop = byop + 1
self._byot = byot
self._byo = False
[docs] def get_time(self):
"""Return string representation of remaining time."""
if self._last > 0: # when running:
r_time = self._main_t - (time.time() - self._last + self._elapsed)
if (r_time - int(r_time)) < 0.75:
sep = ":"
else:
sep = " "
else: # not running:
if self._byo and self._byop > 0:
self._elapsed = 0
r_time = self._main_t - self._elapsed
sep = ":"
if r_time < 0:
self._byo = True
self._main_t = self._byot
self._byop -= 1
if self._byop > 0:
self._elapsed = 0
self._last = time.time()
self.byost = "(" + str(self._byop) + ")"
return self.get_time()
else:
r_time = 0
self.byost = "lost on time"
return "{0:0>2}".format(int(r_time / 60)) + sep + "{0:0>2}".format(int(r_time % 60))
[docs] def start(self):
"""Start the clock."""
self._last = time.time()
[docs] def stop(self):
"""Stop the clock."""
self._elapsed += time.time() - self._last
self._last = 0
[docs] def is_running(self):
"""Return True if the clock is running."""
if self._last > 0:
return True
else:
return False
[docs]def main():
"""Parse the arguments and run the clock."""
# TODO refactor into smaller functions
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-m', type=int, default=10,
help="main time in minutes (default is 10)")
parser.add_argument('-b', type=int, nargs=2, default=[5, 20],
help="japanese byoyomi: number of periods, period length in"
" seconds (default is 5 periods, 20 seconds)")
parser.add_argument('-c', '--camera', dest='cam', action='store_true',
help="camera on")
parser.add_argument('-d', type=int, default=0,
help="video device id")
parser.add_argument('-r', type=int, nargs=2, default=[640, 480],
help="set camera resolution")
args = parser.parse_args()
pygame.init()
pygame.display.set_mode((600, 130))
pygame.display.set_caption("Go timer")
screen = pygame.display.get_surface()
clock = pygame.time.Clock()
font = pygame.font.Font(pygame.font.match_font('monospace'), 80)
font2 = pygame.font.Font(None, 25)
done = False
first = True
main_time = args.m * 60
timers = (Timer(main_time, args.b[0], args.b[1]), Timer(main_time, args.b[0], args.b[1]))
if args.cam:
capture = subprocess.Popen(['python', 'src/capture.py', '-c', '-d', str(args.d), '-r',
str(args.r[0]),
str(args.r[1])], stdin=subprocess.PIPE)
last = 0
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if time.time() - last < 0.7:
continue
last = time.time()
if first:
timers[0].start()
first = False
if args.cam:
print >> capture.stdin, "stop"
print >> capture.stdin, "take"
continue
if args.cam:
print >> capture.stdin, "take"
for timer in timers:
if timer.is_running():
timer.stop()
else:
timer.start()
screen.fill([0, 0, 0])
text1 = font.render(timers[0].get_time(), True, [128, 255, 128])
screen.blit(text1, [10, 10])
text2 = font.render(timers[1].get_time(), True, [128, 255, 128])
screen.blit(text2, [300, 10])
text3 = font2.render(timers[0].byost, True, [128, 255, 128])
screen.blit(text3, [10, 90])
text4 = font2.render(timers[1].byost, True, [128, 255, 128])
screen.blit(text4, [300, 90])
pygame.display.flip()
clock.tick(15)
if args.cam:
print >> capture.stdin, "exit"
if __name__ == '__main__':
try:
main()
finally:
pygame.quit()