HTML graphs
parent
067443e935
commit
38c4d7b7a7
120
olap.php
120
olap.php
|
@ -42,6 +42,7 @@ class OLAP
|
|||
'tr' => 'По вертикали',
|
||||
'td' => 'По горизонтали',
|
||||
'cell' => 'В ячейке',
|
||||
'graph' => 'График',
|
||||
);
|
||||
static $cell = array();
|
||||
|
||||
|
@ -140,7 +141,8 @@ class OLAP
|
|||
$gf = array();
|
||||
foreach(array('type', 'field', 'func', 'sort_dir', 'sort_field', 'sort_aggr', 'sort_func') as $k)
|
||||
$gf[$k] = $request["group-$k-$i"];
|
||||
if (self::$group_types[$gf['type']] && strlen($gf['field']))
|
||||
if (self::$group_types[$gf['type']] && strlen($gf['field']) &&
|
||||
($gf['type'] != 'graph' || !$request['csv']))
|
||||
{
|
||||
$gf['num'] = count($group_fields);
|
||||
$group_fields[] = $gf;
|
||||
|
@ -272,16 +274,19 @@ class OLAP
|
|||
|
||||
if ($request['csv'])
|
||||
self::$add_spanned = true;
|
||||
$tables = self::build_tables($group_fields, $data, $tdkeys);
|
||||
|
||||
$vars = array(
|
||||
'build' => 1,
|
||||
'tables' => $tables,
|
||||
'rpt_link' => "?".http_build_query($_GET+$_POST),
|
||||
'csv_link' => "?csv=1&".http_build_query($_GET+$_POST),
|
||||
'memory' => file_size_string(memory_get_usage()),
|
||||
'time_elapsed' => sprintf("%.3f", microtime(true)-$time_start),
|
||||
);
|
||||
if ($group_fields[0]['type'] == 'graph')
|
||||
$vars['graphs'] = self::build_graphs($group_fields, $data, $tdkeys);
|
||||
else
|
||||
{
|
||||
$vars['tables'] = self::build_tables($group_fields, $data, $tdkeys);
|
||||
$vars['csv_link'] = "?csv=1&".http_build_query($_GET+$_POST);
|
||||
}
|
||||
$vars['memory'] = file_size_string(memory_get_usage());
|
||||
$vars['time_elapsed'] = sprintf("%.3f", microtime(true)-$time_start);
|
||||
|
||||
$template->vars($vars);
|
||||
if ($request['csv'])
|
||||
|
@ -295,6 +300,99 @@ class OLAP
|
|||
print $template->parse('admin_olap.tpl');
|
||||
}
|
||||
|
||||
static $graph_scale = 600; /* пикселей */
|
||||
static $graph_logarithmic = false;
|
||||
static function build_graphs($fields, &$data, &$tdkeys)
|
||||
{
|
||||
$my = array_shift($fields);
|
||||
$keys = $my['sort'] ? array_keys($my['sort']) : $my['keys'];
|
||||
self::do_sort($keys, $my['sort'], $my['sort_dir']);
|
||||
$graphs = array();
|
||||
if (count($fields))
|
||||
{
|
||||
foreach ($fields as &$v)
|
||||
if ($v['sort'])
|
||||
$v['orig_sort'] = &$v['sort'];
|
||||
foreach ($keys as $k)
|
||||
{
|
||||
if (array_key_exists($k, $data))
|
||||
{
|
||||
foreach ($fields as &$v)
|
||||
if ($v['orig_sort'])
|
||||
$v['sort'] = &$v['orig_sort'][$k];
|
||||
$gr = self::build_graphs($fields, $data[$k], $tdkeys);
|
||||
foreach ($gr as &$g)
|
||||
{
|
||||
array_unshift($g['desc'], array(
|
||||
'field' => self::$current_src['fielddescs'][$my['field']]['name'],
|
||||
'func' => self::$functions[$my['func']]['name'],
|
||||
'value' => self::field_format($my['field'], '', '', $k)
|
||||
));
|
||||
$graphs[] = $g;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$gr = array(
|
||||
'desc' => array(),
|
||||
'field' => self::$current_src['fielddescs'][$my['field']]['name'],
|
||||
'func' => self::$functions[$my['func']]['name'],
|
||||
'data' => array(),
|
||||
'max' => NULL,
|
||||
'min' => NULL,
|
||||
);
|
||||
foreach ($keys as $k)
|
||||
{
|
||||
if (array_key_exists($k, $data))
|
||||
{
|
||||
$v = floatval($data[$k]);
|
||||
if (self::$graph_logarithmic)
|
||||
{
|
||||
if ($v >= 1)
|
||||
$v = 1+log($v);
|
||||
elseif ($v <= -1)
|
||||
$v = -1-log(-$v);
|
||||
}
|
||||
$gr['data'][] = array(self::field_format($my['field'], '', '', $k), $v);
|
||||
if ($gr['max'] === NULL || $gr['max'] < $v)
|
||||
$gr['max'] = $v;
|
||||
if ($gr['min'] === NULL || $gr['min'] > $v)
|
||||
$gr['min'] = $v;
|
||||
}
|
||||
}
|
||||
if ($gr['min'] >= 0)
|
||||
$gr['min'] = 0;
|
||||
else
|
||||
$gr['bi_sign'] = true;
|
||||
if ($gr['max'] > $gr['min'])
|
||||
{
|
||||
if ($gr['bi_sign'])
|
||||
{
|
||||
foreach ($gr['data'] as &$d)
|
||||
{
|
||||
if ($d[1] >= 0)
|
||||
{
|
||||
$d[1] = intval($d[1]/$gr['max']*self::$graph_scale/2);
|
||||
$d[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$d[2] = intval($d[1]/$gr['min']*self::$graph_scale/2);
|
||||
$d[1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
foreach ($gr['data'] as &$d)
|
||||
$d[1] = intval(($d[1]-$gr['min'])/($gr['max']-$gr['min'])*self::$graph_scale);
|
||||
}
|
||||
$graphs[] = $gr;
|
||||
}
|
||||
return $graphs;
|
||||
}
|
||||
|
||||
static function recurse_tables($fields, &$bytype, &$data, &$tdkeys)
|
||||
{
|
||||
if ($fields && $fields[0]['type'] == 'tables')
|
||||
|
@ -581,6 +679,10 @@ class OLAP
|
|||
}
|
||||
static function group_type_cmp($a, $b)
|
||||
{
|
||||
if ($a == 'graph')
|
||||
return -1;
|
||||
elseif ($b == 'graph')
|
||||
return 1;
|
||||
$r = self::$group_types[$a['type']]['num']-self::$group_types[$b['type']]['num'];
|
||||
if ($r == 0)
|
||||
$r = $a['num']-$b['num'];
|
||||
|
@ -592,7 +694,7 @@ class OLAP
|
|||
static function field_format($field, $func, $aggr, $value)
|
||||
{
|
||||
$o = &self::$current_src['fielddescs'][$field]['options_hash'];
|
||||
if ($o && $o[$value])
|
||||
if ($o && $o[$value] && !$aggr)
|
||||
return $o[$value];
|
||||
elseif (preg_match('/^-?\d+\.\d+$/s', $value))
|
||||
{
|
||||
|
@ -621,4 +723,4 @@ class OLAP
|
|||
$row[$tf] = Template::timestamp($row[$field]);
|
||||
return date($f, $row[$tf]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -96,8 +96,41 @@
|
|||
<!-- IF build -->
|
||||
<h1>Отчёт</h1>
|
||||
<p><a href="{s rpt_link}">Ссылка на данный отчёт</a> | <a href="{s csv_link}">В формате CSV</a></p>
|
||||
<!-- IF NOT tables -->
|
||||
<!-- IF and(not tables, not graphs) -->
|
||||
<p>Нет данных для показа.</p>
|
||||
<!-- ELSIF graphs -->
|
||||
<!-- FOR graph = graphs -->
|
||||
<!-- IF graph.desc -->
|
||||
<!-- SET o = 0 -->
|
||||
<!-- FOR d = graph.desc -->
|
||||
<!-- SET o = or(o, not(graph#), ne(get(get(get(get(graphs,sub(graph#,1)),'desc'),d#),'value'),d.value)) -->
|
||||
<!-- IF o -->
|
||||
<p style="margin-left: {mul(d#,20)}px">{d.field}<!-- IF d.func --> ({lc d.func})<!-- END -->: {d.value}</p>
|
||||
<!-- END -->
|
||||
<!-- END -->
|
||||
<div style="margin-left: {mul(count(table.desc),20)}px">
|
||||
<!-- END -->
|
||||
<table>
|
||||
<!-- IF graph.bi_sign -->
|
||||
<tr><th colspan="3">- {graph.field}<!-- IF graph.func --> ({lc graph.func})<!-- END --> +</th></tr>
|
||||
<!-- FOR g = graph.data -->
|
||||
<tr>
|
||||
<td><div style="float: right; background: red; height: 7px; width: {g.2}px"></div></td>
|
||||
<td>{s g.0}</td>
|
||||
<td><div style="background: blue; height: 7px; width: {g.1}px"></div></td>
|
||||
</tr>
|
||||
<!-- END -->
|
||||
<!-- ELSE -->
|
||||
<tr><th style="text-align: left" colspan="2">{graph.field}<!-- IF graph.func --> ({lc graph.func})<!-- END --></th></tr>
|
||||
<!-- FOR g = graph.data -->
|
||||
<tr><td>{s g.0}</td><td><div style="background: blue; height: 7px; width: {g.1}px"></div></td></tr>
|
||||
<!-- END -->
|
||||
<!-- END -->
|
||||
</table>
|
||||
<!-- IF graph.desc -->
|
||||
</div>
|
||||
<!-- END -->
|
||||
<!-- END -->
|
||||
<!-- ELSE -->
|
||||
<!-- FOR table = tables -->
|
||||
<!-- IF table.desc -->
|
||||
|
|
Loading…
Reference in New Issue