From d8dba26a08f4664081aba129d4f71cfc420b7093 Mon Sep 17 00:00:00 2001 From: epriestley <git@epriestley.com> Date: Wed, 17 Apr 2019 07:17:28 -0700 Subject: [PATCH] Add a "sin()" function to charts Summary: Depends on D20443. Ref T13279. This is probably not terribly useful on its own, but is mostly a function which takes another function as an argument, and a step toward more useful functions like arithmetic and drawing a picture of an owl. The only structural change here is that functions now read data parameters (domain, sample limit) using a more tailored "ChartDataQuery" instead of reading the actual axis. Mostly, I want a more cohesive representation of query state that can be easily passed to sub-functions, as here. Test Plan: {F6382432} Reviewers: amckinley Reviewed By: amckinley Subscribers: yelirekim Maniphest Tasks: T13279 Differential Revision: https://secure.phabricator.com/D20444 --- src/__phutil_library_map__.php | 4 ++ .../fact/chart/PhabricatorChartDataQuery.php | 37 ++++++++++++++++ .../PhabricatorConstantChartFunction.php | 7 ++- .../chart/PhabricatorFactChartFunction.php | 26 ++++++----- .../chart/PhabricatorSinChartFunction.php | 44 +++++++++++++++++++ .../fact/chart/PhabricatorXChartFunction.php | 8 ++-- .../PhabricatorFactChartController.php | 15 ++++--- 7 files changed, 116 insertions(+), 25 deletions(-) create mode 100644 src/applications/fact/chart/PhabricatorChartDataQuery.php create mode 100644 src/applications/fact/chart/PhabricatorSinChartFunction.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 2ceb024377..f27f81b13d 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2650,6 +2650,7 @@ phutil_register_library_map(array( 'PhabricatorChangesetCachePurger' => 'applications/cache/purger/PhabricatorChangesetCachePurger.php', 'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php', 'PhabricatorChartAxis' => 'applications/fact/chart/PhabricatorChartAxis.php', + 'PhabricatorChartDataQuery' => 'applications/fact/chart/PhabricatorChartDataQuery.php', 'PhabricatorChartFunction' => 'applications/fact/chart/PhabricatorChartFunction.php', 'PhabricatorChatLogApplication' => 'applications/chatlog/application/PhabricatorChatLogApplication.php', 'PhabricatorChatLogChannel' => 'applications/chatlog/storage/PhabricatorChatLogChannel.php', @@ -4564,6 +4565,7 @@ phutil_register_library_map(array( 'PhabricatorShortSite' => 'aphront/site/PhabricatorShortSite.php', 'PhabricatorShowFiletreeSetting' => 'applications/settings/setting/PhabricatorShowFiletreeSetting.php', 'PhabricatorSimpleEditType' => 'applications/transactions/edittype/PhabricatorSimpleEditType.php', + 'PhabricatorSinChartFunction' => 'applications/fact/chart/PhabricatorSinChartFunction.php', 'PhabricatorSite' => 'aphront/site/PhabricatorSite.php', 'PhabricatorSlackAuthProvider' => 'applications/auth/provider/PhabricatorSlackAuthProvider.php', 'PhabricatorSlowvoteApplication' => 'applications/slowvote/application/PhabricatorSlowvoteApplication.php', @@ -8625,6 +8627,7 @@ phutil_register_library_map(array( 'PhabricatorChangesetCachePurger' => 'PhabricatorCachePurger', 'PhabricatorChangesetResponse' => 'AphrontProxyResponse', 'PhabricatorChartAxis' => 'Phobject', + 'PhabricatorChartDataQuery' => 'Phobject', 'PhabricatorChartFunction' => 'Phobject', 'PhabricatorChatLogApplication' => 'PhabricatorApplication', 'PhabricatorChatLogChannel' => array( @@ -10860,6 +10863,7 @@ phutil_register_library_map(array( 'PhabricatorShortSite' => 'PhabricatorSite', 'PhabricatorShowFiletreeSetting' => 'PhabricatorSelectSetting', 'PhabricatorSimpleEditType' => 'PhabricatorEditType', + 'PhabricatorSinChartFunction' => 'PhabricatorChartFunction', 'PhabricatorSite' => 'AphrontSite', 'PhabricatorSlackAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorSlowvoteApplication' => 'PhabricatorApplication', diff --git a/src/applications/fact/chart/PhabricatorChartDataQuery.php b/src/applications/fact/chart/PhabricatorChartDataQuery.php new file mode 100644 index 0000000000..15708341f7 --- /dev/null +++ b/src/applications/fact/chart/PhabricatorChartDataQuery.php @@ -0,0 +1,37 @@ +<?php + +final class PhabricatorChartDataQuery + extends Phobject { + + private $limit; + private $minimumValue; + private $maximumValue; + + public function setMinimumValue($minimum_value) { + $this->minimumValue = $minimum_value; + return $this; + } + + public function getMinimumValue() { + return $this->minimumValue; + } + + public function setMaximumValue($maximum_value) { + $this->maximumValue = $maximum_value; + return $this; + } + + public function getMaximumValue() { + return $this->maximumValue; + } + + public function setLimit($limit) { + $this->limit = $limit; + return $this; + } + + public function getLimit() { + return $this->limit; + } + +} diff --git a/src/applications/fact/chart/PhabricatorConstantChartFunction.php b/src/applications/fact/chart/PhabricatorConstantChartFunction.php index f170491bce..b5dc334dd8 100644 --- a/src/applications/fact/chart/PhabricatorConstantChartFunction.php +++ b/src/applications/fact/chart/PhabricatorConstantChartFunction.php @@ -27,10 +27,9 @@ final class PhabricatorConstantChartFunction $this->value = $arguments[0]; } - public function getDatapoints($limit) { - $axis = $this->getXAxis(); - $x_min = $axis->getMinimumValue(); - $x_max = $axis->getMaximumValue(); + public function getDatapoints(PhabricatorChartDataQuery $query) { + $x_min = $query->getMinimumValue(); + $x_max = $query->getMaximumValue(); $points = array(); $steps = $this->newLinearSteps($x_min, $x_max, 2); diff --git a/src/applications/fact/chart/PhabricatorFactChartFunction.php b/src/applications/fact/chart/PhabricatorFactChartFunction.php index 0ae1548c91..fbeec9c81b 100644 --- a/src/applications/fact/chart/PhabricatorFactChartFunction.php +++ b/src/applications/fact/chart/PhabricatorFactChartFunction.php @@ -77,15 +77,15 @@ final class PhabricatorFactChartFunction $this->datapoints = $points; } - public function getDatapoints($limit) { + public function getDatapoints(PhabricatorChartDataQuery $query) { $points = $this->datapoints; if (!$points) { return array(); } - $axis = $this->getXAxis(); - $x_min = $axis->getMinimumValue(); - $x_max = $axis->getMaximumValue(); + $x_min = $query->getMinimumValue(); + $x_max = $query->getMaximumValue(); + $limit = $query->getLimit(); if ($x_min !== null) { foreach ($points as $key => $point) { @@ -104,14 +104,16 @@ final class PhabricatorFactChartFunction } // If we have too many data points, throw away some of the data. - $count = count($points); - if ($count > $limit) { - $ii = 0; - $every = ceil($count / $limit); - foreach ($points as $key => $point) { - $ii++; - if (($ii % $every) && ($ii != $count)) { - unset($points[$key]); + if ($limit !== null) { + $count = count($points); + if ($count > $limit) { + $ii = 0; + $every = ceil($count / $limit); + foreach ($points as $key => $point) { + $ii++; + if (($ii % $every) && ($ii != $count)) { + unset($points[$key]); + } } } } diff --git a/src/applications/fact/chart/PhabricatorSinChartFunction.php b/src/applications/fact/chart/PhabricatorSinChartFunction.php new file mode 100644 index 0000000000..876a153a59 --- /dev/null +++ b/src/applications/fact/chart/PhabricatorSinChartFunction.php @@ -0,0 +1,44 @@ +<?php + +final class PhabricatorSinChartFunction + extends PhabricatorChartFunction { + + const FUNCTIONKEY = 'sin'; + + private $argument; + + protected function newArguments(array $arguments) { + if (count($arguments) !== 1) { + throw new Exception( + pht( + 'Chart function "sin(..)" expects one argument, got %s.', + count($arguments))); + } + + $argument = $arguments[0]; + + if (!($argument instanceof PhabricatorChartFunction)) { + throw new Exception( + pht( + 'Argument to chart function should be a function, got %s.', + phutil_describe_type($argument))); + } + + $this->argument = $argument; + } + + public function getDatapoints(PhabricatorChartDataQuery $query) { + $points = $this->argument->getDatapoints($query); + + foreach ($points as $key => $point) { + $points[$key]['y'] = sin(deg2rad($points[$key]['y'])); + } + + return $points; + } + + public function hasDomain() { + return false; + } + +} diff --git a/src/applications/fact/chart/PhabricatorXChartFunction.php b/src/applications/fact/chart/PhabricatorXChartFunction.php index 05c5bf7040..6e2eae9535 100644 --- a/src/applications/fact/chart/PhabricatorXChartFunction.php +++ b/src/applications/fact/chart/PhabricatorXChartFunction.php @@ -14,10 +14,10 @@ final class PhabricatorXChartFunction } } - public function getDatapoints($limit) { - $axis = $this->getXAxis(); - $x_min = $axis->getMinimumValue(); - $x_max = $axis->getMaximumValue(); + public function getDatapoints(PhabricatorChartDataQuery $query) { + $x_min = $query->getMinimumValue(); + $x_max = $query->getMaximumValue(); + $limit = $query->getLimit(); $points = array(); $steps = $this->newLinearSteps($x_min, $x_max, $limit); diff --git a/src/applications/fact/controller/PhabricatorFactChartController.php b/src/applications/fact/controller/PhabricatorFactChartController.php index b7c3611e1f..9a5a492d21 100644 --- a/src/applications/fact/controller/PhabricatorFactChartController.php +++ b/src/applications/fact/controller/PhabricatorFactChartController.php @@ -20,25 +20,30 @@ final class PhabricatorFactChartController extends PhabricatorFactController { $functions[] = id(new PhabricatorFactChartFunction()) ->setArguments(array('tasks.open-count.create')); - $functions[] = id(new PhabricatorConstantChartFunction()) - ->setArguments(array(256)); - - $functions[] = id(new PhabricatorXChartFunction()) + $x_function = id(new PhabricatorXChartFunction()) ->setArguments(array()); + $functions[] = id(new PhabricatorSinChartFunction()) + ->setArguments(array($x_function)); + list($domain_min, $domain_max) = $this->getDomain($functions); $axis = id(new PhabricatorChartAxis()) ->setMinimumValue($domain_min) ->setMaximumValue($domain_max); + $data_query = id(new PhabricatorChartDataQuery()) + ->setMinimumValue($domain_min) + ->setMaximumValue($domain_max) + ->setLimit(2000); + $datasets = array(); foreach ($functions as $function) { $function->setXAxis($axis); $function->loadData(); - $points = $function->getDatapoints(2000); + $points = $function->getDatapoints($data_query); $x = array(); $y = array();