1<?php
2
3/*
4	Phoronix Test Suite
5	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
6	Copyright (C) 2010 - 2019, Phoronix Media
7	Copyright (C) 2010 - 2019, Michael Larabel
8	pts_OverviewGraph.php: A graping object to create an "overview" / mini graphs of a pts_result_file for pts_Graph
9
10	This program is free software; you can redistribute it and/or modify
11	it under the terms of the GNU General Public License as published by
12	the Free Software Foundation; either version 3 of the License, or
13	(at your option) any later version.
14
15	This program is distributed in the hope that it will be useful,
16	but WITHOUT ANY WARRANTY; without even the implied warranty of
17	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18	GNU General Public License for more details.
19
20	You should have received a copy of the GNU General Public License
21	along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24class pts_OverviewGraph extends pts_graph_core
25{
26	protected $result_file = null;
27
28	protected $system_identifiers;
29	protected $test_titles;
30	protected $graphs_per_row;
31	protected $graph_item_width;
32
33	protected $graph_row_height = 120;
34	protected $graph_row_count;
35
36	public function __construct($result_file)
37	{
38		$result_object = null;
39		parent::__construct($result_object, $result_file);
40
41		// System Identifiers
42		if($result_file->is_multi_way_comparison())
43		{
44			// Multi way comparisons currently render the overview graph as blank
45			return;
46		}
47
48		$this->system_identifiers = $result_file->get_system_identifiers();
49		if(count($this->system_identifiers) < 2)
50		{
51			// No point in generating this when there is only one identifier
52			return;
53		}
54
55		$result_objects = array();
56		$test_titles = array();
57		foreach($result_file->get_result_objects() as $result_object)
58		{
59			if($result_object->test_profile->get_display_format() == 'BAR_GRAPH')
60			{
61				$result_objects[] = $result_object;
62				$test_titles[] = $result_object->test_profile->get_title();
63				foreach($result_object->test_result_buffer->buffer_items as &$buffer_item)
64				pts_arrays::unique_push($this->graph_identifiers, $buffer_item->get_result_identifier());
65			}
66		}
67
68		$result_object_count = count($result_objects);
69		if($result_object_count < 3)
70		{
71			// No point in generating this if there aren't many tests
72			return;
73		}
74		$result_file->override_result_objects($result_objects);
75
76		// Test Titles
77		$this->i['identifier_size'] = 6.5;
78		$this->i['graph_width'] = 1000;
79
80		list($longest_title_width, $longest_title_height) = pts_svg_dom::estimate_text_dimensions(pts_strings::find_longest_string($test_titles), $this->i['identifier_size']);
81
82		$this->i['left_start'] += 20;
83		$this->graphs_per_row = min((count($this->system_identifiers) > 10 ? 6 : 10), floor(($this->i['graph_width'] - $this->i['left_start'] - $this->i['left_end_right']) / ($longest_title_width + 4)));
84		$this->graph_item_width = floor(($this->i['graph_width'] - $this->i['left_start'] - $this->i['left_end_right']) / $this->graphs_per_row);
85		$this->graph_row_count = ceil($result_object_count / $this->graphs_per_row);
86
87		$this->i['top_start'] += 20 + (count($this->system_identifiers) / 3 * $this->i['identifier_size']);
88		$height = $this->i['top_start'] + ($this->graph_row_count * ($this->graph_row_height + 15));
89
90		$this->i['graph_title'] = $result_file->get_title();
91		$this->i['graph_y_title'] = null;
92		$this->i['graph_proportion'] = 'HIB';
93		$this->i['show_background_lines'] = true;
94
95		$this->update_graph_dimensions($this->i['graph_width'], $height, true);
96		$this->result_file = $result_file;
97
98		return true;
99	}
100	public function renderGraph()
101	{
102		if($this->result_file == null)
103		{
104			return false;
105		}
106		$this->i['graph_max_value'] = 1.0;
107		$l_height = 15;
108		$this->i['key_line_height'] = $l_height;
109
110		if(($key_count = count($this->system_identifiers)) > 8)
111		{
112			$this->update_graph_dimensions(-1, $this->i['graph_height'] + (floor(($key_count - 8) / 4) * 14), true);
113		}
114
115		// Do the actual work
116		$this->render_graph_init();
117		$this->render_graph_key();
118
119		for($i = 0; $i < $this->graph_row_count; $i++)
120		{
121			$this->render_graph_base($this->i['left_start'], $this->i['top_start'] + ($i * ($this->graph_row_height + $l_height)), $this->i['graph_left_end'], $this->i['top_start'] + ($i * ($this->graph_row_height + $l_height)) + $this->graph_row_height);
122			$this->render_graph_value_ticks($this->i['left_start'], $this->i['top_start'] + ($i * ($this->graph_row_height + $l_height)), $this->i['graph_left_end'], $this->i['top_start'] + ($i * ($this->graph_row_height + $l_height)) + $this->graph_row_height, false);
123		}
124
125		$row = 0;
126		$col = 0;
127
128		$bar_count = count($this->system_identifiers);
129		$inter_width = $this->graph_item_width * 0.1;
130		$bar_width = floor(($this->graph_item_width - ($inter_width * 2)) / $bar_count);
131		$has_graphed_a_bar = false;
132
133		foreach($this->result_file->get_result_objects() as $i => $result_object)
134		{
135			$top_start = $this->i['top_start'] + ($row * ($this->graph_row_height + $l_height));
136			$top_end = round($this->i['top_start'] + ($row * ($this->graph_row_height + $l_height)) + $this->graph_row_height);
137			$px_bound_left = $this->i['left_start'] + ($this->graph_item_width * ($col % $this->graphs_per_row));
138			$px_bound_right = $px_bound_left + $this->graph_item_width;
139
140			$this->svg_dom->add_text_element($result_object->test_profile->get_title(), array('x' => ($px_bound_left + ($this->graph_item_width * 0.5)), 'y' => ($top_end + 3), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['headers'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge'));
141
142			if($result_object->test_profile->get_display_format() == 'BAR_GRAPH')
143			{
144				$all_values = $result_object->test_result_buffer->get_values();
145
146				foreach($all_values as $ai => $av)
147				{
148					if(!is_numeric($av))
149					{
150						unset($all_values[$ai]);
151					}
152				}
153				if(empty($all_values))
154				{
155					continue;
156				}
157
158				switch($result_object->test_profile->get_result_proportion())
159				{
160					case 'HIB':
161						$divide_value = max($all_values);
162						break;
163					case 'LIB':
164						$divide_value = min($all_values);
165						break;
166				}
167
168				foreach($result_object->test_result_buffer->get_buffer_items() as $x => $buffer_item)
169				{
170					$paint_color = $this->get_paint_color($buffer_item->get_result_identifier());
171
172					switch($result_object->test_profile->get_result_proportion())
173					{
174						case 'HIB':
175							$value = $divide_value != 0 ? $buffer_item->get_result_value() / $divide_value : 0;
176							break;
177						case 'LIB':
178							$value = $divide_value / $buffer_item->get_result_value();
179							break;
180					}
181
182					$graph_size = round(($value / $this->i['graph_max_value']) * ($top_end - $top_start));
183					$value_plot_top = $top_end + 1 - $graph_size;
184
185					$px_left = $px_bound_left + $inter_width + ($bar_width * $x);
186					$px_right = $px_left + $bar_width;
187
188					$this->svg_dom->add_element('rect', array('x' => $px_left, 'y' => $value_plot_top, 'width' => $bar_width, 'height' => ($top_end - $value_plot_top), 'fill' => $paint_color, 'stroke' => self::$c['color']['body_light'], 'stroke-width' => 1));
189				}
190
191				$has_graphed_a_bar = true;
192			}
193
194			if(($i + 1) % $this->graphs_per_row == 0 && $i != 0)
195			{
196				$this->svg_dom->draw_svg_line($this->i['left_start'] + $this->graph_item_width, $top_end, $this->i['graph_left_end'] - ($this->i['graph_width'] % $this->graph_item_width), $top_end, self::$c['color']['notches'], 10, array('stroke-dasharray' => '1,' . ($this->graph_item_width - 1)));
197				$this->svg_dom->draw_svg_line($this->i['left_start'], $top_end, $this->i['graph_left_end'], $top_end, self::$c['color']['notches'], 1);
198
199				$row++;
200			}
201			$col++;
202		}
203
204		if($has_graphed_a_bar == false)
205		{
206			// Don't show an empty overview graph...
207			//$this->skip_graph = true;
208		}
209
210
211		//$this->render_graph_base($this->i['left_start'], $this->i['top_start'], $this->i['graph_left_end'], $this->i['graph_top_end']);
212		$this->render_graph_heading();
213		//$this->render_graph_watermark();
214
215		return true;
216	}
217}
218
219?>
220