Skip to content

Commit

Permalink
fix: let request.session track the number of times an experiment was …
Browse files Browse the repository at this point in the history
…played
  • Loading branch information
BeritJanssen committed Nov 12, 2024
1 parent d744901 commit bdd0d3d
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 33 deletions.
17 changes: 5 additions & 12 deletions backend/experiment/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def serialize_social_media_config(
}


def serialize_phase(phase: Phase, participant: Participant) -> dict:
def serialize_phase(phase: Phase, participant: Participant, times_played: int) -> dict:
"""Serialize phase
Args:
Expand All @@ -103,7 +103,7 @@ def serialize_phase(phase: Phase, participant: Participant) -> dict:
"""
blocks = list(phase.blocks.order_by("index").all())

next_block = get_upcoming_block(phase, participant)
next_block = get_upcoming_block(phase, participant, times_played)
if not next_block:
return None

Expand Down Expand Up @@ -137,7 +137,7 @@ def serialize_block(block_object: Block, language: str = "en") -> dict:
}


def get_upcoming_block(phase: Phase, participant: Participant):
def get_upcoming_block(phase: Phase, participant: Participant, times_played: int):
"""return next block with minimum finished sessions for this participant
if all blocks have been played an equal number of times, return None
Expand All @@ -154,15 +154,8 @@ def get_upcoming_block(phase: Phase, participant: Participant):

min_session_count = min(finished_session_counts)
if not phase.dashboard:
phase_profile, _created = Result.objects.get_or_create(
participant=participant, question_key=f"{str(phase)}-xplayed"
)
max_session_count = max(finished_session_counts)
if max_session_count == min_session_count:
if phase_profile.score != min_session_count:
phase_profile.score += 1
phase_profile.save()
return None
if times_played != min_session_count:
return None
next_block_index = finished_session_counts.index(min_session_count)
return serialize_block(blocks[next_block_index])

Expand Down
14 changes: 8 additions & 6 deletions backend/experiment/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def setUpTestData(cls):
block.save()

def test_serialize_phase(self):
phase = serialize_phase(self.phase1, self.participant)
phase = serialize_phase(self.phase1, self.participant, 0)
self.assertIsNotNone(phase)
next_block_slug = phase.get("nextBlock").get("slug")
self.assertEqual(phase.get("dashboard"), [])
Expand All @@ -50,30 +50,32 @@ def test_serialize_phase(self):
block=Block.objects.get(slug=next_block_slug),
finished_at=timezone.now(),
)
phase = serialize_phase(self.phase1, self.participant)
phase = serialize_phase(self.phase1, self.participant, 0)
self.assertIsNone(phase)

def test_upcoming_block(self):
block = get_upcoming_block(self.phase1, self.participant)
block = get_upcoming_block(self.phase1, self.participant, 0)
self.assertEqual(block.get("slug"), "rhythm_intro")
Session.objects.create(
block=Block.objects.get(slug=block.get("slug")),
participant=self.participant,
finished_at=timezone.now(),
)
block = get_upcoming_block(self.phase1, self.participant)
block = get_upcoming_block(self.phase1, self.participant, 0)
self.assertIsNone(block)
for i in range(3):
block = get_upcoming_block(self.phase2, self.participant)
block = get_upcoming_block(self.phase2, self.participant, 0)
self.assertIsNotNone(block)
self.assertIn(block.get("slug"), ["ddi", "hbat_bit", "rhdis"])
Session.objects.create(
block=Block.objects.get(slug=block.get("slug")),
participant=self.participant,
finished_at=timezone.now(),
)
block = get_upcoming_block(self.phase2, self.participant)
block = get_upcoming_block(self.phase2, self.participant, 0)
self.assertIsNone(block)
block = get_upcoming_block(self.phase1, self.participant, 1)
self.assertIsNotNone(block)

def test_serialize_block(self):
# Create the experiment & phase for the block
Expand Down
31 changes: 25 additions & 6 deletions backend/experiment/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ class TestExperimentViews(TestCase):
@classmethod
def setUpTestData(cls):
cls.participant = Participant.objects.create()
session = cls.client.session
session["participant_id"] = cls.participant.id
session.save()
theme_config = create_theme_config()
experiment = Experiment.objects.create(
slug="test_series",
Expand All @@ -47,6 +44,11 @@ def setUpTestData(cls):
cls.final_phase = Phase.objects.create(experiment=experiment, index=3)
cls.block4 = Block.objects.create(slug="block4", phase=cls.final_phase)

def setUp(self):
session = self.client.session
session["participant_id"] = self.participant.id
session.save()

def test_get_experiment(self):
# check that the correct block is returned correctly
response = self.client.get("/experiment/test_series/")
Expand All @@ -69,6 +71,21 @@ def test_get_experiment(self):
self.assertEqual(response_json.get("socialMedia").get("content"), "Please play this Test experiment!")
self.assertEqual(response_json.get("socialMedia").get("tags"), ["aml", "toontjehoger"])
self.assertEqual(response_json.get("socialMedia").get("channels"), ["facebook", "twitter", "weibo"])
Session.objects.create(
block=self.block4, participant=self.participant, finished_at=timezone.now()
)
# starting second round of experiment
response = self.client.get("/experiment/test_series/")
response_json = response.json()
self.assertIsNotNone(response_json)
self.assertEqual(response_json.get("nextBlock").get("slug"), "block1")
Session.objects.create(
block=self.block1, participant=self.participant, finished_at=timezone.now()
)
response = self.client.get("/experiment/test_series/")
response_json = response.json()
self.assertIsNotNone(response_json)
self.assertIn(response_json.get("nextBlock").get("slug"), ("block2", "block3"))

def test_experiment_not_found(self):
# if Experiment does not exist, return 404
Expand Down Expand Up @@ -164,9 +181,9 @@ def test_experiment_get_fallback_content(self):

# request experiment with language set to English (British)
response = self.client.get(
"/experiment/test_experiment_translated_content/", headers={"Accept-Language": "en-Gb"}
"/experiment/test_experiment_translated_content/",
headers={"Accept-Language": "en-Gb"},
)

# since English translation is available, the English content should be returned
self.assertEqual(response.json().get("name"), "Test Experiment Fallback Content")

Expand All @@ -180,7 +197,9 @@ def test_experiment_get_fallback_content(self):
response = self.client.get("/experiment/test_experiment_translated_content/", headers={"Accept-Language": "nl"})

# since no Dutch translation is available, the fallback content should be returned
self.assertEqual(response.json().get("name"), "Test Experiment Fallback Content")=å
self.assertEqual(
response.json().get("name"), "Test Experiment Fallback Content"
)

def test_get_block(self):
# Create a block
Expand Down
21 changes: 12 additions & 9 deletions backend/experiment/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,18 @@ def get_experiment(
{"error": "This experiment does not have phases and blocks configured"},
status=500,
)
phase_key = 'f"{slug}-phase"'
phase_index = request.session.get(phase_key, 0)
if phase_index == len(phases):
phase_index = 0
serialized_phase = serialize_phase(phases[phase_index], participant)
if not serialized_phase:
phase_index += 1
request.session[phase_key] = phase_index
serialized_phase = serialize_phase(phases[phase_index], participant)
times_played_key = 'f"{slug}-xplayed"'
times_played = request.session.get(times_played_key, 0)
for phase in phases:
serialized_phase = serialize_phase(phase, participant, times_played)
if serialized_phase:
return JsonResponse(
{**serialize_experiment(experiment), **serialized_phase}
)
# if no phase was found, start from scratch by incrementing times_pleyd
times_played += 1
request.session[times_played_key] = times_played
serialized_phase = serialize_phase(phases[0], participant, times_played)
return JsonResponse({**serialize_experiment(experiment), **serialized_phase})


Expand Down

0 comments on commit bdd0d3d

Please sign in to comment.