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

Hotfix/speech2song #1036

Merged
merged 3 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion backend/experiment/actions/base_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ def action(self):
action_dict = self.__dict__
action_dict['view'] = self.ID

if self.style is not None:
# we may have already converted the style object to a dictionary, e.g., after copying an Action object
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just interested: Why could this be converted to a dict already? Shouldn't serialization ideally happen at the end?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not if we are using copies of the same object, which speech2song does. It makes on Trial object, and from that creates an array of [Trial]*n_representations. As the serialization goes through the list of actions, it will have already converted the Playback's style object to a dict, so in the next step it will attempt to apply the to_dict method again to the style attribute. Took me quite a long time to understand what was going on and why.

if self.style is not None and type(self.style) is not dict:
action_dict['style'] = self.style.to_dict()

return action_dict
14 changes: 8 additions & 6 deletions backend/experiment/rules/speech2song.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from experiment.questions.languages import LANGUAGE, LanguageQuestion
from experiment.questions.utils import question_by_key

from session.models import Session

from result.utils import prepare_result

n_representations = 8
Expand Down Expand Up @@ -59,9 +61,9 @@ def first_round(self, experiment):
playlist = Playlist(experiment.playlists.all())

return [
explainer,
consent,
playlist,
explainer,
]

def next_round(self, session):
Expand Down Expand Up @@ -152,7 +154,7 @@ def next_round(self, session):
return Final(
title=_('End of experiment'),
session=session,
score_message=_(
final_text=_(
'Thank you for contributing your time to science!')
)
if session.current_round % 2 == 0:
Expand All @@ -166,7 +168,7 @@ def next_round(self, session):
return actions


def next_single_representation(session, is_speech, group_id):
def next_single_representation(session: Session, is_speech: bool, group_id: int) -> list:
""" combine a question after the first representation,
and several repeated representations of the sound,
with a final question"""
Expand All @@ -176,8 +178,8 @@ def next_single_representation(session, is_speech, group_id):
return actions


def next_repeated_representation(session, is_speech, group_id=-1):
if group_id >= 0:
def next_repeated_representation(session: Session, is_speech: bool, group_id: int = -1) -> list:
if group_id == 0:
# for the Test case, there is no previous section to look at
section = session.playlist.section_set.get(group=group_id)
else:
Expand All @@ -187,7 +189,7 @@ def next_repeated_representation(session, is_speech, group_id=-1):
return actions


def speech_or_sound_question(session, section, is_speech):
def speech_or_sound_question(session, section, is_speech) -> Trial:
if is_speech:
question = question_speech(session, section)
else:
Expand Down
72 changes: 72 additions & 0 deletions backend/experiment/rules/tests/test_speech2song.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from django.test import TestCase

from experiment.models import Experiment
from participant.models import Participant
from result.models import Result
from section.models import Playlist
from session.models import Session

from experiment.actions import Trial
from experiment.rules.speech2song import next_repeated_representation, next_single_representation, sound, Speech2Song
from experiment.serializers import serialize_actions


class Speech2SongTest(TestCase):

@classmethod
def setUpTestData(cls):
section_csv = ("transforming,Sometimes behave so strangely.wav,0,2.14,s2s/TEST/Sometimes behave so strangely.wav,1,0\n"
"transforming,And a joy it would be.wav,0,0.94,s2s/EN/Transforming/And a joy it would be.wav,1,1\n"
"non-transforming,The limpid Walbrook.wav,0,1.20,s2s/EN/Non-Transforming/The limpid Walbrook.wav,0,1\n"
"transforming,De abacaxi não tem.wav,0,1.19,s2s/BP/Transforming/De abacaxi não tem.wav,1,2\n"
"non-transforming,Minha sobrinha.wav,0,0.99,s2s/BP/Non-Transforming/Minha sobrinha.wav,0,2\n"
"transforming,三分钟读一页书.wav,0,1.51,s2s/MC/Transforming/三分钟读一页书.wav,1,3\n"
"non-transforming,网上有地图.wav,0,1.13,s2s/MC/Non-Transforming/网上有地图.wav,0,3\n"
"transforming,Hermit Thrush1.wav,0,1.19,s2s/ENV/Transforming/Hermit Thrush1.wav,1,4\n"
"non-transforming,Snow walking.wav,0,1.30,s2s/ENV/Non-Transforming/Snow walking.wav,0,4\n"
)
cls.playlist = Playlist.objects.create(name='TestSpeech2Song')
cls.playlist.csv = section_csv
cls.playlist.update_sections()
cls.participant = Participant.objects.create()
cls.experiment = Experiment.objects.create(
rules='SPEECH_TO_SONG', slug='s2s', rounds=42)
cls.session = Session.objects.create(
experiment=cls.experiment,
participant=cls.participant,
playlist=cls.playlist
)

def test_sound_method(self):
section = self.playlist.section_set.first()
view = sound(section)
self.assertEqual(type(view), Trial)

def test_single_presentation(self):
group = self.playlist.section_set.first().group
actions = next_single_representation(self.session, True, int(group))
self.assertEqual(type(actions), list)

def test_repeated_presentation(self):
section = self.playlist.section_set.first()
Result.objects.create(
question_key='speech2song',
session=self.session,
section=section,
score=2
)
actions = next_repeated_representation(self.session, True)
self.assertEqual(type(actions), list)

def test_next_round(self):
speech2song = Speech2Song()
actions = speech2song.next_round(self.session)
self.assertEqual(type(actions), list)

def test_next_round_serialization(self):
speech2song = Speech2Song()
actions = speech2song.next_round(self.session)
serialized = serialize_actions(actions)
self.assertEqual(type(serialized), list)
for s in serialized:
self.assertEqual(type(s), dict)
Loading