4
var $interval_start, $interval_end, $interval_items;
5
var $window_start, $window_size, $window_items;
10
const NAME_FORMAT_DEFAULT = 0;
11
const NAME_FORMAT_HUMAN = 0;
12
const NAME_FORMAT_ISO8601 = 1;
15
We can configure for types of windows:
16
<---> no limits (all_mode, end_mode)
17
----> specified window_size from the end (end_mode)
18
|---> specified window_start without size limit (all_mode)
19
|--| specified start and size limits ()
22
specified size => !end_mode
23
specified start => !all_mode
26
specified begin => !end_mode
27
specified_end => !end_mode, !all_mode
29
end_mode: INTERVAL: no start, no end WINDOW: no start
30
all_mode: INTERVAL: no_end WINDOW: no size
32
mode = 2, Unlocked by INTERVAL and WINDOW
33
mode = 1, Unlocked by INTERVAL, but locked by WINDOW
34
mode = 0, Locked by INTERVAL
36
We expecting after Apply, the intervals are only allowed to grow.
47
const NEED_AMOUNT = 1;
48
const FLAG_FLEXIBLE = 2;
49
const FLAG_REDUCIBLE = 6;
51
const WINDOW_RIGHT = 1;
52
const WINDOW_LEFT = 2;
53
const WINDOW_NEIGHBOURHOOD = 3; // Diameter as a size
54
const WINDOW_MAXIMUM = 4;
56
const SEQUENCE_AUTO = 1;
57
const SEQUENCE_FORWARD = 1;
58
const SEQUENCE_BACKWARD = 2;
59
const SEQUENCE_UNSORTED = 3;
60
const SEQUENCE_RANDOM = 4;
62
const MODE_LOCKED = 0; // Exact value is defined (in experiment)
63
const MODE_WINDOWLOCKED = 1; // Locked by Window
64
const MODE_UNLOCKED = 2;
67
function __construct(array &$props = NULL, READER &$reader = NULL, LOGGROUP &$grp = NULL, $flags = 0) {
68
if (($props)&&(isset($props['experiment']))&&(preg_match("/(\d+)-(\d+)/", $props['experiment'], $m))) {
69
$this->interval_start = $m[1];
70
$this->interval_end = $m[2];
74
$this->all_mode = INTERVAL::MODE_LOCKED;
75
$this->end_mode = INTERVAL::MODE_LOCKED;
77
throw new ADEIException(translate("Invalid INTERVAL '%s': have end but no start", $props['experiment']));
80
if ($m[1]) $this->end_mode = INTERVAL::MODE_LOCKED;
81
else $this->end_mode = INTERVAL::MODE_UNLOCKED;
82
$this->all_mode = INTERVAL::MODE_UNLOCKED;
85
$this->all_mode = INTERVAL::MODE_UNLOCKED;
86
$this->end_mode = INTERVAL::MODE_UNLOCKED;
88
$this->interval_start = 0;
89
$this->interval_end = 0;
92
if (($props)&&(isset($props['window']))) {
93
if (preg_match("/^(\d+)$/", $props['window'], $m)) {
94
$this->window_size = $m[1];
95
if ($this->interval_end) {
96
if ($this->window_size) {
97
$this->window_start = dsMathPreciseSubstract($this->interval_end, $this->window_size);
99
if ($this->interval_start > $this->window_start) {
101
$this->window_start = 0;
102
$this->window_size = 0;
105
$this->window_start = $this->interval_start;
106
$this->window_size = dsMathPreciseSubstract($this->interval_end, $this->interval_start);
109
$this->window_start = 0;
112
if (($m[1])&&($this->all_mode)) $this->all_mode = INTERVAL::MODE_WINDOWLOCKED;
116
} elseif (preg_match("/^(([\d.]+)-([\d.]+))?,?(([+-.eE\d]+):([+-.eE\d]+))?$/", $props['window'], $m)) {
118
$this->window_start = $m[2];
119
if (!$this->window_start) $this->window_start = $this->interval_start;
120
$this->window_size = dsMathPreciseSubstract($m[3], $this->window_start);
122
if (($this->window_start<$this->interval_start)||($this->window_size<0)) {
124
$this->window_start = 0;
125
$this->window_size = 0;
128
// interval_start is 0 if still unlocked, so don't care
129
if (($this->window_start)&&($this->end_mode)) $this->end_mode = INTERVAL::MODE_WINDOWLOCKED;
130
if (($this->window_size)&&($this->all_mode)) $this->all_mode = INTERVAL::MODE_WINDOWLOCKED;
134
$this->y_min = $m[5];
135
$this->y_max = $m[6];
136
if ($this->y_min > $this->y_max) {
143
$this->window_size = 0;
144
$this->window_start = 0;
150
if ($this->interval_end) {
151
$this->window_start = $this->interval_start;
152
$this->window_size = dsMathPreciseSubstract($this->interval_end, $this->interval_start);
154
$this->window_size = 0;
155
$this->window_start = 0;
163
$this->interval_items = -1;
164
$this->window_items = -1;
167
$this->sequence = INTERVAL::SEQUENCE_AUTO;
169
if (($reader)&&($grp)) $this->ApplyReader($reader, $grp, $flags);
171
$this->flexibility = $flags&(INTERVAL::FLAG_FLEXIBLE|INTERVAL::FLAG_REDUCIBLE);
174
function SetupInterval($from, $to) {
175
$this->interval_start = $from;
176
$this->interval_end = $to;
180
$this->all_mode = INTERVAL::MODE_LOCKED;
181
$this->end_mode = INTERVAL::MODE_LOCKED;
183
throw new ADEIException(translate("Invalid INTERVAL '%s': have end but no start", "$from-$to"));
186
if ($from) $this->end_mode = INTERVAL::MODE_LOCKED;
187
else $this->end_mode = INTERVAL::MODE_UNLOCKED;
188
$this->all_mode = INTERVAL::MODE_UNLOCKED;
191
$this->window_start = 0;
192
$this->window_size = 0;
195
function SetupWindow($type = INTERVAL::WINDOW_MAXIMUM, $center = 0, $size = 0, $flags = 0) {
197
case INTERVAL::WINDOW_RIGHT:
198
$this->window_start = $center;
199
$this->window_size = $size;
201
if (($this->window_start)&&($this->end_mode)) $this->end_mode = INTERVAL::MODE_WINDOWLOCKED;
202
if (($this->window_size)&&($this->all_mode)) $this->all_mode = INTERVAL::MODE_WINDOWLOCKED;
204
$this->sequence = INTERVAL::SEQUENCE_FORWARD;
206
case INTERVAL::WINDOW_LEFT:
209
$this->window_start = dsMathPreciseSubstract($center, $size);
210
if ($this->end_mode) $this->end_mode = INTERVAL::MODE_WINDOWLOCKED;
212
$this->window_start = 0;
214
if ($this->all_mode) $this->all_mode = INTERVAL::MODE_WINDOWLOCKED;
216
$this->window_start = $center;
218
if (($center)&&($this->end_mode)) $this->end_mode = INTERVAL::MODE_WINDOWLOCKED;
220
$this->window_size = $size;
221
$this->sequence = INTERVAL::SEQUENCE_BACKWARD;
223
case INTERVAL::WINDOW_MAXIMUM:
224
if (($this->interval_end)&&($this->interval_start)) {
225
$this->window_start = $this->interval_start;
226
$this->window_size = dsMathPreciseSubstract($this->interval_end, $this->interval_start);
227
} elseif ($this->interval_start) {
228
$this->window_start = $this->interval_start;
229
$this->window_size = 0;
230
} elseif (!$this->interval_end) {
231
$this->window_start = 0;
232
$this->window_size = 0;
234
throw new ADEIException(translate("Invalid INTERVAL: have end but no start"));
237
$this->sequence = INTERVAL::SEQUENCE_FORWARD;
238
return; /* Updating is not needed */
239
case INTERVAL::WINDOW_NEIGHBOURHOOD:
242
$this->window_start = dsMathPreciseSubstract($center, $size / 2);
243
if ($this->end_mode) $this->end_mode = INTERVAL::MODE_WINDOWLOCKED;
245
$this->window_start = 0;
247
$this->window_size = $size;
248
if ($this->all_mode) $this->all_mode = INTERVAL::MODE_WINDOWLOCKED;
250
$this->window_start = $center;
251
$this->window_size = $size;
253
if (($center)&&($this->end_mode)) $this->end_mode = INTERVAL::MODE_WINDOWLOCKED;
255
$this->sequence = INTERVAL::SEQUENCE_AUTO;
258
throw new ADEIException(translate("Invalid window type '%s' is specified", $type));
261
$this->UpdateWindow(true);
264
function SetSequence($seq = false) {
265
if ($seq === false) $this->sequence = INTERVAL::SEQUENCE_AUTO;
266
else $this->sequence = $seq;
269
function EnableFlexibility($reducible = false) {
271
$this->flexibility = (INTERVAL::FLAG_FLEXIBLE|INTERVAL::FLAG_REDUCIBLE);
273
$this->flexibility = INTERVAL::FLAG_FLEXIBLE;
277
function UpdateWindow($forbid_empty_window = false) {
278
if (($this->interval_start)&&($this->interval_start > $this->window_start)) {
279
$this->window_size -= dsMathPreciseSubstract($this->interval_start, $this->window_start);
281
if ($this->window_size < 0) {
282
$this->window_start = 0;
283
$this->window_size = 0;
285
if ($forbid_empty_window)
286
throw new ADEIException(translate("The WINDOW is out of the INTERVAL '%s' range", $this->interval_start . "-" . $this->interval_end));
288
$this->window_start = $this->interval_start;
291
$this->window_items = -1;
294
if (($this->interval_end)&&(($this->window_start + $this->window_size) > $this->interval_end)) {
295
if ($this->interval_end <= $this->window_start) {
296
$this->window_start = 0;
297
$this->window_size = 0;
299
if ($forbid_empty_window)
300
throw new ADEIException(translate("The WINDOW is out of the INTERVAL '%s' range", $this->interval_start . "-" . $this->interval_end));
302
$this->window_size = dsMathPreciseSubstract($this->interval_end, $this->window_start);
304
$this->window_items = -1;
308
function Apply($first, $last, $records = false) {
311
if ($records !== false) $this->interval_items = $records;
313
if ($this->end_mode) {
314
$this->interval_start = $first;
315
$this->interval_end = $last;
316
} elseif ($this->all_mode) {
317
$this->interval_end = $last;
320
if ($this->end_mode == INTERVAL::MODE_UNLOCKED) {
321
if ($this->all_mode == INTERVAL::MODE_UNLOCKED) {
322
$this->window_start = $this->interval_start;
323
$this->window_size = dsMathPreciseSubstract($this->interval_end, $this->interval_start);
325
$this->window_start = dsMathPreciseSubstract($this->interval_end, $this->window_size);
326
$this->UpdateWindow();
329
if ($this->all_mode == INTERVAL::MODE_UNLOCKED) {
330
$this->window_size = dsMathPreciseSubstract($this->interval_end, $this->window_start);
331
$this->UpdateWindow();
333
$this->UpdateWindow();
338
function ApplyReader(READER &$reader, LOGGROUP &$grp, $flags = 0) {
339
if (($flags&INTERVAL::NEED_AMOUNT)||($this->end_mode)||($this->all_mode)) {
340
if (flags&INTERVAL::NEED_AMOUNT) {
341
$info = $reader->GetGroupInfo($grp, READER::NEED_INFO|READER::NEED_COUNT);
342
$this->Apply($info['first'], $info['last'], $info['records']);
344
$info = $reader->GetGroupInfo($grp, READER::NEED_INFO);
345
$this->Apply($info['first'], $info['last']);
348
$this->UpdateWindow();
352
function ApplyCache(CACHE &$cache) {
353
if (($flags&INTERVAL::NEED_AMOUNT)||($this->end_mode)||($this->all_mode)) {
354
if (flags&INTERVAL::NEED_AMOUNT) {
355
$info = $cache->GetInfo(CACHE::NEED_COUNT);
356
$this->Apply($info['first'], $info['last'], $info['records']);
358
$info = $cache->GetInfo();
359
$this->Apply($info['first'], $info['last']);
362
$this->UpdateWindow();
366
function Limit($min = 0, $max = 0) {
367
if (($min)&&($min > $this->interval_start)) {
368
if ($min > $this->interval_end)
369
$this->interval_start = $this->interval_end;
371
$this->interval_start = $min;
375
if (($max)&&($max < $this->interval_end)) {
376
if ($max < $this->interval_start)
377
$this->interval_end = $this->interval_start;
379
$this->interval_end = $max;
385
$this->all_mode = INTERVAL::MODE_LOCKED;
386
$this->end_mode = INTERVAL::MODE_LOCKED;
387
} elseif ($min) $this->end_mode = INTERVAL::MODE_LOCKED;
390
$this->interval_items = -1;
391
$this->UpdateWindow();
395
function GetSQL(CACHEDB &$cache, $limit = 0, $use_subseconds = false) {
399
$res['limit'] = " LIMIT " . abs($limit);
403
if ($use_subseconds) {
404
$res['list'] = "UNIX_TIMESTAMP(time) AS timestamp, `ns`";
406
if (($this->sequence == INTERVAL::SEQUENCE_UNSORTED)/*||($limit == 1)*/)
408
elseif (($limit < 0)||($this->sequence == INTERVAL::SEQUENCE_BACKWARD))
409
$res['sort'] = "ORDER BY `time` DESC, `ns` DESC";
411
$res['sort'] = "ORDER BY `time` ASC, `ns` ASC";
413
$res['list'] = "UNIX_TIMESTAMP(time) AS timestamp";
415
if (($this->sequence == INTERVAL::SEQUENCE_UNSORTED)/*||($limit == 1)*/)
417
elseif (($limit < 0)||($this->sequence == INTERVAL::SEQUENCE_BACKWARD))
418
$res['sort'] = "ORDER BY `time` DESC";
420
$res['sort'] = "ORDER BY `time` ASC";
424
$from = $this->window_start;
425
if ($this->window_size > 0) {
426
$to = dsMathPreciseAdd($this->window_start, $this->window_size);
428
$ifrom = (int)floor($from);
429
$ito = (int)floor($to);
431
if (($use_subseconds)&&(($ifrom != $from)||($ito != $to))) {
432
if ($ifrom == $ito) {
433
$sqlfrom = $cache->SQLTime($ifrom);
434
if ($from == $ifrom) $nfrom = 0;
435
else $nfrom = round(1000000000*("0" . strstr($from, ".")));
436
if ($to == $ito) $nto = 0;
437
else $nto = round(1000000000*("0" . strstr($to, ".")));
439
$res['cond'] = "WHERE ((`time` = $sqlfrom) AND (`ns` >= $nfrom) AND (`ns` < $nto))";
442
if ($ifrom != $from) {
443
$nfrom = round(1000000000*("0" . strstr($from, ".")));
444
$sqlfrom = $cache->SQLTime($ifrom);
445
$cond = "((`time` = $sqlfrom) AND (`ns` >= $nfrom))";
449
if ($ifrom != $ito) {
450
if ($cond) $cond .= " OR ";
452
$sqlfrom = $cache->SQLTime($ifrom);
453
$sqlto = $cache->SQLTime($ito);
454
$cond .= "((`time` >= $sqlfrom) AND (`time` < $sqlto))";
455
} else $sqlto = false;
458
if ($cond) $cond .= " OR ";
459
if (!$sqlto) $sqlto = $cache->SQLTime($ito);
461
$nto = round(1000000000*("0" . strstr($to, ".")));
462
$cond .= "((`time` = $sqlto) AND (`ns` < $nto))";
465
$res['cond'] = "WHERE ($cond)";
468
$sqlfrom = $cache->SQLTime($ifrom);
469
$sqlto = $cache->SQLTime($ito);
470
$res['cond'] = "WHERE ((`time` >= $sqlfrom) AND (`time` < $sqlto))";
473
if ($this->sequence == INTERVAL::SEQUENCE_BACKWARD) $sign = '<';
476
$ifrom = (int)floor($from);
477
$sqlfrom = $cache->SQLTime($ifrom);
479
if (($use_subseconds)&&($ifrom != $from)) {
480
$nfrom = round(1000000000*("0" . strstr($from, ".")));
481
$res['cond'] = "WHERE (((`time` = $sqlfrom) AND (`ns` $sign $nfrom)) OR (`time` $sign $sqlfrom))";
483
$res['cond'] = "WHERE `time` $sign $sqlfrom";
490
function GetWindowStart() {
491
// if ($this->window_start)||
492
return $this->window_start;
495
function GetWindowEnd() {
496
return dsMathPreciseAdd($this->window_start, $this->window_size);
499
function GetWindowSize() {
500
return $this->window_size;
504
function GetName($format = NAME_FORMAT_DEFAULT) {
506
case NAME_FORMAT_HUMAN:
507
throw new ADEIException(translate("Not implemented yet"));
509
case NAME_FORMAT_ISO8601:
510
if (($this->window_start)&&($this->window_size))
511
return date("Ymd\THis", floor($this->window_start)) . "-" . date("Ymd\THis", ceil($this->window_start + $this->window_size));
512
else if ($this->window_size) {
513
$ws = $this->window_size;
517
$msg .= floor($ws / 86400) . "d";
521
$msg .= floor($ws / 3600) . "h";
525
$msg .= floor($ws / 60) . "m";
528
$msg .= floor($ws) . "s";
529
} else if ($ws >= 0.001) {
530
$msg = floor($ws*1000) . "ms";
531
} else if ($ws >= 0.000001) {
532
$msg = floor($ws*1000000) . "us";
534
$msg = floor($ws*1000000000) . "ns";
541
throw new ADEIException(translate("Unknown format is requested"));
b'\\ No newline at end of file'