Skip to content

Commit

Permalink
Merge branch 'develop' into fix/logos
Browse files Browse the repository at this point in the history
  • Loading branch information
BeritJanssen committed Jun 11, 2024
2 parents 9cf22fd + 38669ad commit 2989ea1
Show file tree
Hide file tree
Showing 18 changed files with 383 additions and 30 deletions.
2 changes: 1 addition & 1 deletion backend/aml/base_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,4 @@
}
}

SUBPATH = os.getenv('AML_SUBPATH', None)
SUBPATH = os.getenv('AML_SUBPATH', '')
105 changes: 105 additions & 0 deletions backend/experiment/rules/tests/test_toontjehoger_4_absolute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from unittest.mock import patch

from django.test import TestCase

from section.models import Playlist as PlaylistModel

from experiment.rules.toontjehoger_4_absolute import ToontjeHoger4Absolute


class TestToontjeHoger4Absolute(TestCase):

def setUp(self):
# Mock the file_exists_validator function from section.models
# instead of section.validators as it is imported in the Playlist class
# which is in the section.models module
patcher = patch('section.models.file_exists_validator')
self.mock_file_exists_validator = patcher.start()
self.mock_file_exists_validator.return_value = None
self.addCleanup(patcher.stop)

def test_initializes_correctly(self):
toontje_hoger_4_absolute = ToontjeHoger4Absolute()
assert toontje_hoger_4_absolute.ID == 'TOONTJE_HOGER_4_ABSOLUTE'

def test_validate_valid_playlist(self):
csv_data = (
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-1.mp3,a,1\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-2.mp3,c,2\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-10.mp3,b,10\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-3.mp3,a,3\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-8.mp3,b,8\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-4.mp3,b,4\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-5.mp3,c,5\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-9.mp3,b,9\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-6.mp3,b,6\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-7.mp3,b,7\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-11.mp3,b,11\n"
)
playlist = PlaylistModel.objects.create(name='TestToontjeHoger4Absolute')
playlist.csv = csv_data
playlist.update_sections()

toontje_hoger_4_absolute = ToontjeHoger4Absolute()
self.assertEqual(
toontje_hoger_4_absolute.validate_playlist(playlist), []
)

def test_validate_invalid_integer_groups(self):
csv_data = (
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-1.mp3,a,a\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-2.mp3,c,2\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-3.mp3,a,4\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-4.mp3,b,4\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-5.mp3,c,11\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-6.mp3,b,7\n"
)
playlist = PlaylistModel.objects.create(name='TestToontjeHoger4Absolute')
playlist.csv = csv_data
playlist.update_sections()

toontje_hoger_4_absolute = ToontjeHoger4Absolute()

self.assertEqual(
toontje_hoger_4_absolute.validate_playlist(playlist),
["Groups in playlist sections should be numbers. This playlist has groups: ['a', '2', '4', '4', '11', '7']"]
)

def test_validate_invalid_sequential_groups(self):
csv_data = (
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-1.mp3,a,8\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-2.mp3,c,3\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-3.mp3,a,3\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-4.mp3,b,4\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-5.mp3,c,11\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-6.mp3,b,1\n"
)
playlist = PlaylistModel.objects.create(name='TestToontjeHoger4Absolute')
playlist.csv = csv_data
playlist.update_sections()

toontje_hoger_4_absolute = ToontjeHoger4Absolute()

self.assertEqual(
toontje_hoger_4_absolute.validate_playlist(playlist),
['Groups in playlist sections should be sequential numbers starting from 1 to the number of sections in the playlist (6). E.g. "1, 2, 3, ... 6"']
)

def test_validate_invalid_tags(self):
csv_data = (
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-1.mp3,a,1\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-2.mp3,c,2\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-3.mp3,a,3\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-4.mp3,b,4\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-5.mp3,c,5\n"
"Albania 2018 - Eugent Bushpepa,Mall,7.046,45.0,ToontjeHoger4Absolute/audio-6.mp3,d,6\n"
)
playlist = PlaylistModel.objects.create(name='TestToontjeHoger4AbsoluteInvalidTags')
playlist.csv = csv_data
playlist.update_sections()

toontje_hoger_4_absolute = ToontjeHoger4Absolute()
self.assertEqual(
toontje_hoger_4_absolute.validate_playlist(playlist),
['Tags in playlist sections should be \'a\', \'b\' or \'c\'. This playlist has tags: [\'a\', \'b\', \'c\', \'d\']']
)
83 changes: 83 additions & 0 deletions backend/experiment/rules/tests/test_toontjehoger_5_tempo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from unittest.mock import patch

