Universität Ulm, Fakultät für Mathematik und Wirtschaftswissenschaften, SAI

SS 99 || Ferienprojekt zu Allgemeine Informatik II || Puzzle Library

MODULE ChessClocks


MODULE ChessClocks;

   IMPORT Clocks, Objects, Op := Operations, Scales, Services, Shards, Times;

   TYPE
      Interface = POINTER TO InterfaceRec;

      ChessClock = POINTER TO ChessClockRec;
      ChessClockRec =
	 RECORD
	    (Services.ObjectRec)
	    if: Interface;
	    numberOfPlayers: SHORTINT;
	    timelimit: Times.Time; (* relative *)
	    abstimelimit: Times.Time; (* absolute *)
	 END;
      Player = SHORTINT; (* player number, starting from 0 *)

   TYPE
      StartProc = PROCEDURE (chessclock: ChessClock;
                             auth: Shards.Lid) : BOOLEAN;
      StopProc = PROCEDURE (chessclock: ChessClock;
                            auth: Shards.Lid) : BOOLEAN;
      SwitchProc = PROCEDURE (chessclock: ChessClock;
	                      auth: Shards.Lid; player: Player) : BOOLEAN;

      RunningProc = PROCEDURE (chessclock: ChessClock) : BOOLEAN;
      CurrentPlayerProc = PROCEDURE (chessclock: ChessClock) : Player;
      GetClockProc = PROCEDURE (chessclock: ChessClock; player: Player;
	                        VAR clock: Clocks.Clock);

      InterfaceRec =
	 RECORD
	    (Objects.ObjectRec)
	    start: StartProc;
	    stop: StopProc;
	    switch: SwitchProc;
	    running: RunningProc;
	    currentPlayer: CurrentPlayerProc;
	    getClock: GetClockProc;
	 END;

   (* === private procedures ============================================= *)

   PROCEDURE InitModule;
      VAR
	 type: Services.Type;
   BEGIN
      Services.CreateType(type, "ChessClocks.ChessClock", "");
   END InitModule;

   PROCEDURE MakeAbsolute(time: Times.Time; VAR abstime: Times.Time);
      VAR
	 timeval: Times.TimeValueRec;
   BEGIN
      Times.GetValue(time, timeval);
      Times.CreateAndSet(abstime, Scales.absolute,
                         timeval.epoch, timeval.second, timeval.usec);
   END MakeAbsolute;

   (* === exported procedures ============================================ *)

   PROCEDURE Init(chessclock: ChessClock; if: Interface;
                  numberOfPlayers: SHORTINT;
		  timelimit: Times.Time);
   BEGIN
      ASSERT((if.start # NIL) & (if.stop # NIL) & (if.switch # NIL) &
         (if.running # NIL) & (if.currentPlayer # NIL) & (if.getClock # NIL));
      ASSERT(numberOfPlayers > 0);
      ASSERT(Scales.IsRelative(timelimit));
      chessclock.if := if;
      chessclock.numberOfPlayers := numberOfPlayers;
      chessclock.timelimit := timelimit;
      MakeAbsolute(timelimit, chessclock.abstimelimit);
   END Init;

   PROCEDURE Start(chessclock: ChessClock; auth: Shards.Lid) : BOOLEAN;
   BEGIN
      RETURN chessclock.if.start(chessclock, auth)
   END Start;

   PROCEDURE Stop(chessclock: ChessClock; auth: Shards.Lid) : BOOLEAN;
   BEGIN
      RETURN chessclock.if.stop(chessclock, auth)
   END Stop;

   PROCEDURE Switch(chessclock: ChessClock;
                    auth: Shards.Lid; player: Player) : BOOLEAN;
   BEGIN
      RETURN chessclock.if.switch(chessclock, auth, player)
   END Switch;

   PROCEDURE Running(chessclock: ChessClock) : BOOLEAN;
   BEGIN
      RETURN chessclock.if.running(chessclock)
   END Running;

   PROCEDURE CurrentPlayer(chessclock: ChessClock) : Player;
   BEGIN
      RETURN chessclock.if.currentPlayer(chessclock)
   END CurrentPlayer;

   PROCEDURE GetClock(chessclock: ChessClock; player: Player;
                      VAR clock: Clocks.Clock);
   BEGIN
      chessclock.if.getClock(chessclock, player, clock);
   END GetClock;

   (* === exported procedures that are not propagated to the impl. *)

   PROCEDURE NumberOfPlayers(chessclock: ChessClock) : SHORTINT;
   BEGIN
      RETURN chessclock.numberOfPlayers
   END NumberOfPlayers;

   PROCEDURE TimeLeft(chessclock: ChessClock; player: Player;
                      VAR time: Times.Time);
      VAR
	 clock: Clocks.Clock;
	 currentTime: Times.Time;
   BEGIN
      GetClock(chessclock, player, clock);
      Clocks.GetTime(clock, currentTime);
      Op.Sub3(time, chessclock.abstimelimit, currentTime);
   END TimeLeft;

   PROCEDURE GetTimeLimit(chessclock: ChessClock;
                          VAR timelimit: Times.Time);
   BEGIN
      timelimit := chessclock.timelimit;
   END GetTimeLimit;

BEGIN
   InitModule;
END ChessClocks.

SS 99 || Ferienprojekt zu Allgemeine Informatik II || Puzzle Library

Andreas Borchert, 26. Juli 1999