|
@@ -1,193 +1,219 @@
|
1
|
|
-<?
|
2
|
|
-class GOOGLE_CHARTS {
|
3
|
|
- protected $URL = 'https://chart.googleapis.com/chart';
|
4
|
|
- protected $Labels = [];
|
5
|
|
- protected $Data = [];
|
6
|
|
- protected $Options = [];
|
7
|
|
-
|
8
|
|
- public function __construct($Type, $Width, $Height, $Options) {
|
9
|
|
- if ($Width * $Height > 300000 || $Height > 1000 || $Width > 1000) {
|
10
|
|
- trigger_error('Tried to make chart too large.');
|
|
1
|
+<?php
|
|
2
|
+class GOOGLE_CHARTS
|
|
3
|
+{
|
|
4
|
+ protected $URL = 'https://chart.googleapis.com/chart';
|
|
5
|
+ protected $Labels = [];
|
|
6
|
+ protected $Data = [];
|
|
7
|
+ protected $Options = [];
|
|
8
|
+
|
|
9
|
+ public function __construct($Type, $Width, $Height, $Options)
|
|
10
|
+ {
|
|
11
|
+ if ($Width * $Height > 300000 || $Height > 1000 || $Width > 1000) {
|
|
12
|
+ trigger_error('Tried to make chart too large.');
|
|
13
|
+ }
|
|
14
|
+ $this->URL .= "?cht=$Type&chs={$Width}x$Height";
|
|
15
|
+ $this->Options = $Options;
|
11
|
16
|
}
|
12
|
|
- $this->URL .= "?cht=$Type&chs={$Width}x$Height";
|
13
|
|
- $this->Options = $Options;
|
14
|
|
- }
|
15
|
17
|
|
16
|
|
- protected function encode($Number) {
|
17
|
|
- if ($Number == -1) {
|
18
|
|
- return '__';
|
|
18
|
+ protected function encode($Number)
|
|
19
|
+ {
|
|
20
|
+ if ($Number == -1) {
|
|
21
|
+ return '__';
|
|
22
|
+ }
|
|
23
|
+ $CharKey = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.';
|
|
24
|
+ return $CharKey[floor($Number / 64)].$CharKey[floor($Number % 64)];
|
19
|
25
|
}
|
20
|
|
- $CharKey = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.';
|
21
|
|
- return $CharKey[floor($Number / 64)].$CharKey[floor($Number % 64)];
|
22
|
|
- }
|
23
|
|
-
|
24
|
|
- public function color($Colors) {
|
25
|
|
- $this->URL .= '&chco='.$Colors;
|
26
|
|
- }
|
27
|
26
|
|
28
|
|
- public function lines($Thickness, $Solid = 1, $Blank = 0) {
|
29
|
|
- $this->URL .= "&chls=$Thickness,$Solid,$Blank";
|
30
|
|
- }
|
|
27
|
+ public function color($Colors)
|
|
28
|
+ {
|
|
29
|
+ $this->URL .= '&chco='.$Colors;
|
|
30
|
+ }
|
31
|
31
|
|
32
|
|
- public function title($Title, $Color = '', $Size = '') {
|
33
|
|
- $this->URL .= '&chtt='.str_replace(array(' ', "\n"), array('+', '|'), $Title);
|
34
|
|
- if (!empty($Color)) {
|
35
|
|
- $this->URL .= '&chts='.$Color;
|
|
32
|
+ public function lines($Thickness, $Solid = 1, $Blank = 0)
|
|
33
|
+ {
|
|
34
|
+ $this->URL .= "&chls=$Thickness,$Solid,$Blank";
|
36
|
35
|
}
|
37
|
|
- if (!empty($Size)) {
|
38
|
|
- $this->URL .= ','.$Size;
|
|
36
|
+
|
|
37
|
+ public function title($Title, $Color = '', $Size = '')
|
|
38
|
+ {
|
|
39
|
+ $this->URL .= '&chtt='.str_replace(array(' ', "\n"), array('+', '|'), $Title);
|
|
40
|
+ if (!empty($Color)) {
|
|
41
|
+ $this->URL .= '&chts='.$Color;
|
|
42
|
+ }
|
|
43
|
+ if (!empty($Size)) {
|
|
44
|
+ $this->URL .= ','.$Size;
|
|
45
|
+ }
|
39
|
46
|
}
|
40
|
|
- }
|
41
|
47
|
|
42
|
|
- public function legend($Items, $Placement = '') {
|
43
|
|
- $this->URL .= '&chdl='.str_replace(' ', '+', implode('|', $Items));
|
44
|
|
- if (!empty($Placement)) {
|
45
|
|
- if (!in_array($Placement, array('b', 't', 'r', 'l', 'bv', 'tv'))) {
|
46
|
|
- trigger_error('Invalid legend placement.');
|
47
|
|
- }
|
48
|
|
- $this->URL .= '&chdlp='.$Placement;
|
|
48
|
+ public function legend($Items, $Placement = '')
|
|
49
|
+ {
|
|
50
|
+ $this->URL .= '&chdl='.str_replace(' ', '+', implode('|', $Items));
|
|
51
|
+ if (!empty($Placement)) {
|
|
52
|
+ if (!in_array($Placement, array('b', 't', 'r', 'l', 'bv', 'tv'))) {
|
|
53
|
+ trigger_error('Invalid legend placement.');
|
|
54
|
+ }
|
|
55
|
+ $this->URL .= '&chdlp='.$Placement;
|
|
56
|
+ }
|
49
|
57
|
}
|
50
|
|
- }
|
51
|
58
|
|
52
|
|
- public function add($Label, $Data) {
|
53
|
|
- if ($Label !== false) {
|
54
|
|
- $this->Labels[] = $Label;
|
|
59
|
+ public function add($Label, $Data)
|
|
60
|
+ {
|
|
61
|
+ if ($Label !== false) {
|
|
62
|
+ $this->Labels[] = $Label;
|
|
63
|
+ }
|
|
64
|
+ $this->Data[] = $Data;
|
55
|
65
|
}
|
56
|
|
- $this->Data[] = $Data;
|
57
|
|
- }
|
58
|
66
|
|
59
|
|
- public function grid_lines($SpacingX = 0, $SpacingY = -1, $Solid = 1, $Blank = 1) {
|
60
|
|
- //Can take 2 more parameters for offset, but we're not bothering with that right now
|
61
|
|
- $this->URL .= "&chg=$SpacingX,$SpacingY,$Solid,$Blank";
|
62
|
|
- }
|
|
67
|
+ public function grid_lines($SpacingX = 0, $SpacingY = -1, $Solid = 1, $Blank = 1)
|
|
68
|
+ {
|
|
69
|
+ //Can take 2 more parameters for offset, but we're not bothering with that right now
|
|
70
|
+ $this->URL .= "&chg=$SpacingX,$SpacingY,$Solid,$Blank";
|
|
71
|
+ }
|
63
|
72
|
|
64
|
|
- public function transparent() {
|
65
|
|
- $this->URL .= '&chf=bg,s,FFFFFF00';
|
66
|
|
- }
|
|
73
|
+ public function transparent()
|
|
74
|
+ {
|
|
75
|
+ $this->URL .= '&chf=bg,s,FFFFFF00';
|
|
76
|
+ }
|
67
|
77
|
|
68
|
78
|
|
69
|
|
- public function url() {
|
70
|
|
- return $this->URL;
|
71
|
|
- }
|
|
79
|
+ public function url()
|
|
80
|
+ {
|
|
81
|
+ return $this->URL;
|
|
82
|
+ }
|
72
|
83
|
}
|
73
|
84
|
|
74
|
|
-class AREA_GRAPH extends GOOGLE_CHARTS {
|
75
|
|
- public function __construct ($Width, $Height, $Options = []) {
|
76
|
|
- parent::__construct('lc', $Width, $Height, $Options);
|
77
|
|
- }
|
|
85
|
+class AREA_GRAPH extends GOOGLE_CHARTS
|
|
86
|
+{
|
|
87
|
+ public function __construct($Width, $Height, $Options = [])
|
|
88
|
+ {
|
|
89
|
+ parent::__construct('lc', $Width, $Height, $Options);
|
|
90
|
+ }
|
78
|
91
|
|
79
|
|
- public function color ($Color) {
|
80
|
|
- $this->URL .= '&chco='.$Color.'&chm=B,'.$Color.'50,0,0,0';
|
81
|
|
- }
|
|
92
|
+ public function color($Color)
|
|
93
|
+ {
|
|
94
|
+ $this->URL .= '&chco='.$Color.'&chm=B,'.$Color.'50,0,0,0';
|
|
95
|
+ }
|
82
|
96
|
|
83
|
|
- public function generate() {
|
84
|
|
- $Max = max($this->Data);
|
85
|
|
- $Min = ((isset($this->Options['Break'])) ? $Min = min($this->Data) : 0);
|
86
|
|
- $Data = [];
|
87
|
|
- foreach ($this->Data as $Value) {
|
88
|
|
- $Data[] = $this->encode((($Value - $Min) / ($Max - $Min)) * 4095);
|
|
97
|
+ public function generate()
|
|
98
|
+ {
|
|
99
|
+ $Max = max($this->Data);
|
|
100
|
+ $Min = ((isset($this->Options['Break'])) ? $Min = min($this->Data) : 0);
|
|
101
|
+ $Data = [];
|
|
102
|
+ foreach ($this->Data as $Value) {
|
|
103
|
+ $Data[] = $this->encode((($Value - $Min) / ($Max - $Min)) * 4095);
|
|
104
|
+ }
|
|
105
|
+ $this->URL .= "&chxt=y,x&chxs=0,h&chxl=1:|".implode('|', $this->Labels).'&chxr=0,'.$Min.','.($Max - $Min).'&chd=e:'.implode('', $Data);
|
89
|
106
|
}
|
90
|
|
- $this->URL .= "&chxt=y,x&chxs=0,h&chxl=1:|".implode('|', $this->Labels).'&chxr=0,'.$Min.','.($Max - $Min).'&chd=e:'.implode('', $Data);
|
91
|
|
- }
|
92
|
107
|
}
|
93
|
108
|
|
94
|
|
-class PIE_CHART extends GOOGLE_CHARTS {
|
95
|
|
- public function __construct ($Width, $Height, $Options = []) {
|
96
|
|
- $Type = ((isset($this->Options['3D'])) ? 'p3' : 'p');
|
97
|
|
- parent::__construct($Type, $Width, $Height, $Options);
|
98
|
|
- }
|
99
|
|
-
|
100
|
|
- public function generate() {
|
101
|
|
- $Sum = array_sum($this->Data);
|
102
|
|
- $Other = isset($this->Options['Other']);
|
103
|
|
- $Sort = isset($this->Options['Sort']);
|
104
|
|
- $LabelPercent = isset($this->Options['Percentage']);
|
105
|
|
-
|
106
|
|
- if ($Sort && !empty($this->Labels)) {
|
107
|
|
- array_multisort($this->Data, SORT_DESC, $this->Labels);
|
108
|
|
- } elseif ($Sort) {
|
109
|
|
- sort($this->Data);
|
110
|
|
- $this->Data = array_reverse($this->Data);
|
111
|
|
- }
|
112
|
|
-
|
113
|
|
- $Data = [];
|
114
|
|
- $Labels = $this->Labels;
|
115
|
|
- $OtherPercentage = 0.00;
|
116
|
|
- $OtherData = 0;
|
117
|
|
-
|
118
|
|
- foreach ($this->Data as $Key => $Value) {
|
119
|
|
- $ThisPercentage = number_format(($Value / $Sum) * 100, 2);
|
120
|
|
- $ThisData = ($Value / $Sum) * 4095;
|
121
|
|
- if ($Other && $ThisPercentage < 1) {
|
122
|
|
- $OtherPercentage += $ThisPercentage;
|
123
|
|
- $OtherData += $ThisData;
|
124
|
|
- unset($Data[$Key]);
|
125
|
|
- unset($Labels[$Key]);
|
126
|
|
- continue;
|
127
|
|
- }
|
128
|
|
- if ($LabelPercent) {
|
129
|
|
- $Labels[$Key] .= ' ('.$ThisPercentage.'%)';
|
130
|
|
- }
|
131
|
|
- $Data[] = $this->encode($ThisData);
|
132
|
|
- }
|
133
|
|
- if ($OtherPercentage > 0) {
|
134
|
|
- $OtherLabel = 'Other';
|
135
|
|
- if ($LabelPercent) {
|
136
|
|
- $OtherLabel .= ' ('.$OtherPercentage.'%)';
|
137
|
|
- }
|
138
|
|
- $Labels[] = $OtherLabel;
|
139
|
|
- $Data[] = $this->encode($OtherData);
|
140
|
|
- }
|
141
|
|
- $this->URL .= "&chl=".implode('|', $Labels).'&chd=e:'.implode('', $Data);
|
142
|
|
- }
|
|
109
|
+class PIE_CHART extends GOOGLE_CHARTS
|
|
110
|
+{
|
|
111
|
+ public function __construct($Width, $Height, $Options = [])
|
|
112
|
+ {
|
|
113
|
+ $Type = ((isset($this->Options['3D'])) ? 'p3' : 'p');
|
|
114
|
+ parent::__construct($Type, $Width, $Height, $Options);
|
|
115
|
+ }
|
|
116
|
+
|
|
117
|
+ public function generate()
|
|
118
|
+ {
|
|
119
|
+ $Sum = array_sum($this->Data);
|
|
120
|
+ $Other = isset($this->Options['Other']);
|
|
121
|
+ $Sort = isset($this->Options['Sort']);
|
|
122
|
+ $LabelPercent = isset($this->Options['Percentage']);
|
|
123
|
+
|
|
124
|
+ if ($Sort && !empty($this->Labels)) {
|
|
125
|
+ array_multisort($this->Data, SORT_DESC, $this->Labels);
|
|
126
|
+ } elseif ($Sort) {
|
|
127
|
+ sort($this->Data);
|
|
128
|
+ $this->Data = array_reverse($this->Data);
|
|
129
|
+ }
|
|
130
|
+
|
|
131
|
+ $Data = [];
|
|
132
|
+ $Labels = $this->Labels;
|
|
133
|
+ $OtherPercentage = 0.00;
|
|
134
|
+ $OtherData = 0;
|
|
135
|
+
|
|
136
|
+ foreach ($this->Data as $Key => $Value) {
|
|
137
|
+ $ThisPercentage = number_format(($Value / $Sum) * 100, 2);
|
|
138
|
+ $ThisData = ($Value / $Sum) * 4095;
|
|
139
|
+ if ($Other && $ThisPercentage < 1) {
|
|
140
|
+ $OtherPercentage += $ThisPercentage;
|
|
141
|
+ $OtherData += $ThisData;
|
|
142
|
+ unset($Data[$Key]);
|
|
143
|
+ unset($Labels[$Key]);
|
|
144
|
+ continue;
|
|
145
|
+ }
|
|
146
|
+ if ($LabelPercent) {
|
|
147
|
+ $Labels[$Key] .= ' ('.$ThisPercentage.'%)';
|
|
148
|
+ }
|
|
149
|
+ $Data[] = $this->encode($ThisData);
|
|
150
|
+ }
|
|
151
|
+ if ($OtherPercentage > 0) {
|
|
152
|
+ $OtherLabel = 'Other';
|
|
153
|
+ if ($LabelPercent) {
|
|
154
|
+ $OtherLabel .= ' ('.$OtherPercentage.'%)';
|
|
155
|
+ }
|
|
156
|
+ $Labels[] = $OtherLabel;
|
|
157
|
+ $Data[] = $this->encode($OtherData);
|
|
158
|
+ }
|
|
159
|
+ $this->URL .= "&chl=".implode('|', $Labels).'&chd=e:'.implode('', $Data);
|
|
160
|
+ }
|
143
|
161
|
}
|
144
|
162
|
|
145
|
163
|
|
146
|
|
-class LOG_BAR_GRAPH extends GOOGLE_CHARTS {
|
147
|
|
- //TODO: Finish.
|
148
|
|
- public function __construct ($Base, $Width, $Height, $Options = []) {
|
149
|
|
- parent::__construct('lc', $Width, $Height, $Options);
|
150
|
|
- }
|
|
164
|
+class LOG_BAR_GRAPH extends GOOGLE_CHARTS
|
|
165
|
+{
|
|
166
|
+ //TODO: Finish.
|
|
167
|
+ public function __construct($Base, $Width, $Height, $Options = [])
|
|
168
|
+ {
|
|
169
|
+ parent::__construct('lc', $Width, $Height, $Options);
|
|
170
|
+ }
|
151
|
171
|
|
152
|
|
- public function color ($Color) {
|
153
|
|
- $this->URL .= '&chco='.$Color.'&chm=B,'.$Color.'50,0,0,0';
|
154
|
|
- }
|
|
172
|
+ public function color($Color)
|
|
173
|
+ {
|
|
174
|
+ $this->URL .= '&chco='.$Color.'&chm=B,'.$Color.'50,0,0,0';
|
|
175
|
+ }
|
155
|
176
|
|
156
|
|
- public function generate() {
|
157
|
|
- $Max = max($this->Data);
|
158
|
|
- $Min = ((isset($this->Options['Break'])) ? $Min = min($this->Data) : 0);
|
159
|
|
- $Data = [];
|
160
|
|
- foreach ($this->Data as $Value) {
|
161
|
|
- $Data[] = $this->encode((($Value - $Min) / ($Max - $Min)) * 4095);
|
|
177
|
+ public function generate()
|
|
178
|
+ {
|
|
179
|
+ $Max = max($this->Data);
|
|
180
|
+ $Min = ((isset($this->Options['Break'])) ? $Min = min($this->Data) : 0);
|
|
181
|
+ $Data = [];
|
|
182
|
+ foreach ($this->Data as $Value) {
|
|
183
|
+ $Data[] = $this->encode((($Value - $Min) / ($Max - $Min)) * 4095);
|
|
184
|
+ }
|
|
185
|
+ $this->URL .= "&chxt=y,x&chxs=0,h&chxl=1:|".implode('|', $this->Labels).'&chxr=0,'.$Min.','.($Max-$Min).'&chd=e:'.implode('', $Data);
|
162
|
186
|
}
|
163
|
|
- $this->URL .= "&chxt=y,x&chxs=0,h&chxl=1:|".implode('|', $this->Labels).'&chxr=0,'.$Min.','.($Max-$Min).'&chd=e:'.implode('', $Data);
|
164
|
|
- }
|
165
|
187
|
}
|
166
|
188
|
|
167
|
|
-class POLL_GRAPH extends GOOGLE_CHARTS {
|
168
|
|
- public function __construct () {
|
169
|
|
- $this->URL .= '?cht=bhg';
|
170
|
|
- }
|
171
|
|
-
|
172
|
|
- public function add($Label, $Data) {
|
173
|
|
- if ($Label !== false) {
|
174
|
|
- $this->Labels[] = Format::cut_string($Label, 35);
|
175
|
|
- }
|
176
|
|
- $this->Data[] = $Data;
|
177
|
|
- }
|
178
|
|
-
|
179
|
|
- public function generate() {
|
180
|
|
- $Count = count($this->Data);
|
181
|
|
- $Height = (30 * $Count) + 20;
|
182
|
|
- $Max = max($this->Data);
|
183
|
|
- $Sum = array_sum($this->Data);
|
184
|
|
- $Increment = ($Max / $Sum) * 25; // * 100% / 4divisions
|
185
|
|
- $Data = [];
|
186
|
|
- $Labels = [];
|
187
|
|
- foreach ($this->Data as $Key => $Value) {
|
188
|
|
- $Data[] = $this->encode(($Value / $Max) * 4095);
|
189
|
|
- $Labels[] = '@t'.str_replace(array(' ', ','),array('+', '\,'), $this->Labels[$Key]).',000000,1,'.round((($Key + 1) / $Count) - (12 / $Height), 2).':0,12';
|
190
|
|
- }
|
191
|
|
- $this->URL .= "&chbh=25,0,5&chs=214x$Height&chl=0%|".round($Increment, 1)."%|".round($Increment * 2, 1)."%|".round($Increment * 3, 1)."%|".round($Increment * 4, 1)."%&chm=".implode('|', $Labels).'&chd=e:'.implode('', $Data);
|
192
|
|
- }
|
|
189
|
+class POLL_GRAPH extends GOOGLE_CHARTS
|
|
190
|
+{
|
|
191
|
+ public function __construct()
|
|
192
|
+ {
|
|
193
|
+ $this->URL .= '?cht=bhg';
|
|
194
|
+ }
|
|
195
|
+
|
|
196
|
+ public function add($Label, $Data)
|
|
197
|
+ {
|
|
198
|
+ if ($Label !== false) {
|
|
199
|
+ $this->Labels[] = Format::cut_string($Label, 35);
|
|
200
|
+ }
|
|
201
|
+ $this->Data[] = $Data;
|
|
202
|
+ }
|
|
203
|
+
|
|
204
|
+ public function generate()
|
|
205
|
+ {
|
|
206
|
+ $Count = count($this->Data);
|
|
207
|
+ $Height = (30 * $Count) + 20;
|
|
208
|
+ $Max = max($this->Data);
|
|
209
|
+ $Sum = array_sum($this->Data);
|
|
210
|
+ $Increment = ($Max / $Sum) * 25; // * 100% / 4divisions
|
|
211
|
+ $Data = [];
|
|
212
|
+ $Labels = [];
|
|
213
|
+ foreach ($this->Data as $Key => $Value) {
|
|
214
|
+ $Data[] = $this->encode(($Value / $Max) * 4095);
|
|
215
|
+ $Labels[] = '@t'.str_replace(array(' ', ','), array('+', '\,'), $this->Labels[$Key]).',000000,1,'.round((($Key + 1) / $Count) - (12 / $Height), 2).':0,12';
|
|
216
|
+ }
|
|
217
|
+ $this->URL .= "&chbh=25,0,5&chs=214x$Height&chl=0%|".round($Increment, 1)."%|".round($Increment * 2, 1)."%|".round($Increment * 3, 1)."%|".round($Increment * 4, 1)."%&chm=".implode('|', $Labels).'&chd=e:'.implode('', $Data);
|
|
218
|
+ }
|
193
|
219
|
}
|