Class TimeService


  • @Scope("singleton")
    @Service
    public class TimeService
    extends Object
    This is the simulation time-keeper and event queue. Here's how it works:
    • You create it with four parameters: (base, start, rate, modulo), defined as
      • base is the start time of the simulation scenario. So if we are simulating a period in the summer of 2007, base might be 2007-06-21-12:00.
      • start is the start time of the simulation run.
      • rate is the time-compression ratio for the simulation. So if we are running one-hour timeslots every 5 seconds, the rate would be 720.
      • modulo controls the values of simulation time values reported. If we are running one-hour timeslots, then the modulo should be one hour, expressed in milliseconds. If we are running one-hour timeslots but want to update time every 30 minutes of simulated time, then the modulo would be 30*60*1000. Note that this will not work correctly unless the calls to updateTime() are made at modulo/rate intervals. Also note that the reported time is computed as rawTime - rawTime % modulo, which means it will never be ahead of the raw simulation time.
    • Some process periodically calls updateTime(), at least once every simulated hour. This sets the currentTime property to the correct scenario time as
      currentTime = base + (systemTime - start) * rate
      and runs any simulation actions that are due.
    • If you want something to happen sometime in the future, you add an action by calling addAction(time, action). Assuming time is not in the past, then the action (a closure with a single argument, the current time) is added to a time-ordered queue, and will be run when its time arrives.
    Note that all times are absolute times represented as UTC; timezone offset is 0, and there is no "daylight-saving" time. If we want to represent the effects of DST, we'll have to have our customers wake up earlier in the summertime.
    Author:
    John Collins
    • Constructor Detail

      • TimeService

        public TimeService()
        Default constructor. You need to set base, rate, start, and modulo before using it.
      • TimeService

        public TimeService​(long base,
                           long start,
                           long rate,
                           long modulo)
        Handy constructor for testing
    • Method Detail

      • getInstance

        public static TimeService getInstance()
        Returns the most-recently created instance of TimeService. Intended to be used only for testing in Spring-free environment. Note that this is not a Singleton-type instance getter - it will not create an instance.
      • init

        public void init​(org.joda.time.Instant start)
        Sets current time to modulo before the desired start time. This allows scheduling of actions to take place on the first tick, which should be at the desired start time. Call this after setting clock parameters.
      • updateTime

        public void updateTime()
        Updates simulation time when called as specified by clock parameters, then runs any actions that may be due.
      • truncateInstant

        public org.joda.time.Instant truncateInstant​(org.joda.time.Instant time,
                                                     long mod)
        Returns the most recent Instant at which time % modulo was zero
      • setClockParameters

        public void setClockParameters​(long base,
                                       long rate,
                                       long modulo)
        Sets base, rate, and modulo clock parameters with a single call. We do not set start at this point, because it is changed whenever the clock is paused and therefore needs to be treated separately.
      • setClockParameters

        public void setClockParameters​(Map<String,​Long> params)
        Sets base, rate, and modulo parameters from a map, which is wrapped in a Configuration to allow for conversions and default values. The map must contain entries named "base", "rate", and "modulo". We also init the clock here, because we have all the parameters.
      • setClockParameters

        public void setClockParameters​(Competition comp)
        Sets base, rate, and modulo from a Competition instance
      • getBase

        public long getBase()
      • getBaseInstant

        public org.joda.time.Instant getBaseInstant()
      • getStart

        public long getStart()
      • setStart

        public void setStart​(long start)
      • getRate

        public long getRate()
      • getModulo

        public long getModulo()
      • getCurrentTime

        public org.joda.time.Instant getCurrentTime()
        Returns the current time as an Instant
      • getCurrentDateTime

        public org.joda.time.DateTime getCurrentDateTime()
      • getHourOfDay

        public int getHourOfDay()
        Returns the current hour-of-day
      • setCurrentTime

        @StateChange
        public void setCurrentTime​(org.joda.time.Instant time)
        Sets current time to a specific value. Intended for testing purposes only.
      • getOffset

        public long getOffset()
        Computes and returns the offset in msec between the current system time and the current clock time.
      • setCurrentTime

        @StateChange
        protected void setCurrentTime​(org.joda.time.base.AbstractDateTime time)
        Sets current time to a specific value. Intended for testing purposes only.
      • setCurrentTime

        public void setCurrentTime()
      • addAction

        public void addAction​(org.joda.time.Instant time,
                              TimedAction act)
        Adds an action to the simulation queue, to be triggered at the specified time.