      *>-----------------------------------------------------------
      *> Stopwatch objects enable you to carry out timings.
      *>-----------------------------------------------------------

      *S000. Identification paragraph, showing class-name and superclass
      *      name.
       class-id. Stopwatch as "stopwtch"
              inherits from Base.

       configuration section.
      *S005. List of the classes used by Stopwatch
       repository.
           class Base as "base"
           .
       factory.
      *>----------------------------------------------------------------
      *> S010. This is the factory working-storage section. Data
      *> declared here can only be accessed from factory methods.
      *>----------------------------------------------------------------
       working-storage section.
       01 osCount                   pic x(4) comp-5.

      *>---------------------------------------------------------------
      *> S015.
      *> Returns a new instance of Stopwatch.
      *>---------------------------------------------------------------
       method-id. "new".

       linkage section.
       01 lnkWatch                 object reference Stopwatch.
       procedure division returning lnkWatch.
      *----S015. Create the new object using an inherited method.
           invoke super "new" returning lnkWatch
      *----S020. Count the new object.
           add 1 to osCount
           exit method.

       end method "new".

      *>---------------------------------------------------------------
      *> Return the instances of Stopwatch created.
      *>---------------------------------------------------------------
       method-id. "howMany".
       linkage section.
       01 lnkCount                 pic  x(4) comp-5.
       procedure division returning lnkCount.
      *----S025. Copy the class data to the returning parameter.
           move osCount to lnkCount
           exit method.

       end method "howMany".
       end factory.

      *>---------------------------------------------------------------
      *> S030. The Object identifier indicates the start of data and
      *>       code for instances of Stopwatch.
      *>---------------------------------------------------------------
       object.
      *>----------------------------------------------------------------
      *>S035. This working-storage section holds the instance data for
      *>      each stopwatch. Each instance has its own unique set of
      *>      instance data.
      *>----------------------------------------------------------------
       working-storage section.
       01 osWatchState             pic x comp-5 value 0.
        88 watchRunning            value 1.
        88 watchStopped            value 0.
       01 elapsedTime.
        03 elapsedHours            pic 99 value zeroes.
        03 elapsedMins             pic 99 value zeroes.
        03 elapsedSecs             pic 9(4) value zeroes.

       01 startTime.
        03 stopHours               pic 99.
        03 stopMins                pic 99.
        03 stopSecs                pic 9(4).

      *>-----------------------------------------------------------
      *> S040. Start the timer.
      *>-----------------------------------------------------------
       method-id. "Start".
       procedure division.
      *----S045. Only start a stopwatch if it is not running.
           if watchStopped
               accept startTime from time
               set watchRunning to true
           end-if
           exit method.
       end method "Start".

      *>-----------------------------------------------------------
      *> Reset the timer.
      *>-----------------------------------------------------------
       method-id. "reset".

       procedure division.
      *----S050. Only reset a stopwatch if it is not running.
           if watchStopped
               move all zeroes to startTime, elapsedTime
           end-if
           exit method.
       end method "reset".

      *>-----------------------------------------------------------
      *> Stop the timer.
      *>-----------------------------------------------------------
       method-id. "stop".
       local-storage section.
       01 lsTime.
        03 lsHours                 pic 99.
        03 lsMins                  pic 99.
        03 lsSecs                  pic 9(4).
       01 lsTempTime.
        03 lsTempHours             pic 99.
        03 lsTempMins              pic 99.
        03 lsTempSecs              pic 9(4).

       procedure division.
      *----S050. Only stop a stopwatch if it is already running.
           if watchRunning
               accept lsTime from time
               invoke self "subtractTimes" using startTime lsTime
               invoke self "addTimes" using lsTime elapsedTime
               set watchstopped to true
           end-if
           exit method.
       end method "stop".

      *>-----------------------------------------------------------
      *> PRIVATE. Add two times together.
      *>-----------------------------------------------------------
       method-id. "addTimes".
       local-storage section.
       01 lsTimeInSecs1            pic 9(8).
       01 lsTimeInSecs2            pic 9(8).
       linkage section.
       01 lnkTime1.
        03 lnkHours1               pic 99.
        03 lnkMins1                pic 99.
        03 lnkSecs1                pic 9(4).
       01 lnkTime2.
        03 lnkHours2               pic 99.
        03 lnkMins2                pic 99.
        03 lnkSecs2                pic 9(4).

       procedure division using lnkTime1 lnkTime2.
           invoke self "timeIntoSeconds" using lnkTime1
                                    returning lsTimeInSecs1
           invoke self "timeIntoSeconds" using lnkTime2
                                    returning lsTimeInSecs2
           add lsTimeInSecs1 to lsTimeInSecs2
           invoke self "secondsIntoTime" using lsTimeInSecs2
                                     returning lnkTime2
           exit method.
       end method "addTimes".
      *>-----------------------------------------------------------
      *> PRIVATE. Calculate the time elapsed between two times.
      *>-----------------------------------------------------------
       method-id. "subtractTimes".
       local-storage section.
       01 lsTimeInSecs1            pic 9(8).
       01 lsTimeInSecs2            pic 9(8).
       linkage section.
       01 lnkTime1.
        03 lnkHours1               pic 99.
        03 lnkMins1                pic 99.
        03 lnkSecs1                pic 9(4).
       01 lnkTime2.
        03 lnkHours2               pic 99.
        03 lnkMins2                pic 99.
        03 lnkSecs2                pic 9(4).

       procedure division using lnkTime1 lnkTime2.
           invoke self "timeIntoSeconds" using lnkTime1
                                    returning lsTimeInSecs1
           invoke self "timeIntoSeconds" using lnkTime2
                                    returning lsTimeInSecs2
           subtract lsTimeInSecs1 from lsTimeInSecs2
           invoke self "secondsIntoTime" using lsTimeInSecs2
                                     returning lnkTime2
           exit method.
       end method "subtractTimes".



      *>-----------------------------------------------------------
      *> Stop the watch and return the elapsed time, formatted for
      *> display.
      *>-----------------------------------------------------------
       Method-id. "getTimeFormatted".

       local-storage section.
       01 lsTime.
        03 lsHours                 pic 99.
        03 lsMins                  pic 99.
        03 lsSecs                  pic 9(4).

       linkage section.
       01 lnkTime.
        03 lnkHours                pic 99.
        03 filler                  pic x.
        03 lnkMins                 pic 99.
        03 filler                  pic x.
        03 lnkSecs                 pic 99.
        03 filler                  pic x.
        03 lnkThousandths          pic 99.
       procedure division returning lnkTime.
           if watchRunning
      *--------S100. If the watch is running, use the current time
      *        for the calculation.
               accept lsTime from time
               invoke self "subtractTimes" using startTime lsTime
               invoke self "addTimes" using elapsedTime lsTime
               move lsSecs(1:2) to lnkSecs
               move lsSecs(3:2) to lnkThousandths
               move lsMins to lnkMins
               move lsHours to lnkHours
           else
      *--------S100. If the watch is running, use the current time
      *        for the calculation.
               move elapsedHours to lnkHours
               move elapsedMins to lnkMins
               move elapsedSecs(1:2) to lnkSecs
               move elapsedSecs(3:2) to lnkThousandths
           end-if
           exit method.
       end method "getTimeFormatted".

      *>-----------------------------------------------------------
      *> PRIVATE. Turn hhmmss format time into seconds.
      *>-----------------------------------------------------------
       method-id. "timeIntoSeconds".
       linkage section.
       01 lnkTime.
        03 lnkHours                pic 99.
        03 lnkMins                 pic 99.
        03 lnkSecs                 pic 9(4).
       01 lnkSeconds               pic 9(8). *> Result returned in units
                                             *> of 1/100 seconds
       procedure division using lnkTime returning lnkSeconds.
      *----S110.
           compute lnkSeconds = (  lnkHours * 360000 + lnkMins * 6000
                                 + lnkSecs )
           exit method.
       end method "timeIntoSeconds".

      *>-----------------------------------------------------------
      *> PRIVATE. Turn seconds into hhmmss format time.
      *>-----------------------------------------------------------
       method-id. "secondsIntoTime".
       local-storage section.
       01 lsSeconds                pic 9(6).
       linkage section.
       01 lnkTime.
        03 lnkHours                pic 99.
        03 lnkMins                 pic 99.
        03 lnkSecs                 pic 9(4).
       01 lnkSeconds               pic 9(8).

       procedure division using lnkSeconds returning lnkTime.
      *----S120.
           move lnkSeconds to lsSeconds
           compute lnkHours = ( function integer (lsSeconds / 360000) )
           compute lsSeconds = lsSeconds - lnkHours * 360000
           compute lnkMins = ( function integer (lsSeconds / 6000) )
           compute lnkSecs = lsSeconds - lnkMins * 6000
           exit method.
       end method "secondsIntoTime".

       end object.
       end class Stopwatch.
