lib/experiments/no_sandboxes_fall_2024_experiment.rb
# frozen_string_literal: true
require_dependency "#{Rails.root}/lib/tag_manager"
# This handles course submissions for new instructors
# for our Fall 2024 test of "no sandbox" vs traditional sandbox drafting.
# The first course from a new instructor will get randomly assigned to
# the experimental condition or the control, until we reach the target
# number of experiment courses.
#
# During the Fall 2024, we decided to extend the experiment to Spring 2025,
# and as of September 2024, the code is being modified accordingly. It's
# already done its work for Fall 2024 new courses.
class NoSandboxesFall2024Experiment
EXPERIMENT_TAG = 'no_sandbox_spring_2025_experiment_condition'
CONTROL_TAG = 'no_sandbox_spring_2025_control_condition'
TAG_KEY = 'no_sandbox_spring_2025_experiment'
TARGET_NEW_INSTRUCTOR_COUNT = 50
def self.experiment_courses
Tag.courses_tagged_with EXPERIMENT_TAG
end
def self.control_courses
Tag.courses_tagged_with CONTROL_TAG
end
def initialize(course, creator)
return unless Features.wiki_ed?
unless Setting.exists?(key: 'no_sandbox_spring_2025_experiment')
Setting.create(key: 'no_sandbox_spring_2025_experiment',
value: { experiment_condition_count: 0 })
end
@experiment_setting = Setting.find_by(key: 'no_sandbox_spring_2025_experiment')
@course = course
@creator = creator
process_course
end
private
def process_course
# screen for eligibility
return unless eligible?
# handle not-first course from new instructor
handle_multiple_courses { return }
# check current number of experiment condition instructors
return if enough_already?
# choose randomly
coin_flip = [true, false].sample
# add tag and flag if selected
if coin_flip
mark_course_for_experiment
@experiment_setting.value[:experiment_condition_count] += 1
@experiment_setting.save!
else
mark_course_for_control
end
end
def eligible?
# screen out courses that weren't persisted
return false unless @course.persisted?
# Only courses happening in --Fall 2024-- Spring 2025
return false unless @course.start > '2025-01-01'.to_date
return false unless @course.start < '2025-04-01'.to_date
# Only first-time instructors
return false if @creator.returning_instructor?
true
end
# If another course from the same new instructor is already in the experiment
# we put this course into the same condition.
def handle_multiple_courses
if (@creator.courses & NoSandboxesFall2024Experiment.experiment_courses).any?
mark_course_for_experiment
yield
elsif (@creator.courses & NoSandboxesFall2024Experiment.control_courses).any?
mark_course_for_control
yield
end
end
def enough_already?
@experiment_setting.value[:experiment_condition_count] >= TARGET_NEW_INSTRUCTOR_COUNT
end
def mark_course_for_experiment
TagManager.new(@course).add(tag: EXPERIMENT_TAG, key: TAG_KEY)
@course.add_flag(key: :no_sandboxes)
end
def mark_course_for_control
TagManager.new(@course).add(tag: CONTROL_TAG, key: TAG_KEY)
end
end