From a4653a8877ae65c4de4a7bf709603abbf0106bf7 Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Wed, 4 Feb 2026 09:29:06 -0500 Subject: [PATCH 1/3] Remove deprecated makeExperimentSegment function --- condition-rules-v5/index.html | 39 ++--------------------------------- condition-rules-v6/index.html | 39 ++--------------------------------- 2 files changed, 4 insertions(+), 74 deletions(-) diff --git a/condition-rules-v5/index.html b/condition-rules-v5/index.html index 5a22ba7..d6d8e7d 100644 --- a/condition-rules-v5/index.html +++ b/condition-rules-v5/index.html @@ -979,8 +979,8 @@

Test Results

conditions: this.conditionCodes.map(conditionCode => this.makeCondition(conditionCode, conditionIdMap, payloadIdMap, levelCombinationIdMap, false)), stateTimeLogs: [], queries: this.makeQueries(), - experimentSegmentInclusion: this.makeExperimentSegment(segmentNamePrefix, "Inclusion"), - experimentSegmentExclusion: this.makeExperimentSegment(segmentNamePrefix, "Exclusion"), + experimentSegmentInclusion: [], + experimentSegmentExclusion: [], factors: this.experimentTypeSelect.value !== "Factorial" ? [] : this.makeFactors(this.conditionCodes, levelIdMap), stratificationFactor: null, conditionPayloads: this.makePayloads(decisionPoint, conditionIdMap, payloadIdMap, levelCombinationIdMap, useReference) @@ -1309,41 +1309,6 @@

