mirror of
https://github.com/seigler/cryptohistory.org
synced 2025-07-26 01:06:12 +00:00
functioning rest-style chart server!
This commit is contained in:
commit
e1784bdd4c
8 changed files with 434 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
# https://git-scm.com/docs/gitignore
|
||||
# https://help.github.com/articles/ignoring-files
|
||||
# Example .gitignore files: https://github.com/github/gitignore
|
||||
/bower_components/
|
||||
/node_modules/
|
||||
/vendor/
|
||||
/.brackets.json
|
7
composer.json
Normal file
7
composer.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"require": {
|
||||
"seigler/neat-charts": "@dev",
|
||||
"altorouter/altorouter": "1.1.0",
|
||||
"phpFastCache/phpFastCache": "^4.3"
|
||||
}
|
||||
}
|
187
composer.lock
generated
Normal file
187
composer.lock
generated
Normal file
|
@ -0,0 +1,187 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "1bb799d5b600f9167c5a63c390825771",
|
||||
"content-hash": "8a896903dde64517a29ad409d716c428",
|
||||
"packages": [
|
||||
{
|
||||
"name": "altorouter/altorouter",
|
||||
"version": "v1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dannyvankooten/AltoRouter.git",
|
||||
"reference": "09d9d946c546bae6d22a7654cdb3b825ffda54b4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dannyvankooten/AltoRouter/zipball/09d9d946c546bae6d22a7654cdb3b825ffda54b4",
|
||||
"reference": "09d9d946c546bae6d22a7654cdb3b825ffda54b4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"AltoRouter.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Danny van Kooten",
|
||||
"email": "dannyvankooten@gmail.com",
|
||||
"homepage": "http://dannyvankooten.com/"
|
||||
},
|
||||
{
|
||||
"name": "Koen Punt",
|
||||
"homepage": "https://github.com/koenpunt"
|
||||
},
|
||||
{
|
||||
"name": "niahoo",
|
||||
"homepage": "https://github.com/niahoo"
|
||||
}
|
||||
],
|
||||
"description": "A lightning fast router for PHP",
|
||||
"homepage": "https://github.com/dannyvankooten/AltoRouter",
|
||||
"keywords": [
|
||||
"lightweight",
|
||||
"router",
|
||||
"routing"
|
||||
],
|
||||
"time": "2014-04-16 09:44:40"
|
||||
},
|
||||
{
|
||||
"name": "phpfastcache/phpfastcache",
|
||||
"version": "4.3.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPSocialNetwork/phpfastcache.git",
|
||||
"reference": "348f765dbb426f5da1d009802ab496909e4ad691"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPSocialNetwork/phpfastcache/zipball/348f765dbb426f5da1d009802ab496909e4ad691",
|
||||
"reference": "348f765dbb426f5da1d009802ab496909e4ad691",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-apc": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-memcache": "*",
|
||||
"ext-memcached": "*",
|
||||
"ext-predis": "*",
|
||||
"ext-redis": "*",
|
||||
"ext-sqlite": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/phpFastCache/phpFastCache.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Khoa Bui",
|
||||
"email": "khoaofgod@gmail.com",
|
||||
"homepage": "http://www.phpfastcache.com",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Georges.L",
|
||||
"email": "contact@geolim4.com",
|
||||
"homepage": "https://github.com/Geolim4",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "PHP Cache Class - Supported Redis, Cookie, Predis, APC, MemCached, WinCache, Files, PDO, Reduce mySQL Call by Caching",
|
||||
"homepage": "http://www.phpfastcache.com",
|
||||
"keywords": [
|
||||
"APC Cache",
|
||||
"apc",
|
||||
"cache",
|
||||
"cache class",
|
||||
"caching",
|
||||
"cookie",
|
||||
"files cache",
|
||||
"memcache",
|
||||
"memcached",
|
||||
"mysql cache",
|
||||
"pdo cache",
|
||||
"php cache",
|
||||
"predis",
|
||||
"redis",
|
||||
"wincache"
|
||||
],
|
||||
"time": "2016-05-17 22:29:47"
|
||||
},
|
||||
{
|
||||
"name": "seigler/neat-charts",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/seigler/neat-charts.git",
|
||||
"reference": "352794cbfcd9d7e4d7d6973188cf35e69d21f723"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/seigler/neat-charts/zipball/352794cbfcd9d7e4d7d6973188cf35e69d21f723",
|
||||
"reference": "352794cbfcd9d7e4d7d6973188cf35e69d21f723",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"NeatCharts\\LineChart": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Joshua Seigler",
|
||||
"email": "joshua@seigler.net",
|
||||
"homepage": "https://joshua.seigler.net/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Generates clean-looking SVG charts",
|
||||
"homepage": "https://github.com/seigler/neat-charts",
|
||||
"keywords": [
|
||||
"chart",
|
||||
"charts",
|
||||
"svg"
|
||||
],
|
||||
"time": "2016-06-29 18:58:29"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"seigler/neat-charts": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": []
|
||||
}
|
54
index.php
Normal file
54
index.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
require_once 'vendor/autoload.php';
|
||||
require_once 'vendor/seigler/neat-charts/src/NeatCharts/NeatChart.php';
|
||||
require_once 'vendor/seigler/neat-charts/src/NeatCharts/LineChart.php';
|
||||
|
||||
use phpFastCache\CacheManager;
|
||||
|
||||
CacheManager::setup([
|
||||
'storage' => 'files',
|
||||
'path' => sys_get_temp_dir().'/cryptohistory-cache/'
|
||||
]);
|
||||
|
||||
$router = new AltoRouter();
|
||||
|
||||
$router->map('GET', '/', function() {
|
||||
require __DIR__ . '/views/index.php';
|
||||
});
|
||||
|
||||
// map cryptocurrency stuff
|
||||
$router->map( 'GET', '/charts/[BTC_DASH:pair]/[7d|24h:duration]/[svg|png:format]', function($pair, $duration, $format) {
|
||||
require __DIR__ . '/views/chart.php';
|
||||
renderChart(
|
||||
$pair,
|
||||
60 * 60 * 24 * ($duration == '7d' ? 7 : 1),
|
||||
($duration == '7d' ? 1800 : 300),
|
||||
$format,
|
||||
'#000',
|
||||
800,
|
||||
200,
|
||||
12
|
||||
);
|
||||
return true;
|
||||
});
|
||||
|
||||
// match current request url
|
||||
$match = $router->match();
|
||||
|
||||
// call closure or throw 404 status
|
||||
try {
|
||||
if( !$match || !is_callable( $match['target'] ) || false === call_user_func_array( $match['target'], $match['params'] )) {
|
||||
// no route was matched
|
||||
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
|
||||
echo '<h1>404 Not Found</h1><p>Page not found</p>';
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
header($_SERVER["SERVER_PROTOCOL"]." 500 Server Error", true, 500);
|
||||
echo 'There was some problem generating that for you.';
|
||||
return true;
|
||||
}
|
||||
|
||||
?>
|
89
views/chart.php
Normal file
89
views/chart.php
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
use phpFastCache\CacheManager;
|
||||
|
||||
function getJson($url) {
|
||||
if (empty($url)) {
|
||||
trigger_error('Missing or empty JSON url');
|
||||
}
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json'));
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
||||
// http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/
|
||||
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||||
// curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
// curl_setopt($ch, CURLOPT_CAINFO, getcwd() . "/VeriSignClass3PublicPrimaryCertificationAuthority-G5.pem");
|
||||
|
||||
$result = curl_exec($ch);
|
||||
$result = json_decode($result) or trigger_error('Couldn\'t parse JSON');
|
||||
return $result;
|
||||
}
|
||||
|
||||
function renderChart(
|
||||
$pair,
|
||||
$dataDuration = (7 * 24 * 60 * 60),
|
||||
$dataResolution = 1800,
|
||||
$format = 'svg',
|
||||
$color = '#000',
|
||||
$width = 800,
|
||||
$height = 200,
|
||||
$fontSize = 12
|
||||
) {
|
||||
|
||||
$result = CacheManager::get('poloniex-'.$pair.'-'.$dataDuration.'-'.$format);
|
||||
|
||||
if (is_null($result)) {
|
||||
$startTime = time() - $dataDuration;
|
||||
$poloniexUrl = 'https://poloniex.com/public?command=returnChartData¤cyPair=' . $pair . '&start=' . $startTime . '&end=9999999999&period=' . $dataResolution;
|
||||
|
||||
$poloniexJson = CacheManager::get('poloniex-json-'.$pair.'-'.$dataDuration);
|
||||
|
||||
if(is_null($poloniexJson)) {
|
||||
$poloniexJson = getJson($poloniexUrl);
|
||||
// Write to cache for next time
|
||||
CacheManager::set('poloniex-json-'.$pair.'-'.$dataDuration, $poloniexJson, $dataDuration);
|
||||
}
|
||||
|
||||
$chartData = [];
|
||||
|
||||
foreach ($poloniexJson as $item) {
|
||||
$chartData[$item->date] = $item->weightedAverage;
|
||||
}
|
||||
|
||||
$poloniexChart = new NeatCharts\LineChart($chartData, [
|
||||
'width'=>800,
|
||||
'height'=>200,
|
||||
'lineColor'=>"#1C75BC", // Dash blue
|
||||
'labelColor'=>"#000",
|
||||
'smoothed'=>false,
|
||||
'fontSize'=>12
|
||||
]);
|
||||
$result = $poloniexChart->render();
|
||||
|
||||
if ($format == 'png') {
|
||||
$im = new Imagick();
|
||||
$im->setBackgroundColor(new ImagickPixel("transparent"));
|
||||
$im->readImageBlob($result);
|
||||
$im->setImageFormat("png32");
|
||||
$result = $im->getImageBlob();
|
||||
$im->clear();
|
||||
$im->destroy();
|
||||
}
|
||||
CacheManager::set('poloniex-'.$pair.'-'.$dataDuration.'-'.$format, $result, $dataDuration);
|
||||
$resultExpires = time() + $dataDuration;
|
||||
} else {
|
||||
$resultExpires = CacheManager::getInfo('poloniex-'.$pair.'-'.$dataDuration.'-'.$format)[ 'expired_time' ];
|
||||
$startTime = $resultExpires - $dataDuration;
|
||||
}
|
||||
|
||||
header('Expires: '.gmdate("D, d M Y H:i:s", $resultExpires));
|
||||
if ($format == 'svg') {
|
||||
header('Content-type: image/svg+xml; charset=utf-8');
|
||||
header('Content-Disposition: inline; filename="Dash-chart-' . gmdate('Y-m-d\THis+0', $startTime) . '--' . gmdate('Y-m-d\THis+0') . '.svg"');
|
||||
} else if ($format == 'png') {
|
||||
header("Content-Type: image/png");
|
||||
header('Content-Disposition: inline; filename="Dash-chart-' . gmdate('Y-m-d\THis+0', $startTime) . '--' . gmdate('Y-m-d\THis+0') . '.png"');
|
||||
}
|
||||
echo $result;
|
||||
}
|
23
views/fakeStockData.php
Normal file
23
views/fakeStockData.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
$chartData = [];
|
||||
|
||||
$offset = 100 * (rand()/getRandMax())**4;
|
||||
$scale = 100 * (rand()/getRandMax())**2;
|
||||
$volatility = 0.5 * (rand()/getRandMax())**3;
|
||||
|
||||
for ($n = 0, $current = $offset + 0.5 * $scale; $n < 96; $n++) {
|
||||
$current -= $offset;
|
||||
$current *= 1 + $volatility * (rand()/getRandMax() - 0.5);
|
||||
$current += $offset;
|
||||
$chartData[$n] = $current;
|
||||
}
|
||||
|
||||
$stockChart = new NeatCharts\LineChart($chartData, [
|
||||
"width"=>500,
|
||||
"height"=>150,
|
||||
"fontSize"=>10
|
||||
]);
|
||||
print $stockChart->render();
|
||||
|
||||
?>
|
24
views/fakeTempData.php
Normal file
24
views/fakeTempData.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
$chartData = [];
|
||||
|
||||
$start = 100 * (rand()/getRandMax())**3;
|
||||
$volatility = rand()/getRandMax() + 0.01;
|
||||
$velocity = (rand()/getRandMax() - 0.5);
|
||||
$acceleration = 0.1 * (rand()/getRandMax())**2;
|
||||
|
||||
for ($n = 0, $current = $start; $n < 12; $n++) {
|
||||
$velocity *= 0.5;
|
||||
$velocity += $acceleration * 2 * (rand()/getRandMax() - 0.5);
|
||||
$current += $velocity;
|
||||
$chartData[$n] = $current;
|
||||
}
|
||||
|
||||
$tempChart = new NeatCharts\LineChart($chartData, [
|
||||
"width"=>700,
|
||||
"height"=>400,
|
||||
"lineColor"=>"#D00",
|
||||
"labelColor"=>"#777",
|
||||
"smoothed"=>true
|
||||
]);
|
||||
print $tempChart->render();
|
||||
?>
|
43
views/index.php
Normal file
43
views/index.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0">
|
||||
<title>NeatCharts demo</title>
|
||||
<style>
|
||||
main {
|
||||
-webkit-columns: 800px 2;
|
||||
-moz-columns: 800px 2;
|
||||
columns: 800px 2;
|
||||
}
|
||||
section {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
max-width: 800px;
|
||||
padding: 10px;
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1>NeatCharts demo</h1>
|
||||
</header>
|
||||
<main>
|
||||
<section>
|
||||
<h2>Poloniex Dash/BTC Price</h2>
|
||||
<img src="/charts/dash/24h" alt="Poloniex Dash/BTC price">
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Fake Stock Market Data</h2>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Monotonically Smoothed Chart</h2>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue