Skip to content

Commit

Permalink
Fixed: Fix prepare_result function calls and add type hints (#701)
Browse files Browse the repository at this point in the history
* Fix: Fix prepare_result function calls in listening_conditions.py by adding key parameter

* fix: Fix Trial instantiation in ListeningConditions (second parameter is html, see trial.py)

* refactor: Add type hints to prepare_result function

* refactor: Include type hints to Trial class constructor

* Add test cases for ListeningConditions class

* fix(lint): Fix formatting in trial.py and remove unnecessary lines in test_listening_conditions.py

(cherry picked from commit 6f52358)
  • Loading branch information
drikusroor committed Jan 26, 2024
1 parent dab5b27 commit 6458b5d
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 13 deletions.
12 changes: 11 additions & 1 deletion backend/experiment/actions/trial.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.utils.translation import gettext_lazy as _

from .base_action import BaseAction
from experiment.actions.form import Form

class Trial(BaseAction): # pylint: disable=too-few-public-methods
"""
Expand All @@ -16,7 +17,16 @@ class Trial(BaseAction): # pylint: disable=too-few-public-methods

ID = 'TRIAL_VIEW'

def __init__(self, playback=None, html=None, feedback_form=None, title='', config=None, result_id=None, style=None):
def __init__(
self,
playback = None,
html: str = None,
feedback_form: Form = None,
title='',
config = None,
result_id = None,
style = None
):
'''
- playback: Playback object (may be None)
- html: HTML object (may be None)
Expand Down
12 changes: 7 additions & 5 deletions backend/experiment/rules/listening_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def next_round(self, session, request_session=None):
feedback_form = None
if round_number == 1:
key = 'quiet_room'
result_pk = prepare_result(session, expected_response=key)
result_pk = prepare_result(key, session, expected_response=key)
feedback_form = Form([
ChoiceQuestion(
key=key,
Expand All @@ -35,7 +35,7 @@ def next_round(self, session, request_session=None):
)])
elif round_number == 2:
key = 'internet_connection'
result_pk = prepare_result(session, expected_response=key)
result_pk = prepare_result(key, session, expected_response=key)
feedback_form = Form([ChoiceQuestion(
key='internet_connection',
question=_(
Expand All @@ -50,7 +50,7 @@ def next_round(self, session, request_session=None):
)])
elif round_number == 3:
key = 'headphones'
result_pk = prepare_result(session, expected_response=key)
result_pk = prepare_result(key, session, expected_response=key)
feedback_form = Form([
ChoiceQuestion(
key=key,
Expand All @@ -67,7 +67,7 @@ def next_round(self, session, request_session=None):
])
elif round_number == 4:
key = 'notifications_off'
result_pk = prepare_result(session, expected_response=key)
result_pk = prepare_result(key, session, expected_response=key)
feedback_form = Form([
ChoiceQuestion(
key=key,
Expand Down Expand Up @@ -96,7 +96,9 @@ def next_round(self, session, request_session=None):
session, message, request_session)
]
return actions
view = Trial(playback, feedback_form)

view = Trial(playback, feedback_form=feedback_form)

return [view]

def first_round(self, experiment):
Expand Down
76 changes: 76 additions & 0 deletions backend/experiment/rules/tests/test_listening_conditions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from django.test import TestCase
from section.models import Section, Song, Playlist as PlaylistModel
from participant.models import Participant
from session.models import Session
from experiment.models import Experiment
from experiment.rules.listening_conditions import ListeningConditions
from experiment.actions import Consent, Explainer, Final, Playback, Playlist, StartSession, Trial, Form
from experiment.actions.form import Form
from experiment.actions.playback import Playback


class ListeningConditionsTest(TestCase):

def setUp(self):
playlist = PlaylistModel.objects.create(
name='test'
)
song = Song.objects.create(
artist="Cheese Shop",
name="Gouda"
)
Section.objects.create(
playlist=playlist,
song=song,
filename="not/to_be_found.mp3",
tag=0
)
self.experiment = Experiment.objects.create(
name='test',
slug='TEST',
)
participant = Participant.objects.create()
self.session = Session.objects.create(
experiment=Experiment.objects.first(),
participant=participant,
playlist=playlist
)

def test_first_round(self):
listening_conditions = ListeningConditions()
actions = listening_conditions.first_round(self.experiment)

self.assertIsInstance(actions[0], Consent)
self.assertIsInstance(actions[1], Explainer)
self.assertIsInstance(actions[2], Playlist)
self.assertIsInstance(actions[3], StartSession)

def test_next_round_first_round(self):
listening_conditions = ListeningConditions()
listening_conditions.first_round(self.experiment)
actions = listening_conditions.next_round(self.session)

self.assertIsInstance(actions[0], Trial)

self.assertIsInstance(actions[0].feedback_form, Form)
self.assertEqual(len(actions[0].feedback_form.form), 1)
self.assertEqual(actions[0].feedback_form.form[0].key, 'quiet_room')

def test_next_round_final_round(self):
listening_conditions = ListeningConditions()
listening_conditions.first_round(self.experiment)
listening_conditions.next_round(self.session)
listening_conditions.next_round(self.session)
listening_conditions.next_round(self.session)
listening_conditions.next_round(self.session)
actions = listening_conditions.next_round(self.session)

self.assertIsInstance(actions[0], Trial)
self.assertIsInstance(actions[0].playback, Playback)
self.assertIsNone(actions[0].feedback_form) # Assuming no feedback form for the final round
self.assertIsInstance(actions[1], Final)

def test_next_round_does_not_throw_error(self):
listening_conditions = ListeningConditions()
listening_conditions.next_round(self.session)

16 changes: 9 additions & 7 deletions backend/result/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from session.models import Session
from .models import Result

from experiment.questions.profile_scoring_rules import PROFILE_SCORING_RULES
Expand All @@ -16,7 +17,7 @@ def get_result(session, data):
return result

def handle_results(data, session):
"""
"""
if the given_result is an array of results, retrieve and save results for all of them
else, handle results at top level
"""
Expand All @@ -39,7 +40,7 @@ def prepare_profile_result(question_key, participant, **kwargs):
- question_key: the key of the question in the questionnaire dictionaries
- participant: the participant on which the Result is going to be registered
possible kwargs:
- expected_response: optionally, provide the correct answer, used for scoring
- expected_response: optionally, provide the correct answer, used for scoring
- comment: optionally, provide a comment to be saved in the database
- scoring_rule: optionally, provide a scoring rule
'''
Expand All @@ -52,13 +53,14 @@ def prepare_profile_result(question_key, participant, **kwargs):
)
return result

def prepare_result(question_key, session, **kwargs):

def prepare_result(question_key: str, session: Session, **kwargs) -> int:
''' Create a Result object, and provide its id to be serialized
- question_key: the key of the question in the questionnaire dictionaries
- session: the session on which the Result is going to be registered
possible kwargs:
- section: optionally, provide a section to which the Result is going to be tied
- expected_response: optionally, provide the correct answer, used for scoring
- expected_response: optionally, provide the correct answer, used for scoring
- comment: optionally, provide a comment to be saved in the database, e.g. "training phase"
- scoring_rule: optionally, provide a scoring rule
'''
Expand All @@ -71,7 +73,7 @@ def prepare_result(question_key, session, **kwargs):

def score_result(data, session):
"""
Create a result for given session, based on the result data
Create a result for given session, based on the result data
(form element or top level data)
parameters:
session: a Session object
Expand All @@ -85,7 +87,7 @@ def score_result(data, session):
result.save_json_data(data)
result.given_response = data.get('value')
# Calculate score: by default, apply a scoring rule
# Can be overridden by defining calculate_score in the rules file
# Can be overridden by defining calculate_score in the rules file
if result.session:
score = session.experiment_rules().calculate_score(result, data)
# refresh session data in case anything was changed within calculate_score function
Expand All @@ -103,4 +105,4 @@ def apply_scoring_rule(result, data):
scoring_rule = SCORING_RULES.get(result.scoring_rule)
if scoring_rule:
return scoring_rule(result, data)
return None
return None

0 comments on commit 6458b5d

Please sign in to comment.