function Legend($x = false, $y = false, MASK $mask = NULL, INTERVAL $ivl = NULL) { global $GRAPH_DELTA_SIZE; global $GRAPH_FAST_LEGEND; $spec = $this->CreateLegendSpec($x, $y); list($xmin, $xmax) = $this->GetLegendSpecXInterval($spec); $x = $spec['x']; $y = $spec['y']; $group = $this->reader->CreateGroup(); $caches = $this->reader->CreateCacheSet($group, $mask); $ivl = $this->PrepareInterval($this->reader, $group, $caches, $ivl, array($xmim, $xmax)); $cfg = $this->GetAgregatingProperties($caches, $ivl); $iv = $this->GetLegendInterval($spec, $cfg); if (!$GRAPH_FAST_LEGEND || $cfg['type'] == CACHE::TYPE_MEAN) { return $this->LegendSlow($spec, $iv, $mask, $ivl); } $cache_flags = CACHE::TRUNCATE_INTERVALS; $itemlist_flags = REQUEST::NEED_AXISINFO; $axes = $this->reader->CreateAxes(); $a = array_merge($cfg, array('limit' => 1, 'amount' => 0)); $result = array(); $notfound = true; $caches->EnumerateAxes($axes, CACHESet::CACHE_ITEMS | $itemlist_flags); $itempositions = array_fill(0, $axes->GetAxesNumber(), 0); // counters by axis $itempos = array(); // itemid in group => itemid in axis foreach ($caches as $key => $cachewrap) { $cache = $cachewrap->GetCache(); $size = $cachewrap->GetWidth(); $list = $cachewrap->GetItemList($itemlist_flags); $a['resolution'] = $cache->resolution->Get($ivl, $cfg['amount']); $points = $cachewrap->GetIntervals($iv, $a, $cache_flags); $operation_info = $points->GetOperationInfo(); $group_result = array(); foreach ($points as $t => $v) { for ($i = 0; $i < $size; $i++) { $axis = $axes->GetAxis($list[$i]['axis']); $axispos = $axis->GetPosition(); $itempos[$i] = $itempositions[$axispos]++; list($min, $max) = $this->GetLegendSpecYInterval($spec, $axispos); if (($v["max" . $i] < $min || $v["min" . $i] > $max) == false) { array_push($group_result, array("id" => $i, "name" => $list[$i]['name'], "mode" => "interval", "interval" => array("from" => $iv->GetWindowStart(), "to" => $iv->GetWindowEnd(), "resolution" => $operation_info['resolution']), "value" => array("min" => $this->ValueFormat($v["min{$i}"]), "max" => $this->ValueFormat($v["max{$i}"]), "mean" => $this->ValueFormat($v["mean{$i}"])), "color" => $axis->GetChannelColor($itempos[$i]))); } } $notfound = false; break; } unset($points); /* Trully saying this is suboptimal on the rapidly changing data, where MINMAX jumping up and down. GetNeighbors will get just latest point, but MINMAX could use as an end point, just previous one */ if ($notfound) { // Indexing items for ($i = 0; $i < $size; $i++) { $axis = $axes->GetAxis($list[$i]['axis']); $axispos = $axis->GetPosition(); $itempos[$i] = $itempositions[$axispos]++; } $neighbors = $cachewrap->GetNeighbors($x); if (sizeof($neighbors['left']) > 0 && sizeof($neighbors['right']) > 0) { $keys1 = array_keys($neighbors['left']); $x1 = $keys1[0]; $keys2 = array_keys($neighbors['right']); $x2 = $keys2[0]; $check1 = true; if (!$this->interpolate_gaps) { /* We don't check expected gap, since otherwise this points would be found before neighbors lookup */ /* echo "$x $x1\n"; echo ($x - $x1) . "\n"; echo $this->allowed_gap . "\n"; */ $distance = max(dsMathPreciseSubstract($x, $x1), dsMathPreciseSubstract($x2, $x)); if ($this->allowed_gap && $distance > $this->allowed_gap) { $check1 = false; } if ($operation_info['resolution'] && $distance > 2 * $operation_info['resolution']) { $check1 = false; } } if ($check1 && dsMathPreciseCompare($x1, $xmin) >= 0 && dsMathPreciseCompare($x2, $xmax) <= 0) { $coef = dsMathPreciseSubstract($x, $x1) / dsMathPreciseSubstract($x2, $x1); for ($i = 0; $i < $size; $i++) { $axis = $axes->GetAxis($list[$i]['axis']); $axispos = $axis->GetPosition(); list($min, $max) = $this->GetLegendSpecYInterval($spec, $axispos); $y1 = $neighbors['left'][$x1][$i]; $y2 = $neighbors['right'][$x2][$i]; $y = $y1 + $coef * ($y2 - $y1); //DS.Precision if ($y > $min && $y < $max) { array_push($group_result, array("id" => $i, "name" => $list[$i]['name'], "mode" => "approximation", "approximation" => array("x1" => $x1, "y1" => $this->ValueFormat($y1), "x2" => $x2, "y2" => $this->ValueFormat($y2)), "color" => $axis->GetChannelColor($itempos[$i]))); } } } } } if ($group_result) { array_push($result, array("title" => $cachewrap->GetGroupTitle(), "results" => $group_result)); } } // print_r($legend); return $result; }
function GetPoint(&$key1, &$ivl1, &$key2, &$ivl2) { $this->row = array(); switch ($this->type) { case CACHE::TYPE_MEAN: if ($this->empty_key) { $nextkey = dsMathPreciseAdd($this->empty_key, $this->expected_gap); if ($nextkey > $key1) { $this->empty_key = false; } else { $this->key = $this->empty_key; $this->row[0] = false; $this->empty_key = $nextkey; return false; } } $this->missing = 0; if ($ivl1) { if ($ivl2 && ($this->flags & CACHE::REPORT_EMPTY || $this->flags & CACHE::MISSING_INFO)) { $key1end = dsMathPreciseAdd($key1, $ivl1['width']); $distance = dsMathPreciseSubstract($key2, $key1end); if ($this->allowed_gap && $distance > $this->allowed_gap) { $this->missing = $distance; if ($this->expected_gap && $distance > 2 * $this->expected_gap) { $this->gaps = true; if ($this->flags & CACHE::REPORT_EMPTY) { $this->empty_key = dsMathPreciseAdd($key1end, $this->expected_gap); } } } } $ivl =& $ivl1; $this->key = dsMathPreciseAdd($key1, $ivl['width'] / 2); } else { $ivl =& $ivl2; $this->key = dsMathPreciseAdd($key2, $ivl['width'] / 2); } if ($this->allowed_gap && !$this->missing && $ivl['maxgap'] > $this->allowed_gap) { $this->missing = $ivl['maxgap']; } for ($i = 0; $i < $this->ids; $i++) { $this->row[$i] = $ivl['mean' . $i]; } break; case CACHE::TYPE_MINMAX: if ($this->started) { $key1end = dsMathPreciseAdd($key1, $ivl1['width']); if ($ivl2) { $distance = dsMathPreciseSubstract($key2, $key1end); if ($this->expected_gap && $distance > 2 * $this->expected_gap) { $this->MINMAXLast($key1end, $ivl1); if ($this->allowed_gap && $distance > $this->allowed_gap) { $this->missing = $distance; $this->gaps = true; if ($this->flags & CACHE::REPORT_EMPTY) { $this->empty_key = dsMathPreciseAdd($key1end, $this->expected_gap); } } return false; } if ($distance > 0) { $this->MINMAXStep($key1end, $ivl1, $key2, $ivl2); } else { $this->MINMAXStep($key1end = false, $ivl1, $key2, $ivl2); } } else { if ($ivl1) { $this->MINMAXLast($key1end, $ivl1); } } } else { if ($ivl2) { if ($this->empty_key) { $nextkey = dsMathPreciseAdd($this->empty_key, $this->expected_gap); if ($nextkey > $key2) { $this->empty_key = false; } else { $this->key = $this->empty_key; $this->row[0] = false; $this->empty_key = $nextkey; return false; } } else { if ($ivl1 && $this->allowed_gap) { $key1end = dsMathPreciseAdd($key1, $ivl1['width']); $distance = dsMathPreciseSubstract($key2, $key1end); if ($distance > $this->allowed_gap) { $this->gaps = true; if ($this->flags & CACHE::REPORT_EMPTY) { $this->empty_key = dsMathPreciseAdd($key1end, $this->expected_gap); return false; } } } } if (!$ivl2['width']) { $this->key = $key2; for ($i = 0; $i < $this->ids; $i++) { $this->row[$i] = $ivl2['mean' . $i]; } $this->missing = 0; if ($this->flags & CACHE::MISSING_INFO && $this->allowed_gap) { if ($this->interval && $this->interval->valid()) { $this->row3 = $this->interval->current(); $this->key3 = $this->interval->key(); $this->interval->next(); $distance = dsMathPreciseSubstract($key3, $key2); if ($distance > $this->allowed_gap) { $this->missing = $distance; } } } } else { $this->MINMAXFirst($key2, $ivl2); } } else { /* if not started and no ivl2 - we are done */ unset($this->irow); } } break; default: throw new ADEIException(translate("Invalid interval aggregation mode (%u) is specified", $this->type)); } return true; // print_r($ivl1); }
function GetRequestWindowSize() { if ($this->request_window_size > 0) { return $this->request_window_size; } else { if ($this->request_window_start !== false) { if (!$this->end_by_data) { return dsMathPreciseSubstract($this->GetRequestEndTime(), $this->request_window_start); } } } return $this->GetWindowSize(); }
function ParseTitleDate($spec) { global $GRAPH_SUBSECOND_THRESHOLD; $spec['length'] = dsMathPreciseSubstract($spec['to'], $spec['from']); $from = $spec['from']; $to = $spec['to']; $length = $spec['length']; $afrom = getdate($from); $ato = getdate($to); if ($length > 315360000) { // 10 years $date_format = 'Y'; $label_interval = 1; $date_title = $afrom['year'] . " - " . $ato['year']; } elseif ($length > 31104000) { // 1 year if ($afrom['year'] == $ato['year']) { $date_format = 'M'; $label_interval = 2; $date_title = $afrom['year']; } else { $date_format = 'M, Y'; $label_interval = 2; $date_title = $afrom['year'] . " - " . $ato['year']; } } elseif ($length > 1036800) { // 12 days $date_format = 'M d'; $label_interval = 3; if ($afrom['year'] == $ato['year']) { if ($afrom['mon'] == $ato['mon']) { $date_title = $afrom['month'] . ", " . $afrom['year']; } else { $date_title = $afrom['year']; } } else { $date_title = $afrom['year'] . " - " . $ato['year']; } } elseif ($length > 86400) { // 1 day $date_format = 'M d, H:i'; $label_interval = 4; if ($afrom['year'] == $ato['year']) { if ($afrom['mon'] == $ato['mon']) { $date_title = $afrom['month'] . ", " . $afrom['year']; } else { $date_title = $afrom['year']; } } else { $date_title = $afrom['year'] . " - " . $ato['year']; } } elseif ($length > 14400) { // 4 hours $date_format = 'H:i'; $label_interval = 2; if ($afrom['year'] == $ato['year']) { if ($afrom['mon'] == $ato['mon']) { if ($afrom['mday'] == $ato['mday']) { $date_title = $afrom['month'] . " " . $afrom['mday'] . ", " . $afrom['year']; } else { $date_title = $afrom['month'] . " " . $afrom['mday'] . " - " . $ato['mday'] . ", " . $afrom['year']; } } else { $date_title = date("M", $from) . " " . $afrom['mday'] . " - " . date("M", $to) . " " . $ato['mday'] . ", " . $afrom['year']; } } else { $date_title = date("M j, Y", $from) . " - " . date("M j, Y", $to); } } else { if ($length > $GRAPH_SUBSECOND_THRESHOLD) { $date_format = 'H:i:s'; $label_interval = 4; if ($afrom['year'] == $ato['year']) { if ($afrom['mon'] == $ato['mon']) { if ($afrom['mday'] == $ato['mday']) { $date_title = $afrom['month'] . " " . $afrom['mday'] . ", " . $afrom['year']; } else { $date_title = $afrom['month'] . " " . $afrom['mday'] . " - " . $ato['mday'] . ", " . $afrom['year']; } } else { $date_title = date("M", $from) . " " . $afrom['mday'] . " - " . date("M", $to) . " " . $ato['mday'] . ", " . $afrom['year']; } } else { $date_title = date("M j, Y", $from) . " - " . date("M j, Y", $to); } } else { $ifrom = floor($from); if (is_float($from)) { $rfrom = substr(printf("%.9F", $from - $ifrom), 2); } else { $pos = strpos($from, "."); if ($pos === false) { $rfrom = 0; } else { $rfrom = substr($from, $pos + 1); } } $date_title = date("M j, Y H:i:s", $ifrom); if ($rfrom) { $date_title .= "." . $rfrom; $rfrom = "0.{$rfrom}"; } } } if ($date_title == "") { $date_title = "All data"; } return $date_title; }
function dsMathPreciseSubstract($a, $b) { if ($a < $b) { return -dsMathPreciseSubstract($b, $a); } $pos = strpos($a, "."); if ($pos === false) { $ra = 0; $ia = (int) $a; } else { $ia = (int) floor($a); if (is_float($a)) { $ra = $a - $ia; } else { if ($ia < 0) { $ra = 1 - ("0." . substr($a, $pos + 1)); } else { $ra = "0." . substr($a, $pos + 1); } } } $pos = strpos($b, "."); if ($pos === false) { $rb = 0; $ib = (int) $b; } else { $ib = (int) floor($b); if (is_float($b)) { $rb = $b - $ib; } else { if ($ib < 0) { $rb = 1 - ("0." . substr($b, $pos + 1)); } else { $rb = "0." . substr($b, $pos + 1); } } } if ($ra || $rb) { $r = $ra - $rb; # if ($a < 0) echo "$a,$b $ia,$ib, $ra,$rb = $r\n"; if ($r < 0) { if ($ia > $ib) { return $ia - $ib - 1 . strstr(sprintf("%.24F", $r + 1), "."); } else { return 0; } } else { if ($r > 0) { if ($ia < $ib) { return 0; } else { return $ia - $ib . strstr(sprintf("%.24F", $r), "."); } } else { if ($ia > $ib) { return $ia - $ib; } else { return 0; } } } } else { return $ia - $ib; } }