1   package org.djutils.stats.summarizers;
2   
3   import java.util.Calendar;
4   
5   import org.djutils.exceptions.Throw;
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  public class TimestampWeightedTally implements TimestampTallyInterface
20  {
21      
22      private static final long serialVersionUID = 20200228L;
23  
24      
25      private WeightedTally wrappedWeightedTally;
26  
27      
28      private double startTime = Double.NaN;
29  
30      
31      private double lastTimestamp = Double.NaN;
32  
33      
34      private double lastValue = Double.NaN;
35  
36      
37      private boolean active = false;
38  
39      
40  
41  
42  
43      public TimestampWeightedTally(final String description)
44      {
45          this.wrappedWeightedTally = new WeightedTally(description);
46          initialize();
47      }
48  
49      
50      @Override
51      public void initialize()
52      {
53          synchronized (this.wrappedWeightedTally.semaphore)
54          {
55              this.wrappedWeightedTally.initialize();
56              this.startTime = Double.NaN;
57              this.lastTimestamp = Double.NaN;
58              this.lastValue = 0.0;
59              this.active = true;
60          }
61      }
62  
63      
64      @Override
65      public final boolean isActive()
66      {
67          return this.active;
68      }
69  
70      
71      @Override
72      public final void endObservations(final Number timestamp)
73      {
74          ingest(timestamp, this.lastValue);
75          this.active = false;
76      }
77  
78      
79      @Override
80      public void endObservations(final Calendar timestamp)
81      {
82          endObservations(timestamp.getTimeInMillis());
83      }
84  
85      
86  
87  
88  
89      public double getLastValue()
90      {
91          return this.lastValue;
92      }
93  
94      
95  
96  
97  
98  
99  
100     public double ingest(final Calendar timestamp, final double value)
101     {
102         Throw.whenNull(timestamp, "timestamp object may not be null");
103         return ingest(timestamp.getTimeInMillis(), value);
104     }
105 
106     
107 
108 
109 
110 
111 
112     public double ingest(final Number timestamp, final double value)
113     {
114         Throw.whenNull(timestamp, "timestamp object may not be null");
115         Throw.when(Double.isNaN(value), IllegalArgumentException.class, "value may not be NaN");
116         double timestampDouble = timestamp.doubleValue();
117         Throw.when(Double.isNaN(timestampDouble), IllegalArgumentException.class, "timestamp may not be NaN");
118         Throw.when(timestampDouble < this.lastTimestamp, IllegalArgumentException.class,
119                 "times not offered in ascending order. Last time was " + this.lastTimestamp + ", new timestamp was "
120                         + timestampDouble);
121 
122         synchronized (this.wrappedWeightedTally.semaphore)
123         {
124             
125             if ((Double.isNaN(this.lastTimestamp) || timestampDouble > this.lastTimestamp) && this.active)
126             {
127                 if (Double.isNaN(this.startTime))
128                 {
129                     this.startTime = timestampDouble;
130                 }
131                 else
132                 {
133                     double deltaTime = Math.max(0.0, timestampDouble - this.lastTimestamp);
134                     this.wrappedWeightedTally.ingest(deltaTime, this.lastValue);
135                 }
136                 this.lastTimestamp = timestampDouble;
137             }
138             this.lastValue = value;
139             return value;
140         }
141     }
142 
143     
144     @Override
145     public final String getDescription()
146     {
147         return this.wrappedWeightedTally.getDescription();
148     }
149 
150     
151     @Override
152     public final long getN()
153     {
154         return this.wrappedWeightedTally.getN();
155     }
156 
157     
158     @Override
159     public final double getMax()
160     {
161         return this.wrappedWeightedTally.getMax();
162     }
163 
164     
165     @Override
166     public final double getMin()
167     {
168         return this.wrappedWeightedTally.getMin();
169     }
170 
171     
172     @Override
173     public final double getWeightedSampleMean()
174     {
175         return this.wrappedWeightedTally.getWeightedSampleMean();
176     }
177 
178     
179     @Override
180     public final double getWeightedSampleStDev()
181     {
182         return this.wrappedWeightedTally.getWeightedSampleStDev();
183     }
184 
185     
186     @Override
187     public final double getWeightedPopulationStDev()
188     {
189         return this.wrappedWeightedTally.getWeightedPopulationStDev();
190     }
191 
192     
193     @Override
194     public final double getWeightedSampleVariance()
195     {
196         return this.wrappedWeightedTally.getWeightedSampleVariance();
197     }
198 
199     
200     @Override
201     public final double getWeightedPopulationVariance()
202     {
203         return this.wrappedWeightedTally.getWeightedPopulationVariance();
204     }
205 
206     
207     @Override
208     public final double getWeightedSum()
209     {
210         return this.wrappedWeightedTally.getWeightedSum();
211     }
212 
213     
214     @Override
215     @SuppressWarnings("checkstyle:designforextension")
216     public String toString()
217     {
218         return this.wrappedWeightedTally.toString();
219     }
220 
221 }