3
include($JPGRAPH_PATH . "/jpgraph.php");
4
include($JPGRAPH_PATH . "/jpgraph_line.php");
5
include($JPGRAPH_PATH . "/jpgraph_date.php");
19
var $use_cache_timewindow;
22
var $aggregator; // Aggregating algorithm
23
var $interpolate_gaps; // Do not indicate missing data, do linear interpolation instead
24
var $allowed_gap; // The allowed gaps between data, report if greater (if no interpolation)
26
var $show_marks; // Set marks on the graph if data gaps are detected
27
var $show_gaps; // Present information about gaps in the data on graph
30
const MARKS_NEVER = 0;
31
const MARKS_DEFAULT = 1;
33
const MARKS_ALWAYS = 3;
37
const SHOW_POINTS = 2;
41
function __construct(DATARequest &$props = NULL, CACHE &$cache = NULL) {
42
global $GRAPH_DEFAULT_HEIGHT, $GRAPH_DEFAULT_WIDTH;
45
global $GRAPH_INTERPOLATE_DATA_GAPS;
46
global $GRAPH_ACCURACY_MARKS_IF_GAPS;
48
global $GRAPH_INDICATE_MISSING_DATA;
49
global $GRAPH_INDICATE_DATA_DENSITY;
51
if ($props) $this->req = &$props;
52
else $this->req = new DATARequest();
54
if ($cache) $this->cache = &$cache;
55
else $this->cache = $this->req->CreateCache();
57
$opts = &$this->req->GetOptions();
58
$this->use_cache_timewindow = $opts->Get('use_cache_timewindow');
59
if ($this->use_cache_timewindow) {
60
$this->interval = $this->req->CreateInterval();
61
$this->interval->ApplyCache($this->cache);
63
$iinfo = $this->req->GetIntervalInfo();
64
$this->interval = $this->cache->CreateInterval($iinfo);
67
$this->set_time_axes = !$opts->Get('optimize_time_axes');
69
if (isset($this->req->props['aggregation']))
70
$this->aggregator = $this->req->props['aggregation'];
72
$this->aggregator = CACHE::TYPE_AUTO;
75
if (isset($this->req->props['show_marks']))
76
$this->show_marks = $this->req->props['show_marks'];
78
if ($GRAPH_ACCURACY_MARKS_IF_GAPS)
79
$this->show_marks = DRAW::MARKS_GAPS;
81
$this->show_marks = DRAW::MARKS_DEFAULT;
84
if (isset($this->req->props['show_gaps']))
85
$this->show_gaps = $this->req->props['show_gaps'];
87
if ($GRAPH_INDICATE_DATA_DENSITY) {
88
eval("\$this->show_gaps = DRAW::$GRAPH_INDICATE_DATA_DENSITY;");
90
$this->show_gaps = $GRAPH_INDICATE_DATA_DENSITY;
93
if (isset($this->req->props['interpolate']))
94
$this->interpolate_gaps = $this->req->props['interpolate'];
96
$this->interpolate_gaps = $opts->Get('graph_interpolate', $GRAPH_INTERPOLATE_DATA_GAPS);
98
$this->allowed_gap = $opts->Get('maximal_allowed_gap', false);
101
$minfo = $this->req->GetMaskInfo();
102
$this->mask = $this->cache->CreateMask($minfo);
105
$this->tmpfile = $this->GetTmpFile();
107
/* DS, ToDo: We should restore some variables before we can reuse files
108
if (is_file($TMP_PATH . "/" . $this->tmpfile)) $this->ready = true;
110
if (isset($this->req->props['frame_height'])) $this->height = $this->req->props['frame_height'];
111
else $this->height = $GRAPH_DEFAULT_HEIGHT;
112
if (isset($this->req->props['frame_width'])) $this->width = $this->req->props['frame_width'];
113
else $this->width = $GRAPH_DEFAULT_WIDTH;
115
$this->ready = false;
119
function GetTmpFile() {
120
global $ADEI_SESSION;
124
$props = $this->req->props;
125
unset($props['window']);
126
unset($props['format']);
127
unset($props['mask_mode']);
128
unset($props['resample']);
129
unset($props['filename']);
131
$dir = "clients/" . $ADEI_SESSION . "/draw." . $this->req->props['db_server'] . "__" . $this->req->props['db_name'] . "__" . $this->req->props['db_group'] . "/" . md5(serialize($props)) . "/";
133
if (!is_dir($TMP_PATH . "/" . $dir)) {
134
if (!@mkdir($TMP_PATH . "/" . $dir, 0755, true))
135
throw new ADEIException(translate("DRAW class have not access to the temporary directory"));
138
return $dir . time() . "_" . $this->interval->window_start . "_" . $this->interval->window_size . ".png";
141
function GetAgregatingProperties(&$iv, $size) {
142
global $GRAPH_MAX_POINTS_PER_GRAPH;
143
global $GRAPH_MAX_APPROXIMATION_INTERVAL;
144
global $GRAPH_AUTOAGGREGATION_MINMAX_THRESHOLD;
146
$points = $this->width * $size;
147
if ($points > $GRAPH_MAX_POINTS_PER_GRAPH) {
148
$limit = (int)floor($this->width * $GRAPH_MAX_POINTS_PER_GRAPH / $points);
150
$intivl = $this->width / $limit;
151
if ($intivl > $GRAPH_MAX_APPROXIMATION_INTERVAL) {
152
$limit = (int)ceil($this->width / $GRAPH_MAX_APPROXIMATION_INTERVAL);
154
} else $limit = $this->width;
156
$precision = (int)ceil(2 * $this->width / $limit);
158
$res = $this->cache->resolution->Get($iv, $limit /* amount is here */);
160
if ($this->aggregator) $aggregator = $this->aggregator;
162
if ($precision < $GRAPH_AUTOAGGREGATION_MINMAX_THRESHOLD) $aggregator = CACHE::TYPE_MINMAX;
163
elseif (!$this->cache->resolution->GetWindowSize($res)) $aggregator = CACHE::TYPE_MINMAX;
164
else $aggregator = CACHE::TYPE_MEAN;
168
"type" => $aggregator,
171
"precision" => $precision,
176
function Legend($x = false, $y = false, &$mask = NULL, INTERVAL &$ivl = NULL) {
177
global $GRAPH_DELTA_SIZE;
179
if ($ivl) $iv = $ivl;
180
else $iv = $this->interval;
182
if (!$mask) $mask = &$this->mask;
184
$list = $this->cache->GetItemList($mask, 0);
187
if (isset($this->req->props['x'])) $x = $this->req->props['x'];
188
else throw new ADEIException(translate("The X coordinate is not specified"));
192
if (isset($this->req->props['y'])) $y = $this->req->props['y'];
193
else throw new ADEIException(translate("The Y coordinate is not specified"));
196
if (isset($this->req->props['xmin'])) $xmin = $this->req->props['xmin'];
197
else throw new ADEIException(translate("The XMin is not specified"));
198
if (isset($this->req->props['xmax'])) $xmax = $this->req->props['xmax'];
199
else throw new ADEIException(translate("The XMax is not specified"));
200
if (isset($this->req->props['ymin'])) $ymin = $this->req->props['ymin'];
201
else throw new ADEIException(translate("The YMin is not specified"));
202
if (isset($this->req->props['ymax'])) $ymax = $this->req->props['ymax'];
203
else throw new ADEIException(translate("The yMax is not specified"));
206
$size = sizeof($this->mask->ids);
207
$a = $this->GetAgregatingProperties($iv, $size);
209
if ($a["limit"] > 0) {
211
"4" is due to the fact what maximal approximation error is two
212
intervals. See description in cache.php.
213
FIXME: limit could be decreased due to the border points
216
if ($a['type'] == CACHE::TYPE_MINMAX)
217
$delta_size = 4 * $this->width / $a["limit"];
219
$delta_size = 2 * $this->width / $a["limit"];
221
if ($delta_size < $GRAPH_DELTA_SIZE)
222
$delta_size = $GRAPH_DELTA_SIZE;
224
$delta_size = $GRAPH_DELTA_SIZE;
227
// echo "$delta_size ($GRAPH_DELTA_SIZE)\n";
230
// echo date('c',$x) . "(" . date('c',$xmin) . " - " . date('c', $xmax) . ")\n";
232
$iv->SetupInterval($xmin, $xmax);
233
$iv->SetupWindow(INTERVAL::WINDOW_NEIGHBOURHOOD, $x, (dsMathPreciseSubstract($xmax, $xmin) * $delta_size) / $this->width);
234
// echo date('c',(int)$iv->window_start) . " - " . date('c',(int)$iv->GetWindowEnd()) . "\n";
237
$iv->window_size = (dsMathPreciseSubstract($xmax, $xmin) * $delta_size) / $this->width;
238
$iv->window_start = dsMathPreciseSubstract($x, $iv->window_size / 2);
239
if ($iv->window_start < $xmin) {
240
$iv->window_size -= dsMathPreciseSubstract($xmin, $iv->window_start);
241
$iv->window_start = $xmin;
245
$ywin = (($ymax - $ymin) * $GRAPH_DELTA_SIZE) / $this->height;
246
$min = $y - $ywin / 2;
247
$max = $y + $ywin / 2;
250
$flags = CACHE::TRUNCATE_INTERVALS;
251
$iv->EnableFlexibility();
254
$points = $this->cache->GetIntervals($mask, $iv, 1, 0, $a["resolution"], $flags);
257
$f=fopen("/tmp/xxx6", "w");
258
fprintf($f, "$x $y ($delta_size), [" . $this->width . "x" . $this->height . "]\n");
259
fprintf($f, "$xmin - $xmax, $ymin:$ymax)\n");
260
fprintf($f, "$resolution\n");
261
fprintf($f, print_r($a,true));
262
fprintf($f, print_r($mask, true));
263
fprintf($f, print_r($iv, true));
264
fprintf($f, print_r($list, true));
265
fprintf($f, "ID's: " . $size . "\n");
268
$result = array(); $notfound = true;
269
foreach($points as $t => $v) {
270
// fwrite($f, $t . ": ");
271
// fwrite($f, print_r($v, true));
273
// echo date('c', $t) . "\n";
277
for ($i=0;$i<$size;$i++) {
278
if ((($v["max" .$i]<$min)||($v["min" .$i]>$max))==false) {
279
array_push($result, array(
281
"name" => xml_escape($list[$i]['name'])
290
$neighbors = $this->cache->GetNeighbors($mask, $x);
291
if ((sizeof($neighbors['left']) > 0)&&(sizeof($neighbors['right']) > 0)) {
292
$keys1 = array_keys($neighbors['left']); $x1=$keys1[0];
293
$keys2 = array_keys($neighbors['right']);$x2=$keys2[0];
294
// echo "X: $x ($xmin, $xmax)\n";
295
// echo "Y: $y ($min, $max)\n";
297
// echo "X: $x1, $x, $x2\n";
300
if ((!$this->interpolate_gaps)&&($this->allowed_gap)) {
301
/* We don't check expected gap, since otherwise this points
302
would be found before neighbors lookup */
303
if ((dsMathPreciseSubstract($x, $x1)>$this->allowed_gap)||(dsMathPreciseSubstract($x2, $x)>$this->allowed_gap)) $check1 = false;
306
if (($check1)&&(dsMathPreciseCompare($x1, $xmin)>=0)&&(dsMathPreciseCompare($x2, $xmax)<=0)) {
307
$coef = dsMathPreciseSubstract($x, $x1) / dsMathPreciseSubstract($x2, $x1);
308
// echo $coef . "(" . $size . ")\n";
309
for ($i=0;$i<$size;$i++) {
310
$y1 = $neighbors['left'][$x1][$i];
311
$y2 = $neighbors['right'][$x2][$i];
312
$y = $y1 + $coef*($y2 - $y1); //DS.Precision
314
// print "Y: $y1 - $y - $y2\n";
315
if (($y>$min)&&($y<$max)) {
316
array_push($result, array(
318
"name" => xml_escape($list[$i]['name'])
327
// fprintf($f, print_r($ivl, true));
328
fprintf($f, print_r($result, true));
332
return array("legend" => $result);
335
function Create(&$mask = NULL, INTERVAL &$iv = NULL) {
336
global $GRAPH_MARGINS;
337
global $GRAPH_MAX_CACHE_GAP;
338
global $GRAPH_COLORS;
339
global $GRAPH_LINE_WEIGHT;
340
global $GRAPH_ACCURACY_MARKS_OUTSET;
341
global $GRAPH_ACCURACY_MARKS_MULTIOUTSET;
342
global $GRAPH_ACCURACY_MARKS_COLOR;
343
global $GRAPH_ACCURACY_MARKS_TYPE;
344
global $GRAPH_ACCURACY_MARKS_SIZE;
345
global $GRAPH_SUBSECOND_THRESHOLD;
347
global $GRAPH_DENSITY_PLOT_VALID_SIZE;
348
global $GRAPH_DENSITY_PLOT_VALID_COLOR;
349
global $GRAPH_DENSITY_PLOT_INVALID_SIZE;
350
global $GRAPH_DENSITY_PLOT_INVALID_COLOR;
351
global $GRAPH_DENSITY_POINTS_TYPE;
352
global $GRAPH_DENSITY_POINTS_SIZE;
353
global $GRAPH_DENSITY_POINTS_COLOR;
354
global $GRAPH_DENSITY_POINTS_OUTLINE;
358
if ($this->ready) return;
359
if (!$iv) $iv = &$this->interval;
360
if (!$mask) $mask = &$this->mask;
362
$size = sizeof($mask->ids);
363
$a = $this->GetAgregatingProperties($iv, $size);
364
$precision = $a['precision'];
366
if ($a['limit']) $precision = (int)ceil(2 * $this->width / $a["limit"]);
370
$flags = ($this->interpolate_gaps?0:CACHE::REPORT_EMPTY)|(($this->show_gaps==DRAW::SHOW_GAPS)?CACHE::MISSING_INFO:0);
371
$points = $this->cache->GetPoints($mask, $iv, $a['type'], $a['limit'], $a['amount'], $a['resolution'], $flags);
372
if ($this->allowed_gap !== false) $points->SetOption("allowed_gap", $this->allowed_gap);
376
if ($size > 10) $points = 100;
377
else if ($size > 5) $points = 20;
378
else if ($size > 3) {
379
$points = $this->width / $size;
382
// $points = $this->cache->GetPoints($mask, $iv, CACHE::TYPE_MINMAX);
383
$points = $this->cache->GetPoints($mask, $iv, CACHE::TYPE_MINMAX, $points);
385
$points = $this->cache->GetPoints($mask, $iv, CACHE::TYPE_MINMAX, $this->width);
393
$missing = true; // last point was missing
394
$amount_on_missing = false;
395
$time_on_addon = false;
397
for ($i=0;$i<$size;$i++)
398
$values[$i] = array();
400
if (($iv->y_min)||($iv->y_max)) {
404
for ($i=0;$i<$size;$i++) {
412
if ($this->show_gaps) {
418
if ($this->show_gaps) {
424
foreach($points as $t => $v) {
426
if ($this->show_gaps) {
427
$gapinfo = $points->missing_data();
428
if ($gapinfo) array_push($mvalue, 1);
429
else array_push($mvalue, 0);
435
/* if ($time_on_addon) {
436
if ($this->show_gaps) {
437
array_push($mvalue, 2);
440
array_push($time, $time_on_addon);
441
for ($i=0;$i<$size;$i++) {
442
array_push($values[$i], false);
445
$time_on_addon = false;
448
$amount_on_missing = $amount;
453
array_push($time, $t);
454
if (($min)||($max)) {
455
foreach ($v as $key => $value) {
460
$at_max[$key] = false;
463
$at_min[$key] = true;
466
} elseif ($at_min[$key]) {
470
$at_min[$key] = false;
473
$at_max[$key] = true;
479
$at_max[$key] = true;
480
} elseif ($value < $min) {
482
$at_min[$key] = true;
485
array_push($values[$key], $value);
488
if ($this->show_gaps) {
489
foreach ($v as $key => $value) {
490
if ($value < $realmin) $realmin = $value;
491
if ($value > $realmax) $realmax = $value;
492
array_push($values[$key], $value);
495
foreach ($v as $key => $value) {
496
array_push($values[$key], $value);
502
if ($amount === $amount_on_missing) {
503
if ($this->show_gaps) {
504
/* Yes, this point is set only to prolong last single (standalone) point to interval,
505
so it would be visualized by jpgraph. But in reality it is not a point */
506
array_push($mvalue, 2);
509
$pos = sizeof($values[0]) - 1;
510
array_push($time, $time[$pos]);
511
for ($i=0;$i<$size;$i++) {
512
array_push($values[$i], $values[$i][$pos]);
515
// $time_on_addon = $t;
516
$amount_on_missing = false;
519
if ($this->show_gaps) {
520
array_push($mvalue, 2);
523
// $time_on_addon = false;
525
array_push($time, $t);
526
for ($i=0;$i<$size;$i++) {
527
array_push($values[$i], false);
536
if ((!$missing)&&($amount === $amount_on_missing)) {
537
if ($this->show_gaps) {
538
array_push($mvalue, 2);
541
$pos = sizeof($values[0]) - 1;
542
array_push($time, $time[$pos]);//$t);
543
for ($i=0;$i<$size;$i++) {
544
array_push($values[$i], $values[$i][$pos]);
548
// echo "Points detected: $amount(" . sizeof($time) . ")\n";
551
throw new ADEIException(translate("No data available"));
554
if ($amount != sizeof($time)) {
557
$have_gaps = $points->missing_points();
561
if ($this->show_gaps == DRAW::SHOW_GAPS) $show_gaps = DRAW::SHOW_GAPS;
562
else if (($this->show_gaps == DRAW::SHOW_POINTS)||(($have_gaps)&&($this->show_gaps == DRAW::SHOW_EMPTY))) $show_gaps = DRAW::SHOW_POINTS;
566
if ((!$min)&&(!$max)) {
567
if ($realmin == $realmax) {
569
$px = $realmax / $this->height;
572
} elseif ($realmin < 0) {
573
$px = (-$realmax) / $this->height;
577
$px = 1 / $this->height;
582
$px = ($realmax - $realmin) / $this->height;
583
$min = $realmin - 4 * $px;
584
$max = $realmax + 4 * $px;
587
$px = ($max - $min) / $this->height;
590
$realmax = $max + 2*$px;
592
// echo "$min ($realmin) , $max ($realmax) \n";
599
$to = $time[sizeof($time)-1];
600
$length = dsMathPreciseSubstract($to, $from);
602
// Calculating real accuracy, but only if single plot, otherwise not important
604
$precision = (int)ceil(2 * $this->width / $amount);
607
if ($GRAPH_MAX_CACHE_GAP) {
608
if ((($from - $iv->window_start) < $GRAPH_MAX_CACHE_GAP)||
609
(($to - $iv->window_start - $iv->window_size) < $GRAPH_MAX_CACHE_GAP)) {
610
$range1 = date("c", ceil($iv->window_start)) . " and " . date("c", floor($iv->window_start + $iv->window_size));
611
$range2 = date("c", ceil($from)) . " and " . date("c", floor($to));
612
throw new ADEIException(translate("The data is missing in CACHE: Needed: $range1, Available: $range2"));
618
$this->graph = new Graph($this->width, $this->height, "auto");
619
$this->graph->img->SetMargin($GRAPH_MARGINS['left'],$GRAPH_MARGINS['top'],$GRAPH_MARGINS['right'],$GRAPH_MARGINS['bottom']);
622
// $this->graph->SetTickDensity(TICKD_SPARSE, TICKD_VERYSPARSE);
623
// $this->graph->title->Set("Example on Date scale");
624
// $this->graph->xaxis->scale->SetTimeAlign(MINADJ_15);
625
// $this->graph->xscale->SetGrace(10)
627
if ($length > $GRAPH_SUBSECOND_THRESHOLD) {
628
if (($this->set_time_axes)||($from == $to)) {
629
$from = $iv->window_start;
630
$to = dsMathPreciseAdd($iv->window_start, $iv->window_size);
632
if (($min)||($max)) $this->graph->SetScale("datlin", $min, $max, $from, $to);
633
else $this->graph->SetScale("datlin", true, true, $from, $to);
635
$length = $iv->window_size;
637
if (($min)||($max)) $this->graph->SetScale("datlin", $min, $max);
638
else $this->graph->SetScale("datlin");
641
$this->scale_start = 0;
642
$this->scale_coef = 1;
644
if (($this->set_time_axes)||($from == $to)) {
645
$from = $iv->window_start;
646
$to = dsMathPreciseAdd($iv->window_start, $iv->window_size);
648
$length = $iv->window_size;
650
if ($length > $GRAPH_SUBSECOND_THRESHOLD) {
651
if (($min)||($max)) $this->graph->SetScale("datlin", $min, $max, $from, $to);
652
else $this->graph->SetScale("datlin", true, true, $from, $to);
654
$this->scale_start = 0;
655
$this->scale_coef = 1;
661
$afrom = getdate($from);
666
if ($length > 315360000) { // 10 years
667
$this->graph->xaxis->scale->SetDateFormat('Y');
668
$this->graph->xaxis->SetTextLabelInterval(1);
670
} elseif ($length > 31104000) { // 1 year
671
$this->graph->xaxis->scale->SetDateFormat('M');
672
$this->graph->xaxis->SetTextLabelInterval(2);
674
if ($afrom['year'] == $ato['year']) $date_title = $afrom['year'];
675
else $date_title = $afrom['year'] . " - " . $ato['year'];
676
} elseif ($length > 1036800) { // 12 days
677
$this->graph->xaxis->scale->SetDateFormat('M d');
678
$this->graph->xaxis->SetTextLabelInterval(3);
680
if ($afrom['year'] == $ato['year']) {
681
if ($afrom['mon'] == $ato['mon']) {
682
$date_title = $afrom['month'] . ", " . $afrom['year'];
684
$date_title = $afrom['year'];
687
$date_title = $afrom['year'] . " - " . $ato['year'];
689
} elseif ($length > 86400) { // 1 day
690
$this->graph->xaxis->scale->SetDateFormat('M d, H:i');
691
$this->graph->xaxis->SetTextLabelInterval(4);
693
if ($afrom['year'] == $ato['year']) {
694
if ($afrom['mon'] == $ato['mon']) {
695
$date_title = $afrom['month'] . ", " . $afrom['year'];
697
$date_title = $afrom['year'];
700
$date_title = $afrom['year'] . " - " . $ato['year'];
702
} elseif ($length > 14400) { // 4 hours
703
$this->graph->xaxis->SetTextLabelInterval(2);
704
$this->graph->xaxis->scale->SetDateFormat('H:i');
706
if ($afrom['year'] == $ato['year']) {
707
if ($afrom['mon'] == $ato['mon']) {
708
if ($afrom['mday'] == $ato['mday']) {
709
$date_title = $afrom['month'] . " " . $afrom['mday'] . ", " . $afrom['year'];
711
$date_title = $afrom['month'] . " " . $afrom['mday'] . " - " . $ato['mday'] . ", " . $afrom['year'];
714
$date_title = date("M", $from) . " " . $afrom['mday'] . " - " . date("M", $to) . " " . $ato['mday'] . ", " . $afrom['year'];
717
$date_title = date("M j, Y", $from) . " - " . date("M j, Y", $to);
719
} else if ($length > $GRAPH_SUBSECOND_THRESHOLD) {
720
if ($length > 10) $this->graph->xaxis->SetTextLabelInterval(4);
721
else $this->graph->xaxis->SetTextLabelInterval(4);
722
$this->graph->xaxis->scale->SetDateFormat('H:i:s');
724
if ($afrom['year'] == $ato['year']) {
725
if ($afrom['mon'] == $ato['mon']) {
726
if ($afrom['mday'] == $ato['mday']) {
727
$date_title = $afrom['month'] . " " . $afrom['mday'] . ", " . $afrom['year'];
729
$date_title = $afrom['month'] . " " . $afrom['mday'] . " - " . $ato['mday'] . ", " . $afrom['year'];
732
$date_title = date("M", $from) . " " . $afrom['mday'] . " - " . date("M", $to) . " " . $ato['mday'] . ", " . $afrom['year'];
735
$date_title = date("M j, Y", $from) . " - " . date("M j, Y", $to);
738
$ifrom = floor($from);
739
if (is_float($from)) $rfrom = substr(printf("%.9F", $from - $ifrom),2);
741
$pos = strpos($from, ".");
742
if ($pos === false) $rfrom = 0;
743
else $rfrom = substr($from, $pos + 1);
746
$date_title = date("M j, Y H:i:s", $ifrom);
748
$date_title .= "." . $rfrom;
752
if ($length > $this->width/1000) {
756
elseif ($length > $this->width/1000000) {
764
$reallength = (int)floor($length*$coef);
765
$rem = ($reallength + 10) % 1000;
766
if ($rem<20) $ilength = $reallength - ($rem - 10);
767
else $ilength = $reallength;
769
// echo $reallength . " - " . $length . "\n";
771
$date_title .= " + " . $ilength . $suffix;
773
// echo $coef . " - " . $ilength . "(" . $length . ")\n";
774
$first_num = substr($ilength, 0, 1);
775
$second_num = substr($ilength, 1, 1);
777
if ((++$first_num)==10)
778
$istep = "1" . str_repeat("0", strlen($ilength) - 1);
780
$istep = $first_num . str_repeat("0", strlen($ilength) - 2);
781
} else $istep = $first_num . str_repeat("0", strlen($ilength) - 2);
783
if (($min)||($max)) $this->graph->SetScale("linlin", $min, $max, 0, $reallength); // + 1);
784
else $this->graph->SetScale("linlin", true, true, 0, $reallength);// + 1);
785
$this->graph->xscale->ticks->Set($istep, $istep/4);
787
$ticks = floor(($ilength+1) / $istep);
789
if ($this->width < 350) {
790
if ($this->width < 70) $lpt = $ticks;
791
else $lpt = ceil ($ticks / ($this->width / 70));
792
} else $lpt = round($ticks / 5);
794
$this->graph->xaxis->SetTextLabelInterval($lpt);
796
foreach ($time as &$t) {
799
$it = (int)floor($t);
800
$pos = strpos($t, ".");
801
if ($pos === false) $rt = 0;
802
else $rt = "0." . substr($t, $pos + 1);
804
// echo $coef . ": " . $t;
805
$t = ($it - $ifrom)*$coef + floor(($rt - $rfrom)*$coef);
806
// echo " - " . $t . "\n";
809
$this->scale_start = $from;
810
$this->scale_coef = $coef;
812
// $this->graph->xaxis->SetTextLabelInterval(1);
815
$title = $this->req->props['db_name'];
816
/* Full location information. Too long
817
$title = $this->req->props['db_server'] . ":" . $this->req->props['db_name'] . ":" . $this->req->props['db_group'];
819
/* Precision information. Confusing
821
$operation_info = $points->GetOperationInfo();
823
if (isset($operation_info["resolution"])) $title .= ", res: " . $operation_info["resolution"];
824
if (isset($operation_info["aggregation"])) {
825
switch ($operation_info["aggregation"]) {
826
case CACHE::TYPE_MINMAX:
829
case CACHE::TYPE_MEAN:
834
if ($precision) $title .= ", acc. " . $precision . "px";
835
if ($date_title) $title = "$date_title ($title)";
837
$this->graph->xaxis->SetFont(FF_ARIAL, FS_NORMAL, 8);
838
// $this->graph->xaxis->SetLabelAngle(0);
840
$this->graph->title->Set($title);
841
$this->graph->xaxis->SetPos("min");
844
switch ($this->show_marks) {
845
case DRAW::MARKS_ALWAYS:
848
case DRAW::MARKS_GAPS:
853
case DRAW::MARKS_DEFAULT:
855
if (($GRAPH_ACCURACY_MARKS_MULTIOUTSET)&&($precision > $GRAPH_ACCURACY_MARKS_MULTIOUTSET)) {
860
if (($GRAPH_ACCURACY_MARKS_OUTSET)&&($precision > $GRAPH_ACCURACY_MARKS_OUTSET)) {
865
case DRAW::MARKS_NEVER:
871
if ($GRAPH_ACCURACY_MARKS_COLOR) $marks = $GRAPH_ACCURACY_MARKS_COLOR;
872
else $marks = "black";
874
if ($GRAPH_ACCURACY_MARKS_TYPE) {
875
eval("\$mtype=$GRAPH_ACCURACY_MARKS_TYPE;");
877
$mtype = MARK_FILLEDCIRCLE;
882
for ($i = 0; $i < $size; $i++) {
884
$f = fopen("/tmp/xxx.7", "a+");
885
fwrite($f, print_r($iv, true) . "\n");
886
fwrite($f, $i . " of " . $size . "\n");
887
fwrite($f, date("r", ceil($iv->window_start)) . " - " . date("r", floor($iv->window_start + $iv->window_size)) . "\n");
888
fwrite($f, print_r($time, true));
889
fwrite($f, print_r($values[$i], true));
892
if (sizeof($time) > 0) {
893
$plot = new LinePlot($values[$i], $time);
894
if (sizeof($GRAPH_COLORS)) {
895
$color = $GRAPH_COLORS[$i%sizeof($GRAPH_COLORS)];
896
$plot->SetColor($color);
897
if ($GRAPH_LINE_WEIGHT) {
898
$plot->SetWeight($GRAPH_LINE_WEIGHT);
904
$plot->mark->SetType($mtype);
905
if ($GRAPH_ACCURACY_MARKS_SIZE) $plot->mark->SetSize($GRAPH_ACCURACY_MARKS_SIZE);
906
$plot->mark->SetFillColor(($color&&($size>1))?$color:$marks);
909
$this->graph->Add($plot);
915
$range = date("c", ceil($iv->window_start)) . " and " . date("c", floor($iv->window_start + $iv->window_size));
916
throw new ADEIException(translate("No data between $range"));
919
if ($show_gaps == DRAW::SHOW_GAPS) {
924
foreach ($mvalue as $idx => &$val) {
928
array_push($gtime, $time[$idx]);
929
array_push($gvalue, $realmax);
934
array_push($gtime, $time[$idx]);
935
array_push($gvalue, $realmax);
937
array_push($gtime, $time[$idx]);
938
array_push($gvalue, false);
945
if (sizeof($gtime) > 0) {
946
$plot = new LinePlot($gvalue, $gtime);
947
$plot->SetColor($GRAPH_DENSITY_PLOT_INVALID_COLOR);
948
$plot->SetWeight($GRAPH_DENSITY_PLOT_INVALID_SIZE);
949
$this->graph->Add($plot);
951
} else if ($show_gaps == DRAW::SHOW_POINTS) {
952
foreach ($mvalue as &$val) {
953
if ($val>1) $val = false;
954
else $val = $realmax;
957
$plot = new LinePlot($mvalue, $time);
958
$plot->SetColor($GRAPH_DENSITY_PLOT_VALID_COLOR);
959
$plot->SetWeight($GRAPH_DENSITY_PLOT_VALID_SIZE);
961
if ($GRAPH_DENSITY_POINTS_TYPE) {
962
eval("\$mtype=$GRAPH_DENSITY_POINTS_TYPE;");
966
$plot->mark->SetType($mtype);
967
$plot->mark->SetColor($GRAPH_DENSITY_POINTS_OUTLINE);
968
$plot->mark->SetFillColor($GRAPH_DENSITY_POINTS_COLOR);
969
$plot->mark->SetSize($GRAPH_DENSITY_POINTS_SIZE);
970
$this->graph->Add($plot);
977
// echo $realmin . "\n";
981
/* $graph->img->SetMargin(40,110,20,40);
982
//$graph ->xaxis->scale-> SetDateFormat( 'Y-m-d');
983
$graph->xaxis->SetFont(FF_ARIAL,FS_NORMAL,6);
984
$graph->xaxis->SetLabelAngle(45);
987
$graph->ygrid->Show(true,true);
988
$Size = sizeof($Data->TimeSeries);
989
for($i=3; $i<6;$i++){
990
$lineplot[$i]=new LinePlot($Data->TimeSeries[$i]["Value"], $Data->TimeSeries[$i]["Time"]);
991
$lineplot[$i]->SetColor($Data->TimeSeries[$i]["Color"]);
992
$lineplot[$i]->SetLegend($Data->TimeSeries[$i]["Name"]);
993
$graph->Add($lineplot[$i]);
995
$graph->Stroke($TempDir."Lin-".$FileName.".png");
1001
// $graph = new Graph($this->width, $this->heigh /*, "auto"*/);
1002
// $graph->SetScale('intlin'/* ymin, ymax, xmin, xmax */);
1005
// $lineplot = new LinePlot($dataarray);
1009
function Save($file = false) {
1014
copy($TMP_PATH . "/" . $this->tmpfile, $file);
1018
return $this->tmpfile;
1022
$this->graph->Stroke($file);
1026
$this->graph->Stroke($TMP_PATH . "/" . $this->tmpfile);
1027
return $this->tmpfile;
1030
function GetScaleInfo() {
1031
/* if (!$this->scale_coef) {
1032
$f = fopen("/tmp/xxx.10", "w");
1033
fwrite($f, print_r($this, true));
1037
// "a" => date("c", $this->graph->xaxis->scale->scale[1]),
1038
"xmin" => dsMathPreciseAdd($this->graph->xaxis->scale->scale[0] / $this->scale_coef, $this->scale_start),
1039
"xmax" => dsMathPreciseAdd($this->graph->xaxis->scale->scale[1] / $this->scale_coef, $this->scale_start),
1040
"ymin" => $this->graph->yaxis->scale->scale[0],
1041
"ymax" => $this->graph->yaxis->scale->scale[1]
1045
static function Display($file = false) {
1049
if (preg_match("/^[A-Za-z0-9\/_]\.png$/",$str)) return false;
1050
return @readfile($TMP_PATH . "/" . $file);
b'\\ No newline at end of file'