Test Results

} return queries; } - - makeExperimentSegment(segmentNamePrefix, type) { - const name = `${segmentNamePrefix} ${type} Segment`; - const groupForSegment = []; - if (type === "Inclusion") { - groupForSegment.push( - { - createdAt: this.date, - updatedAt: this.date, - versionNumber: 1, - groupId: "All", - type: "All" - } - ); - } - - return { - createdAt: this.date, - updatedAt: this.date, - versionNumber: 1, - segment: { - createdAt: this.date, - updatedAt: this.date, - versionNumber: 1, - id: this.idGenerator.uuidv4(), - name: name, - description: name, - context: this.appContextSelect.value, - type: "private", - individualForSegment: [], - groupForSegment: groupForSegment, - subSegments: [] - } - } - } } class FetchWrapper { diff --git a/condition-rules-v6/index.html b/condition-rules-v6/index.html index 9e7362e..91be492 100644 --- a/condition-rules-v6/index.html +++ b/condition-rules-v6/index.html @@ -979,8 +979,8 @@

Test Results

conditions: this.conditionCodes.map(conditionCode => this.makeCondition(conditionCode, conditionIdMap, payloadIdMap, levelCombinationIdMap, false)), stateTimeLogs: [], queries: this.makeQueries(), - experimentSegmentInclusion: this.makeExperimentSegment(segmentNamePrefix, "Inclusion"), - experimentSegmentExclusion: this.makeExperimentSegment(segmentNamePrefix, "Exclusion"), + experimentSegmentInclusion: [], + experimentSegmentExclusion: [], factors: this.experimentTypeSelect.value !== "Factorial" ? [] : this.makeFactors(this.conditionCodes, levelIdMap), stratificationFactor: null, conditionPayloads: this.makePayloads(decisionPoint, conditionIdMap, payloadIdMap, levelCombinationIdMap, useReference) @@ -1308,41 +1308,6 @@

Test Results

} return queries; } - - makeExperimentSegment(segmentNamePrefix, type) { - const name = `${segmentNamePrefix} ${type} Segment`; - const groupForSegment = []; - if (type === "Inclusion") { - groupForSegment.push( - { - createdAt: this.date, - updatedAt: this.date, - versionNumber: 1, - groupId: "All", - type: "All" - } - ); - } - - return { - createdAt: this.date, - updatedAt: this.date, - versionNumber: 1, - segment: { - createdAt: this.date, - updatedAt: this.date, - versionNumber: 1, - id: this.idGenerator.uuidv4(), - name: name, - description: name, - context: this.appContextSelect.value, - type: "private", - individualForSegment: [], - groupForSegment: groupForSegment, - subSegments: [] - } - } - } } class FetchWrapper { From 507e9093a702ec903f949fca113b8277e5b7666e Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Wed, 4 Feb 2026 12:43:02 -0500 Subject: [PATCH 2/3] Update old statuses to new ones --- condition-rules-v6/index.html | 58 +++++++++++++++++------------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/condition-rules-v6/index.html b/condition-rules-v6/index.html index 91be492..803399a 100644 --- a/condition-rules-v6/index.html +++ b/condition-rules-v6/index.html @@ -543,8 +543,8 @@

Test Results

Student
Inactive - Enrolling - Complete + Running + Paused Student 1 (Individual) @@ -702,8 +702,8 @@

Test Results

for (let i = 0; i < this.conditionCells.length; i += 3) { this.conditionCellMap[`student${Math.floor(i / 3) + 1}`] = { inactive: this.conditionCells[i], - enrolling: this.conditionCells[i + 1], - enrollmentComplete: this.conditionCells[i + 2] + running: this.conditionCells[i + 1], + paused: this.conditionCells[i + 2] }; } this.responseTimeCellMap = { @@ -1017,70 +1017,70 @@

Test Results

// Student 1 (Individual) visits the decision point the first time (Inactive) await this.visitDecisionPoint(student1.name, student1.id, null); - // Update experiment status to enrolling - await this.updateExperimentStatus("enrolling"); + // Update experiment status to running + await this.updateExperimentStatus("running"); - // Student 1 (Individual) visits the decision point the second time (Enrolling) + // Student 1 (Individual) visits the decision point the second time (Running) await this.visitDecisionPoint(student1.name, student1.id, null); - // Student 2 (Individual) visits the decision point the first time (Enrolling) + // Student 2 (Individual) visits the decision point the first time (Running) await this.visitDecisionPoint(student2.name, student2.id, null); - // Student 3 (Individual) visits the decision point the first time (Enrolling) + // Student 3 (Individual) visits the decision point the first time (Running) await this.visitDecisionPoint(student3.name, student3.id, null); - // Student 4 (Individual) visits the decision point the first time (Enrolling) + // Student 4 (Individual) visits the decision point the first time (Running) await this.visitDecisionPoint(student4.name, student4.id, null); - // Update experiment status to enrollment complete - await this.updateExperimentStatus("enrollmentComplete"); + // Update experiment status to paused + await this.updateExperimentStatus("paused"); - // Student 1 (Individual) visits the decision point the third time (Enrollment Complete) + // Student 1 (Individual) visits the decision point the third time (Paused) await this.visitDecisionPoint(student1.name, student1.id, null); - // Student 2 (Individual) visits the decision point the second time (Enrollment Complete) + // Student 2 (Individual) visits the decision point the second time (Paused) await this.visitDecisionPoint(student2.name, student2.id, null); - // Student 3 (Individual) visits the decision point the second time (Enrollment Complete) + // Student 3 (Individual) visits the decision point the second time (Paused) await this.visitDecisionPoint(student3.name, student3.id, null); - // Student 4 (Individual) visits the decision point the second time (Enrollment Complete) + // Student 4 (Individual) visits the decision point the second time (Paused) await this.visitDecisionPoint(student4.name, student4.id, null); - // Student 5 (Individual) visits the decision point the first time (Enrollment Complete) + // Student 5 (Individual) visits the decision point the first time (Paused) await this.visitDecisionPoint(student5.name, student5.id, null); } else { // Student 1 (Group A) visits the decision point the first time (Inactive) await this.visitDecisionPoint(student1.name, student1.id, "Group A"); - // Update experiment status to enrolling - await this.updateExperimentStatus("enrolling"); + // Update experiment status to running + await this.updateExperimentStatus("running"); - // Student 1 (Group A) visits the decision point the second time (Enrolling) + // Student 1 (Group A) visits the decision point the second time (Running) await this.visitDecisionPoint(student1.name, student1.id, "Group A"); - // Student 2 (Group A) visits the decision point the first time (Enrolling) + // Student 2 (Group A) visits the decision point the first time (Running) await this.visitDecisionPoint(student2.name, student2.id, "Group A"); - // Student 4 (Group B) visits the decision point the first time (Enrolling) + // Student 4 (Group B) visits the decision point the first time (Running) await this.visitDecisionPoint(student4.name, student4.id, "Group B"); - // Update experiment status to enrollment complete - await this.updateExperimentStatus("enrollmentComplete"); + // Update experiment status to paused + await this.updateExperimentStatus("paused"); - // Student 1 (Group A) visits the decision point the third time (Enrollment Complete) + // Student 1 (Group A) visits the decision point the third time (Paused) await this.visitDecisionPoint(student1.name, student1.id, "Group A"); - // Student 2 (Group A) visits the decision point the second time (Enrollment Complete) + // Student 2 (Group A) visits the decision point the second time (Paused) await this.visitDecisionPoint(student2.name, student2.id, "Group A"); - // Student 3 (Group A) visits the decision point the first time (Enrollment Complete) + // Student 3 (Group A) visits the decision point the first time (Paused) await this.visitDecisionPoint(student3.name, student3.id, "Group A"); - // Student 4 (Group B) visits the decision point the second time (Enrolling) + // Student 4 (Group B) visits the decision point the second time (Running) await this.visitDecisionPoint(student4.name, student4.id, "Group B"); - // Student 5 (Group B) visits the decision point the first time (Enrolling) + // Student 5 (Group B) visits the decision point the first time (Running) await this.visitDecisionPoint(student5.name, student5.id, "Group B"); } } From 4a65a09440dc277527ef85a3c858a7c42a717eb1 Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Thu, 5 Feb 2026 14:23:27 -0500 Subject: [PATCH 3/3] Implement proper status updating to 'paused' and apply group membership to all students --- condition-rules-v6/index.html | 76 +++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/condition-rules-v6/index.html b/condition-rules-v6/index.html index 803399a..6f20555 100644 --- a/condition-rules-v6/index.html +++ b/condition-rules-v6/index.html @@ -830,10 +830,10 @@

Test Results

} // Create experiment - await this.createExperiment(); + const experimentData = await this.createExperiment(); // Perform test - await this.performTest(); + await this.performTest(experimentData); // Delete the experiment await this.deleteExperiment(); @@ -986,10 +986,14 @@

Test Results

conditionPayloads: this.makePayloads(decisionPoint, conditionIdMap, payloadIdMap, levelCombinationIdMap, useReference) } // console.log("experimentData:", JSON.stringify(experimentData, null, 2)); - await this.fetchWrapper.post(`${this.hostUrlSelect.value}/api/experiments`, experimentData); + return await this.fetchWrapper.post(`${this.hostUrlSelect.value}/api/experiments`, experimentData); } - async performTest() { + async updateExperiment(experimentData, updateData) { + await this.fetchWrapper.put(`${this.hostUrlSelect.value}/api/experiments/${this.experimentId}`, { ...experimentData, ...updateData }); + } + + async performTest(experimentData) { // Empty the condition cells for (const conditionCell of this.conditionCells) { conditionCell.innerText = ""; @@ -1015,40 +1019,40 @@