from django.test import TestCase

from section.models import Playlist

from experiment.rules.toontjehoger_5_tempo import ToontjeHoger5Tempo


class TestToontjeHoger5Tempo(TestCase):

def setUp(self):
# Mock the file_exists_validator function from section.models
# instead of section.validators as it is imported in the Playlist class
# which is in the section.models module
patcher = patch('section.models.file_exists_validator')
self.mock_file_exists_validator = patcher.start()
self.mock_file_exists_validator.return_value = None
self.addCleanup(patcher.stop)

def test_validate_playlist_valid(self):
csv_data = (
"song-01,artist-01,7.046,45.0,ToontjeHoger5Tempo/song-01.mp3,C3_P2_OR,ch\n"
"song-02,artist-02,7.046,45.0,ToontjeHoger5Tempo/song-02.mp3,C2_P1_OR,ch\n"
"song-03,artist-03,7.046,45.0,ToontjeHoger5Tempo/song-03.mp3,C4_P2_OR,ch\n"
"song-04,artist-04,7.046,45.0,ToontjeHoger5Tempo/song-04.mp3,C4_P2_OR,ch\n"
"song-05,artist-05,7.046,45.0,ToontjeHoger5Tempo/song-05.mp3,C5_P2_OR,or\n"
"song-06,artist-06,7.046,45.0,ToontjeHoger5Tempo/song-06.mp3,C5_P2_CH,or\n"
"song-07,artist-07,7.046,45.0,ToontjeHoger5Tempo/song-07.mp3,C4_P1_OR,or\n"
"song-08,artist-08,7.046,45.0,ToontjeHoger5Tempo/song-08.mp3,C2_P1_CH,or\n"
"song-09,artist-09,7.046,45.0,ToontjeHoger5Tempo/song-09.mp3,C3_P1_OR,or\n"
"song-10,artist-10,7.046,45.0,ToontjeHoger5Tempo/song-10.mp3,C2_P2_OR,or\n"
)
playlist = Playlist.objects.create(name='TestToontjeHoger5Tempo')
playlist.csv = csv_data
playlist.update_sections()

toontje_hoger_5_tempo_rules = ToontjeHoger5Tempo()
self.assertEqual(
toontje_hoger_5_tempo_rules.validate_playlist(playlist), []
)

def test_validate_playlist_invalid_tags(self):
csv_data = (
"song-01,artist-01,7.046,45.0,ToontjeHoger5Tempo/song-01.mp3,F4_P2_OR,ch\n"
"song-02,artist-02,7.046,45.0,ToontjeHoger5Tempo/song-02.mp3,C4_P9_OR,ch\n"
"song-03,artist-03,7.046,45.0,ToontjeHoger5Tempo/song-03.mp3,C4_P2_ZR,ch\n"
"song-04,artist-04,7.046,45.0,ToontjeHoger5Tempo/song-04.mp3,C6_P1_OR,or\n"
"song-05,artist-05,7.046,45.0,ToontjeHoger5Tempo/song-05.mp3,C1_P3_OR,or\n"
"song-06,artist-06,7.046,45.0,ToontjeHoger5Tempo/song-06.mp3,C1_P1_OZ,or\n"
)
playlist = Playlist.objects.create(name='TestToontjeHoger5Tempo')
playlist.csv = csv_data
playlist.update_sections()

toontje_hoger_5_tempo_rules = ToontjeHoger5Tempo()
self.assertEqual(
toontje_hoger_5_tempo_rules.validate_playlist(playlist),
[
"Tags should start with either 'C', 'J' or 'R', followed by a number between "
"1 and 5, followed by '_P', followed by either 1 or 2, followed by either "
"'_OR' or '_CH'. Invalid tags: C1_P1_OZ, C1_P3_OR, C4_P2_ZR, C4_P9_OR, "
'C6_P1_OR, F4_P2_OR'
]
)

def test_validate_playlist_invalid_groups(self):
csv_data = (
"song-01,artist-01,7.046,45.0,ToontjeHoger5Tempo/song-01.mp3,C3_P2_OR,ch\n"
"song-02,artist-02,7.046,45.0,ToontjeHoger5Tempo/song-02.mp3,C2_P1_OR,ch\n"
"song-03,artist-03,7.046,45.0,ToontjeHoger5Tempo/song-03.mp3,C4_P2_OR,ch\n"
)
playlist = Playlist.objects.create(name='TestToontjeHoger5Tempo')
playlist.csv = csv_data
playlist.update_sections()

toontje_hoger_5_tempo_rules = ToontjeHoger5Tempo()
self.assertEqual(
toontje_hoger_5_tempo_rules.validate_playlist(playlist),
[
"The playlist must contain two groups: 'or' and 'ch'. Found: ['ch']"
]
)
51 changes: 51 additions & 0 deletions backend/experiment/rules/tests/test_toontjehoger_kids_5_tempo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from unittest.mock import patch

from django.test import TestCase

from section.models import Playlist

from experiment.rules.toontjehogerkids_5_tempo import ToontjeHogerKids5Tempo


class ToontjeHogerKids5TempoTest(TestCase):

def setUp(self):
# Mock the file_exists_validator function from section.models
# instead of section.validators as it is imported in the Playlist class
# which is in the section.models module
patcher = patch('section.models.file_exists_validator')
self.mock_file_exists_validator = patcher.start()
self.mock_file_exists_validator.return_value = None
self.addCleanup(patcher.stop)

# Toontje Hoger Kids 5 Tempo does not have the strict tag validation
# that Toontje Hoger 5 Tempo has. Therefore, we must ensure that
# the validate_playlist method does not raise any errors for tags
# that would be considered invalid in Toontje Hoger 5 Tempo.
def test_validate_playlist_valid(self):
csv_data = (
"song-01,artist-01,7.046,45.0,ToontjeHoger5Tempo/song-01.mp3,C3_P2_OR,ch\n"
"song-02,artist-02,7.046,45.0,ToontjeHoger5Tempo/song-02.mp3,C2_P1_OR,ch\n"
"song-03,artist-03,7.046,45.0,ToontjeHoger5Tempo/song-03.mp3,C4_P2_OR,ch\n"
"song-04,artist-04,7.046,45.0,ToontjeHoger5Tempo/song-04.mp3,C4_P2_OR,ch\n"
"song-05,artist-05,7.046,45.0,ToontjeHoger5Tempo/song-05.mp3,C5_P2_OR,ch\n"
"song-06,artist-06,7.046,45.0,ToontjeHoger5Tempo/song-06.mp3,C5_P2_CH,ch\n"
"song-07,artist-07,7.046,45.0,ToontjeHoger5Tempo/song-07.mp3,C4_P1_OR,ch\n"
"song-08,artist-08,7.046,45.0,ToontjeHoger5Tempo/song-08.mp3,C2_P1_CH,or\n"
"song-09,artist-09,7.046,45.0,ToontjeHoger5Tempo/song-09.mp3,C3_P1_OR,or\n"
"song-10,artist-10,7.046,45.0,ToontjeHoger5Tempo/song-10.mp3,C2_P2_OR,or\n"
"song-11,artist-11,7.046,45.0,ToontjeHoger5Tempo/song-11.mp3,F4_P2_OR,or\n"
"song-12,artist-12,7.046,45.0,ToontjeHoger5Tempo/song-12.mp3,C4_P9_OR,or\n"
"song-13,artist-13,7.046,45.0,ToontjeHoger5Tempo/song-13.mp3,C4_P2_ZR,or\n"
"song-14,artist-14,7.046,45.0,ToontjeHoger5Tempo/song-14.mp3,C6_P1_OR,or\n"
"song-15,artist-15,7.046,45.0,ToontjeHoger5Tempo/song-15.mp3,C1_P3_OR,or\n"
"song-16,artist-16,7.046,45.0,ToontjeHoger5Tempo/song-16.mp3,C1_P1_OZ,or\n"
)
playlist = Playlist.objects.create(name='TestToontjeHoger5Tempo')
playlist.csv = csv_data
playlist.update_sections()

toontje_hoger_5_tempo_rules = ToontjeHogerKids5Tempo()
self.assertEqual(
toontje_hoger_5_tempo_rules.validate_playlist(playlist), []
)
44 changes: 40 additions & 4 deletions backend/experiment/rules/toontjehoger_3_plink.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import logging
from os.path import join
import re

from django.template.loader import render_to_string

from .toontjehoger_1_mozart import toontjehoger_ranks
from experiment.actions import Explainer, Step, Score, Final, Playlist, Info, Trial
from experiment.actions.playback import PlayButton
from experiment.actions.form import AutoCompleteQuestion, RadiosQuestion, Form
from .base import Base

