Skip to content

Commit

Permalink
Add device experiment #75
Browse files Browse the repository at this point in the history
  • Loading branch information
bwalkerl committed Jan 13, 2025
1 parent 66aa9ba commit e8b49d1
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 31 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Configuration
Visit the Site Administration menu and navigate to Plugins->Admin Tools->Manage Experiments. This page allows you to add new experiments, as well as edit existing experiments. To add a new experiment, fill in the fields, and click 'Add Experiment'. To edit the details of an existing experiment, click on the Edit link inside of the experiments table, to go to the edit page.

### Scopes and audiences
The plugin currently has two scopes that experiments can lie under, Request scope and Session scope.
The plugin currently has three scopes that experiments can lie under, Request scope, Session scope and Device scope.

#### Request scope

Expand All @@ -49,6 +49,10 @@ Request scope experiments are run on every http request. Any request scope will

Session scope experiments are called when a user logs into the site. At this time, a condition set will be decided on, and users will continue to have that condition set applied for the length of their session. This does not apply to guest users, only logged in users. When a user logs out, and logs back in, a new set of conditions is applied to the account, which may be the same condition set.

#### Device scope

Device scope experiments are similar to a session experiment but is set before the session exists, and is deterministic for all requests coming from a specific device or user.

### Conditions

Each experiment can have multiple condition sets avaiable, of which 1 is applied to a given user at a given time. The condition set is picked based on the weighting you specify when creating the condition, which corresponds to the % of users that it applies to.
Expand Down
72 changes: 66 additions & 6 deletions classes/experiment_manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class tool_abconfig_experiment_manager {

// Experiment functions.

/** @var array Experiment js that needs to be rendered. */
private static $renderjs = [];

/**
* Add an experiment
* @param string $name
Expand All @@ -51,8 +54,14 @@ public function add_experiment($name, $shortname, $scope) {
if ($this->experiment_exists($shortname)) {
$return = false;
} else {
$return = $DB->insert_record('tool_abconfig_experiment',
array('name' => $name, 'shortname' => $shortname, 'scope' => $scope, 'enabled' => 0, 'adminenabled' => 0));
$return = $DB->insert_record('tool_abconfig_experiment', [
'name' => $name,
'shortname' => $shortname,
'scope' => $scope,
'enabled' => 0,
'adminenabled' => 0,
'numoffset' => rand(0, 99),
]);
}
self::invalidate_experiment_cache();
return $return;
Expand Down Expand Up @@ -82,9 +91,10 @@ public function experiment_exists($shortname) {
* @param string $scope
* @param int $enabled
* @param int $adminenabled
* @param int $numoffset
* @return bool
*/
public function update_experiment($prevshortname, $name, $shortname, $scope, $enabled, $adminenabled) {
public function update_experiment($prevshortname, $name, $shortname, $scope, $enabled, $adminenabled, $numoffset) {
global $DB;
// Check whether the experiment exists to be updated.
if (!$this->experiment_exists($prevshortname)) {
Expand All @@ -93,9 +103,15 @@ public function update_experiment($prevshortname, $name, $shortname, $scope, $en
// Get id of record.
$sqlexperiment = $DB->sql_compare_text($prevshortname, strlen($prevshortname));
$record = $DB->get_record_sql('SELECT * FROM {tool_abconfig_experiment} WHERE shortname = ?', array($sqlexperiment));

$return = $DB->update_record('tool_abconfig_experiment', array('id' => $record->id, 'name' => $name,
'shortname' => $shortname, 'scope' => $scope, 'enabled' => $enabled, 'adminenabled' => $adminenabled));
$return = $DB->update_record('tool_abconfig_experiment', (object) [
'id' => $record->id,
'name' => $name,
'shortname' => $shortname,
'scope' => $scope,
'enabled' => $enabled,
'adminenabled' => $adminenabled,
'numoffset' => $numoffset,
]);
}
self::invalidate_experiment_cache();
return $return;
Expand Down Expand Up @@ -300,6 +316,23 @@ public function get_active_session() {
});
}

/**
* Get active devices.
* @return mixed
*/
public function get_active_device() {
$experiments = self::get_experiments();

// Filter array for only enabled session experiments.
return array_filter($experiments, function ($experiment) {
if ($experiment['enabled'] == 1 && $experiment['scope'] == 'device') {
return true;
} else {
return false;
}
});
}

/**
* Get active experiments
* @return mixed
Expand All @@ -317,6 +350,33 @@ public function get_active_experiments() {
});
}

/**
* Sets experiment JS to be rendered.
* @param string $key
* @param string $value
* @return void
*/
public function set_render_js(string $key, string $value): void {
self::$renderjs[$key] = $value;
}

/**
* Gets experiment JS to be rendered.
* @return array
*/
public function get_render_js(): array {
return self::$renderjs;
}

/**
* Unsets experiment JS.
* @param string $key
* @return void
*/
public function remove_render_js(string $key): void {
unset(self::$renderjs[$key]);
}

/**
* Log commands
* @param string $commands
Expand Down
13 changes: 12 additions & 1 deletion classes/form/edit_experiment.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,20 @@ public function definition() {
$mform->addRule('experimentshortname', get_string('formexperimentshortnamereq', 'tool_abconfig'), 'required');

// Setup Data array for scopes.
$scopes = ['request' => get_string('request', 'tool_abconfig'), 'session' => get_string('session', 'tool_abconfig')];
$scopes = [
'request' => get_string('request', 'tool_abconfig'),
'session' => get_string('session', 'tool_abconfig'),
'device' => get_string('device', 'tool_abconfig'),
];
$mform->addElement('select', 'scope', get_string('formexperimentscopeselect', 'tool_abconfig'), $scopes);

$mform->addElement('text', 'numoffset', get_string('offset', 'tool_abconfig'));
$mform->setType('numoffset', PARAM_INT);
$mform->hideIf('numoffset', 'scope', 'neq', 'device');
$mform->addRule('numoffset', get_string('err_numeric', 'form'), 'numeric', null, 'client');
$mform->addRule('numoffset', get_string('maximumchars', '', 2), 'maxlength', 2, 'client');
$mform->addHelpButton('numoffset', 'offset', 'tool_abconfig');

// Enabled checkbox.
$mform->addElement('advcheckbox', 'enabled', get_string('formexperimentenabled', 'tool_abconfig'));

Expand Down
6 changes: 5 additions & 1 deletion classes/form/manage_experiments.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ public function definition() {
$mform = $this->_form;

// Setup Data array for scopes.
$scopes = ['request' => get_string('request', 'tool_abconfig'), 'session' => get_string('session', 'tool_abconfig')];
$scopes = [
'request' => get_string('request', 'tool_abconfig'),
'session' => get_string('session', 'tool_abconfig'),
'device' => get_string('device', 'tool_abconfig'),
];

// Add section for adding experiments.
$mform->addElement('header', 'addexperiment', get_string('formaddexperiment', 'tool_abconfig'));
Expand Down
5 changes: 3 additions & 2 deletions db/install.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="admin/tool/abconfig/db" VERSION="20190920" COMMENT="XMLDB file for Moodle admin/tool/abconfig"
<XMLDB PATH="admin/tool/abconfig/db" VERSION="20250113" COMMENT="XMLDB file for Moodle admin/tool/abconfig"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
>
Expand All @@ -12,6 +12,7 @@
<FIELD NAME="scope" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="enabled" TYPE="int" LENGTH="1" NOTNULL="false" SEQUENCE="false" COMMENT="Bool flag for whether the experiment is enabled or disabled"/>
<FIELD NAME="adminenabled" TYPE="int" LENGTH="1" NOTNULL="false" SEQUENCE="false" COMMENT="Field to track whether this experiment is enabled for admins"/>
<FIELD NAME="numoffset" TYPE="int" LENGTH="5" NOTNULL="false" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
Expand All @@ -33,4 +34,4 @@
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
</XMLDB>
15 changes: 15 additions & 0 deletions db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,20 @@ function xmldb_tool_abconfig_upgrade($oldversion) {
upgrade_plugin_savepoint(true, 2022070600, 'tool', 'abconfig');
}

if ($oldversion < 2025011300) {

// Define field numoffset to be added to tool_abconfig_experiment.
$table = new xmldb_table('tool_abconfig_experiment');
$field = new xmldb_field('numoffset', XMLDB_TYPE_INTEGER, '5', null, null, null, null, 'adminenabled');

// Conditionally launch add field numoffset.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

// Abconfig savepoint reached.
upgrade_plugin_savepoint(true, 2025011300, 'tool', 'abconfig');
}

return true;
}
6 changes: 4 additions & 2 deletions edit_experiment.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
$experiment = $DB->get_record('tool_abconfig_experiment', array('id' => $eid));
$data = array('experimentname' => $experiment->name, 'experimentshortname' => $experiment->shortname,
'prevshortname' => $experiment->shortname, 'scope' => $experiment->scope,
'id' => $experiment->id, 'enabled' => $experiment->enabled, 'adminenabled' => $experiment->adminenabled);
'id' => $experiment->id, 'enabled' => $experiment->enabled, 'adminenabled' => $experiment->adminenabled,
'numoffset' => $experiment->numoffset ?? rand(0, 99));

$customarray = array('eid' => $experiment->id);

Expand All @@ -72,6 +73,7 @@
$eid = $fromform->id;
$prevshortname = $fromform->prevshortname;
$adminenabled = $fromform->adminenabled;
$numoffset = $fromform->numoffset;

// If eid is empty, do nothing.
if ($eid == 0) {
Expand All @@ -83,7 +85,7 @@
$manager->delete_experiment($shortname);
$manager->delete_all_conditions($eid);
} else {
$manager->update_experiment($prevshortname, $name, $shortname, $scope, $enabled, $adminenabled);
$manager->update_experiment($prevshortname, $name, $shortname, $scope, $enabled, $adminenabled, $numoffset);
}

redirect($prevurl);
Expand Down
3 changes: 3 additions & 0 deletions lang/en/tool_abconfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,12 @@
// Short Strings.
$string['request'] = 'Request';
$string['session'] = 'Session';
$string['device'] = 'Device';
$string['name'] = 'Experiment name';
$string['shortname'] = 'Short experiment name';
$string['scope'] = 'Experiment scope';
$string['offset'] = 'Offset';
$string['offset_help'] = 'Offset value between 0 and 99 that will be used to rotate device hashes.';
$string['edit'] = 'Edit';
$string['enabled'] = 'Enabled';
$string['yes'] = 'Yes';
Expand Down
Loading

0 comments on commit e8b49d1

Please sign in to comment.