Test Results

const student5 = makeStudent("student5"); if (this.assignmentUnitSelect.value === "Individual") { // Student 1 (Individual) visits the decision point the first time (Inactive) - await this.visitDecisionPoint(student1.name, student1.id, null); + await this.visitDecisionPoint(student1.name, student1.id, "Group A"); // Update experiment status to running await this.updateExperimentStatus("running"); // Student 1 (Individual) visits the decision point the second time (Running) - await this.visitDecisionPoint(student1.name, student1.id, null); + await this.visitDecisionPoint(student1.name, student1.id, "Group A"); // Student 2 (Individual) visits the decision point the first time (Running) - await this.visitDecisionPoint(student2.name, student2.id, null); + await this.visitDecisionPoint(student2.name, student2.id, "Group A"); // Student 3 (Individual) visits the decision point the first time (Running) - await this.visitDecisionPoint(student3.name, student3.id, null); + await this.visitDecisionPoint(student3.name, student3.id, "Group A"); // Student 4 (Individual) visits the decision point the first time (Running) - await this.visitDecisionPoint(student4.name, student4.id, null); + await this.visitDecisionPoint(student4.name, student4.id, "Group A"); // Update experiment status to paused - await this.updateExperimentStatus("paused"); + await this.updateExperimentStatus("paused", experimentData); // Student 1 (Individual) visits the decision point the third time (Paused) - await this.visitDecisionPoint(student1.name, student1.id, null); + await this.visitDecisionPoint(student1.name, student1.id, "Group A"); // Student 2 (Individual) visits the decision point the second time (Paused) - await this.visitDecisionPoint(student2.name, student2.id, null); + await this.visitDecisionPoint(student2.name, student2.id, "Group A"); // Student 3 (Individual) visits the decision point the second time (Paused) - await this.visitDecisionPoint(student3.name, student3.id, null); + await this.visitDecisionPoint(student3.name, student3.id, "Group A"); // Student 4 (Individual) visits the decision point the second time (Paused) - await this.visitDecisionPoint(student4.name, student4.id, null); + await this.visitDecisionPoint(student4.name, student4.id, "Group A"); // Student 5 (Individual) visits the decision point the first time (Paused) - await this.visitDecisionPoint(student5.name, student5.id, null); + await this.visitDecisionPoint(student5.name, student5.id, "Group A"); } else { // Student 1 (Group A) visits the decision point the first time (Inactive) await this.visitDecisionPoint(student1.name, student1.id, "Group A"); @@ -1066,7 +1070,7 @@

Test Results

await this.visitDecisionPoint(student4.name, student4.id, "Group B"); // Update experiment status to paused - await this.updateExperimentStatus("paused"); + await this.updateExperimentStatus("paused", experimentData); // Student 1 (Group A) visits the decision point the third time (Paused) await this.visitDecisionPoint(student1.name, student1.id, "Group A"); @@ -1085,14 +1089,23 @@

Test Results

} } - async updateExperimentStatus(experimentStatus) { + async updateExperimentStatus(experimentStatus, experimentData = undefined) { if (experimentStatus === this.experimentStatus) { return; } - await this.fetchWrapper.post(`${this.hostUrlSelect.value}/api/experiments/state`, { - experimentId: this.experimentId, - state: experimentStatus - }); + if (experimentStatus === "paused") { + const postExperimentRule = this.postExperimentRuleSelect.value === "Continue" ? "continue" : "assign"; + const postExperimentConditionCode = ["Continue", "Default"].includes(this.postExperimentRuleSelect.value) ? null : this.postExperimentRuleSelect.value; + const condition = experimentData.conditions.find(c => c.conditionCode === postExperimentConditionCode); + const postExperimentConditionId = condition ? condition.id : null; + const updateData = { state: "paused", postExperimentRule: postExperimentRule, revertTo: postExperimentConditionId }; + await this.updateExperiment(experimentData, updateData); + } else { + await this.fetchWrapper.post(`${this.hostUrlSelect.value}/api/experiments/state`, { + experimentId: this.experimentId, + state: experimentStatus + }); + } this.experimentStatus = experimentStatus; // Delay for a specified number of milliseconds @@ -1105,17 +1118,18 @@

Test Results

const initStartTime = Date.now(); await upClient.init(); this.responseTimeCellMap.init.responseTimes.push(Date.now() - initStartTime); - if (group && this.assignmentUnitSelect.value !== "Individual") { - const groupType = this.assignmentUnitSelect.value; - const groupMembership = { - [groupType]: ["Group A", "Group B"] - } - const workingGroup = { - [groupType]: group - } - await upClient.setGroupMembership(groupMembership); - await upClient.setWorkingGroup(workingGroup); + + // Group membership is required for the user to be enrolled if there's any group-level global exclusions defined for the context + const groupType = this.assignmentUnitSelect.value; + const groupMembership = { + [groupType]: ["Group A", "Group B"] } + const workingGroup = { + [groupType]: group + } + await upClient.setGroupMembership(groupMembership); + await upClient.setWorkingGroup(workingGroup); + const experimentSite = `Site_${this.experimentId}`; const experimentTarget = `Target_${this.experimentId}`; const assignStartTime = Date.now();