mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 23:02:42 +01:00
Simplify implementation of "pure" Chart functions
Summary: Depends on D20445. Ref T13279. I'm not sure what the class tree of functions actually looks like, and I suspect it isn't really a tree, so I'm hesitant to start subclassing. Instead, try adding some `isSomethingSomething()` methods. We have some different types of functions: # Some functions can be evaluated anywhere, like "constant(3)", which always evaluates to 3. # Some functions can't be evaluated anywhere, but have values everywhere in some domain. This is most interesting functions, like "number of open tasks". These functions also usually have a distinct set of interesting points, and are constant between those points (any count of anything, like "open points in project" or "tasks closed by alice", etc). # Some functions can be evaluated almost nowhere and have only discrete values. This is most of the data we actually store, which is just "+1" when a task is opened and "-1" when a task is closed. Soon, I'd like to be able to show ("all tasks" - "open tasks") and draw a chart of closed tasks. This is somewhat tricky because the two datasets are of the second class of function (straight lines connecting dots) but their "interesting" x values won't be the same (users don't open and close tasks every second, or at the same time). The "subtract X Y" function will need to be able to know that `subtract "all tasks" 3` and `subtract "all tasks" "closed tasks"` evaluate slightly differently. To make this worse, the data we actually //store// is of the third class of function (just the "derivative" of the line chart), then we accumulate it in the application after we pull it out of the database. So the code will need to know that `subtract "derivative of all tasks" "derivative of closed tasks"` is meaningless, or the UI needs to make that clear, or it needs to interpret it to mean "accumulate the derivative into a line first". Anyway, I'll sort that out in future changes. For now, simplify the easy case of functions in class (1), where they're just actual functions. Add "shift(function, number)" and "scale(function, number)". These are probably like "mul" and "add" but they can't take two functions -- the second value must always be a constant. Maybe these will go away in the future and become `add(function, constant(3))` or something? Test Plan: {F6382885} Reviewers: amckinley Reviewed By: amckinley Subscribers: yelirekim Maniphest Tasks: T13279 Differential Revision: https://secure.phabricator.com/D20446
This commit is contained in:
parent
edaf17f3fe
commit
70c643c685
11 changed files with 251 additions and 53 deletions
|
@ -2817,6 +2817,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorCoreCreateTransaction' => 'applications/transactions/xaction/PhabricatorCoreCreateTransaction.php',
|
'PhabricatorCoreCreateTransaction' => 'applications/transactions/xaction/PhabricatorCoreCreateTransaction.php',
|
||||||
'PhabricatorCoreTransactionType' => 'applications/transactions/xaction/PhabricatorCoreTransactionType.php',
|
'PhabricatorCoreTransactionType' => 'applications/transactions/xaction/PhabricatorCoreTransactionType.php',
|
||||||
'PhabricatorCoreVoidTransaction' => 'applications/transactions/xaction/PhabricatorCoreVoidTransaction.php',
|
'PhabricatorCoreVoidTransaction' => 'applications/transactions/xaction/PhabricatorCoreVoidTransaction.php',
|
||||||
|
'PhabricatorCosChartFunction' => 'applications/fact/chart/PhabricatorCosChartFunction.php',
|
||||||
'PhabricatorCountFact' => 'applications/fact/fact/PhabricatorCountFact.php',
|
'PhabricatorCountFact' => 'applications/fact/fact/PhabricatorCountFact.php',
|
||||||
'PhabricatorCountdown' => 'applications/countdown/storage/PhabricatorCountdown.php',
|
'PhabricatorCountdown' => 'applications/countdown/storage/PhabricatorCountdown.php',
|
||||||
'PhabricatorCountdownApplication' => 'applications/countdown/application/PhabricatorCountdownApplication.php',
|
'PhabricatorCountdownApplication' => 'applications/countdown/application/PhabricatorCountdownApplication.php',
|
||||||
|
@ -4475,6 +4476,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSSHWorkflow' => 'infrastructure/ssh/PhabricatorSSHWorkflow.php',
|
'PhabricatorSSHWorkflow' => 'infrastructure/ssh/PhabricatorSSHWorkflow.php',
|
||||||
'PhabricatorSavedQuery' => 'applications/search/storage/PhabricatorSavedQuery.php',
|
'PhabricatorSavedQuery' => 'applications/search/storage/PhabricatorSavedQuery.php',
|
||||||
'PhabricatorSavedQueryQuery' => 'applications/search/query/PhabricatorSavedQueryQuery.php',
|
'PhabricatorSavedQueryQuery' => 'applications/search/query/PhabricatorSavedQueryQuery.php',
|
||||||
|
'PhabricatorScaleChartFunction' => 'applications/fact/chart/PhabricatorScaleChartFunction.php',
|
||||||
'PhabricatorScheduleTaskTriggerAction' => 'infrastructure/daemon/workers/action/PhabricatorScheduleTaskTriggerAction.php',
|
'PhabricatorScheduleTaskTriggerAction' => 'infrastructure/daemon/workers/action/PhabricatorScheduleTaskTriggerAction.php',
|
||||||
'PhabricatorScopedEnv' => 'infrastructure/env/PhabricatorScopedEnv.php',
|
'PhabricatorScopedEnv' => 'infrastructure/env/PhabricatorScopedEnv.php',
|
||||||
'PhabricatorSearchAbstractDocument' => 'applications/search/index/PhabricatorSearchAbstractDocument.php',
|
'PhabricatorSearchAbstractDocument' => 'applications/search/index/PhabricatorSearchAbstractDocument.php',
|
||||||
|
@ -4564,6 +4566,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php',
|
'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php',
|
||||||
'PhabricatorSetupIssueUIExample' => 'applications/uiexample/examples/PhabricatorSetupIssueUIExample.php',
|
'PhabricatorSetupIssueUIExample' => 'applications/uiexample/examples/PhabricatorSetupIssueUIExample.php',
|
||||||
'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
|
'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
|
||||||
|
'PhabricatorShiftChartFunction' => 'applications/fact/chart/PhabricatorShiftChartFunction.php',
|
||||||
'PhabricatorShortSite' => 'aphront/site/PhabricatorShortSite.php',
|
'PhabricatorShortSite' => 'aphront/site/PhabricatorShortSite.php',
|
||||||
'PhabricatorShowFiletreeSetting' => 'applications/settings/setting/PhabricatorShowFiletreeSetting.php',
|
'PhabricatorShowFiletreeSetting' => 'applications/settings/setting/PhabricatorShowFiletreeSetting.php',
|
||||||
'PhabricatorSimpleEditType' => 'applications/transactions/edittype/PhabricatorSimpleEditType.php',
|
'PhabricatorSimpleEditType' => 'applications/transactions/edittype/PhabricatorSimpleEditType.php',
|
||||||
|
@ -8811,6 +8814,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorCoreCreateTransaction' => 'PhabricatorCoreTransactionType',
|
'PhabricatorCoreCreateTransaction' => 'PhabricatorCoreTransactionType',
|
||||||
'PhabricatorCoreTransactionType' => 'PhabricatorModularTransactionType',
|
'PhabricatorCoreTransactionType' => 'PhabricatorModularTransactionType',
|
||||||
'PhabricatorCoreVoidTransaction' => 'PhabricatorModularTransactionType',
|
'PhabricatorCoreVoidTransaction' => 'PhabricatorModularTransactionType',
|
||||||
|
'PhabricatorCosChartFunction' => 'PhabricatorChartFunction',
|
||||||
'PhabricatorCountFact' => 'PhabricatorFact',
|
'PhabricatorCountFact' => 'PhabricatorFact',
|
||||||
'PhabricatorCountdown' => array(
|
'PhabricatorCountdown' => array(
|
||||||
'PhabricatorCountdownDAO',
|
'PhabricatorCountdownDAO',
|
||||||
|
@ -10775,6 +10779,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
),
|
),
|
||||||
'PhabricatorSavedQueryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorSavedQueryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
|
'PhabricatorScaleChartFunction' => 'PhabricatorChartFunction',
|
||||||
'PhabricatorScheduleTaskTriggerAction' => 'PhabricatorTriggerAction',
|
'PhabricatorScheduleTaskTriggerAction' => 'PhabricatorTriggerAction',
|
||||||
'PhabricatorScopedEnv' => 'Phobject',
|
'PhabricatorScopedEnv' => 'Phobject',
|
||||||
'PhabricatorSearchAbstractDocument' => 'Phobject',
|
'PhabricatorSearchAbstractDocument' => 'Phobject',
|
||||||
|
@ -10864,6 +10869,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSetupIssue' => 'Phobject',
|
'PhabricatorSetupIssue' => 'Phobject',
|
||||||
'PhabricatorSetupIssueUIExample' => 'PhabricatorUIExample',
|
'PhabricatorSetupIssueUIExample' => 'PhabricatorUIExample',
|
||||||
'PhabricatorSetupIssueView' => 'AphrontView',
|
'PhabricatorSetupIssueView' => 'AphrontView',
|
||||||
|
'PhabricatorShiftChartFunction' => 'PhabricatorChartFunction',
|
||||||
'PhabricatorShortSite' => 'PhabricatorSite',
|
'PhabricatorShortSite' => 'PhabricatorSite',
|
||||||
'PhabricatorShowFiletreeSetting' => 'PhabricatorSelectSetting',
|
'PhabricatorShowFiletreeSetting' => 'PhabricatorSelectSetting',
|
||||||
'PhabricatorSimpleEditType' => 'PhabricatorEditType',
|
'PhabricatorSimpleEditType' => 'PhabricatorEditType',
|
||||||
|
|
|
@ -5,9 +5,9 @@ abstract class PhabricatorChartFunction
|
||||||
|
|
||||||
private $xAxis;
|
private $xAxis;
|
||||||
private $yAxis;
|
private $yAxis;
|
||||||
private $limit;
|
|
||||||
|
|
||||||
private $argumentParser;
|
private $argumentParser;
|
||||||
|
private $sourceFunction;
|
||||||
|
|
||||||
final public function getFunctionKey() {
|
final public function getFunctionKey() {
|
||||||
return $this->getPhobjectClassConstant('FUNCTIONKEY', 32);
|
return $this->getPhobjectClassConstant('FUNCTIONKEY', 32);
|
||||||
|
@ -44,6 +44,12 @@ abstract class PhabricatorChartFunction
|
||||||
$parser->setHaveAllArguments(true);
|
$parser->setHaveAllArguments(true);
|
||||||
$parser->parseArguments();
|
$parser->parseArguments();
|
||||||
|
|
||||||
|
$source_argument = $parser->getSourceFunctionArgument();
|
||||||
|
if ($source_argument) {
|
||||||
|
$source_function = $this->getArgument($source_argument->getName());
|
||||||
|
$this->setSourceFunction($source_function);
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +77,15 @@ abstract class PhabricatorChartFunction
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function setSourceFunction(PhabricatorChartFunction $source) {
|
||||||
|
$this->sourceFunction = $source;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getSourceFunction() {
|
||||||
|
return $this->sourceFunction;
|
||||||
|
}
|
||||||
|
|
||||||
final public function setXAxis(PhabricatorChartAxis $x_axis) {
|
final public function setXAxis(PhabricatorChartAxis $x_axis) {
|
||||||
$this->xAxis = $x_axis;
|
$this->xAxis = $x_axis;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -89,6 +104,67 @@ abstract class PhabricatorChartFunction
|
||||||
return $this->yAxis;
|
return $this->yAxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function canEvaluateFunction() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function evaluateFunction($x) {
|
||||||
|
throw new PhutilMethodNotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasDomain() {
|
||||||
|
if ($this->canEvaluateFunction()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PhutilMethodNotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDatapoints(PhabricatorChartDataQuery $query) {
|
||||||
|
if ($this->canEvaluateFunction()) {
|
||||||
|
$points = $this->newSourceDatapoints($query);
|
||||||
|
foreach ($points as $key => $point) {
|
||||||
|
$y = $point['y'];
|
||||||
|
$y = $this->evaluateFunction($y);
|
||||||
|
$points[$key]['y'] = $y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $points;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->newDatapoints($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newDatapoints(PhabricatorChartDataQuery $query) {
|
||||||
|
throw new PhutilMethodNotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newSourceDatapoints(PhabricatorChartDataQuery $query) {
|
||||||
|
$source = $this->getSourceFunction();
|
||||||
|
if ($source) {
|
||||||
|
return $source->getDatapoints($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->newDefaultDatapoints($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newDefaultDatapoints(PhabricatorChartDataQuery $query) {
|
||||||
|
$x_min = $query->getMinimumValue();
|
||||||
|
$x_max = $query->getMaximumValue();
|
||||||
|
$limit = $query->getLimit();
|
||||||
|
|
||||||
|
$points = array();
|
||||||
|
$steps = $this->newLinearSteps($x_min, $x_max, $limit);
|
||||||
|
foreach ($steps as $step) {
|
||||||
|
$points[] = array(
|
||||||
|
'x' => $step,
|
||||||
|
'y' => $step,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $points;
|
||||||
|
}
|
||||||
|
|
||||||
protected function newLinearSteps($src, $dst, $count) {
|
protected function newLinearSteps($src, $dst, $count) {
|
||||||
$count = (int)$count;
|
$count = (int)$count;
|
||||||
$src = (int)$src;
|
$src = (int)$src;
|
||||||
|
|
|
@ -5,6 +5,7 @@ final class PhabricatorChartFunctionArgument
|
||||||
|
|
||||||
private $name;
|
private $name;
|
||||||
private $type;
|
private $type;
|
||||||
|
private $isSourceFunction;
|
||||||
|
|
||||||
public function setName($name) {
|
public function setName($name) {
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
|
@ -39,6 +40,15 @@ final class PhabricatorChartFunctionArgument
|
||||||
return $this->type;
|
return $this->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setIsSourceFunction($is_source_function) {
|
||||||
|
$this->isSourceFunction = $is_source_function;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIsSourceFunction() {
|
||||||
|
return $this->isSourceFunction;
|
||||||
|
}
|
||||||
|
|
||||||
public function newValue($value) {
|
public function newValue($value) {
|
||||||
switch ($this->getType()) {
|
switch ($this->getType()) {
|
||||||
case 'fact-key':
|
case 'fact-key':
|
||||||
|
|
|
@ -151,4 +151,43 @@ final class PhabricatorChartFunctionArgumentParser
|
||||||
implode(', ', $argument_list));
|
implode(', ', $argument_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSourceFunctionArgument() {
|
||||||
|
$required_type = 'function';
|
||||||
|
|
||||||
|
$sources = array();
|
||||||
|
foreach ($this->argumentMap as $key => $argument) {
|
||||||
|
if (!$argument->getIsSourceFunction()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($argument->getType() !== $required_type) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Function "%s" defines an argument "%s" which is marked as a '.
|
||||||
|
'source function, but the type of this argument is not "%s".',
|
||||||
|
$this->getFunctionArgumentSignature(),
|
||||||
|
$argument->getName(),
|
||||||
|
$required_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
$sources[$key] = $argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$sources) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($sources) > 1) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Function "%s" defines more than one argument as a source '.
|
||||||
|
'function (arguments: %s). Functions must have zero or one '.
|
||||||
|
'source function.',
|
||||||
|
$this->getFunctionArgumentSignature(),
|
||||||
|
implode(', ', array_keys($sources))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return head($sources);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,6 @@ final class PhabricatorConstantChartFunction
|
||||||
|
|
||||||
const FUNCTIONKEY = 'constant';
|
const FUNCTIONKEY = 'constant';
|
||||||
|
|
||||||
private $value;
|
|
||||||
|
|
||||||
protected function newArguments() {
|
protected function newArguments() {
|
||||||
return array(
|
return array(
|
||||||
$this->newArgument()
|
$this->newArgument()
|
||||||
|
@ -15,26 +13,12 @@ final class PhabricatorConstantChartFunction
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDatapoints(PhabricatorChartDataQuery $query) {
|
protected function canEvaluateFunction() {
|
||||||
$x_min = $query->getMinimumValue();
|
return true;
|
||||||
$x_max = $query->getMaximumValue();
|
|
||||||
|
|
||||||
$value = $this->getArgument('n');
|
|
||||||
|
|
||||||
$points = array();
|
|
||||||
$steps = $this->newLinearSteps($x_min, $x_max, 2);
|
|
||||||
foreach ($steps as $step) {
|
|
||||||
$points[] = array(
|
|
||||||
'x' => $step,
|
|
||||||
'y' => $value,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $points;
|
protected function evaluateFunction($x) {
|
||||||
}
|
return $this->getArgument('n');
|
||||||
|
|
||||||
public function hasDomain() {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
25
src/applications/fact/chart/PhabricatorCosChartFunction.php
Normal file
25
src/applications/fact/chart/PhabricatorCosChartFunction.php
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCosChartFunction
|
||||||
|
extends PhabricatorChartFunction {
|
||||||
|
|
||||||
|
const FUNCTIONKEY = 'cos';
|
||||||
|
|
||||||
|
protected function newArguments() {
|
||||||
|
return array(
|
||||||
|
$this->newArgument()
|
||||||
|
->setName('x')
|
||||||
|
->setType('function')
|
||||||
|
->setIsSourceFunction(true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function canEvaluateFunction() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function evaluateFunction($x) {
|
||||||
|
return cos(deg2rad($x));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorScaleChartFunction
|
||||||
|
extends PhabricatorChartFunction {
|
||||||
|
|
||||||
|
const FUNCTIONKEY = 'scale';
|
||||||
|
|
||||||
|
protected function newArguments() {
|
||||||
|
return array(
|
||||||
|
$this->newArgument()
|
||||||
|
->setName('x')
|
||||||
|
->setType('function')
|
||||||
|
->setIsSourceFunction(true),
|
||||||
|
$this->newArgument()
|
||||||
|
->setName('scale')
|
||||||
|
->setType('number'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function canEvaluateFunction() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function evaluateFunction($x) {
|
||||||
|
return $x * $this->getArgument('scale');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorShiftChartFunction
|
||||||
|
extends PhabricatorChartFunction {
|
||||||
|
|
||||||
|
const FUNCTIONKEY = 'shift';
|
||||||
|
|
||||||
|
protected function newArguments() {
|
||||||
|
return array(
|
||||||
|
$this->newArgument()
|
||||||
|
->setName('x')
|
||||||
|
->setType('function')
|
||||||
|
->setIsSourceFunction(true),
|
||||||
|
$this->newArgument()
|
||||||
|
->setName('shift')
|
||||||
|
->setType('number'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function canEvaluateFunction() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function evaluateFunction($x) {
|
||||||
|
return $x * $this->getArgument('shift');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,26 +9,17 @@ final class PhabricatorSinChartFunction
|
||||||
return array(
|
return array(
|
||||||
$this->newArgument()
|
$this->newArgument()
|
||||||
->setName('x')
|
->setName('x')
|
||||||
->setType('function'),
|
->setType('function')
|
||||||
|
->setIsSourceFunction(true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function assignArguments(array $arguments) {
|
protected function canEvaluateFunction() {
|
||||||
$this->argument = $arguments[0];
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDatapoints(PhabricatorChartDataQuery $query) {
|
protected function evaluateFunction($x) {
|
||||||
$points = $this->getArgument('x')->getDatapoints($query);
|
return sin(deg2rad($x));
|
||||||
|
|
||||||
foreach ($points as $key => $point) {
|
|
||||||
$points[$key]['y'] = sin(deg2rad($points[$key]['y']));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $points;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hasDomain() {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,25 +9,12 @@ final class PhabricatorXChartFunction
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDatapoints(PhabricatorChartDataQuery $query) {
|
protected function canEvaluateFunction() {
|
||||||
$x_min = $query->getMinimumValue();
|
return true;
|
||||||
$x_max = $query->getMaximumValue();
|
|
||||||
$limit = $query->getLimit();
|
|
||||||
|
|
||||||
$points = array();
|
|
||||||
$steps = $this->newLinearSteps($x_min, $x_max, $limit);
|
|
||||||
foreach ($steps as $step) {
|
|
||||||
$points[] = array(
|
|
||||||
'x' => $step,
|
|
||||||
'y' => $step,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $points;
|
protected function evaluateFunction($x) {
|
||||||
}
|
return $x;
|
||||||
|
|
||||||
public function hasDomain() {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,27 @@ final class PhabricatorFactChartController extends PhabricatorFactController {
|
||||||
$functions[] = id(new PhabricatorSinChartFunction())
|
$functions[] = id(new PhabricatorSinChartFunction())
|
||||||
->setArguments(array($x_function));
|
->setArguments(array($x_function));
|
||||||
|
|
||||||
|
$cos_function = id(new PhabricatorCosChartFunction())
|
||||||
|
->setArguments(array($x_function));
|
||||||
|
|
||||||
|
$functions[] = id(new PhabricatorShiftChartFunction())
|
||||||
|
->setArguments(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'scale',
|
||||||
|
array(
|
||||||
|
'cos',
|
||||||
|
array(
|
||||||
|
'scale',
|
||||||
|
array('x'),
|
||||||
|
0.001,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
10,
|
||||||
|
),
|
||||||
|
200,
|
||||||
|
));
|
||||||
|
|
||||||
list($domain_min, $domain_max) = $this->getDomain($functions);
|
list($domain_min, $domain_max) = $this->getDomain($functions);
|
||||||
|
|
||||||
$axis = id(new PhabricatorChartAxis())
|
$axis = id(new PhabricatorChartAxis())
|
||||||
|
@ -83,6 +104,9 @@ final class PhabricatorFactChartController extends PhabricatorFactController {
|
||||||
'yMax' => $y_max,
|
'yMax' => $y_max,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: Move this back up, it's just down here for now to make
|
||||||
|
// debugging easier so the main page throws a more visible exception when
|
||||||
|
// something goes wrong.
|
||||||
if ($is_chart_mode) {
|
if ($is_chart_mode) {
|
||||||
return $this->newChartResponse();
|
return $this->newChartResponse();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue