Changeset View
Changeset View
Standalone View
Standalone View
src/applications/fact/controller/PhabricatorFactChartController.php
<?php | <?php | ||||
final class PhabricatorFactChartController extends PhabricatorFactController { | final class PhabricatorFactChartController extends PhabricatorFactController { | ||||
public function handleRequest(AphrontRequest $request) { | public function handleRequest(AphrontRequest $request) { | ||||
$viewer = $request->getViewer(); | $viewer = $request->getViewer(); | ||||
// When drawing a chart, we send down a placeholder piece of HTML first, | // When drawing a chart, we send down a placeholder piece of HTML first, | ||||
// then fetch the data via async request. Determine if we're drawing | // then fetch the data via async request. Determine if we're drawing | ||||
// the structure or actually pulling the data. | // the structure or actually pulling the data. | ||||
$mode = $request->getURIData('mode'); | $mode = $request->getURIData('mode'); | ||||
$is_chart_mode = ($mode === 'chart'); | $is_chart_mode = ($mode === 'chart'); | ||||
$is_draw_mode = ($mode === 'draw'); | $is_draw_mode = ($mode === 'draw'); | ||||
$functions = array(); | $argvs = array(); | ||||
$functions[] = id(new PhabricatorFactChartFunction()) | |||||
->setArguments(array('tasks.count.create')); | |||||
$functions[] = id(new PhabricatorFactChartFunction()) | |||||
->setArguments(array('tasks.open-count.create')); | |||||
$x_function = id(new PhabricatorXChartFunction()) | |||||
->setArguments(array()); | |||||
$functions[] = id(new PhabricatorConstantChartFunction()) | $argvs[] = array('fact', 'tasks.count.create'); | ||||
->setArguments(array(360)); | |||||
$functions[] = id(new PhabricatorSinChartFunction()) | $argvs[] = array('constant', 360); | ||||
->setArguments(array($x_function)); | |||||
$cos_function = id(new PhabricatorCosChartFunction()) | $argvs[] = array('fact', 'tasks.open-count.create'); | ||||
->setArguments(array($x_function)); | |||||
$functions[] = id(new PhabricatorShiftChartFunction()) | $argvs[] = array( | ||||
->setArguments( | 'sum', | ||||
array( | |||||
array( | |||||
'scale', | |||||
array( | |||||
'cos', | |||||
array( | array( | ||||
'scale', | 'accumulate', | ||||
array('x'), | array('fact', 'tasks.count.create'), | ||||
0.001, | |||||
), | ), | ||||
array( | |||||
'accumulate', | |||||
array('fact', 'tasks.open-count.create'), | |||||
), | ), | ||||
10, | ); | ||||
), | |||||
200, | $argvs[] = array( | ||||
)); | 'compose', | ||||
array('scale', 0.001), | |||||
array('cos'), | |||||
array('scale', 100), | |||||
array('shift', 800), | |||||
); | |||||
$functions = array(); | |||||
foreach ($argvs as $argv) { | |||||
$functions[] = id(new PhabricatorComposeChartFunction()) | |||||
->setArguments(array($argv)); | |||||
} | |||||
$subfunctions = array(); | |||||
foreach ($functions as $function) { | |||||
foreach ($function->getSubfunctions() as $subfunction) { | |||||
$subfunctions[] = $subfunction; | |||||
} | |||||
} | |||||
foreach ($subfunctions as $subfunction) { | |||||
$subfunction->loadData(); | |||||
} | |||||
list($domain_min, $domain_max) = $this->getDomain($functions); | list($domain_min, $domain_max) = $this->getDomain($functions); | ||||
$axis = id(new PhabricatorChartAxis()) | $axis = id(new PhabricatorChartAxis()) | ||||
->setMinimumValue($domain_min) | ->setMinimumValue($domain_min) | ||||
->setMaximumValue($domain_max); | ->setMaximumValue($domain_max); | ||||
$data_query = id(new PhabricatorChartDataQuery()) | $data_query = id(new PhabricatorChartDataQuery()) | ||||
->setMinimumValue($domain_min) | ->setMinimumValue($domain_min) | ||||
->setMaximumValue($domain_max) | ->setMaximumValue($domain_max) | ||||
->setLimit(2000); | ->setLimit(2000); | ||||
$datasets = array(); | $datasets = array(); | ||||
foreach ($functions as $function) { | foreach ($functions as $function) { | ||||
$function->setXAxis($axis); | $points = $function->newDatapoints($data_query); | ||||
$function->loadData(); | |||||
$points = $function->getDatapoints($data_query); | |||||
$x = array(); | $x = array(); | ||||
epriestley: This is pretty hard to read as a PHP specification, but I'm showing that these two chains are… | |||||
$y = array(); | $y = array(); | ||||
foreach ($points as $point) { | foreach ($points as $point) { | ||||
$x[] = $point['x']; | $x[] = $point['x']; | ||||
$y[] = $point['y']; | $y[] = $point['y']; | ||||
} | } | ||||
$datasets[] = array( | $datasets[] = array( | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | return $this->newPage() | ||||
->setCrumbs($crumbs) | ->setCrumbs($crumbs) | ||||
->appendChild($box); | ->appendChild($box); | ||||
} | } | ||||
private function getDomain(array $functions) { | private function getDomain(array $functions) { | ||||
$domain_min_list = null; | $domain_min_list = null; | ||||
$domain_max_list = null; | $domain_max_list = null; | ||||
foreach ($functions as $function) { | foreach ($functions as $function) { | ||||
if ($function->hasDomain()) { | |||||
$domain = $function->getDomain(); | $domain = $function->getDomain(); | ||||
list($domain_min, $domain_max) = $domain; | list($function_min, $function_max) = $domain; | ||||
if ($domain_min !== null) { | if ($function_min !== null) { | ||||
$domain_min_list[] = $domain_min; | $domain_min_list[] = $function_min; | ||||
} | } | ||||
if ($domain_max !== null) { | if ($function_max !== null) { | ||||
$domain_max_list[] = $domain_max; | $domain_max_list[] = $function_max; | ||||
} | |||||
} | } | ||||
} | } | ||||
$domain_min = null; | $domain_min = null; | ||||
$domain_max = null; | $domain_max = null; | ||||
if ($domain_min_list) { | if ($domain_min_list) { | ||||
$domain_min = min($domain_min_list); | $domain_min = min($domain_min_list); | ||||
Show All 22 Lines |
This is pretty hard to read as a PHP specification, but I'm showing that these two chains are now equivalent:
That is, A(X + Y) is the same as A(X) + A(Y). In the screenshot, they produce the same datapoints and draw on top of one another. This is heartening.