diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -3622,6 +3622,7 @@ 'PhabricatorMarkupInterface' => 'infrastructure/markup/PhabricatorMarkupInterface.php', 'PhabricatorMarkupOneOff' => 'infrastructure/markup/PhabricatorMarkupOneOff.php', 'PhabricatorMarkupPreviewController' => 'infrastructure/markup/PhabricatorMarkupPreviewController.php', + 'PhabricatorMaxChartFunction' => 'applications/fact/chart/PhabricatorMaxChartFunction.php', 'PhabricatorMemeEngine' => 'applications/macro/engine/PhabricatorMemeEngine.php', 'PhabricatorMemeRemarkupRule' => 'applications/macro/markup/PhabricatorMemeRemarkupRule.php', 'PhabricatorMentionRemarkupRule' => 'applications/people/markup/PhabricatorMentionRemarkupRule.php', @@ -3676,6 +3677,7 @@ 'PhabricatorMetronome' => 'infrastructure/util/PhabricatorMetronome.php', 'PhabricatorMetronomeTestCase' => 'infrastructure/util/__tests__/PhabricatorMetronomeTestCase.php', 'PhabricatorMetronomicTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorMetronomicTriggerClock.php', + 'PhabricatorMinChartFunction' => 'applications/fact/chart/PhabricatorMinChartFunction.php', 'PhabricatorModularTransaction' => 'applications/transactions/storage/PhabricatorModularTransaction.php', 'PhabricatorModularTransactionType' => 'applications/transactions/storage/PhabricatorModularTransactionType.php', 'PhabricatorMonogramDatasourceEngineExtension' => 'applications/typeahead/engineextension/PhabricatorMonogramDatasourceEngineExtension.php', @@ -9748,6 +9750,7 @@ 'PhabricatorMarkupInterface', ), 'PhabricatorMarkupPreviewController' => 'PhabricatorController', + 'PhabricatorMaxChartFunction' => 'PhabricatorChartFunction', 'PhabricatorMemeEngine' => 'Phobject', 'PhabricatorMemeRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorMentionRemarkupRule' => 'PhutilRemarkupRule', @@ -9814,6 +9817,7 @@ 'PhabricatorMetronome' => 'Phobject', 'PhabricatorMetronomeTestCase' => 'PhabricatorTestCase', 'PhabricatorMetronomicTriggerClock' => 'PhabricatorTriggerClock', + 'PhabricatorMinChartFunction' => 'PhabricatorChartFunction', 'PhabricatorModularTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorModularTransactionType' => 'Phobject', 'PhabricatorMonogramDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension', diff --git a/src/applications/fact/chart/PhabricatorChartStackedAreaDataset.php b/src/applications/fact/chart/PhabricatorChartStackedAreaDataset.php --- a/src/applications/fact/chart/PhabricatorChartStackedAreaDataset.php +++ b/src/applications/fact/chart/PhabricatorChartStackedAreaDataset.php @@ -9,8 +9,10 @@ PhabricatorChartDataQuery $data_query) { $functions = $this->getFunctions(); + $reversed_functions = array_reverse($functions, true); + $function_points = array(); - foreach ($functions as $function_idx => $function) { + foreach ($reversed_functions as $function_idx => $function) { $function_points[$function_idx] = array(); $datapoints = $function->newDatapoints($data_query); @@ -36,7 +38,7 @@ } ksort($must_define); - foreach ($functions as $function_idx => $function) { + foreach ($reversed_functions as $function_idx => $function) { $missing = array(); foreach ($must_define as $x) { if (!isset($function_points[$function_idx][$x])) { @@ -136,6 +138,8 @@ $series[] = $bounds; } + $series = array_reverse($series); + $events = array(); foreach ($raw_points as $function_idx => $points) { $event_list = array(); diff --git a/src/applications/fact/chart/PhabricatorMaxChartFunction.php b/src/applications/fact/chart/PhabricatorMaxChartFunction.php new file mode 100644 --- /dev/null +++ b/src/applications/fact/chart/PhabricatorMaxChartFunction.php @@ -0,0 +1,40 @@ +newArgument() + ->setName('x') + ->setType('function'), + $this->newArgument() + ->setName('max') + ->setType('number'), + ); + } + + public function getDomain() { + return $this->getArgument('x')->getDomain(); + } + + public function newInputValues(PhabricatorChartDataQuery $query) { + return $this->getArgument('x')->newInputValues($query); + } + + public function evaluateFunction(array $xv) { + $yv = $this->getArgument('x')->evaluateFunction($xv); + $max = $this->getArgument('max'); + + foreach ($yv as $k => $y) { + if ($y > $max) { + $yv[$k] = null; + } + } + + return $yv; + } + +} diff --git a/src/applications/fact/chart/PhabricatorMinChartFunction.php b/src/applications/fact/chart/PhabricatorMinChartFunction.php new file mode 100644 --- /dev/null +++ b/src/applications/fact/chart/PhabricatorMinChartFunction.php @@ -0,0 +1,40 @@ +newArgument() + ->setName('x') + ->setType('function'), + $this->newArgument() + ->setName('min') + ->setType('number'), + ); + } + + public function getDomain() { + return $this->getArgument('x')->getDomain(); + } + + public function newInputValues(PhabricatorChartDataQuery $query) { + return $this->getArgument('x')->newInputValues($query); + } + + public function evaluateFunction(array $xv) { + $yv = $this->getArgument('x')->evaluateFunction($xv); + $min = $this->getArgument('min'); + + foreach ($yv as $k => $y) { + if ($y < $min) { + $yv[$k] = null; + } + } + + return $yv; + } + +} diff --git a/src/applications/fact/daemon/PhabricatorFactDaemon.php b/src/applications/fact/daemon/PhabricatorFactDaemon.php --- a/src/applications/fact/daemon/PhabricatorFactDaemon.php +++ b/src/applications/fact/daemon/PhabricatorFactDaemon.php @@ -15,7 +15,7 @@ } $this->log(pht('Zzz...')); - $this->sleep(60 * 5); + $this->sleep(15); } } diff --git a/src/applications/project/chart/PhabricatorProjectBurndownChartEngine.php b/src/applications/project/chart/PhabricatorProjectBurndownChartEngine.php --- a/src/applications/project/chart/PhabricatorProjectBurndownChartEngine.php +++ b/src/applications/project/chart/PhabricatorProjectBurndownChartEngine.php @@ -32,37 +32,62 @@ if ($project_phids) { foreach ($project_phids as $project_phid) { $function = $this->newFunction( - 'accumulate', - array('fact', 'tasks.open-count.create.project', $project_phid)); + 'min', + array( + 'accumulate', + array('fact', 'tasks.open-count.assign.project', $project_phid), + ), + 0); $function->getFunctionLabel() - ->setName(pht('Tasks Created')) - ->setColor('rgba(0, 0, 200, 1)') - ->setFillColor('rgba(0, 0, 200, 0.15)'); + ->setName(pht('Tasks Moved Into Project')) + ->setColor('rgba(0, 200, 200, 1)') + ->setFillColor('rgba(0, 200, 200, 0.15)'); $functions[] = $function; - $function = $this->newFunction( - 'accumulate', - array('fact', 'tasks.open-count.status.project', $project_phid)); + 'min', + array( + 'accumulate', + array('fact', 'tasks.open-count.status.project', $project_phid), + ), + 0); $function->getFunctionLabel() - ->setName(pht('Tasks Closed / Reopened')) + ->setName(pht('Tasks Reopened')) ->setColor('rgba(200, 0, 200, 1)') ->setFillColor('rgba(200, 0, 200, 0.15)'); $functions[] = $function; - $function = $this->newFunction( - 'accumulate', - array('fact', 'tasks.open-count.assign.project', $project_phid)); + 'sum', + array( + 'accumulate', + array('fact', 'tasks.open-count.create.project', $project_phid), + ), + array( + 'max', + array( + 'accumulate', + array('fact', 'tasks.open-count.status.project', $project_phid), + ), + 0, + ), + array( + 'max', + array( + 'accumulate', + array('fact', 'tasks.open-count.assign.project', $project_phid), + ), + 0, + )); $function->getFunctionLabel() - ->setName(pht('Tasks Rescoped')) - ->setColor('rgba(0, 200, 200, 1)') - ->setFillColor('rgba(0, 200, 200, 0.15)'); + ->setName(pht('Tasks Created')) + ->setColor('rgba(0, 0, 200, 1)') + ->setFillColor('rgba(0, 0, 200, 0.15)'); $functions[] = $function; }