Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a Practice ruleset to implement training phases #1360

Open
wants to merge 23 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0dec215
feat: add practice rules file
BeritJanssen Sep 3, 2024
84d9f11
feat: use Practice parent class in Duration Discrimination type rules
BeritJanssen Sep 10, 2024
ad738a8
use practice subclass for h_bat type experiments
BeritJanssen Sep 17, 2024
fa069b8
Merge branch 'develop' into feature/practice-rules
BeritJanssen Sep 17, 2024
3bf0159
fix: add conditions for h_bat
BeritJanssen Sep 23, 2024
24783d0
Merge branch 'develop' into feature/practice-rules
BeritJanssen Oct 21, 2024
5fd38ae
apply practice rules to h_bat
BeritJanssen Oct 21, 2024
05b5eb0
further abstraction: unify get_next_trial
BeritJanssen Oct 22, 2024
9f9f65b
fix tests
BeritJanssen Oct 22, 2024
77990a6
Merge branch 'develop' into feature/practice-rules
BeritJanssen Nov 5, 2024
8a5b796
fix: replace session.load_json_data()
BeritJanssen Nov 5, 2024
755da0b
fix unit tests
BeritJanssen Nov 5, 2024
a35e930
remove print statements from `create_default_questions`
BeritJanssen Nov 5, 2024
d6d8032
rename get_previous_n_results -> last_n_results
BeritJanssen Nov 5, 2024
85019b8
add tests for session .last_result methods
BeritJanssen Nov 5, 2024
476668b
rename session.json_data practice_finished -> practice_done throughout
BeritJanssen Nov 5, 2024
80a43fc
base rhythm_discrimination on practice rules
BeritJanssen Nov 5, 2024
a431269
correct title counter for practice
BeritJanssen Nov 5, 2024
c231a14
delete practice utils file
BeritJanssen Nov 5, 2024
ce1b7ac
Merge branch 'develop' into feature/practice-rules
BeritJanssen Nov 5, 2024
eacd97f
fix rhythm_discrimination test
BeritJanssen Nov 5, 2024
bac92b8
fix: condition for successful practice rhythm_discrimination
BeritJanssen Nov 5, 2024
b7f47b0
update and improve documentation
BeritJanssen Nov 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions backend/docs/experiment_rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

::: experiment.rules.base

## experiment.rules.staircasing
## experiment.rules.practice

::: experiment.rules.util.staircasing
::: experiment.rules.practice

## experiment.rules.practice
## experiment.rules.staircasing

::: experiment.rules.util.practice
::: experiment.rules.util.staircasing
129 changes: 42 additions & 87 deletions backend/experiment/rules/anisochrony.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import logging
from django.utils.translation import gettext_lazy as _

from section.models import Section
from experiment.actions import Trial, Explainer, Step
from experiment.actions.form import ChoiceQuestion, Form
from experiment.actions.playback import Autoplay
from experiment.actions import Explainer, Step
from experiment.actions.utils import render_feedback_trivia
from .duration_discrimination import DurationDiscrimination

Expand All @@ -16,12 +13,23 @@ class Anisochrony(DurationDiscrimination):
start_diff = 180000
practice_diff = 270000
max_turnpoints = 8
catch_condition = 'REGULAR'
task_description = "Anisochrony"
subtask = ""
first_condition = "irregular"
second_condition = "regular"
first_condition_i18n = _("IRREGULAR")
second_condition_i18n = _("REGULAR")
section_count = 249

def get_response_explainer(self, correct, correct_response, button_label=_('Next fragment')):
correct_response = _('REGULAR') if correct_response=='REGULAR' else _('IRREGULAR')
if correct:
def get_feedback_explainer(self, session):
button_label = _("Next fragment")
last_result = session.last_result()
correct_response = (
self.first_condition_i18n
if last_result.expected_response == self.first_condition
else self.second_condition_i18n
)
if last_result.given_response == last_result.expected_response:
instruction = _(
'The tones were {}. Your answer was CORRECT.').format(correct_response)
else:
Expand All @@ -33,88 +41,35 @@ def get_response_explainer(self, correct, correct_response, button_label=_('Next
button_label=button_label
)

def next_trial_action(self, session, trial_condition, difficulty):
"""
Provide the next trial action
Arguments:
- session: the session
- trial_condition: 1 for catch trial, 0 for normal trial
- difficulty: the current difficulty (in ms) of the trial
"""
from result.utils import prepare_result
if trial_condition == 1:
# catch trial
difference = 0
else:
difference = difficulty
try:
section = session.playlist.section_set.get(song__name=difference)
except Section.DoesNotExist:
return None
expected_response = 'REGULAR' if difference == 0 else 'IRREGULAR'
key = 'if_regular'
question = ChoiceQuestion(
key=key,
question=_(
"Were the tones REGULAR or IRREGULAR?"),
choices={
'REGULAR': _('REGULAR'),
'IRREGULAR': _('IRREGULAR')
},
view='BUTTON_ARRAY',
result_id=prepare_result(key, session, section=section, expected_response=expected_response),
submits=True
)

playback = Autoplay([section])
form = Form([question])
config = {
'listen_first': True,
'response_time': section.duration + .1
}
view = Trial(
playback=playback,
feedback_form=form,
title=_('Anisochrony'),
config=config
)
return view

def intro_explanation(self, *args):
def get_intro_explanainer(self):
return Explainer(
instruction=_(
'In this test you will hear a series of tones for each trial.'),
"In this test you will hear a series of tones for each trial."
),
steps=[
Step(_(
"It's your job to decide if the tones sound REGULAR or IRREGULAR")),
Step(_(
'During the experiment it will become more difficult to hear the difference.')),
Step(_(
"Try to answer as accurately as possible, even if you're uncertain.")),
Step(_(
"Remember: try not to move or tap along with the sounds")),
Step(_(
'This test will take around 4 minutes to complete. Try to stay focused for the entire test!'))
Step(
_("It's your job to decide if the tones sound REGULAR or IRREGULAR")
),
Step(
_(
"During the experiment it will become more difficult to hear the difference."
)
),
Step(
_(
"Try to answer as accurately as possible, even if you're uncertain."
)
),
Step(_("Remember: try not to move or tap along with the sounds")),
Step(
_(
"This test will take around 4 minutes to complete. Try to stay focused for the entire test!"
)
),
],
button_label='Ok'
button_label=_("Ok"),
)

def calculate_score(self, result, data):
# a result's score is used to keep track of how many correct results were in a row
# for catch trial, set score to 2 -> not counted for calculating turnpoints
try:
expected_response = result.expected_response
except Exception as e:
logger.log(e)
expected_response = None
if expected_response and expected_response == result.given_response:
if expected_response == 'IRREGULAR':
return 1
else:
return 2
else:
return 0

def get_final_text(self, difference):
percentage = round(difference / 6000, 2)
feedback = _(
Expand All @@ -123,8 +78,8 @@ def get_final_text(self, difference):
Our brains use this to process rhythm even better!")
return render_feedback_trivia(feedback, trivia)

def get_difficulty(self, session, multiplier=1.0):
if session.final_score == 0:
def get_difficulty(self, session):
if not session.json_data.get("practice_done"):
return self.practice_diff
else:
return super(Anisochrony, self).get_difficulty(session, multiplier)
return super().get_difficulty(session)
Loading