diff --git a/src/SOFe/Capital/AccountQueryMetric.php b/src/SOFe/Capital/AccountQueryMetric.php index 270f6b0..4a59e54 100644 --- a/src/SOFe/Capital/AccountQueryMetric.php +++ b/src/SOFe/Capital/AccountQueryMetric.php @@ -43,6 +43,10 @@ public function getLabelTable() : string { return "capital_acc_label"; } + public function getTimestampColumn() : string { + return "capital_acc.touch"; + } + public function getExpr() : string { return $this->expr; } diff --git a/src/SOFe/Capital/Analytics/Top/DatabaseUtils.php b/src/SOFe/Capital/Analytics/Top/DatabaseUtils.php index 95abc94..40ccfbb 100644 --- a/src/SOFe/Capital/Analytics/Top/DatabaseUtils.php +++ b/src/SOFe/Capital/Analytics/Top/DatabaseUtils.php @@ -226,12 +226,21 @@ public function compute(string $runId, QueryArgs $query) : Generator { $metricExpr .= " INNER JOIN $labelTable AS t{$i} USING (id)"; } - if (!$query->metric->usesIdOnly()) { - $metricExpr .= " INNER JOIN $mainTable USING (id)"; - } + $metricExpr .= " INNER JOIN $mainTable USING (id)"; $metricExpr .= " WHERE grouping_label.name = :groupingLabel AND grouping_label.value = capital_analytics_top_cache.group_value"; + if ($query->interval !== null) { + $tsColumn = $query->metric->getTimestampColumn(); + $timeDiffExpr = match ($this->db->dialect) { + SqlDialect::SQLITE => "JULIANDAY(CURRENT_TIMESTAMP) - JULIANDAY($tsColumn)", + SqlDialect::MYSQL => "TIMESTAMPDIFF(SECOND, $tsColumn, CURRENT_TIMESTAMP)", + }; + $metricExpr .= " AND $timeDiffExpr < :interval"; + $vars["interval"] = new GenericVariable("interval", GenericVariable::TYPE_INT, null); + $args["interval"] = $query->interval; + } + $i = 0; foreach ($query->labelSelector->getEntries() as $name => $value) { $metricExpr .= " AND t{$i}.name = :name{$i}"; diff --git a/src/SOFe/Capital/Analytics/Top/Mod.php b/src/SOFe/Capital/Analytics/Top/Mod.php index 217c20f..db23db1 100644 --- a/src/SOFe/Capital/Analytics/Top/Mod.php +++ b/src/SOFe/Capital/Analytics/Top/Mod.php @@ -21,7 +21,7 @@ final class Mod implements Singleton, FromContext { use SingletonArgs, SingletonTrait; - public const API_VERSION = "0.1.0"; + public const API_VERSION = "0.2.0"; public static function fromSingletonArgs(Analytics\Config $config, MainClass $plugin, AwaitStd $std, DatabaseUtils $dbu) : self { Info::registerByReflection("capital.analytics.top", PaginationInfo::class); diff --git a/src/SOFe/Capital/Analytics/Top/QueryArgs.php b/src/SOFe/Capital/Analytics/Top/QueryArgs.php index 3ec8dab..12544fc 100644 --- a/src/SOFe/Capital/Analytics/Top/QueryArgs.php +++ b/src/SOFe/Capital/Analytics/Top/QueryArgs.php @@ -4,6 +4,7 @@ namespace SOFe\Capital\Analytics\Top; +use pocketmine\utils\Binary; use SOFe\Capital\AccountLabels; use SOFe\Capital\AccountQueryMetric; use SOFe\Capital\Config\Parser; @@ -31,7 +32,7 @@ final class QueryArgs { private ?string $hash = null; /** - * @param LabelSelector $labelSelector The labels that filter the cacounts/transactions. + * @param LabelSelector $labelSelector The labels that filter the accounts/transactions. * @param string $groupingLabel The label to group by. * @param array $displayLabels The labels to display in the top list. Keys are InfoAPI info names and values are the labels to display. * @param self::ORDERING_* $ordering Whether to sort ascendingly or descendingly. @@ -43,6 +44,7 @@ public function __construct( public string $groupingLabel, public array $displayLabels, public string $ordering, + public ?int $interval, public QueryMetric $metric, ) { } @@ -64,6 +66,12 @@ public function hash() : string { $bytes .= $this->groupingLabel; $bytes .= "\0"; + if ($this->interval !== null) { + $bytes .= "\1" . Binary::writeLong($this->interval); + } else { + $bytes .= "\0"; + } + $bytes .= get_class($this->metric); $bytes .= "\0"; @@ -89,6 +97,11 @@ public static function parse(Parser $config, Schema $schema) : self { self::ORDERING_DESC => self::ORDERING_DESC, default => $config->setValue("ordering", self::ORDERING_DESC, "Invalid ordering"), }; + $interval = $config->expectNullableNumber("interval", 24, <<<'EOT' + Number of hours of data to consider. + Only accounts used in this interval or transactions that took place in this interval are considered. + EOT); + $interval = $interval !== null ? (int) ($interval * 3600) : null; $metric = AccountQueryMetric::parseConfig($config, "metric"); return new self( @@ -96,6 +109,7 @@ public static function parse(Parser $config, Schema $schema) : self { groupingLabel: $groupingLabel, displayLabels: $displayLabels, ordering: $ordering, + interval: $interval, metric: $metric, ); } diff --git a/src/SOFe/Capital/QueryMetric.php b/src/SOFe/Capital/QueryMetric.php index fc566b1..31eb5aa 100644 --- a/src/SOFe/Capital/QueryMetric.php +++ b/src/SOFe/Capital/QueryMetric.php @@ -9,6 +9,8 @@ public function getMainTable() : string; public function getLabelTable() : string; + public function getTimestampColumn() : string; + public function getExpr() : string; public function usesIdOnly() : bool; diff --git a/src/SOFe/Capital/TransactionQueryMetric.php b/src/SOFe/Capital/TransactionQueryMetric.php index 9b51449..83b4e98 100644 --- a/src/SOFe/Capital/TransactionQueryMetric.php +++ b/src/SOFe/Capital/TransactionQueryMetric.php @@ -51,6 +51,10 @@ public function getLabelTable() : string { return "capital_tran_label"; } + public function getTimestampColumn() : string { + return "capital_acc.touch"; + } + public function getExpr() : string { return $this->expr; } diff --git a/suitetest/cases/config-regen-currency/expect-config.yml b/suitetest/cases/config-regen-currency/expect-config.yml index ed3eb27..f7f3973 100644 --- a/suitetest/cases/config-regen-currency/expect-config.yml +++ b/suitetest/cases/config-regen-currency/expect-config.yml @@ -125,6 +125,10 @@ analytics: Whether to sort results ascendingly or descendingly. Use "asc" for ascending sort and "desc" for descending sort. ordering: desc + '#interval': |- + Number of hours of data to consider. + Only accounts used in this interval or transactions that took place in this interval are considered. + interval: 24 '#metric': |- The statistic used to combine multiple values. diff --git a/suitetest/cases/mysql/expect-config.yml b/suitetest/cases/mysql/expect-config.yml index 24c169d..e5919dd 100644 --- a/suitetest/cases/mysql/expect-config.yml +++ b/suitetest/cases/mysql/expect-config.yml @@ -116,6 +116,10 @@ analytics: Whether to sort results ascendingly or descendingly. Use "asc" for ascending sort and "desc" for descending sort. ordering: desc + '#interval': |- + Number of hours of data to consider. + Only accounts used in this interval or transactions that took place in this interval are considered. + interval: 24 '#metric': |- The statistic used to combine multiple values. diff --git a/suitetest/cases/sqlite/expect-config.yml b/suitetest/cases/sqlite/expect-config.yml index 24c169d..e5919dd 100644 --- a/suitetest/cases/sqlite/expect-config.yml +++ b/suitetest/cases/sqlite/expect-config.yml @@ -116,6 +116,10 @@ analytics: Whether to sort results ascendingly or descendingly. Use "asc" for ascending sort and "desc" for descending sort. ordering: desc + '#interval': |- + Number of hours of data to consider. + Only accounts used in this interval or transactions that took place in this interval are considered. + interval: 24 '#metric': |- The statistic used to combine multiple values.