From 51500842d79914c49c34c3b85a86c635e6cba6af Mon Sep 17 00:00:00 2001 From: Joshua Seigler Date: Sun, 26 Jun 2016 16:59:39 -0400 Subject: [PATCH] separated SVG generation from demo file --- SVGChartBuilder.php | 166 ++++++++++++++++++++++++++++++++++++++++++++ Util.php | 14 ---- buffer.php | 2 +- index.php | 156 +---------------------------------------- 4 files changed, 170 insertions(+), 168 deletions(-) create mode 100644 SVGChartBuilder.php diff --git a/SVGChartBuilder.php b/SVGChartBuilder.php new file mode 100644 index 0000000..ec8a007 --- /dev/null +++ b/SVGChartBuilder.php @@ -0,0 +1,166 @@ + $thisY) { + if (!is_null($previousValue)) { + $absoluteDeltas[] = abs($thisY - $previousValue); + } + if ($thisY < $yMin) { + $yMin = $thisY; + $yMinX = $thisX; + } + if ($thisY > $yMax) { + $yMax = $thisY; + $yMaxX = $thisX; + } + $previousValue = $thisY; + } + $yRange = $yMax - $yMin; + end($chartData); + $xMax = key($chartData); + reset($chartData); + $xMin = key($chartData); + $xRange = $xMax - $xMin; + $count = count($chartData); + $medianDelta = abs(median($absoluteDeltas)); + + /* + We want the height of the median y-delta to be the same as + the width of one x-delta, which puts the median slope at + 45 degrees. This improves comprehension. + http://vis4.net/blog/posts/doing-the-line-charts-right/ + */ + $aspectRatio = $yRange / $medianDelta / $count; + $height = floor($aspectRatio * $width); + + function labelFormat($float, $sigFigs = 4, $minPlaces = 1) { + return number_format($float, max( + $minPlaces, + $sigFigs + floor(-log($float, 10))) + /* this floor(log) thing is the first significant place value */ + ); + } + + /* Transform data coords to chart coords */ + function transformX($x, $xMin, $xRange, $width) { + return round( + ($x - $xMin) / $xRange * $width + , 2); + } + function transformY($y, $yMax, $yRange, $height) { + return round( + // SVG has y axis reversed, 0 is at the top + ($yMax - $y) / $yRange * $height + , 2); + } + + $chartPoints = "M"; + foreach ($chartData as $x => $y) { + $chartPoints .= transformX($x, $xMin, $xRange, $width) . ',' . transformY($y, $yMax, $yRange, $height) . ' + '; + } + + $numLabels = floor($height / 25); + $labelModulation = 10 ** (1 + floor(-log($yRange / $numLabels, 10)));// / 5; + $labelInterval = ceil($yRange / $numLabels * $labelModulation) / $labelModulation; + + // Top and bottom grid lines + $gridLines = + "M0,0 ".$width.",0 + M0,".$height.",".$width.",".$height." + "; + + // Top and bottom grid labels + $gridText = + ''.labelFormat($yMax).'' . + ''.labelFormat($yMin).''; + + // Start at the first "nice" Y value > min + 50% of the interval + // Keep going until max - 50% of the interval + // Add Interval each iteration + for ( + $labelY = $yMin - fmod($yMin, $labelInterval) + $labelInterval; + $labelY < $yMax; + $labelY += $labelInterval + ) { + $labelHeight = transformY($labelY, $yMax, $yRange, $height); + if ( + $labelY < $yMax - 0.4 * $labelInterval && + $labelY > $yMin + 0.4 * $labelInterval + ) { + $gridLines .= "M0,".$labelHeight." ".$width.",".$labelHeight." + "; + $gridText .= ''.labelFormat($labelY).''; + } + } + + return ' + + + + + + + + + + + + + + + '.( $gridText ).' + + +'; + } +} diff --git a/Util.php b/Util.php index f6bcfec..eb55c1b 100644 --- a/Util.php +++ b/Util.php @@ -18,18 +18,4 @@ class Util { $result = json_decode($result) or trigger_error('Couldn\'t parse JSON'); return $result; } - - public static function median($arr) { - sort($arr); - $count = count($arr); //total numbers in array - $middleval = floor(($count-1)/2); // find the middle value, or the lowest middle value - if($count % 2) { // odd number, middle is the median - $median = $arr[$middleval]; - } else { // even number, calculate avg of 2 medians - $low = $arr[$middleval]; - $high = $arr[$middleval+1]; - $median = (($low+$high)/2); - } - return $median; - } } diff --git a/buffer.php b/buffer.php index 3ed3bf7..bcb839a 100644 --- a/buffer.php +++ b/buffer.php @@ -53,7 +53,7 @@ fclose($f); } $last_modified_time = time(); - $etag = md5_file($file); + $etag = md5_file('buffer'.$file); // always send headers header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT"); diff --git a/index.php b/index.php index 7024745..a35e0a8 100644 --- a/index.php +++ b/index.php @@ -18,161 +18,11 @@ $poloniex_url = 'https://poloniex.com/public?command=returnChartData¤cyPai //14400 //6h //86400 //1d ; - -$dateformat = 'gA'; $last24h = Util::getJson($poloniex_url); $chartData = []; -$absoluteDeltas = []; -$previousValue = null; -$yMin = $xMin = INF; -$yMax = $xMax = -INF; -foreach ($last24h as $datum) { - $thisX = $datum->date; - $thisY = $datum->weightedAverage; - $chartData[$thisX] = $thisY; - if (!is_null($previousValue)) { - $absoluteDeltas[] = abs($thisY - $previousValue); - } - if ($thisY < $yMin) { - $yMin = $thisY; - $yMinX = $thisX; - } - if ($thisY > $yMax) { - $yMax = $thisY; - $yMaxX = $thisX; - } - $previousValue = $thisY; -} -$yRange = $yMax - $yMin; -end($chartData); -$xMax = key($chartData); -reset($chartData); -$xMin = key($chartData); -$xRange = $xMax - $xMin; -$count = count($chartData); -$medianDelta = abs(Util::median($absoluteDeltas)); -$width = 700; - -/* -We want the height of the median y-delta to be the same as -the width of one x-delta, which puts the median slope at -45 degrees. This improves comprehension. -http://vis4.net/blog/posts/doing-the-line-charts-right/ -*/ -$aspectRatio = $yRange / $medianDelta / $count; -$height = floor($aspectRatio * $width); - -function labelFormat($float, $sigFigs = 4, $minPlaces = 1) { - return number_format($float, max( - $minPlaces, - $sigFigs + floor(-log($float, 10))) - /* this floor(log) thing is the first significant place value */ - ); +foreach ($last24h as $item) { + $chartData[$item->date] = $item->weightedAverage; } -/* Transform data coords to chart coords */ -function transformX($x) { - global $xMin, $xRange, $width; - return round( - ($x - $xMin) / $xRange * $width - , 2); -} -function transformY($y) { - global $yMax, $yRange, $height; - return round( - // SVG has y axis reversed, 0 is at the top - ($yMax - $y) / $yRange * $height - , 2); -} - -$chartPoints = "M"; -foreach ($chartData as $x => $y) { - $chartPoints .= transformX($x) . ',' . transformY($y) . ' - '; -} - -$numLabels = floor($height / 25); -$labelModulation = 10 ** (1 + floor(-log($yRange / $numLabels, 10)));// / 5; -$labelInterval = ceil($yRange / $numLabels * $labelModulation) / $labelModulation; - -// Top and bottom grid lines -$gridLines = -"M0,0 ".$width.",0 -M0,".$height.",".$width.",".$height." -"; - -// Top and bottom grid labels -$gridText = - ''.labelFormat($yMax).'' . - ''.labelFormat($yMin).''; - -// Start at the first "nice" Y value > min + 50% of the interval -// Keep going until max - 50% of the interval -// Add Interval each iteration -for ( - $labelY = $yMin - fmod($yMin, $labelInterval) + $labelInterval; - $labelY < $yMax; - $labelY += $labelInterval -) { - $labelHeight = transformY($labelY); - $gridLines .= "M0,".$labelHeight." ".$width.",".$labelHeight." - "; - if ( - $labelY < $yMax - 0.4 * $labelInterval && - $labelY > $yMin + 0.4 * $labelInterval - ) { - $gridText .= ''.labelFormat($labelY).''; - } -} - -// in case some dingbat has PHP short tags enabled -echo '<'.'?xml version="1.0" standalone="no"?'.'>'; - -?> - - - - - - - - - - - - - - - - - - +print SVGChartBuilder::renderStockChart($chartData);