Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15457801
D20452.id48803.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
12 KB
Referenced Files
None
Subscribers
None
D20452.id48803.diff
View Options
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
@@ -2097,6 +2097,7 @@
'PhabricatorAccessLog' => 'infrastructure/log/PhabricatorAccessLog.php',
'PhabricatorAccessLogConfigOptions' => 'applications/config/option/PhabricatorAccessLogConfigOptions.php',
'PhabricatorAccessibilitySetting' => 'applications/settings/setting/PhabricatorAccessibilitySetting.php',
+ 'PhabricatorAccumulateChartFunction' => 'applications/fact/chart/PhabricatorAccumulateChartFunction.php',
'PhabricatorActionListView' => 'view/layout/PhabricatorActionListView.php',
'PhabricatorActionView' => 'view/layout/PhabricatorActionView.php',
'PhabricatorActivitySettingsPanel' => 'applications/settings/panel/PhabricatorActivitySettingsPanel.php',
@@ -7961,6 +7962,7 @@
'PhabricatorAccessLog' => 'Phobject',
'PhabricatorAccessLogConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorAccessibilitySetting' => 'PhabricatorSelectSetting',
+ 'PhabricatorAccumulateChartFunction' => 'PhabricatorChartFunction',
'PhabricatorActionListView' => 'AphrontTagView',
'PhabricatorActionView' => 'AphrontView',
'PhabricatorActivitySettingsPanel' => 'PhabricatorSettingsPanel',
diff --git a/src/applications/fact/chart/PhabricatorAccumulateChartFunction.php b/src/applications/fact/chart/PhabricatorAccumulateChartFunction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/fact/chart/PhabricatorAccumulateChartFunction.php
@@ -0,0 +1,37 @@
+<?php
+
+final class PhabricatorAccumulateChartFunction
+ extends PhabricatorChartFunction {
+
+ const FUNCTIONKEY = 'accumulate';
+
+ protected function newArguments() {
+ return array(
+ $this->newArgument()
+ ->setName('x')
+ ->setType('function')
+ ->setFunctionType('impulse')
+ ->setIsSourceFunction(true),
+ );
+ }
+
+ protected function newDatapoints(PhabricatorChartDataQuery $query) {
+ $source_function = $this->getSourceFunction();
+
+ // Use an unconstrained query to pull all the data from the underlying
+ // source. We need to accumulate data since the beginning of time to
+ // figure out the right Y-intercept -- otherwise, we'll always start at
+ // "0" wherever our domain begins.
+ $empty_query = new PhabricatorChartDataQuery();
+ $points = $source_function->getDatapoints($empty_query);
+
+ $accumulator = 0;
+ foreach ($points as $key => $point) {
+ $accumulator += $point['y'];
+ $points[$key]['y'] = $accumulator;
+ }
+
+ return $query->selectDatapoints($points);
+ }
+
+}
diff --git a/src/applications/fact/chart/PhabricatorChartDataQuery.php b/src/applications/fact/chart/PhabricatorChartDataQuery.php
--- a/src/applications/fact/chart/PhabricatorChartDataQuery.php
+++ b/src/applications/fact/chart/PhabricatorChartDataQuery.php
@@ -34,4 +34,43 @@
return $this->limit;
}
+ public function selectDatapoints(array $points) {
+ $x_min = $this->getMinimumValue();
+ $x_max = $this->getMaximumValue();
+ $limit = $this->getLimit();
+
+ if ($x_min !== null) {
+ foreach ($points as $key => $point) {
+ if ($point['x'] < $x_min) {
+ unset($points[$key]);
+ }
+ }
+ }
+
+ if ($x_max !== null) {
+ foreach ($points as $key => $point) {
+ if ($point['x'] > $x_max) {
+ unset($points[$key]);
+ }
+ }
+ }
+
+ // If we have too many data points, throw away some of the data.
+ 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]);
+ }
+ }
+ }
+ }
+
+ return $points;
+ }
+
}
diff --git a/src/applications/fact/chart/PhabricatorChartFunction.php b/src/applications/fact/chart/PhabricatorChartFunction.php
--- a/src/applications/fact/chart/PhabricatorChartFunction.php
+++ b/src/applications/fact/chart/PhabricatorChartFunction.php
@@ -73,6 +73,27 @@
return $this->argumentParser;
}
+ public function selectAllFunctions() {
+ $result = array();
+ $result[] = $this;
+
+ $parser = $this->getArgumentParser();
+ foreach ($parser->getAllArguments() as $argument) {
+ if ($argument->getType() !== 'function') {
+ continue;
+ }
+
+ $name = $argument->getName();
+ $value = $this->getArgument($name);
+
+ foreach ($value->selectAllFunctions() as $subfunction) {
+ $result[] = $subfunction;
+ }
+ }
+
+ return $result;
+ }
+
public function loadData() {
return;
}
@@ -117,6 +138,34 @@
return false;
}
+ if ($this->isImpulseFunction()) {
+ return true;
+ }
+
+ $source_function = $this->getSourceFunction();
+ if ($source_function) {
+ return $source_function->hasDomain();
+ }
+
+ throw new PhutilMethodNotImplementedException();
+ }
+
+ public function isImpulseFunction() {
+ return false;
+ }
+
+ public function getDomain() {
+ // TODO: We can examine the data to fit a better domain.
+ if ($this->isImpulseFunction()) {
+ $now = PhabricatorTime::getNow();
+ return array($now - phutil_units('90 days in seconds'), $now);
+ }
+
+ $source_function = $this->getSourceFunction();
+ if ($source_function) {
+ return $source_function->getDomain();
+ }
+
throw new PhutilMethodNotImplementedException();
}
diff --git a/src/applications/fact/chart/PhabricatorChartFunctionArgument.php b/src/applications/fact/chart/PhabricatorChartFunctionArgument.php
--- a/src/applications/fact/chart/PhabricatorChartFunctionArgument.php
+++ b/src/applications/fact/chart/PhabricatorChartFunctionArgument.php
@@ -6,6 +6,7 @@
private $name;
private $type;
private $isSourceFunction;
+ private $functionType;
public function setName($name) {
$this->name = $name;
@@ -49,6 +50,15 @@
return $this->isSourceFunction;
}
+ public function setFunctionType($function_type) {
+ $this->functionType = $function_type;
+ return $this;
+ }
+
+ public function getFunctionType() {
+ return $this->functionType;
+ }
+
public function newValue($value) {
switch ($this->getType()) {
case 'fact-key':
@@ -119,8 +129,24 @@
implode(', ', array_keys($functions))));
}
- return id(clone $functions[$function_name])
+ $function = id(clone $functions[$function_name])
->setArguments($value);
+
+ switch ($this->getFunctionType()) {
+ case 'impulse':
+ if (!$function->isImpulseFunction()) {
+ throw new Exception(
+ pht(
+ 'Function must be an impulse function, but "%s" is not '.
+ 'an impulse function.',
+ $function_name));
+ }
+ break;
+ default:
+ break;
+ }
+
+ return $function;
case 'number':
if (!is_float($value) && !is_int($value)) {
throw new Exception(
diff --git a/src/applications/fact/chart/PhabricatorChartFunctionArgumentParser.php b/src/applications/fact/chart/PhabricatorChartFunctionArgumentParser.php
--- a/src/applications/fact/chart/PhabricatorChartFunctionArgumentParser.php
+++ b/src/applications/fact/chart/PhabricatorChartFunctionArgumentParser.php
@@ -72,6 +72,10 @@
return $this;
}
+ public function getAllArguments() {
+ return array_values($this->argumentMap);
+ }
+
public function parseArguments() {
$have_count = count($this->rawArguments);
$want_count = count($this->argumentMap);
diff --git a/src/applications/fact/chart/PhabricatorFactChartFunction.php b/src/applications/fact/chart/PhabricatorFactChartFunction.php
--- a/src/applications/fact/chart/PhabricatorFactChartFunction.php
+++ b/src/applications/fact/chart/PhabricatorFactChartFunction.php
@@ -22,6 +22,10 @@
return $fact->getFunctionArguments();
}
+ public function isImpulseFunction() {
+ return true;
+ }
+
public function loadData() {
$fact = $this->fact;
@@ -44,73 +48,32 @@
return;
}
- $points = array();
-
- $sum = 0;
- foreach ($data as $key => $row) {
- $sum += (int)$row['value'];
- $points[] = array(
- 'x' => (int)$row['epoch'],
- 'y' => $sum,
- );
- }
-
- $this->datapoints = $points;
- }
-
- public function getDatapoints(PhabricatorChartDataQuery $query) {
- $points = $this->datapoints;
- if (!$points) {
- return array();
- }
-
- $x_min = $query->getMinimumValue();
- $x_max = $query->getMaximumValue();
- $limit = $query->getLimit();
+ $map = array();
+ foreach ($data as $row) {
+ $value = (int)$row['value'];
+ $epoch = (int)$row['epoch'];
- if ($x_min !== null) {
- foreach ($points as $key => $point) {
- if ($point['x'] < $x_min) {
- unset($points[$key]);
- }
+ if (!isset($map[$epoch])) {
+ $map[$epoch] = 0;
}
- }
- if ($x_max !== null) {
- foreach ($points as $key => $point) {
- if ($point['x'] > $x_max) {
- unset($points[$key]);
- }
- }
+ $map[$epoch] += $value;
}
- // If we have too many data points, throw away some of the data.
- 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]);
- }
- }
- }
+ $points = array();
+ foreach ($map as $x => $y) {
+ $points[] = array(
+ 'x' => $x,
+ 'y' => $y,
+ );
}
- return $points;
+ $this->datapoints = $points;
}
- public function hasDomain() {
- return true;
+ protected function newDatapoints(PhabricatorChartDataQuery $query) {
+ return $query->selectDatapoints($this->datapoints);
}
- public function getDomain() {
- // TODO: We can examine the data to fit a better domain.
-
- $now = PhabricatorTime::getNow();
- return array($now - phutil_units('90 days in seconds'), $now);
- }
}
diff --git a/src/applications/fact/chart/PhabricatorShiftChartFunction.php b/src/applications/fact/chart/PhabricatorShiftChartFunction.php
--- a/src/applications/fact/chart/PhabricatorShiftChartFunction.php
+++ b/src/applications/fact/chart/PhabricatorShiftChartFunction.php
@@ -22,7 +22,7 @@
}
protected function evaluateFunction($x) {
- return $x * $this->getArgument('shift');
+ return $x + $this->getArgument('shift');
}
}
diff --git a/src/applications/fact/controller/PhabricatorFactChartController.php b/src/applications/fact/controller/PhabricatorFactChartController.php
--- a/src/applications/fact/controller/PhabricatorFactChartController.php
+++ b/src/applications/fact/controller/PhabricatorFactChartController.php
@@ -14,12 +14,6 @@
$functions = 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());
@@ -42,12 +36,21 @@
array(
'scale',
array('x'),
- 0.001,
+ 0.0001,
),
),
- 10,
+ 200,
+ ),
+ 75,
+ ));
+
+ $functions[] = id(new PhabricatorAccumulateChartFunction())
+ ->setArguments(
+ array(
+ array(
+ 'fact',
+ 'tasks.count.create',
),
- 200,
));
list($domain_min, $domain_max) = $this->getDomain($functions);
@@ -61,6 +64,12 @@
->setMaximumValue($domain_max)
->setLimit(2000);
+ foreach ($functions as $function) {
+ foreach ($function->selectAllFunctions() as $subfunction) {
+ $subfunction->loadData();
+ }
+ }
+
$datasets = array();
foreach ($functions as $function) {
$function->setXAxis($axis);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 31, 7:04 PM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7708937
Default Alt Text
D20452.id48803.diff (12 KB)
Attached To
Mode
D20452: Separate "accumulate(...)" from Fact functions
Attached
Detach File
Event Timeline
Log In to Comment