source: trunk/Graph.php

Last change on this file was 95, checked in by chronos, 2 years ago
  • Modified: Updated Common package.
  • Added: Explicit types for better type checking.
  • Fixed: Support for php 8.0.
File size: 10.0 KB
Line 
1<?php
2
3include_once('Application/Core.php');
4
5class MeasureGraph
6{
7 public Database $Database;
8 public int $FontSize;
9 public string $FontFileNameName;
10 public float $ValueToImageHeigthCoefficient;
11 public int $DefaultWidth;
12 public int $DefaultHeight;
13
14 function __construct(Database $Database)
15 {
16 $this->Database = &$Database;
17 $this->DefaultWidth = 800;
18 $this->DefaultHeight = 200;
19 $this->FontSize = 10;
20 $this->FontFileName = './arial.ttf';
21 $this->ValueToImageHeigthCoefficient = 0.9;
22 }
23
24 function Render(): void
25 {
26 global $Config;
27
28 if (!array_key_exists('From',$_GET)) die('Musíte zadat čas počátku');
29 $StartTime = addslashes($_GET['From']);
30 if (!array_key_exists('To',$_GET)) die('Musíte zadat čas konce');
31 $EndTime = addslashes($_GET['To']);
32 if ($EndTime < $StartTime) $EndTime = $StartTime + 60;
33 $TimeDifference = $EndTime - $StartTime;
34 if (!array_key_exists('Measure', $_GET)) die('Musíte zadat měřenou veličinu');
35 $MeasureId = addslashes($_GET['Measure']);
36 if (!array_key_exists('Width', $_GET)) $Width = $this->DefaultWidth;
37 else $Width = addslashes($_GET['Width']);
38 if (!array_key_exists('Height', $_GET)) $Height = $this->DefaultHeight;
39 else $Height = addslashes($_GET['Height']);
40 if (!array_key_exists('Differential', $_GET)) $Differential = $Config['DefaultVariables']['Differential'];
41 else $Differential = addslashes($_GET['Differential']);
42 $VerticalLinesCount = round($Height / ($this->FontSize + 4));
43
44 $PrefixMultiplier = new PrefixMultiplier();
45 $StopWatchStart = GetMicrotime();
46
47 $Measure = new Measure($this->Database);
48 $Measure->Load($MeasureId);
49 $Measure->DivisionCount = $Config['DivisionCount'];
50 $Measure->LevelReducing = $Config['LevelReducing'];
51 $Measure->MaxLevel = $Config['MaxLevel'];
52 $Measure->ReferenceTime = $Config['ReferenceTime'];
53 $Measure->Differential = $Differential;
54
55 $Level = floor(log(($EndTime - $StartTime) / $Measure->DivisionCount / 60) / log($Measure->LevelReducing)) - 1;
56 if ($Level < 0) $Level = 0;
57 if ($Level > $Measure->MaxLevel) $Level = $Measure->MaxLevel;
58
59 $Points = $Measure->GetValues($StartTime, $EndTime, $Level);
60
61 // Calculate total max, avg, min value
62 $MaxValue = -1000000000000000000;
63 $AvgValue = 0;
64 $MinValue = 1000000000000000000;
65 foreach ($Points as $Index => $Item)
66 {
67 //$Points[$Index]['Min'] = $Points[$Index]['Min'] / $Measure['Divider'];
68 //$Points[$Index]['Avg'] = $Points[$Index]['Avg'] / $Measure['Divider'];
69 //$Points[$Index]['Max'] = $Points[$Index]['Max'] / $Measure['Divider'];
70 if ($Points[$Index]['Avg'] > $MaxValue) $MaxValue = $Points[$Index]['Avg'];
71 if ($Points[$Index]['Avg'] < $MinValue) $MinValue = $Points[$Index]['Avg'];
72 if ($Points[$Index]['Max'] > $MaxValue) $MaxValue = $Points[$Index]['Max'];
73 if ($Points[$Index]['Min'] < $MinValue) $MinValue = $Points[$Index]['Min'];
74 $AvgValue = $AvgValue + $Points[$Index]['Avg'];
75 }
76 //$MinValue = round($MinValue * $Measure['Divider']) / $Measure['Divider'];
77 //$MaxValue = round($MaxValue * $Measure['Divider']) / $Measure['Divider'];
78 $AvgValue = $AvgValue / count($Points); //round(* $Measure['Divider']) / $Measure['Divider'];
79
80 // Generate polygon and recalculate y values to fit graph height
81 $PointsMin = array(0, $Height - 1);
82 $PointsAvg = array(0, $Height - 1);
83 $PointsMax = array(0, $Height - 1);
84 if (($MaxValue - $MinValue) == 0) $MaxValue = $MinValue + 1;
85 {
86 foreach ($Points as $Index => $Item)
87 {
88 $PointsMin[] = $Index * $Width / $Measure->DivisionCount;
89 $PointsMin[] = $Height - 1 - ($Points[$Index]['Min'] - $MinValue) /
90 ($MaxValue - $MinValue) * $Height * $this->ValueToImageHeigthCoefficient;
91 $PointsAvg[] = $Index * $Width / $Measure->DivisionCount;
92 $PointsAvg[] = $Height - 1 - ($Points[$Index]['Avg'] - $MinValue) /
93 ($MaxValue - $MinValue) * $Height * $this->ValueToImageHeigthCoefficient;
94 $PointsMax[] = $Index * $Width / $Measure->DivisionCount;
95 $PointsMax[] = $Height - 1 - ($Points[$Index]['Max'] - $MinValue) /
96 ($MaxValue - $MinValue) * $Height * $this->ValueToImageHeigthCoefficient;
97 }
98 }
99 $PointsMin[] = $Width - 1;
100 $PointsMin[] = $Height - 1;
101 $PointsAvg[] = $Width - 1;
102 $PointsAvg[] = $Height - 1;
103 $PointsMax[] = $Width - 1;
104 $PointsMax[] = $Height - 1;
105 $PointsMin[] = $Width - 1;
106 $PointsMin[] = $Height - 1;
107 $PointsAvg[] = $Width - 1;
108 $PointsAvg[] = $Height - 1;
109 $PointsMax[] = $Width - 1;
110 $PointsMax[] = $Height - 1;
111
112 //array_unshift($Points, $Height - 1);
113 //array_unshift($Points, 0);
114 //$Points[] = $Width - 1;
115 //$Points[] = $Height - 1;
116
117 // Generate image
118 $Image = @imagecreate($Width, $Height);
119 $BackgroundColor = imagecolorallocate($Image, 255, 255, 255);
120 $Black = imagecolorallocate($Image, 0, 0, 0);
121 $White = imagecolorallocate($Image, 255, 255, 255);
122 $Gray = imagecolorallocate($Image, 200, 200, 200);
123 $DarkGray = imagecolorallocate($Image, 100, 100, 100);
124 $LightBlue = imagecolorallocate($Image, 150, 150, 255);
125 $Blue = imagecolorallocate($Image, 0, 0, 255);
126 $LightRed = imagecolorallocate($Image, 255, 150, 150);
127 $Red = imagecolorallocate($Image, 255, 0, 0);
128 $Green = imagecolorallocate($Image, 0, 200, 0);
129 $LightGreen = imagecolorallocate($Image, 150, 255, 150);
130
131 imagefilledpolygon($Image, $PointsMax, count($PointsMax) / 2, $LightRed);
132 imagefilledpolygon($Image, $PointsAvg, count($PointsAvg) / 2, $LightGreen);
133 imagefilledpolygon($Image, $PointsMin, count($PointsMin) / 2, $LightBlue);
134
135 $TimeMarks = array(1, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*30,
136 60*60*24*365, 60*60*24*365*10);
137
138 $TimeRange = $EndTime - $StartTime;
139 $TimeMarksIndex = 0;
140 while ((($TimeRange / $TimeMarks[$TimeMarksIndex]) > 1) and ($TimeMarksIndex < (count($TimeMarks) - 1)))
141 $TimeMarksIndex += 1;
142 if ($TimeMarksIndex < 2) $TimeMarksIndex = 2;
143 $MajorTimeMarks = $TimeMarks[$TimeMarksIndex - 1];
144 $MinorTimeMarks = $TimeMarks[$TimeMarksIndex - 2];
145
146 $TimeShift = $Measure->AlignTime($StartTime, $MajorTimeMarks) - $StartTime;
147 //imagestring($Image, 10, 40, 50, $TimeShift, $Black);
148
149 // Zobraz měřítko Y
150 $VerticalLinesDistance = $Height / $VerticalLinesCount;
151 for ($I = 1; $I <= $VerticalLinesCount; $I++)
152 {
153 $Y = $Height - 1 - ($VerticalLinesDistance * $I);
154 for ($X = 1; $X < $Width; $X = $X + 3) imagesetpixel($Image, $X, $Y, $Gray);
155 //imageline($Image, 30, $Y, $Width-1, $Y, IMG_COLOR_STYLED);
156 }
157
158 $TimeShift = $Measure->AlignTime($StartTime, $MinorTimeMarks) - $StartTime;
159
160 // Zobraz měřítko X
161 $LastTextEnd = 0;
162 for ($Time = $StartTime; $Time < $EndTime; $Time += $MajorTimeMarks)
163 {
164 $X = round(($Time - $StartTime + $TimeShift) / $TimeRange * $Width) % $Width;
165 //imageline($Image, 30, $Y, $Width-1, $Y, IMG_COLOR_STYLED);
166 if (($MajorTimeMarks > 60*60*24)) $Text = date('j.n.Y', $Time + $TimeShift);
167 else $Text = date('j.n.Y G:i', $Time + $TimeShift);
168 $BoundBox = imagettfbbox($this->FontSize, 0, $this->FontFileName, $Text);
169 if ($LastTextEnd < ($X - ($BoundBox[2] - $BoundBox[0] + 20) / 2))
170 {
171 for ($Y = 0; $Y < $Height; $Y = $Y + 1) imagesetpixel($Image, $X, $Y, $Gray);
172 imagettftext($Image, $this->FontSize, 0, $X - ($BoundBox[2] - $BoundBox[0]) / 2, $Height - 2, $Black, $this->FontFileName, $Text);
173 $LastTextEnd = $X + ($BoundBox[2] - $BoundBox[0]) / 2;
174 }
175 else for ($Y=0; $Y < $Height; $Y = $Y + 3) imagesetpixel($Image, $X, $Y, $Gray);
176 }
177
178 // Popisky osy Y
179 for ($I = 1; $I <= $VerticalLinesCount; $I++)
180 {
181 $Y = $Height - 1 - ($VerticalLinesDistance * $I);
182 //$Y = $Height - 1 - ($VerticalLinesDistance * $I / ($MaxValue - $MinValue) * $this->ValueToImageHeigthCoefficient * $Height);
183 $Text = $PrefixMultiplier->Add(round(($I * $VerticalLinesDistance / $Height /
184 $this->ValueToImageHeigthCoefficient * ($MaxValue - $MinValue) + $MinValue)),
185 $Measure->Data['Unit'], 3);
186 $BoundBox = imagettfbbox($this->FontSize, 0, $this->FontFileName, $Text);
187 if (($Y - ($BoundBox[5] - $BoundBox[1]) / 2) > 10)
188 imagettftext($Image, $this->FontSize, 0, 2, $Y - ($BoundBox[5] - $BoundBox[1]) / 2, $Black, $this->FontFileName, $Text);
189 }
190 $GenerationTime = floor((GetMicrotime() - $StopWatchStart) * 1000 ) / 1000;
191
192 $Left = $Width - 10;
193 $Text = " Max. ".$PrefixMultiplier->Add($MaxValue, $Measure->Data['Unit']);
194 $BoundingBox = imagettfbbox($this->FontSize, 0, $this->FontFileName, $Text);
195 $Left -= ($BoundingBox[2] - $BoundingBox[0]);
196 imagettftext($Image, $this->FontSize, 0, $Left, 14, $Red, $this->FontFileName, $Text);
197
198 $Text = " Avg. ".$PrefixMultiplier->Add($AvgValue, $Measure->Data['Unit'], 4);
199 $BoundingBox = imagettfbbox($this->FontSize, 0, $this->FontFileName, $Text);
200 $Left -= ($BoundingBox[2] - $BoundingBox[0]);
201 imagettftext($Image, $this->FontSize, 0, $Left, 14, $Green, $this->FontFileName, $Text);
202
203 $Text = " Min. ".$PrefixMultiplier->Add($MinValue, $Measure->Data['Unit']);
204 $BoundingBox = imagettfbbox($this->FontSize, 0, $this->FontFileName, $Text);
205 $Left -= ($BoundingBox[2] - $BoundingBox[0]);
206 imagettftext($Image, $this->FontSize, 0, $Left, 14, $Blue, $this->FontFileName, $Text);
207 //imagestring($Image, 2, 70, 20, 'Vygenerováno za '.$GenerationTime.' sekund', $Black);
208 //imagestring($Image, 2, 50, 30, 'Level: '.$Level, $Black);
209
210 imagettftext($Image, $this->FontSize, 0, 70, 14, $Black, $this->FontFileName, $Measure->Data['Description']);
211 imagerectangle($Image, 0, 0, $Width - 1, $Height - 1, $Black); // Frame border
212 Header("Content-type: image/png");
213 Header("Cache-Control: no-cache"); // Dynamic graph - no cache
214 imagepng($Image);
215 imagedestroy($Image);
216 }
217}
218
219$Core = new Core();
220$Core->ShowPage = false;
221$Core->Run();
222$Graph = new MeasureGraph($Core->Database);
223$Graph->Render();
Note: See TracBrowser for help on using the repository browser.