This file documents the developpment process and the internal
structure of the code from a more general standpoint.

Release process
===============

Code is maintained in Git, and bugs are tracked on a Koumbit Redmine
project here:

    https://redmine.koumbit.net/projects/gameclock/

Details on how to checkout the code should also be available there.

Checklist
---------

 1. look at the issue queues to see if there are any bugs to be fixed:

    https://redmine.koumbit.net/projects/gameclock/issues
    http://bugs.debian.org/gameclock

 2. update the `debian/changelog` with the latest changes:

      dch -i "this release blabla"

 3. update the version number in `gameclock/__init__.py`

 4. lay down a tag:

      git tag -s -u anarcat@debian.org X.Y

 5. build and test the debian package:

      git-buildpackage

 6. push the code and tag:

      git push
      git push --tags

 7. publish the Debian package in Debian with `dput`

 8. publish on PIP

Code structure
==============

The code is written in Python with the GTK GUI frontend. However, it
is designed to support multiple backends and a class could be written
for a ncurses frontend for example.

General
-------

Most classes override the __str__() handler to provide a
human-readable debugging version of the object. There are some global
module variables, more or less self-documented. Command line parsing
is done in the traditionnal 'main block' of python programs.

Game class
----------

The game class is a general representation of a chess game that
doesn't take account the moves, position or board in any way. It only
counts turns and timing. It is now designed to support an arbitrary
number of players (above 0 of course).

It's mostly a placeholder for the clocks (a linked list of Clock
objects, with the head being Game.first_clock). It has a notion of the
clock current active (Game.cur_clock) that gets updated when the turns
end (Game.end_turn(), which in turns calls Clock.stop(), and
Clock.start() on the relevant clocks and increments the turn count)
and when the clocks are switched (Game.switch_clock()).

There's also a handler to start the game (Game.start()) that starts
and updates the right clock and pause the game.

The turn counting is a bit peculiar and so needs a bit of
explaining. It is counted using a float (Game.turns) that is
incremented by a half (0.5) at every Game.end_turn(). So turns, in a
way, count the number of 'two turns', which is a bit of a vocabulary
problem here.

Clock class
-----------

The clock class represents a player's clock. It can be paused, stopped
and started. The difference between pause() and stop() is that pause()
will restart the clock when called twice. stop() will also add extra
time to the player's clock if the clock's mode is fischer.

The way time is counted is this: there is an integer (Clock.time) that
counts the number of miliseconds passed playing by a player. That
number is incremented at the end of that player's turn (and also when
the game is paused). To evaluate the time spent in a turn, a float
(Clock.last_start) that marks the beginning of the turn (or the last
pause()) is marked when the turn starts (or when the game is
unpaused). When the time ends (or the game is pause()d), that time is
compared to the current time as returned by by Python's time()[4]
function and is added to the player's clock time (Clock.time).

All that processing is isolated in Clock.get_time().

So in summary Clock.time contains the time spent by the player
throughout the game not including the turn he's currently playing (if
any). Therefore, to get the proper value, Clock.get_time() needs to be
used.

The Clock class also keeps an string representation (Clock.text), a
cache of a human-readable version of the clock's state. It displays
the hours, minutes and seconds of time counted by the clock. Depending
on the truth value of Clock.miliseconds, it will also (or not) show
the miliseconds. If the clock goes beyond 24h, it will also display
the number of days. If the clock goes below zero it will display a
minus in front of the string.

For performance reasons, that cache is updated only when relevant
(with Clock.update()). Care has been taken to call that function as
little as possible.

Python's strftime() function[4] is currently used for rendering hours,
minutes and seconds.

Similarly, the clock keeps a cache of the negativness of the clock
(Clock.dead). That cache is also updated only when necessary (again
with Clock.update()).

The clock depends on the Game to manage clock changes and its internal
engine is therefore considered to be exposed to other classes.

Also note that a Clock is usually part of a chained list of clocks
through the Clock.next pointer.

FischerClock class
'''''''''''''''''

This is a subclass of the generic Clock class that implements fischer
style time tracking: the stop() function has simply been overriden
to add n miliseconds to the clock before switching.

Also note that the constructor is different to allow customization of
that delay.

Clock precision
'''''''''''''''

There are some areas where the clock might introduce some
imprecision. It can be due to Python's floating point arithmetics,
since the number of miliseconds is deduced from the mantissa of the
float returned by time(), but that's probably negligible.

Most of the imprecision is likely to come from the time spent in the
end_turn() function (and of course the general system processing
between the players brain's, the computer keyboard, the kernel, X11,
GTK and the Python main loop).

I would expect this to be lower than 10ms, but I have absolutely no
metrics to prove that assertion.

[4] http://docs.python.org/lib/module-time.html

User interface
--------------

When/if a new frontend is written, it would probably appropriate to
refactor some code of the GameclockGtkUI class into a parent class. In
the meantime, that code was moved to a separate file to ease
extensibility.

The GTK UI code has became messy. Some work has been done to uncouple
it from the game engine, but it still needs to be improved on that
side. A significant amount of work was done to move the UI buttons to
a separate window that pops up on start up and doesn't clutter the
UI. The code is not much more readable but at least there is more
isolation between the game handling and configuration sides.

There is a ClockUI subclass that regroups each clock's widget. As the
Clock class, it is organised as a chained list and can be iterated
similarly.

A next step would be to cleanup the gtkui.py file to make it more
readable and modular.
