added universal format routine for all output modes

improved rendering performance of all output modes
This commit is contained in:
Steffen Vogel 2011-02-25 00:16:55 +01:00
parent 4456c43263
commit 443081f9a0
8 changed files with 87 additions and 71 deletions

View file

@ -159,11 +159,11 @@ abstract class Interpreter {
$sql = '';
if (isset($from)) {
$sql .= ' AND timestamp >= ' . $from;
$sql .= ' AND timestamp >= ' . $from;
}
if (isset($to)) {
$sql .= ' AND timestamp <= ' . $to;
$sql .= ' AND timestamp <= ' . $to;
}
return $sql;

View file

@ -38,12 +38,12 @@ class MeterInterpreter extends Interpreter {
/**
* Calculates the consumption for interval speciefied by $from and $to
*
* @todo reimplement according to new env
* @todo improfve workaround
*/
public function getConsumption() {
$sql = 'SELECT COUNT(*) FROM `data` WHERE `channel_id` = ' . $this->channel->getId() . parent::buildDateTimeFilterSQL($this->from, $this->to);
$sql = 'SELECT COUNT(*) FROM `data` WHERE `channel_id` = ?' . parent::buildDateTimeFilterSQL($this->from, $this->to);
return $this->conn->fetchColumn($sql, array($this->channel->getId()), 0)/$this->channel->getProperty('resolution'); // return KWh
return $this->conn->fetchColumn($sql, array($this->channel->getId()), 0) / $this->channel->getProperty('resolution'); // return KWh
}
/**
@ -92,13 +92,13 @@ class MeterInterpreter extends Interpreter {
* @todo untested
* @return array with timestamp, values, and pulse count
*/
public function getValues($tuples = NULL, $groupBy = NULL) {
public function getValues($tuples, $groupBy, $callback) {
$pulses = parent::getData($tuples, $groupBy);
$values = array();
foreach ($pulses as $pulse) {
if (isset($last)) {
$values[] = $this->raw2differential($last, $pulse);
$values[] = $callback($this->raw2differential($last, $pulse));
$last = $pulse;
}
else {

View file

@ -37,16 +37,16 @@ class SensorInterpreter extends Interpreter {
* @todo untested
* @param string|integer $groupBy
*/
public function getValues($tuples = NULL, $groupBy = NULL) {
public function getValues($tuples, $groupBy, $callback) {
$data = parent::getData($tuples, $groupBy);
$values = array();
foreach ($data as $reading) {
$values[] = array(
$values[] = $callback(array(
(float) $reading[0],
(float) $reading[1] / $reading[2],
(int) $reading[2]
);
));
}
return $values;
@ -80,14 +80,6 @@ class SensorInterpreter extends Interpreter {
public function getAverage() {
return (float) $this->conn->fetchColumn('SELECT AVG(value) FROM data WHERE channel_id = ?' . parent::buildDateTimeFilterSQL($this->from, $this->to), array($this->channel->getId()), 0);
}
/**
* @todo possible and/or required?
* @return float
*/
public function getConsumption() {
}
}
?>

View file

@ -35,8 +35,8 @@ use Volkszaehler\Interpreter;
* @todo rework
*/
class CSV extends View {
protected $delimiter = ';';
protected $enclosure = '"';
const DELIMITER = ';';
const ENCLOSURE = '"';
protected $csv = array();
@ -115,14 +115,19 @@ class CSV extends View {
* @param Interpreter\InterpreterInterface $interpreter
*/
protected function addData(Interpreter\Interpreter $interpreter) {
$tuples = $interpreter->getValues($this->request->getParameter('tuples'), $this->request->getParameter('group'));
//$this->response->setHeader('Content-Disposition', 'attachment; filename="' . strtolower($interpreter->getEntity()->getProperty('title')) . '.csv"'); // TODO add time?
foreach ($tuples as $row) {
$array = array_map(array($this, 'escape'), $row);
echo implode($this->delimiter, $row) . PHP_EOL;
}
$tuples = $interpreter->getValues(
$this->request->getParameter('tuples'),
$this->request->getParameter('group'),
function($tuple) {
echo implode(CSV::DELIMITER, array(
$tuple[0],
View::formatNumber($tuple[1]),
$tuple[2]
)) . PHP_EOL;
}
);
}
/**
@ -138,7 +143,7 @@ class CSV extends View {
*/
protected function escape($value) {
if (is_string($value)) {
return $this->enclosure . $value . $this->enclosure;
return self::ENCLOSURE . $value . self::ENCLOSURE;
}
elseif (is_numeric($value)) {
return $value;

View file

@ -171,7 +171,7 @@ class JSON extends View {
if (count($queries) > 0) {
$jsonDebug['database'] = array(
'driver' => Util\Configuration::read('db.driver'),
'queries' => $queries
'queries' => array_values($queries)
);
}
@ -208,19 +208,31 @@ class JSON extends View {
/**
* Add data to output queue
*
* @param Interpreter\InterpreterInterface $interpreter
* @param $interpreter
*/
protected function addData(Interpreter\Interpreter $interpreter) {
protected function addData($interpreter) {
$this->json['data']['uuid'] = $interpreter->getEntity()->getUuid();
$data = $interpreter->getValues($this->request->getParameter('tuples'), $this->request->getParameter('group'));
$data = $interpreter->getValues(
$this->request->getParameter('tuples'),
$this->request->getParameter('group'),
function($tuple) {
return array(
$tuple[0],
View::formatNumber($tuple[1]),
$tuple[2]
);
}
);
$min = $interpreter->getMin();
$max = $interpreter->getMax();
$average = $interpreter->getAverage();
$consumption = $interpreter->getConsumption();
if (isset($min)) $this->json['data']['min'] = $min;
if (isset($max)) $this->json['data']['max'] = $max;
if (isset($average)) $this->json['data']['average'] = $average;
$this->json['data']['min'] = $min;
$this->json['data']['max'] = $max;
$this->json['data']['average'] = View::formatNumber($average);
$this->json['data']['consumption'] = View::formatNumber($consumption);
if (count($data) > 0) $this->json['data']['tuples'] = $data;
}

View file

@ -137,6 +137,16 @@ abstract class View {
throw new Exception('Unknown caching mode: ' . $mode);
}
}
/**
* Round decimal numbers to given precission
*
* @param $number float the number
* @return (float|string) the formatted number
*/
public static function formatNumber($number) {
return round($number, self::PRECISSION);
}
public abstract function add($object);
protected abstract function render();

View file

@ -75,10 +75,10 @@ class XML extends View {
$this->addEntity($data);
}
elseif ($data instanceof \Exception) {
//$this->addException($data);
$this->addException($data);
}
elseif ($data instanceof Util\Debug) {
//$this->addDebug($data);
$this->addDebug($data);
}
elseif (is_array($data)) {
$this->xmlRoot->appendChild($this->convertArray($data));
@ -163,11 +163,11 @@ class XML extends View {
protected function addDebug(Util\Debug $debug) {
$xmlDebug = $this->xmlDoc->createElement('debug');
$xmlDebug->appendChild($this->xmlDoc->createElement('time', $debug->getExecutionTime()));
$xmlDebug->appendChild($this->convertArray($debug->getMessages(), 'messages'));
$xmlDebug->appendChild($this->convertArray($debug->getMessages(), 'messages', 'message'));
$xmlDatabase = $this->xmlDoc->createElement('database');
$xmlDatabase->setAttribute('driver', Util\Configuration::read('db.driver'));
$xmlDatabase->appendChild($this->convertArray($debug->getQueries(), 'queries'));
$xmlDatabase->appendChild($this->convertArray($debug->getQueries(), 'queries', 'query'));
$xmlDebug->appendChild($xmlDatabase);
$this->xmlRoot->appendChild($xmlDebug);
@ -198,28 +198,30 @@ class XML extends View {
/**
* Add data to output queue
*
* @param Interpreter\InterpreterInterface $interpreter
* @param $interpreter
*/
protected function addData(Interpreter\InterpreterInterface $interpreter) {
$data = $interpreter->getValues($this->request->getParameter('tuples'), $this->request->getParameter('group'));
protected function addData($interpreter) {
$xmlDoc = $this->xmlDoc;
$xmlData = $this->xmlDoc->createElement('data');
$xmlTuples = $this->xmlDoc->createElement('tuples');
foreach ($data as $tuple) {
$xmlTuple = $this->xmlDoc->createElement('tuple');
$xmlTuple->setAttribute('timestamp', $tuple[0]); // hardcoded data fields for performance optimization
$xmlTuple->setAttribute('value', $tuple[1]);
$xmlTuple->setAttribute('count', $tuple[2]);
$xmlTuples->appendChild($xmlTuple);
}
$data = $interpreter->getValues(
$this->request->getParameter('tuples'),
$this->request->getParameter('group'),
function($tuple) use ($xmlDoc, $xmlTuples) {
$xmlTuple = $xmlDoc->createElement('tuple');
$xmlTuple->setAttribute('timestamp', $tuple[0]); // hardcoded data fields for performance optimization
$xmlTuple->setAttribute('value', View::formatNumber($tuple[1]));
$xmlTuple->setAttribute('count', $tuple[2]);
$xmlTuples->appendChild($xmlTuple);
}
);
$xmlData->appendChild($this->xmlDoc->createElement('uuid', $interpreter->getEntity()->getUuid()));
$xmlData->appendChild($this->xmlDoc->createElement('count', count($data)));
$xmlData->appendChild($this->xmlDoc->createElement('first', (isset($data[0][0])) ? $data[0][0] : NULL));
$xmlData->appendChild($this->xmlDoc->createElement('last', (isset($data[count($data)-1][0])) ? $data[count($data)-1][0] : NULL));
$xmlData->appendChild($this->xmlDoc->createElement('min', $interpreter->getMin()));
$xmlData->appendChild($this->xmlDoc->createElement('max', $interpreter->getMax()));
$xmlData->appendChild($this->xmlDoc->createElement('average', $interpreter->getAverage()));
$xmlData->appendChild($this->xmlDoc->createElement('last', $interpreter->getLast()));
$xmlData->appendChild($this->xmlDoc->createElement('average', self::formatNumber($interpreter->getAverage())));
$xmlData->appendChild($this->xmlDoc->createElement('consumption', self::formatNumber($interpreter->getConsumption())));
$xmlData->appendChild($xmlTuples);
$this->xmlRoot->appendChild($xmlData);
@ -231,28 +233,25 @@ class XML extends View {
* @param array the input array
* @return DOMElement
*/
protected function convertArray(array $array, $identifier = 'array') {
$xmlArray = $this->xmlDoc->createElement($identifier);
protected function convertArray(array $array, $identifierPlural = 'array', $identifierSingular = 'entry') {
$xmlArray = $this->xmlDoc->createElement($identifierPlural);
foreach ($array as $key => $value) {
// determine tagname
if (is_numeric($key)) {
if (substr($identifier, -3) == 'ies') {
$key = substr($identifier, 0, -3) . 'y';
}
elseif (substr($identifier, -1) == 's') {
$key = substr($identifier, 0, -1);
}
else {
$key = 'index' . $key;
}
$key = $identifierSingular;
}
if (is_array($value)) {
$xmlArray->appendChild($this->convertArray($value, $key));
}
else {
$xmlArray->appendChild($this->xmlDoc->createElement($key, (is_scalar($value)) ? $value : 'object'));
elseif (is_numeric($value)) {
$xmlArray->appendChild($this->xmlDoc->createElement($key, self::formatNumber($value)));
}
elseif (is_scalar($value)) {
$xmlArray->appendChild($this->xmlDoc->createElement($key, $value));
}
else { // TODO required?
$xmlArray->appendChild($this->xmlDoc->createElement($key, 'object'));
}
}

View file

@ -26,8 +26,6 @@
use Volkszaehler\Util;
// TODO replace by state class
define('VZ_VERSION', 0.2);
define('VZ_DIR', realpath(__DIR__ . '/../..'));
// class autoloading