from experiment.utils import non_breaking_spaces

from result.utils import prepare_result
from section.models import Playlist

logger = logging.getLogger(__name__)

Expand All @@ -24,6 +25,41 @@ class ToontjeHoger3Plink(Base):
SCORE_EXTRA_2_CORRECT = 4
SCORE_EXTRA_WRONG = 0

def validate_playlist(self, playlist: Playlist):
""" The original Toontjehoger (Plink) playlist has the following format:
```
Billy Joel,Piano Man,0.0,1.0,toontjehoger/plink/2021-005.mp3,70s,vrolijk
Boudewijn de Groot,Avond,0.0,1.0,toontjehoger/plink/2021-010.mp3,90s,tederheid
Bruce Springsteen,The River,0.0,1.0,toontjehoger/plink/2021-016.mp3,80s,droevig
```
"""
errors = []
sections = playlist.section_set.all()
if not [s.song for s in sections]:
errors.append(
'Sections should have associated song objects.')
artist_titles = sections.values_list(
'song__name', 'song__artist').distinct()
if len(artist_titles) != len(sections):
errors.append(
'Sections should have unique combinations of song.artist and song.name fields.')
self.validate_era_and_mood(sections, errors)
return errors

def validate_era_and_mood(self, sections, errors):
eras = sorted(sections.order_by('tag').values_list(
'tag', flat=True).distinct())
if not all(re.match(r'[0-9]0s', e) for e in eras):
errors.append(
'The sections should be tagged with an era in the format [0-9]0s, e.g., 90s')
moods = sorted(sections.order_by('group').values_list(
'group', flat=True).distinct())
if 'droevig' not in moods:
errors.append(
"The sections' groups should be indications of the songs' moods in Dutch"
)
return errors

def first_round(self, experiment):
"""Create data for the first experiment rounds."""

Expand Down Expand Up @@ -206,7 +242,7 @@ def get_era_question(self, session, section):
'era',
session,
section=section,
expected_response=section.group.split(';')[0]
expected_response=section.tag
)
)

Expand All @@ -228,7 +264,7 @@ def get_emotion_question(self, session, section):
'emotion',
session,
section=section,
expected_response=section.group.split(';')[1]
expected_response=section.group
)
)

Expand Down
42 changes: 41 additions & 1 deletion backend/experiment/rules/toontjehoger_4_absolute.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import re
import logging
import random
from os.path import join
from django.template.loader import render_to_string
from section.models import Playlist
from experiment.utils import non_breaking_spaces
from .toontjehoger_1_mozart import toontjehoger_ranks
from experiment.actions import Trial, Explainer, Step, Score, Final, Info
Expand Down Expand Up @@ -149,7 +151,7 @@ def get_score(self, session):
config = {'show_total_score': True}
score = Score(session, config=config, feedback=feedback)
return [score]

def get_final_round(self, session):

# Finish session.
Expand Down Expand Up @@ -184,3 +186,41 @@ def get_final_round(self, session):
)

return [*score, final, info]

def validate_playlist_groups(self, groups):
integer_groups = []
integer_pattern = re.compile(r'^-?\d+$')
for group in groups:
if not integer_pattern.match(str(group)):
return ["Groups in playlist sections should be numbers. This playlist has groups: {}".format(groups)]

integer_groups.append(int(group))

# Check if the groups are sequential and unique
integer_groups.sort()
if integer_groups != list(range(1, len(groups) + 1)):
return ['Groups in playlist sections should be sequential numbers starting from 1 to the number of sections in the playlist ({}). E.g. "1, 2, 3, ... {}"'.format(len(groups), len(groups))]

return []

def validate_playlist(self, playlist: Playlist):
errors = super().validate_playlist(playlist)

# Get group values from sections, ordered by group
groups = list(playlist.section_set.values_list('group', flat=True))

# Check if the groups are sequential and unique
errors += self.validate_playlist_groups(groups)

# Check if the tags are 'a', 'b' or 'c'
tags = list(
playlist.section_set
.values_list('tag', flat=True)
.distinct()
.order_by('tag')
)

if tags != ['a', 'b', 'c']:
errors.append("Tags in playlist sections should be 'a', 'b' or 'c'. This playlist has tags: {}".format(tags))

return errors
Loading

0 comments on commit 2989ea1

Please sign in to comment.