Commit | Line | Data |
---|---|---|
c392540b | 1 | /******************************************************************************* |
11252342 | 2 | * Copyright (c) 2011, 2013 Ericsson |
bfe038ff | 3 | * |
c392540b FC |
4 | * All rights reserved. This program and the accompanying materials are |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
bfe038ff | 8 | * |
c392540b FC |
9 | * Contributors: |
10 | * Francois Chouinard - Initial API and implementation | |
bfe038ff | 11 | * Bernd Hufmann - Implementation of new interfaces/listeners and support for |
fbd124dd | 12 | * time stamp in any order |
e0752744 | 13 | * Francois Chouinard - Moved from LTTng to TMF |
00419b1f | 14 | * Francois Chouinard - Added support for empty initial buckets |
0fcf3b09 | 15 | * Patrick Tasse - Support selection range |
c392540b FC |
16 | *******************************************************************************/ |
17 | ||
e0752744 | 18 | package org.eclipse.linuxtools.tmf.ui.views.histogram; |
c392540b FC |
19 | |
20 | import java.util.Arrays; | |
21 | ||
fbd124dd | 22 | import org.eclipse.core.runtime.ListenerList; |
c392540b FC |
23 | |
24 | /** | |
b544077e | 25 | * Histogram-independent data model. |
f8177ba2 | 26 | * |
b544077e | 27 | * It has the following characteristics: |
c392540b FC |
28 | * <ul> |
29 | * <li>The <i>basetime</i> is the timestamp of the first event | |
30 | * <li>There is a fixed number (<i>n</i>) of buckets of uniform duration | |
31 | * (<i>d</i>) | |
32 | * <li>The <i>timespan</i> of the model is thus: <i>n</i> * <i>d</i> time units | |
33 | * <li>Bucket <i>i</i> holds the number of events that occurred in time range: | |
34 | * [<i>basetime</i> + <i>i</i> * <i>d</i>, <i>basetime</i> + (<i>i</i> + 1) * | |
35 | * <i>d</i>) | |
36 | * </ul> | |
37 | * Initially, the bucket durations is set to 1ns. As the events are read, they | |
38 | * are tallied (using <i>countEvent()</i>) in the appropriate bucket (relative | |
39 | * to the <i>basetime</i>). | |
40 | * <p> | |
41 | * Eventually, an event will have a timestamp that exceeds the <i>timespan</i> | |
42 | * high end (determined by <i>n</i>, the number of buckets, and <i>d</i>, the | |
43 | * bucket duration). At this point, the histogram needs to be compacted. This is | |
44 | * done by simply merging adjacent buckets by pair, in effect doubling the | |
45 | * <i>timespan</i> (<i>timespan'</i> = <i>n</i> * <i>d'</i>, where <i>d'</i> = | |
46 | * 2<i>d</i>). This compaction happens as needed as the trace is read. | |
47 | * <p> | |
fbd124dd | 48 | * The model allows for timestamps in not increasing order. The timestamps can |
bfe038ff | 49 | * be fed to the model in any order. If an event has a timestamp less than the |
fbd124dd | 50 | * <i>basetime</i>, the buckets will be moved to the right to account for the |
bfe038ff | 51 | * new smaller timestamp. The new <i>basetime</i> is a multiple of the bucket |
fbd124dd BH |
52 | * duration smaller then the previous <i>basetime</i>. Note that the <i>basetime</i> |
53 | * might not be anymore a timestamp of an event. If necessary, the buckets will | |
bfe038ff | 54 | * be compacted before moving to the right. This might be necessary to not |
fbd124dd BH |
55 | * loose any event counts at the end of the buckets array. |
56 | * <p> | |
c392540b FC |
57 | * The mapping from the model to the UI is performed by the <i>scaleTo()</i> |
58 | * method. By keeping the number of buckets <i>n</i> relatively large with | |
59 | * respect to to the number of pixels in the actual histogram, we should achieve | |
60 | * a nice result when visualizing the histogram. | |
61 | * <p> | |
f8177ba2 | 62 | * |
00419b1f | 63 | * @version 2.0 |
b544077e | 64 | * @author Francois Chouinard |
c392540b | 65 | */ |
fbd124dd | 66 | public class HistogramDataModel implements IHistogramDataModel { |
c392540b FC |
67 | |
68 | // ------------------------------------------------------------------------ | |
69 | // Constants | |
70 | // ------------------------------------------------------------------------ | |
71 | ||
b544077e BH |
72 | /** |
73 | * The default number of buckets | |
74 | */ | |
c392540b FC |
75 | public static final int DEFAULT_NUMBER_OF_BUCKETS = 16 * 1000; |
76 | ||
b544077e | 77 | /** |
f8177ba2 | 78 | * Number of events after which listeners will be notified. |
b544077e | 79 | */ |
fbd124dd | 80 | public static final int REFRESH_FREQUENCY = DEFAULT_NUMBER_OF_BUCKETS; |
bfe038ff | 81 | |
c392540b FC |
82 | // ------------------------------------------------------------------------ |
83 | // Attributes | |
84 | // ------------------------------------------------------------------------ | |
85 | ||
86 | // Bucket management | |
87 | private final int fNbBuckets; | |
88 | private final long[] fBuckets; | |
89 | private long fBucketDuration; | |
90 | private long fNbEvents; | |
91 | private int fLastBucket; | |
92 | ||
93 | // Timestamps | |
fbd124dd | 94 | private long fFirstBucketTime; // could be negative when analyzing events with descending order!!! |
c392540b FC |
95 | private long fFirstEventTime; |
96 | private long fLastEventTime; | |
0fcf3b09 PT |
97 | private long fSelectionBegin; |
98 | private long fSelectionEnd; | |
c392540b | 99 | private long fTimeLimit; |
bfe038ff | 100 | |
e0752744 | 101 | // Private listener lists |
fbd124dd | 102 | private final ListenerList fModelListeners; |
bfe038ff | 103 | |
e0752744 FC |
104 | // ------------------------------------------------------------------------ |
105 | // Constructors | |
106 | // ------------------------------------------------------------------------ | |
107 | ||
b544077e BH |
108 | /** |
109 | * Default constructor with default number of buckets. | |
110 | */ | |
c392540b | 111 | public HistogramDataModel() { |
00419b1f FC |
112 | this(0, DEFAULT_NUMBER_OF_BUCKETS); |
113 | } | |
114 | ||
115 | /** | |
116 | * Default constructor with default number of buckets. | |
117 | * @param startTime The histogram start time | |
118 | * @since 2.0 | |
119 | */ | |
120 | public HistogramDataModel(long startTime) { | |
121 | this(startTime, DEFAULT_NUMBER_OF_BUCKETS); | |
c392540b FC |
122 | } |
123 | ||
b544077e BH |
124 | /** |
125 | * Constructor with non-default number of buckets. | |
126 | * @param nbBuckets A number of buckets. | |
127 | */ | |
c392540b | 128 | public HistogramDataModel(int nbBuckets) { |
00419b1f FC |
129 | this(0, nbBuckets); |
130 | } | |
131 | ||
132 | /** | |
133 | * Constructor with non-default number of buckets. | |
134 | * @param startTime the histogram start time | |
135 | * @param nbBuckets A number of buckets. | |
136 | * @since 2.0 | |
137 | */ | |
138 | public HistogramDataModel(long startTime, int nbBuckets) { | |
139 | fFirstBucketTime = fFirstEventTime = fLastEventTime = startTime; | |
c392540b FC |
140 | fNbBuckets = nbBuckets; |
141 | fBuckets = new long[nbBuckets]; | |
fbd124dd | 142 | fModelListeners = new ListenerList(); |
c392540b FC |
143 | clear(); |
144 | } | |
145 | ||
b544077e BH |
146 | /** |
147 | * Copy constructor. | |
148 | * @param other A model to copy. | |
149 | */ | |
c392540b FC |
150 | public HistogramDataModel(HistogramDataModel other) { |
151 | fNbBuckets = other.fNbBuckets; | |
152 | fBuckets = Arrays.copyOf(other.fBuckets, fNbBuckets); | |
00419b1f | 153 | fBucketDuration = Math.max(other.fBucketDuration, 1); |
c392540b FC |
154 | fNbEvents = other.fNbEvents; |
155 | fLastBucket = other.fLastBucket; | |
fbd124dd | 156 | fFirstBucketTime = other.fFirstBucketTime; |
c392540b FC |
157 | fFirstEventTime = other.fFirstEventTime; |
158 | fLastEventTime = other.fLastEventTime; | |
0fcf3b09 PT |
159 | fSelectionBegin = other.fSelectionBegin; |
160 | fSelectionEnd = other.fSelectionEnd; | |
c392540b | 161 | fTimeLimit = other.fTimeLimit; |
fbd124dd BH |
162 | fModelListeners = new ListenerList(); |
163 | Object[] listeners = other.fModelListeners.getListeners(); | |
164 | for (Object listener : listeners) { | |
165 | fModelListeners.add(listener); | |
166 | } | |
c392540b FC |
167 | } |
168 | ||
169 | // ------------------------------------------------------------------------ | |
170 | // Accessors | |
171 | // ------------------------------------------------------------------------ | |
172 | ||
b544077e BH |
173 | /** |
174 | * Returns the number of events in the data model. | |
175 | * @return number of events. | |
176 | */ | |
c392540b FC |
177 | public long getNbEvents() { |
178 | return fNbEvents; | |
179 | } | |
180 | ||
b544077e BH |
181 | /** |
182 | * Returns the number of buckets in the model. | |
183 | * @return number of buckets. | |
184 | */ | |
c392540b FC |
185 | public int getNbBuckets() { |
186 | return fNbBuckets; | |
187 | } | |
188 | ||
b544077e BH |
189 | /** |
190 | * Returns the current bucket duration. | |
191 | * @return bucket duration | |
192 | */ | |
c392540b FC |
193 | public long getBucketDuration() { |
194 | return fBucketDuration; | |
195 | } | |
bfe038ff | 196 | |
b544077e BH |
197 | /** |
198 | * Returns the time value of the first bucket in the model. | |
199 | * @return time of first bucket. | |
200 | */ | |
fbd124dd BH |
201 | public long getFirstBucketTime() { |
202 | return fFirstBucketTime; | |
203 | } | |
c392540b | 204 | |
b544077e BH |
205 | /** |
206 | * Returns the time of the first event in the model. | |
207 | * @return time of first event. | |
208 | */ | |
c392540b FC |
209 | public long getStartTime() { |
210 | return fFirstEventTime; | |
211 | } | |
bfe038ff | 212 | |
00419b1f FC |
213 | /** |
214 | * Sets the model start time | |
215 | * @param startTime the histogram range start time | |
216 | * @param endTime the histogram range end time | |
217 | * @since 2.0 | |
218 | */ | |
219 | public void setTimeRange(long startTime, long endTime) { | |
220 | fFirstBucketTime = fFirstEventTime = fLastEventTime = startTime; | |
221 | fBucketDuration = 1; | |
222 | updateEndTime(); | |
223 | while (endTime >= fTimeLimit) { | |
224 | mergeBuckets(); | |
225 | } | |
226 | } | |
227 | ||
b544077e BH |
228 | /** |
229 | * Returns the time of the last event in the model. | |
230 | * @return the time of last event. | |
231 | */ | |
c392540b FC |
232 | public long getEndTime() { |
233 | return fLastEventTime; | |
234 | } | |
235 | ||
b544077e | 236 | /** |
f8177ba2 | 237 | * Returns the time of the current event in the model. |
b544077e | 238 | * @return the time of the current event. |
0fcf3b09 | 239 | * @deprecated As of 2.1, use {@link #getSelectionBegin()} and {@link #getSelectionEnd()} |
b544077e | 240 | */ |
0fcf3b09 | 241 | @Deprecated |
c392540b | 242 | public long getCurrentEventTime() { |
0fcf3b09 PT |
243 | return fSelectionBegin; |
244 | } | |
245 | ||
246 | /** | |
247 | * Returns the begin time of the current selection in the model. | |
248 | * @return the begin time of the current selection. | |
00ff7819 | 249 | * @since 3.0 |
0fcf3b09 PT |
250 | */ |
251 | public long getSelectionBegin() { | |
252 | return fSelectionBegin; | |
253 | } | |
254 | ||
255 | /** | |
256 | * Returns the end time of the current selection in the model. | |
257 | * @return the end time of the current selection. | |
00ff7819 | 258 | * @since 3.0 |
0fcf3b09 PT |
259 | */ |
260 | public long getSelectionEnd() { | |
261 | return fSelectionEnd; | |
c392540b FC |
262 | } |
263 | ||
b544077e BH |
264 | /** |
265 | * Returns the time limit with is: start time + nbBuckets * bucketDuration | |
266 | * @return the time limit. | |
267 | */ | |
c392540b FC |
268 | public long getTimeLimit() { |
269 | return fTimeLimit; | |
270 | } | |
bfe038ff | 271 | |
fbd124dd BH |
272 | // ------------------------------------------------------------------------ |
273 | // Listener handling | |
274 | // ------------------------------------------------------------------------ | |
bfe038ff | 275 | |
b544077e BH |
276 | /** |
277 | * Add a listener to the model to be informed about model changes. | |
278 | * @param listener A listener to add. | |
279 | */ | |
fbd124dd | 280 | public void addHistogramListener(IHistogramModelListener listener) { |
bfe038ff | 281 | fModelListeners.add(listener); |
fbd124dd | 282 | } |
bfe038ff | 283 | |
b544077e BH |
284 | /** |
285 | * Remove a given model listener. | |
286 | * @param listener A listener to remove. | |
287 | */ | |
fbd124dd BH |
288 | public void removeHistogramListener(IHistogramModelListener listener) { |
289 | fModelListeners.remove(listener); | |
290 | } | |
c392540b | 291 | |
f8177ba2 | 292 | // Notify listeners (always) |
fbd124dd BH |
293 | private void fireModelUpdateNotification() { |
294 | fireModelUpdateNotification(0); | |
295 | } | |
bfe038ff | 296 | |
b544077e | 297 | // Notify listener on boundary |
fbd124dd | 298 | private void fireModelUpdateNotification(long count) { |
bfe038ff | 299 | if ((count % REFRESH_FREQUENCY) == 0) { |
fbd124dd | 300 | Object[] listeners = fModelListeners.getListeners(); |
bfe038ff MK |
301 | for (Object listener2 : listeners) { |
302 | IHistogramModelListener listener = (IHistogramModelListener) listener2; | |
fbd124dd BH |
303 | listener.modelUpdated(); |
304 | } | |
305 | } | |
306 | } | |
bfe038ff | 307 | |
c392540b FC |
308 | // ------------------------------------------------------------------------ |
309 | // Operations | |
310 | // ------------------------------------------------------------------------ | |
e0752744 | 311 | |
fbd124dd BH |
312 | @Override |
313 | public void complete() { | |
314 | fireModelUpdateNotification(); | |
315 | } | |
c392540b FC |
316 | |
317 | /** | |
318 | * Clear the histogram model. | |
b544077e | 319 | * @see org.eclipse.linuxtools.tmf.ui.views.distribution.model.IBaseDistributionModel#clear() |
c392540b | 320 | */ |
fbd124dd | 321 | @Override |
c392540b FC |
322 | public void clear() { |
323 | Arrays.fill(fBuckets, 0); | |
324 | fNbEvents = 0; | |
fbd124dd | 325 | fFirstBucketTime = 0; |
c392540b | 326 | fLastEventTime = 0; |
0fcf3b09 PT |
327 | fSelectionBegin = 0; |
328 | fSelectionEnd = 0; | |
c392540b | 329 | fLastBucket = 0; |
f8177ba2 | 330 | fBucketDuration = 1; |
c392540b | 331 | updateEndTime(); |
fbd124dd | 332 | fireModelUpdateNotification(); |
c392540b FC |
333 | } |
334 | ||
335 | /** | |
f8177ba2 | 336 | * Sets the current event time (no notification of listeners) |
bfe038ff | 337 | * |
b544077e | 338 | * @param timestamp A time stamp to set. |
0fcf3b09 | 339 | * @deprecated As of 2.1, use {@link #setSelection(long, long)} |
c392540b | 340 | */ |
0fcf3b09 | 341 | @Deprecated |
c392540b | 342 | public void setCurrentEvent(long timestamp) { |
0fcf3b09 PT |
343 | fSelectionBegin = timestamp; |
344 | fSelectionEnd = timestamp; | |
c392540b FC |
345 | } |
346 | ||
fbd124dd | 347 | /** |
f8177ba2 | 348 | * Sets the current event time with notification of listeners |
bfe038ff | 349 | * |
b544077e | 350 | * @param timestamp A time stamp to set. |
0fcf3b09 | 351 | * @deprecated As of 2.1, use {@link #setSelectionNotifyListeners(long, long)} |
fbd124dd | 352 | */ |
0fcf3b09 | 353 | @Deprecated |
fbd124dd | 354 | public void setCurrentEventNotifyListeners(long timestamp) { |
0fcf3b09 PT |
355 | fSelectionBegin = timestamp; |
356 | fSelectionEnd = timestamp; | |
357 | fireModelUpdateNotification(); | |
358 | } | |
359 | ||
360 | /** | |
361 | * Sets the current selection time range (no notification of listeners) | |
362 | * | |
363 | * @param beginTime The selection begin time. | |
364 | * @param endTime The selection end time. | |
00ff7819 | 365 | * @since 3.0 |
0fcf3b09 PT |
366 | */ |
367 | public void setSelection(long beginTime, long endTime) { | |
368 | fSelectionBegin = beginTime; | |
369 | fSelectionEnd = endTime; | |
370 | } | |
371 | ||
372 | /** | |
373 | * Sets the current selection time range with notification of listeners | |
374 | * | |
375 | * @param beginTime The selection begin time. | |
376 | * @param endTime The selection end time. | |
00ff7819 | 377 | * @since 3.0 |
0fcf3b09 PT |
378 | */ |
379 | public void setSelectionNotifyListeners(long beginTime, long endTime) { | |
380 | fSelectionBegin = beginTime; | |
381 | fSelectionEnd = endTime; | |
fbd124dd BH |
382 | fireModelUpdateNotification(); |
383 | } | |
bfe038ff | 384 | |
c392540b FC |
385 | /** |
386 | * Add event to the correct bucket, compacting the if needed. | |
bfe038ff | 387 | * |
b544077e BH |
388 | * @param eventCount The current event Count (for notification purposes) |
389 | * @param timestamp The timestamp of the event to count | |
f8177ba2 | 390 | * |
c392540b | 391 | */ |
fbd124dd BH |
392 | @Override |
393 | public void countEvent(long eventCount, long timestamp) { | |
bfe038ff | 394 | |
fbd124dd BH |
395 | // Validate |
396 | if (timestamp < 0) { | |
fbd124dd BH |
397 | return; |
398 | } | |
bfe038ff | 399 | |
c392540b | 400 | // Set the start/end time if not already done |
00419b1f | 401 | if ((fFirstBucketTime == 0) && (fLastBucket == 0) && (fBuckets[0] == 0) && (timestamp > 0)) { |
fbd124dd | 402 | fFirstBucketTime = timestamp; |
c392540b FC |
403 | fFirstEventTime = timestamp; |
404 | updateEndTime(); | |
405 | } | |
bfe038ff | 406 | |
fbd124dd BH |
407 | if (timestamp < fFirstEventTime) { |
408 | fFirstEventTime = timestamp; | |
409 | } | |
bfe038ff | 410 | |
c392540b FC |
411 | if (fLastEventTime < timestamp) { |
412 | fLastEventTime = timestamp; | |
413 | } | |
bfe038ff | 414 | |
fbd124dd | 415 | if (timestamp >= fFirstBucketTime) { |
c392540b | 416 | |
fbd124dd BH |
417 | // Compact as needed |
418 | while (timestamp >= fTimeLimit) { | |
419 | mergeBuckets(); | |
420 | } | |
c392540b | 421 | |
fbd124dd | 422 | } else { |
bfe038ff | 423 | |
fbd124dd BH |
424 | // get offset for adjustment |
425 | int offset = getOffset(timestamp); | |
426 | ||
427 | // Compact as needed | |
bfe038ff | 428 | while((fLastBucket + offset) >= fNbBuckets) { |
fbd124dd BH |
429 | mergeBuckets(); |
430 | offset = getOffset(timestamp); | |
431 | } | |
bfe038ff | 432 | |
fbd124dd BH |
433 | moveBuckets(offset); |
434 | ||
435 | fLastBucket = fLastBucket + offset; | |
c392540b | 436 | |
bfe038ff | 437 | fFirstBucketTime = fFirstBucketTime - (offset*fBucketDuration); |
fbd124dd BH |
438 | updateEndTime(); |
439 | } | |
bfe038ff | 440 | |
c392540b | 441 | // Increment the right bucket |
fbd124dd | 442 | int index = (int) ((timestamp - fFirstBucketTime) / fBucketDuration); |
c392540b FC |
443 | fBuckets[index]++; |
444 | fNbEvents++; | |
bfe038ff | 445 | if (fLastBucket < index) { |
c392540b | 446 | fLastBucket = index; |
bfe038ff MK |
447 | } |
448 | ||
fbd124dd | 449 | fireModelUpdateNotification(eventCount); |
c392540b FC |
450 | } |
451 | ||
452 | /** | |
fbd124dd | 453 | * Scale the model data to the width, height and bar width requested. |
bfe038ff | 454 | * |
b544077e BH |
455 | * @param width A width of the histogram canvas |
456 | * @param height A height of the histogram canvas | |
457 | * @param barWidth A width (in pixel) of a histogram bar | |
458 | * @return the result array of size [width] and where the highest value doesn't exceed [height] | |
f8177ba2 | 459 | * |
b544077e | 460 | * @see org.eclipse.linuxtools.tmf.ui.views.histogram.IHistogramDataModel#scaleTo(int, int, int) |
c392540b | 461 | */ |
fbd124dd BH |
462 | @Override |
463 | public HistogramScaledData scaleTo(int width, int height, int barWidth) { | |
c392540b | 464 | // Basic validation |
bfe038ff MK |
465 | if ((width <= 0) || (height <= 0) || (barWidth <= 0)) |
466 | { | |
fbd124dd | 467 | throw new AssertionError("Invalid histogram dimensions (" + width + "x" + height + ", barWidth=" + barWidth + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
bfe038ff | 468 | } |
c392540b FC |
469 | |
470 | // The result structure | |
fbd124dd | 471 | HistogramScaledData result = new HistogramScaledData(width, height, barWidth); |
c392540b FC |
472 | |
473 | // Scale horizontally | |
74237cc3 | 474 | result.fMaxValue = 0; |
bfe038ff | 475 | |
fbd124dd | 476 | int nbBars = width / barWidth; |
bfe038ff MK |
477 | int bucketsPerBar = (fLastBucket / nbBars) + 1; |
478 | result.fBucketDuration = Math.max(bucketsPerBar * fBucketDuration,1); | |
fbd124dd | 479 | for (int i = 0; i < nbBars; i++) { |
c392540b | 480 | int count = 0; |
bfe038ff MK |
481 | for (int j = i * bucketsPerBar; j < ((i + 1) * bucketsPerBar); j++) { |
482 | if (fNbBuckets <= j) { | |
c392540b | 483 | break; |
bfe038ff | 484 | } |
c392540b FC |
485 | count += fBuckets[j]; |
486 | } | |
487 | result.fData[i] = count; | |
488 | result.fLastBucket = i; | |
bfe038ff | 489 | if (result.fMaxValue < count) { |
c392540b | 490 | result.fMaxValue = count; |
bfe038ff | 491 | } |
c392540b FC |
492 | } |
493 | ||
494 | // Scale vertically | |
495 | if (result.fMaxValue > 0) { | |
496 | result.fScalingFactor = (double) height / result.fMaxValue; | |
497 | } | |
498 | ||
bfe038ff | 499 | fBucketDuration = Math.max(fBucketDuration, 1); |
0fcf3b09 PT |
500 | // Set selection begin and end index in the scaled histogram |
501 | if (fSelectionBegin < fFirstBucketTime) { | |
502 | result.fSelectionBeginBucket = -1; | |
503 | } else if (fSelectionBegin > fLastEventTime) { | |
504 | result.fSelectionBeginBucket = fLastBucket; | |
505 | } else { | |
506 | result.fSelectionBeginBucket = (int) ((fSelectionBegin - fFirstBucketTime) / fBucketDuration) / bucketsPerBar; | |
507 | } | |
508 | if (fSelectionEnd < fFirstBucketTime) { | |
509 | result.fSelectionEndBucket = -1; | |
510 | } else if (fSelectionEnd > fLastEventTime) { | |
511 | result.fSelectionEndBucket = fLastBucket; | |
bfe038ff | 512 | } else { |
0fcf3b09 | 513 | result.fSelectionEndBucket = (int) ((fSelectionEnd - fFirstBucketTime) / fBucketDuration) / bucketsPerBar; |
bfe038ff | 514 | } |
c392540b | 515 | |
fbd124dd BH |
516 | result.fFirstBucketTime = fFirstBucketTime; |
517 | result.fFirstEventTime = fFirstEventTime; | |
c392540b FC |
518 | return result; |
519 | } | |
520 | ||
521 | // ------------------------------------------------------------------------ | |
522 | // Helper functions | |
523 | // ------------------------------------------------------------------------ | |
524 | ||
525 | private void updateEndTime() { | |
bfe038ff | 526 | fTimeLimit = fFirstBucketTime + (fNbBuckets * fBucketDuration); |
c392540b FC |
527 | } |
528 | ||
529 | private void mergeBuckets() { | |
bfe038ff MK |
530 | for (int i = 0; i < (fNbBuckets / 2); i++) { |
531 | fBuckets[i] = fBuckets[2 * i] + fBuckets[(2 * i) + 1]; | |
c392540b FC |
532 | } |
533 | Arrays.fill(fBuckets, fNbBuckets / 2, fNbBuckets, 0); | |
534 | fBucketDuration *= 2; | |
535 | updateEndTime(); | |
bfe038ff | 536 | fLastBucket = (fNbBuckets / 2) - 1; |
c392540b | 537 | } |
bfe038ff | 538 | |
fbd124dd BH |
539 | private void moveBuckets(int offset) { |
540 | for(int i = fNbBuckets - 1; i >= offset; i--) { | |
bfe038ff | 541 | fBuckets[i] = fBuckets[i-offset]; |
fbd124dd BH |
542 | } |
543 | ||
544 | for (int i = 0; i < offset; i++) { | |
545 | fBuckets[i] = 0; | |
546 | } | |
547 | } | |
548 | ||
549 | private int getOffset(long timestamp) { | |
550 | int offset = (int) ((fFirstBucketTime - timestamp) / fBucketDuration); | |
bfe038ff | 551 | if (((fFirstBucketTime - timestamp) % fBucketDuration) != 0) { |
fbd124dd BH |
552 | offset++; |
553 | } | |
554 | return offset; | |
555 | } | |
c392540b FC |
556 | |
557 | } |