diff --git a/rl.install b/rl.install index 5313199..6d165fb 100644 --- a/rl.install +++ b/rl.install @@ -56,7 +56,7 @@ function rl_install() { 'experiment_unique' => ['experiment_uuid'], ], 'indexes' => [ - 'experiment_uuid' => ['experiment_uuid'], + 'experiment_updated' => ['experiment_uuid', 'updated'], ], ]; @@ -123,7 +123,7 @@ function rl_install() { 'experiment_arm' => ['experiment_uuid', 'arm_id'], ], 'indexes' => [ - 'experiment_uuid' => ['experiment_uuid'], + 'covering_time_window' => ['experiment_uuid', 'updated', 'arm_id', 'turns', 'rewards', 'created'], ], ]; @@ -249,7 +249,7 @@ function rl_schema() { 'experiment_unique' => ['experiment_uuid'], ], 'indexes' => [ - 'experiment_uuid' => ['experiment_uuid'], + 'experiment_updated' => ['experiment_uuid', 'updated'], ], ]; @@ -307,7 +307,7 @@ function rl_schema() { 'experiment_arm' => ['experiment_uuid', 'arm_id'], ], 'indexes' => [ - 'experiment_uuid' => ['experiment_uuid'], + 'covering_time_window' => ['experiment_uuid', 'updated', 'arm_id', 'turns', 'rewards', 'created'], ], ]; diff --git a/src/Service/ExperimentManager.php b/src/Service/ExperimentManager.php index 3361ebd..54b3163 100644 --- a/src/Service/ExperimentManager.php +++ b/src/Service/ExperimentManager.php @@ -81,7 +81,18 @@ public function getTotalTurns($experiment_uuid) { * {@inheritdoc} */ public function getThompsonScores($experiment_uuid) { - $arms_data = $this->getAllArmsData($experiment_uuid); + return $this->getThompsonScoresWithWindow($experiment_uuid, NULL); + } + + /** + * {@inheritdoc} + */ + public function getThompsonScoresWithWindow($experiment_uuid, $time_window_seconds = NULL) { + $arms_data = $this->storage->getAllArmsDataWithWindow($experiment_uuid, $time_window_seconds); + + if (empty($arms_data)) { + return []; + } return $this->tsCalculator->calculateThompsonScores($arms_data); } diff --git a/src/Service/ExperimentManagerInterface.php b/src/Service/ExperimentManagerInterface.php index 1a67fcc..ba5e745 100644 --- a/src/Service/ExperimentManagerInterface.php +++ b/src/Service/ExperimentManagerInterface.php @@ -83,4 +83,17 @@ public function getTotalTurns($experiment_uuid); */ public function getThompsonScores($experiment_uuid); + /** + * Gets Thompson Sampling scores for all arms with seconds-based time window. + * + * @param string $experiment_uuid + * The experiment UUID. + * @param int|null $time_window_seconds + * Optional time window in seconds. Only considers arms active within this timeframe. + * + * @return array + * Array of Thompson Sampling scores keyed by arm_id. + */ + public function getThompsonScoresWithWindow($experiment_uuid, $time_window_seconds = NULL); + } diff --git a/src/Storage/ExperimentDataStorage.php b/src/Storage/ExperimentDataStorage.php index 8bd5016..668593c 100644 --- a/src/Storage/ExperimentDataStorage.php +++ b/src/Storage/ExperimentDataStorage.php @@ -110,17 +110,11 @@ public function getArmData($experiment_uuid, $arm_id) { * {@inheritdoc} */ public function getAllArmsData($experiment_uuid, $time_window_days = NULL) { - $query = $this->database->select('rl_arm_data', 'ad') - ->fields('ad', ['arm_id', 'turns', 'rewards', 'created', 'updated']) - ->condition('experiment_uuid', $experiment_uuid); - - // Apply time window filter if specified. - if ($time_window_days !== NULL && $time_window_days > 0) { - $cutoff_timestamp = \Drupal::time()->getRequestTime() - ($time_window_days * 86400); - $query->condition('updated', $cutoff_timestamp, '>='); + $time_window_seconds = NULL; + if ($time_window_days && $time_window_days > 0) { + $time_window_seconds = $time_window_days * 86400; } - - return $query->execute()->fetchAllAssoc('arm_id'); + return $this->getAllArmsDataWithWindow($experiment_uuid, $time_window_seconds); } /** @@ -149,4 +143,20 @@ public function getTotalTurns($experiment_uuid, $time_window_days = NULL) { return $result ? (int) $result : 0; } + /** + * {@inheritdoc} + */ + public function getAllArmsDataWithWindow($experiment_uuid, $time_window_seconds = NULL) { + $query = $this->database->select('rl_arm_data', 'ad') + ->fields('ad', ['arm_id', 'turns', 'rewards', 'created', 'updated']) + ->condition('experiment_uuid', $experiment_uuid); + + if ($time_window_seconds && $time_window_seconds > 0) { + $cutoff_timestamp = \Drupal::time()->getRequestTime() - $time_window_seconds; + $query->condition('updated', $cutoff_timestamp, '>='); + } + + return $query->execute()->fetchAllAssoc('arm_id'); + } + } diff --git a/src/Storage/ExperimentDataStorageInterface.php b/src/Storage/ExperimentDataStorageInterface.php index d6b116b..e2a4bc0 100644 --- a/src/Storage/ExperimentDataStorageInterface.php +++ b/src/Storage/ExperimentDataStorageInterface.php @@ -72,4 +72,17 @@ public function getAllArmsData($experiment_uuid); */ public function getTotalTurns($experiment_uuid); + /** + * Gets data for all arms in an experiment with seconds-based time window. + * + * @param string $experiment_uuid + * The experiment UUID. + * @param int|null $time_window_seconds + * Optional time window in seconds. Only returns arms active within this timeframe. + * + * @return array + * Array of arm data objects keyed by arm_id. + */ + public function getAllArmsDataWithWindow($experiment_uuid, $time_window_seconds = NULL); + }