HTML graphs

master
vitalif 2010-11-05 22:15:15 +00:00
parent 067443e935
commit 38c4d7b7a7
2 changed files with 145 additions and 10 deletions

120
olap.php
View File

@ -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]);
}
}
}

View File

@ -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 -->