diff --git a/backend/experiment/admin.py b/backend/experiment/admin.py index ea335a608..d5a2e3765 100644 --- a/backend/experiment/admin.py +++ b/backend/experiment/admin.py @@ -24,7 +24,7 @@ class ExperimentAdmin(InlineActionsModelAdminMixin, admin.ModelAdmin): search_fields = ['name'] inline_actions = ['export', 'export_csv'] fields = ['name', 'slug', 'url', 'hashtag', 'language', 'active', 'rules', - 'rounds', 'bonus_points', 'playlists', 'experiment_series'] + 'rounds', 'bonus_points', 'playlists', 'experiment_series','questions'] inlines = [FeedbackInline] form = ExperimentForm @@ -99,7 +99,6 @@ def export_csv(self, request, obj, parent_obj=None): export_csv.short_description = "Export CSV" - admin.site.register(Experiment, ExperimentAdmin) class ModelFormFieldAsJSON(ModelMultipleChoiceField): diff --git a/backend/experiment/fixtures/experiment.json b/backend/experiment/fixtures/experiment.json index beb0c6fdc..f70c8a6b2 100644 --- a/backend/experiment/fixtures/experiment.json +++ b/backend/experiment/fixtures/experiment.json @@ -242,6 +242,9 @@ 13, 2, 1 + ], + "questions": [ + "msi_01_music_activities", "msi_03_writing", "msi_08_intrigued_styles", "msi_15_internet_search_music", "msi_21_spend_income", "msi_24_music_addiction", "msi_28_track_new", "msi_34_attended_events", "msi_38_listen_music", "msi_05_good_singer", "msi_06_song_first_time", "msi_11_spot_mistakes", "msi_12_performance_diff", "msi_13_trouble_recognising", "msi_18_out_of_beat", "msi_22_out_of_tune", "msi_23_no_idea_in_tune", "msi_26_genre", "msi_14_never_complimented", "msi_27_consider_musician", "msi_32_practice_years", "msi_33_practice_daily", "msi_35_theory_training", "msi_36_instrumental_training", "msi_37_play_instruments", "msi_04_sing_along", "msi_07_from_memory", "msi_10_sing_with_recording", "msi_17_not_sing_harmony", "msi_25_sing_public", "msi_29_sing_after_hearing", "msi_30_sing_back", "msi_02_shivers", "msi_09_rarely_emotions", "msi_16_motivate", "msi_19_identify_special", "msi_20_talk_emotions", "msi_31_memories", "msi_39_best_instrument", "dgf_genre_preference_zh", "dgf_generation", "dgf_education", "dgf_highest_qualification_expectation", "dgf_occupational_status", "dgf_region_of_origin", "dgf_region_of_residence", "dgf_gender_identity_zh", "contact" ] } }, @@ -344,231 +347,10 @@ "experiment_series": null, "playlists": [ 18 + ], + "questions": [ + "dgf_generation", "dgf_gender_identity", "P01_1", "P01_2", "P01_3", "P02_1", "P02_2", "P02_3", "P03_1", "P03_2", "P03_3", "P04_1", "P04_2", "P04_3", "P04_4", "P05_1", "P05_2", "P05_3", "P05_4", "P05_5", "P06_1", "P06_2", "P06_3", "P06_4", "P07_1", "P07_2", "P07_3", "P08_1", "P08_2", "P08_3", "P09_1", "P09_2", "P09_3", "P10_1", "P10_2", "P10_3", "P11_1", "P11_2", "P11_3", "P12_1", "P12_2", "P12_3", "P13_1", "P13_2", "P13_3", "P14_1", "P14_2", "P14_3", "P14_4", "P15_1", "P15_2", "P15_3", "P15_4", "P16_1", "P16_2", "P16_3", "P17_1", "P17_2", "P17_3" ] } -}, -{ - "model": "experiment.feedback", - "pk": 1, - "fields": { - "text": "", - "experiment": 15 - } -}, -{ - "model": "experiment.feedback", - "pk": 2, - "fields": { - "text": "", - "experiment": 15 - } -}, -{ - "model": "experiment.feedback", - "pk": 3, - "fields": { - "text": "", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 4, - "fields": { - "text": "hh started this test at 11:52 and played until 11:58. But filled in the feedback and submitted at 12: 05.", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 5, - "fields": { - "text": "I breakdown music by ear a lot, so I found this very interesting. After the top row I realized I needed to jot down reminders on scratch paper. Figuring out what is the most effective approach to summarizing a snippet is a great problem to solve. Maybe I will craft a longer response in an email.", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 6, - "fields": { - "text": "Not an easy Play. Cannon say That I plagend it well.", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 7, - "fields": { - "text": "", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 8, - "fields": { - "text": "", - "experiment": 14 - } -}, -{ - "model": "experiment.feedback", - "pk": 9, - "fields": { - "text": "Hi folks! This is the second time I played, and it worked just like a memory game where two \"cards\" were identical. The first time I played, it was a little different - one of the cards sounded like it was being played through some kind of filter and the other was normal. Also, when I got to the end one was the \"Westworld\" theme and its match did not really sound like it was a match. Not sure if any of this is intentional but I thought I'd let you know! :)", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 10, - "fields": { - "text": "This was really hard!!", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 11, - "fields": { - "text": "Sometimes when I clicked, no music played. Not sure if my bluetooth connection was hijacked. Every time I could fix it by clicking on another one -- but I guess that decreased my performance a bit.", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 12, - "fields": { - "text": "Boring excerpts. Rules aren't clear.", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 13, - "fields": { - "text": "I notice that when I click play again, then after finishing the game, it adds the points to the previous points. I wonder if this is the intented behaviour. Very cool application tho!", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 14, - "fields": { - "text": "Were last two correct?! ", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 15, - "fields": { - "text": "DJB game post fix 1 ", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 16, - "fields": { - "text": "game 3 o", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 17, - "fields": { - "text": "game 3 or 4 for me ", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 18, - "fields": { - "text": "That's really cool! ", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 19, - "fields": { - "text": "", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 20, - "fields": { - "text": "play across board djb", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 21, - "fields": { - "text": "First four cards I clicked already showed misremembered.", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 22, - "fields": { - "text": "Yes ER theme tune! What nostalgia!! ", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 23, - "fields": { - "text": "None of the songs were from TV shows", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 24, - "fields": { - "text": "This is way too hard", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 25, - "fields": { - "text": "I was too lazy to read the instructions and didn't realize the task at first. But got the hang of it soon enough.", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 26, - "fields": { - "text": "Pairs are much easier to remember when you know the themes (which is not my case for the most part)\nFun to play ! ", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 27, - "fields": { - "text": "Nice work!", - "experiment": 17 - } -}, -{ - "model": "experiment.feedback", - "pk": 28, - "fields": { - "text": "nice", - "experiment": 17 - } } ] diff --git a/backend/experiment/forms.py b/backend/experiment/forms.py index 508c9e47d..acbf046ce 100644 --- a/backend/experiment/forms.py +++ b/backend/experiment/forms.py @@ -2,6 +2,9 @@ from experiment.models import Experiment from experiment.rules import EXPERIMENT_RULES +from django.forms import TypedMultipleChoiceField, CheckboxSelectMultiple +from .questions import QUESTIONS_CHOICES + # session_keys for Export CSV SESSION_CHOICES = [('experiment_id', 'Experiment ID'), ('experiment_name', 'Experiment name'), @@ -127,7 +130,12 @@ def __init__(self, *args, **kwargs): choices += ((i, EXPERIMENT_RULES[i].__name__),) self.fields['rules'] = ChoiceField( - choices=choices + choices=sorted(choices) + ) + + self.fields['questions'] = TypedMultipleChoiceField( + choices=QUESTIONS_CHOICES, + widget=CheckboxSelectMultiple ) class Meta: diff --git a/backend/experiment/migrations/0017_experiment_add_questions_field.py b/backend/experiment/migrations/0017_experiment_add_questions_field.py new file mode 100644 index 000000000..4cd0f1abb --- /dev/null +++ b/backend/experiment/migrations/0017_experiment_add_questions_field.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.20 on 2023-11-16 10:56 + +import django.contrib.postgres.fields +from django.db import migrations, models +import experiment.questions + + +class Migration(migrations.Migration): + + dependencies = [ + ('section', '0005_section_add_validator'), + ('experiment', '0016_add_social_media_fields'), + ] + + operations = [ + migrations.AddField( + model_name='experiment', + name='questions', + field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('DEMOGRAPHICS', [('dgf_gender_identity', '(dgf_gender_identity) With which gender do you currently most identify?'), ('dgf_generation', '(dgf_generation) When were you born?'), ('dgf_country_of_origin', '(dgf_country_of_origin) In which country did you spend the most formative years of your childhood and youth?'), ('dgf_education', '(dgf_education) What is the highest educational qualification that you have attained?'), ('dgf_country_of_residence', '(dgf_country_of_residence) In which country do you currently reside?'), ('dgf_genre_preference', '(dgf_genre_preference) To which group of musical genres do you currently listen most?')]), ('EXTRA_DEMOGRAPHICS', [('dgf_age', '(dgf_age) What is your age?'), ('dgf_country_of_origin_open', '(dgf_country_of_origin_open) In which country did you spend the most formative years of your childhood and youth?'), ('dgf_country_of_residence_open', '(dgf_country_of_residence_open) In which country do you currently reside?'), ('dgf_native_language', '(dgf_native_language) What is your native language?'), ('dgf_highest_qualification_expectation', '(dgf_highest_qualification_expectation) If you are still in education, what is the highest qualification you expect to obtain?'), ('dgf_occupational_status', '(dgf_occupational_status) Occupational status'), ('dgf_gender_reduced', '(dgf_gender_reduced) What is your gender?'), ('dgf_musical_experience', '(dgf_musical_experience) Please select your level of musical experience:')]), ('MSI_F1_ACTIVE_ENGAGEMENT', [('msi_01_music_activities', '(msi_01_music_activities) I spend a lot of my free time doing music-related activities.'), ('msi_03_writing', '(msi_03_writing) I enjoy writing about music, for example on blogs and forums.'), ('msi_08_intrigued_styles', '(msi_08_intrigued_styles) I’m intrigued by musical styles I’m not familiar with and want to find out more.'), ('msi_15_internet_search_music', '(msi_15_internet_search_music) I often read or search the internet for things related to music.'), ('msi_21_spend_income', '(msi_21_spend_income) I don’t spend much of my disposable income on music.'), ('msi_24_music_addiction', '(msi_24_music_addiction) Music is kind of an addiction for me: I couldn’t live without it.'), ('msi_28_track_new', '(msi_28_track_new) I keep track of new music that I come across (e.g. new artists or recordings).'), ('msi_34_attended_events', '(msi_34_attended_events) I have attended _ live music events as an audience member in the past twelve months.'), ('msi_38_listen_music', '(msi_38_listen_music) I listen attentively to music for _ per day.')]), ('MSI_F2_PERCEPTUAL_ABILITIES', [('msi_05_good_singer', '(msi_05_good_singer) I am able to judge whether someone is a good singer or not.'), ('msi_06_song_first_time', '(msi_06_song_first_time) I usually know when I’m hearing a song for the first time.'), ('msi_11_spot_mistakes', '(msi_11_spot_mistakes) I find it difficult to spot mistakes in a performance of a song even if I know the tune.'), ('msi_12_performance_diff', '(msi_12_performance_diff) I can compare and discuss differences between two performances or versions of the same piece of music.'), ('msi_13_trouble_recognising', '(msi_13_trouble_recognising) I have trouble recognising a familiar song when played in a different way or by a different performer.'), ('msi_18_out_of_beat', '(msi_18_out_of_beat) I can tell when people sing or play out of time with the beat.'), ('msi_22_out_of_tune', '(msi_22_out_of_tune) I can tell when people sing or play out of tune.'), ('msi_23_no_idea_in_tune', '(msi_23_no_idea_in_tune) When I sing, I have no idea whether I’m in tune or not.'), ('msi_26_genre', '(msi_26_genre) When I hear a piece of music I can usually identify its genre.')]), ('MSI_F3_MUSICAL_TRAINING', [('msi_14_never_complimented', '(msi_14_never_complimented) I have never been complimented for my talents as a musical performer.'), ('msi_27_consider_musician', '(msi_27_consider_musician) I would not consider myself a musician.'), ('msi_32_practice_years', '(msi_32_practice_years) I engaged in regular, daily practice of a musical instrument (including voice) for _ years.'), ('msi_33_practice_daily', '(msi_33_practice_daily) At the peak of my interest, I practised my primary instrument for _ hours per day.'), ('msi_35_theory_training', '(msi_35_theory_training) I have had formal training in music theory for _ years.'), ('msi_36_instrumental_training', '(msi_36_instrumental_training) I have had _ years of formal training on a musical instrument (including voice) during my lifetime.'), ('msi_37_play_instruments', '(msi_37_play_instruments) How many musical instruments can you play?')]), ('MSI_F4_SINGING_ABILITIES', [('msi_04_sing_along', '(msi_04_sing_along) If somebody starts singing a song I don’t know, I can usually join in.'), ('msi_07_from_memory', '(msi_07_from_memory) I can sing or play music from memory.'), ('msi_10_sing_with_recording', '(msi_10_sing_with_recording) I am able to hit the right notes when I sing along with a recording.'), ('msi_17_not_sing_harmony', '(msi_17_not_sing_harmony) I am not able to sing in harmony when somebody is singing a familiar tune.'), ('msi_25_sing_public', '(msi_25_sing_public) I don’t like singing in public because I’m afraid that I would sing wrong notes.'), ('msi_29_sing_after_hearing', '(msi_29_sing_after_hearing) After hearing a new song two or three times, I can usually sing it by myself.'), ('msi_30_sing_back', '(msi_30_sing_back) I only need to hear a new tune once and I can sing it back hours later.')]), ('MSI_F5_EMOTIONS', [('msi_02_shivers', '(msi_02_shivers) I sometimes choose music that can trigger shivers down my spine.'), ('msi_09_rarely_emotions', '(msi_09_rarely_emotions) Pieces of music rarely evoke emotions for me.'), ('msi_16_motivate', '(msi_16_motivate) I often pick certain music to motivate or excite me.'), ('msi_19_identify_special', '(msi_19_identify_special) I am able to identify what is special about a given musical piece.'), ('msi_20_talk_emotions', '(msi_20_talk_emotions) I am able to talk about the emotions that a piece of music evokes for me.'), ('msi_31_memories', '(msi_31_memories) Music can evoke my memories of past people and places.')]), ('MSI_OTHER', [('msi_39_best_instrument', '(msi_39_best_instrument) The instrument I play best, including voice (or none), is:'), ('ST_01_age_instrument', '(ST_01_age_instrument) What age did you start to play an instrument?'), ('AP_01_absolute_pitch', "(AP_01_absolute_pitch) Do you have absolute pitch? Absolute or perfect pitch is the ability to recognise and name an isolated musical tone without a reference tone, e.g. being able to say 'F#' if someone plays that note on the piano.")]), ('LANGUAGE', [('lang_experience', '(lang_experience) Please rate your previous experience:'), ('lang_mother', '(lang_mother) What is your mother tongue?'), ('lang_second', '(lang_second) What is your second language, if applicable?'), ('lang_third', '(lang_third) What is your third language, if applicable?')]), ('MUSICGENS_17_W_VARIANTS', [('P01_1', '(P01_1) Can you clap in time with a musical beat?'), ('P01_2', '(P01_2) I can tap my foot in time with the beat of the music I hear.'), ('P01_3', '(P01_3) When listening to music, can you move in time with the beat?'), ('P02_1', '(P02_1) I can recognise a piece of music after hearing just a few notes.'), ('P02_2', '(P02_2) I can easily recognise a familiar song.'), ('P02_3', "(P02_3) When I hear the beginning of a song I know immediately whether I've heard it before or not."), ('P03_1', '(P03_1) I can tell when people sing out of tune.'), ('P03_2', '(P03_2) I am able to judge whether someone is a good singer or not.'), ('P03_3', '(P03_3) I find it difficult to spot mistakes in a performance of a song even if I know the tune.'), ('P04_1', '(P04_1) I feel chills when I hear music that I like.'), ('P04_2', '(P04_2) I get emotional listening to certain pieces of music.'), ('P04_3', '(P04_3) I become tearful or cry when I listen to a melody that I like very much.'), ('P04_4', '(P04_4) Music gives me shivers or goosebumps.'), ('P05_1', "(P05_1) When I listen to music I'm absorbed by it."), ('P05_2', '(P05_2) While listening to music, I become so involved that I forget about myself and my surroundings.'), ('P05_3', "(P05_3) When I listen to music I get so caught up in it that I don't notice anything."), ('P05_4', "(P05_4) I feel like I am 'one' with the music."), ('P05_5', '(P05_5) I lose myself in music.'), ('P06_1', '(P06_1) I like listening to music.'), ('P06_2', '(P06_2) I enjoy music.'), ('P06_3', '(P06_3) I listen to music for pleasure.'), ('P06_4', "(P06_4) Music is kind of an addiction for me - I couldn't live without it."), ('P07_1', '(P07_1) I can tell when people sing or play out of time with the beat of the music.'), ('P07_2', '(P07_2) I can hear when people are not in sync when they play a song.'), ('P07_3', '(P07_3) I can tell when music is sung or played in time with the beat.'), ('P08_1', '(P08_1) I can sing or play a song from memory.'), ('P08_2', '(P08_2) Singing or playing music from memory is easy for me.'), ('P08_3', '(P08_3) I find it hard to sing or play a song from memory.'), ('P09_1', "(P09_1) When I sing, I have no idea whether I'm in tune or not."), ('P09_2', '(P09_2) I am able to hit the right notes when I sing along with a recording.'), ('P09_3', '(P09_3) I can sing along with other people.'), ('P10_1', '(P10_1) I have no sense for rhythm (when I listen, play or dance to music).'), ('P10_2', '(P10_2) Understanding the rhythm of a piece is easy for me (when I listen, play or dance to music).'), ('P10_3', '(P10_3) I have a good sense of rhythm (when I listen, play, or dance to music).'), ('P11_1', "(P11_1) Do you have absolute pitch? Absolute pitch is the ability to recognise and name an isolated musical tone without a reference tone, e.g. being able to say 'F#' if someone plays that note on the piano."), ('P11_2', '(P11_2) Do you have perfect pitch?'), ('P11_3', "(P11_3) If someone plays a note on an instrument and you can't see what note it is, can you still name it (e.g. say that is a 'C' or an 'F')?"), ('P12_1', '(P12_1) Can you hear the difference between two melodies?'), ('P12_2', '(P12_2) I can recognise differences between melodies even if they are similar.'), ('P12_3', '(P12_3) I can tell when two melodies are the same or different.'), ('P13_1', '(P13_1) I make up new melodies in my mind.'), ('P13_2', "(P13_2) I make up songs, even when I'm just singing to myself."), ('P13_3', '(P13_3) I like to play around with new melodies that come to my mind.'), ('P14_1', '(P14_1) I have a melody stuck in my mind.'), ('P14_2', '(P14_2) I experience earworms.'), ('P14_3', '(P14_3) I get music stuck in my head.'), ('P14_4', '(P14_4) I have a piece of music stuck on repeat in my head.'), ('P15_1', '(P15_1) Music makes me dance.'), ('P15_2', "(P15_2) I don't like to dance, not even with music I like."), ('P15_3', '(P15_3) I can dance to a beat.'), ('P15_4', '(P15_4) I easily get into a groove when listening to music.'), ('P16_1', '(P16_1) Can you hear the difference between two rhythms?'), ('P16_2', '(P16_2) I can tell when two rhythms are the same or different.'), ('P16_3', '(P16_3) I can recognise differences between rhythms even if they are similar.'), ('P17_1', "(P17_1) I can't help humming or singing along to music that I like."), ('P17_2', "(P17_2) When I hear a tune I like a lot I can't help tapping or moving to its beat."), ('P17_3', '(P17_3) Hearing good music makes me want to sing along.')]), ('STOMP', [('stomp_alternative', '(stomp_alternative) How much do you like alternative music?'), ('stomp_blues', '(stomp_blues) How much do you like blues music?'), ('stomp_classical', '(stomp_classical) How much do you like classical music?'), ('stomp_country', '(stomp_country) How much do you like country music?'), ('stomp_dance', '(stomp_dance) How much do you like dance and electronic music?'), ('stomp_folk', '(stomp_folk) How much do you like folk music?'), ('stomp_funk', '(stomp_funk) How much do you like funk music?'), ('stomp_gospel', '(stomp_gospel) How much do you like gospel music?'), ('stomp_metal', '(stomp_metal) How much do you like heavy metal music?'), ('stomp_world', '(stomp_world) How much do you like world music?'), ('stomp_jazz', '(stomp_jazz) How much do you like jazz music?'), ('stomp_new_age', '(stomp_new_age) How much do you like new-age music?'), ('stomp_opera', '(stomp_opera) How much do you like opera music?'), ('stomp_pop', '(stomp_pop) How much do you like pop music?'), ('stomp_punk', '(stomp_punk) How much do you like punk music?'), ('stomp_rap', '(stomp_rap) How much do you like rap and hip-hop music?'), ('stomp_reggae', '(stomp_reggae) How much do you like reggae music?'), ('stomp_religious', '(stomp_religious) How much do you like religious music?'), ('stomp_rock', '(stomp_rock) How much do you like rock music?'), ('stomp_rnb', '(stomp_rnb) How much do you like soul and R&B music?'), ('stomp_bluegrass', '(stomp_bluegrass) How much do you like bluegrass music?'), ('stomp_oldies', '(stomp_oldies) How much do you like oldies music?'), ('stomp_soundtracks', '(stomp_soundtracks) How much do you like soundtracks and theme-song music?')]), ('TIPI', [('tipi_op', '(tipi_op) I see myself as open to new experiences and complex.'), ('tipi_on', '(tipi_on) I see myself as conventional and uncreative.'), ('tipi_cp', '(tipi_cp) I see myself as dependable and self-disciplined.'), ('tipi_cn', '(tipi_cn) I see myself as disorganised and careless.'), ('tipi_ep', '(tipi_ep) I see myself as extraverted and enthusiastic.'), ('tipi_en', '(tipi_en) I see myself as reserved and quiet.'), ('tipi_ap', '(tipi_ap) I see myself as sympathetic and warm.'), ('tipi_an', '(tipi_an) I see myself as critical and quarrelsome.'), ('tipi_np', '(tipi_np) I see myself as anxious and easily upset.'), ('tipi_nn', '(tipi_nn) I see myself as calm and emotionally stable.')]), ('OTHER', [('dgf_region_of_origin', '(dgf_region_of_origin) In which region did you spend the most formative years of your childhood and youth?'), ('dgf_region_of_residence', '(dgf_region_of_residence) In which region do you currently reside?'), ('dgf_gender_identity_zh', '(dgf_gender_identity_zh) 您目前对自己的性别认识?'), ('dgf_genre_preference_zh', '(dgf_genre_preference_zh) To which group of musical genres do you currently listen most?'), ('contact', '(contact) Contact (optional):')])]), blank=True, default=experiment.questions.get_default_question_keys, size=None), + ), + migrations.AlterField( + model_name='experiment', + name='playlists', + field=models.ManyToManyField(blank=True, to='section.Playlist'), + ), + ] diff --git a/backend/experiment/migrations/0018_set_default_question_data.py b/backend/experiment/migrations/0018_set_default_question_data.py new file mode 100644 index 000000000..5c1c33fb2 --- /dev/null +++ b/backend/experiment/migrations/0018_set_default_question_data.py @@ -0,0 +1,21 @@ +from django.db import migrations +from experiment.rules import EXPERIMENT_RULES + +def set_default_question_data(apps, schema_editor): + + Experiment = apps.get_model("experiment", "Experiment") + + for experiment in Experiment.objects.all(): + experiment.questions = [q.key for q in EXPERIMENT_RULES[experiment.rules]().questions] + experiment.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('experiment', '0017_experiment_add_questions_field'), + ] + + operations = [ + migrations.RunPython(set_default_question_data, reverse_code=migrations.RunPython.noop), + ] diff --git a/backend/experiment/models.py b/backend/experiment/models.py index c6fb10b37..0812485ba 100644 --- a/backend/experiment/models.py +++ b/backend/experiment/models.py @@ -5,6 +5,10 @@ from experiment.rules import EXPERIMENT_RULES from experiment.standards.iso_languages import ISO_LANGUAGES +from django.contrib.postgres.fields import ArrayField +from .questions import QUESTIONS_CHOICES, get_default_question_keys +from django import forms + language_choices = [(key, ISO_LANGUAGES[key]) for key in ISO_LANGUAGES.keys()] language_choices[0] = ('', 'Unset') @@ -36,6 +40,11 @@ class Experiment(models.Model): default="", blank=True, choices=language_choices, max_length=2) experiment_series = models.ForeignKey(ExperimentSeries, on_delete=models.SET_NULL, blank=True, null=True) + questions = ArrayField( + models.TextField(choices=QUESTIONS_CHOICES), + blank=True, + default=get_default_question_keys + ) class Meta: ordering = ['name'] @@ -189,4 +198,4 @@ def max_score(self): class Feedback(models.Model): text = models.TextField() - experiment = models.ForeignKey(Experiment, on_delete=models.CASCADE) \ No newline at end of file + experiment = models.ForeignKey(Experiment, on_delete=models.CASCADE) diff --git a/backend/experiment/questions/__init__.py b/backend/experiment/questions/__init__.py index e69de29bb..4058bc3d6 100644 --- a/backend/experiment/questions/__init__.py +++ b/backend/experiment/questions/__init__.py @@ -0,0 +1,43 @@ +from .demographics import DEMOGRAPHICS, EXTRA_DEMOGRAPHICS +from .goldsmiths import MSI_F1_ACTIVE_ENGAGEMENT, MSI_F2_PERCEPTUAL_ABILITIES, MSI_F3_MUSICAL_TRAINING, MSI_F4_SINGING_ABILITIES, MSI_F5_EMOTIONS, MSI_OTHER +from .languages import LANGUAGE +from .musicgens import MUSICGENS_17_W_VARIANTS +from .stomp import STOMP +from .tipi import TIPI +from .other import OTHER + +# Label of the group as it will apear in the admin +QUESTION_GROUPS = [ ("DEMOGRAPHICS",DEMOGRAPHICS), + ("EXTRA_DEMOGRAPHICS",EXTRA_DEMOGRAPHICS), + ("MSI_F1_ACTIVE_ENGAGEMENT",MSI_F1_ACTIVE_ENGAGEMENT), + ("MSI_F2_PERCEPTUAL_ABILITIES",MSI_F2_PERCEPTUAL_ABILITIES), + ("MSI_F3_MUSICAL_TRAINING",MSI_F3_MUSICAL_TRAINING), + ("MSI_F4_SINGING_ABILITIES",MSI_F4_SINGING_ABILITIES), + ("MSI_F5_EMOTIONS",MSI_F5_EMOTIONS), + ("MSI_OTHER",MSI_OTHER), + ("LANGUAGE",LANGUAGE), + ("MUSICGENS_17_W_VARIANTS",MUSICGENS_17_W_VARIANTS), + ("STOMP",STOMP), + ("TIPI",TIPI), + ("OTHER",OTHER) +] + +QUESTIONS_ALL = [] +KEYS_ALL = [] +QUESTIONS_CHOICES = [] + +for question_group in QUESTION_GROUPS: + QUESTIONS_ALL.extend(question_group[1]) + KEYS_ALL.extend([question.key for question in question_group[1]]) + QUESTIONS_CHOICES.append( (question_group[0], [(q.key,"("+q.key+") "+q.question) for q in question_group[1]]) ) + +def get_default_question_keys(): + return [q.key for q in DEMOGRAPHICS] + + +def get_questions_from_keys(keys): + """ Returns questions in the order of keys""" + return [QUESTIONS_ALL[KEYS_ALL.index(key)] for key in keys] + +if len(KEYS_ALL) != len(set(KEYS_ALL)): + raise Exception("Duplicate question keys") diff --git a/backend/experiment/questions/demographics.py b/backend/experiment/questions/demographics.py index eb3987002..ad8fd11f5 100644 --- a/backend/experiment/questions/demographics.py +++ b/backend/experiment/questions/demographics.py @@ -74,13 +74,6 @@ 'contemporary': _("Hip-hop/R&B/Funk") } ), - # msi_39_best_instrument duplicate in goldsmiths.py - TextQuestion( - key='msi_39_best_instrument', - view='STRING', - question=_("The instrument I play best, including voice (or none), is:") - ), - ] diff --git a/backend/experiment/questions/musicgens.py b/backend/experiment/questions/musicgens.py index 73bd49d3e..120e1ca59 100644 --- a/backend/experiment/questions/musicgens.py +++ b/backend/experiment/questions/musicgens.py @@ -1,3 +1,5 @@ +from django.utils.translation import gettext_lazy as _ + from experiment.actions.form import LikertQuestion, RadiosQuestion def musicgens_question(key, question): @@ -6,258 +8,370 @@ def musicgens_question(key, question): key = key, question = question, choices = { - 1: "Never", - 2: "Not Very Often", - 3: "Occasionally", - 4: "Sometimes", - 5: "Very Often", - 6: "Always" + 1: _("Never"), + 2: _("Rarely"), + 3: _("Once in a while"), + 4: _("Sometimes"), + 5: _("Very often"), + 6: _("Always") }, - explainer = "Please tell us how much you agree" + explainer = _("Please tell us how much you agree") + ) + +def musicgens_radio_question(key, question): + """Define a MusicGens question with three radio buttons """ + return RadiosQuestion( + key = key, + question = question, + choices = { + 1: _("Yes"), + 0: _("No"), + -1: _("I'm not sure") + } ) MUSICGENS_17_W_VARIANTS = [ musicgens_question( "P01_1", - "Can you clap in time with a musical beat?" + _("Can you clap in time with a musical beat?") ), musicgens_question( "P01_2", - "I can tap my foot in time with the beat of the music I hear." + _("I can tap my foot in time with the beat of the music I hear.") ), musicgens_question( "P01_3", - "When listening to music, can you move in time with the beat?" + _("When listening to music, can you move in time with the beat?") ), musicgens_question( "P02_1", - "I can recognise a piece of music after hearing just a few notes." + _("I can recognise a piece of music after hearing just a few notes.") ), musicgens_question( "P02_2", - "I can easily recognise a familiar song." + _("I can easily recognise a familiar song.") ), musicgens_question( "P02_3", - "When I hear the beginning of a song I know immediately whether I've heard it before or not." + _("When I hear the beginning of a song I know immediately whether I've heard it before or not.") ), musicgens_question( "P03_1", - "I can tell when people sing out of tune." + _("I can tell when people sing out of tune.") ), musicgens_question( "P03_2", - "I am able to judge whether someone is a good singer or not." + _("I am able to judge whether someone is a good singer or not.") ), musicgens_question( "P03_3", - "I find it difficult to spot mistakes in a performance of a song even if I know the tune." + _("I find it difficult to spot mistakes in a performance of a song even if I know the tune.") ), musicgens_question( "P04_1", - "I feel chills when I hear music that I like." + _("I feel chills when I hear music that I like.") ), musicgens_question( "P04_2", - "I get emotional listening to certain pieces of music." + _("I get emotional listening to certain pieces of music.") ), musicgens_question( "P04_3", - "I become tearful or cry when I listen to a melody that I like very much." + _("I become tearful or cry when I listen to a melody that I like very much.") ), musicgens_question( "P04_4", - "Music gives me shivers or goosebumps." + _("Music gives me shivers or goosebumps.") ), musicgens_question( "P05_1", - "When I listen to music I'm absorbed by it." + _("When I listen to music I'm absorbed by it.") ), musicgens_question( "P05_2", - "While listening to music, I become so involved that I forget about myself and my surroundings." + _("While listening to music, I become so involved that I forget about myself and my surroundings.") ), musicgens_question( "P05_3", - "When I listen to music I get so caught up in it that I don't notice anything." + _("When I listen to music I get so caught up in it that I don't notice anything.") ), musicgens_question( "P05_4", - "I feel like I am 'one' with the music." + _("I feel like I am 'one' with the music.") ), musicgens_question( "P05_5", - "I lose myself in music." + _("I lose myself in music.") ), musicgens_question( "P06_1", - "I like listening to music." + _("I like listening to music.") ), musicgens_question( "P06_2", - "I enjoy music." + _("I enjoy music.") ), musicgens_question( "P06_3", - "I listen to music for pleasure." + _("I listen to music for pleasure.") ), musicgens_question( "P06_4", - "Music is kind of an addiction for me - I couldn't live without it." + _("Music is kind of an addiction for me - I couldn't live without it.") ), musicgens_question( "P07_1", - "I can tell when people sing or play out of time with the beat of the music." + _("I can tell when people sing or play out of time with the beat of the music.") ), musicgens_question( "P07_2", - "I can hear when people are not in sync when they play a song." + _("I can hear when people are not in sync when they play a song.") ), musicgens_question( "P07_3", - "I can tell when music is sung or played in time with the beat." + _("I can tell when music is sung or played in time with the beat.") ), musicgens_question( "P08_1", - "I can sing or play a song from memory." + _("I can sing or play a song from memory.") ), musicgens_question( "P08_2", - "Singing or playing music from memory is easy for me." + _("Singing or playing music from memory is easy for me.") ), musicgens_question( "P08_3", - "I find it hard to sing or play a song from memory." + _("I find it hard to sing or play a song from memory.") ), musicgens_question( "P09_1", - "When I sing, I have no idea whether I'm in tune or not." + _("When I sing, I have no idea whether I'm in tune or not.") ), musicgens_question( "P09_2", - "I am able to hit the right notes when I sing along with a recording." + _("I am able to hit the right notes when I sing along with a recording.") ), musicgens_question( "P09_3", - "I can sing along with other people." + _("I can sing along with other people.") ), musicgens_question( "P10_1", - "I have no sense for rhythm (when I listen, play or dance to music)." + _("I have no sense for rhythm (when I listen, play or dance to music).") ), musicgens_question( "P10_2", - "Understanding the rhythm of a piece is easy for me (when I listen, play or dance to music)." + _("Understanding the rhythm of a piece is easy for me (when I listen, play or dance to music).") ), musicgens_question( "P10_3", - "I have a good sense of rhythm (when I listen, play, or dance to music)." + _("I have a good sense of rhythm (when I listen, play, or dance to music).") ), - RadiosQuestion( - key = "P11_1", - question = "Do you have absolute pitch? Absolute pitch is the ability to recognise and name an isolated musical tone without a reference tone, e.g. being able to say 'F#' if someone plays that note on the piano.", - choices = { - 1: "Yes", - 0: "No", - -1: "I'm Not Sure" - } + musicgens_radio_question( + "P11_1", + _("Do you have absolute pitch? Absolute pitch is the ability to recognise and name an isolated musical tone without a reference tone, e.g. being able to say 'F#' if someone plays that note on the piano."), ), - RadiosQuestion( - key="P11_2", - question="Do you have perfect pitch?", - choices = { - 1: "Yes", - 0: "No", - -1: "I'm Not Sure" - } + musicgens_radio_question( + "P11_2", + _("Do you have perfect pitch?"), ), - RadiosQuestion( - key="P11_3", - question="If someone plays a note on an instrument and you can't see what note it is, can you still name it (e.g. say that is a 'C' or an 'F')?", - choices = { - 1: "Yes", - 0: "No", - -1: "I'm Not Sure" - } + musicgens_radio_question( + "P11_3", + _("If someone plays a note on an instrument and you can't see what note it is, can you still name it (e.g. say that is a 'C' or an 'F')?") ), musicgens_question( "P12_1", - "Can you hear the difference between two melodies?" + _("Can you hear the difference between two melodies?") ), musicgens_question( "P12_2", - "I can recognise differences between melodies even if they are similar." + _("I can recognise differences between melodies even if they are similar.") ), musicgens_question( "P12_3", - "I can tell when two melodies are the same or different." + _("I can tell when two melodies are the same or different.") ), musicgens_question( "P13_1", - "I make up new melodies in my mind." + _("I make up new melodies in my mind.") ), musicgens_question( "P13_2", - "I make up songs, even when I'm just singing to myself." + _("I make up songs, even when I'm just singing to myself.") ), musicgens_question( "P13_3", - "I like to play around with new melodies that come to my mind." + _("I like to play around with new melodies that come to my mind.") ), musicgens_question( "P14_1", - "I have a melody stuck in my mind." + _("I have a melody stuck in my mind.") ), musicgens_question( "P14_2", - "I experience earworms." + _("I experience earworms.") ), musicgens_question( "P14_3", - "I get music stuck in my head." + _("I get music stuck in my head.") ), musicgens_question( "P14_4", - "I have a piece of music stuck on repeat in my head." + _("I have a piece of music stuck on repeat in my head.") ), musicgens_question( "P15_1", - "Music makes me dance." + _("Music makes me dance.") ), musicgens_question( "P15_2", - "I don't like to dance, not even with music I like." + _("I don't like to dance, not even with music I like.") ), musicgens_question( "P15_3", - "I can dance to a beat." + _("I can dance to a beat.") ), musicgens_question( "P15_4", - "I easily get into a groove when listening to music." + _("I easily get into a groove when listening to music.") ), musicgens_question( "P16_1", - "Can you hear the difference between two rhythms?" + _("Can you hear the difference between two rhythms?") ), musicgens_question( "P16_2", - "I can tell when two rhythms are the same or different." + _("I can tell when two rhythms are the same or different.") ), musicgens_question( "P16_3", - "I can recognise differences between rhythms even if they are similar." + _("I can recognise differences between rhythms even if they are similar.") ), musicgens_question( "P17_1", - "I can't help humming or singing along to music that I like." + _("I can't help humming or singing along to music that I like.") ), musicgens_question( "P17_2", - "When I hear a tune I like a lot I can't help tapping or moving to its beat." + _("When I hear a tune I like a lot I can't help tapping or moving to its beat.") ), musicgens_question( "P17_3", - "Hearing good music makes me want to sing along." + _("Hearing good music makes me want to sing along.") + ) +] + +MUSICGENS_EXTRA = [ + RadiosQuestion( + key = "PHENOTYPES_1", + question = _("Please select the sentence that describes your level of achievement in music."), + choices = { + 1: _("I have no training or recognised talent in this area."), + 2: _("I play one or more musical instruments proficiently."), + 3: _("I have played with a recognised orchestra or band."), + 4: _("I have composed an original piece of music."), + 5: _("My musical talent has been critiqued in a local publication."), + 6: _("My composition has been recorded."), + 7: _("Recordings of my composition have been sold publicly."), + 8: _("My compositions have been critiqued in a national publication."), + 9: _(" My compositions have been critiqued in multiple national publications.") + } + ), + RadiosQuestion( + key = "PHENOTYPES_2", + question = _("How engaged with music are you? Singing, playing, and even writing music counts here. Please choose the answer which describes you best."), + choices = { + 1: _("I am not engaged in music at all."), + 2: _("I am self-taught and play music privately, but I have never played, sung, or shown my music to others."), + 3: _("I have taken lessons in music, but I have never played, sung, or shown my music to others."), + 4: _("I have played or sung, or my music has been played in public concerts in my home town, but I have not been paid for this."), + 5: _("I have played or sung, or my music has been played in public concerts in my home town, and I have been paid for this."), + 6: _("I am professionally active as a musician."), + 7: _("I am professionally active as a musician and have been reviewed/featured in the national or international media and/or have received an award for my musical activities.") + } + ), + RadiosQuestion( + key = "PHENOTYPES_3", + question = _("I have never been complimented for my talents as a musical performer."), + choices = { + 1: _("Completely disagree"), + 2: _("Strongly disagree"), + 3: _("Disagree"), + 4: _("Neither agree nor disagree"), + 5: _("Agree"), + 6: _("Strongly agree"), + 7: _("Completely agree") + } + ), + RadiosQuestion( + key = "PHENOTYPES_4", + question = _("To what extent do you agree that you see yourself as someone who is sophisticated in art, music, or literature?"), + choices = { + 1: _("Agree strongly"), + 2: _("Agree moderately"), + 3: _("Agree slightly"), + 4: _("Disagree slightly"), + 5: _("Disagree moderately"), + 6: _("Disagree strongly") + } + ), + RadiosQuestion( + key = "PHENOTYPES_5", + question = _("At the peak of my interest, I practised ___ hours on my primary instrument (including voice)."), + choices = { + 1: _("0"), + 2: _("0.5"), + 3: _("1"), + 4: _("1.5"), + 5: _("3–4"), + 6: _("5 or more") + } + ), + RadiosQuestion( + key = "PHENOTYPES_6", + question = _("How often did you play or sing during the most active period?"), + choices = { + 1: _("Every day"), + 2: _("More than 1x per week"), + 3: _("1x per week"), + 4: _("1x per month") + } + ), + RadiosQuestion( + key = "PHENOTYPES_7", + question = _("How long (duration) did you play or sing during the most active period?"), + choices = { + 1: _("More than 1 hour per week"), + 2: _("1 hour per week"), + 3: _("Less than 1 hour per week") + } + ), + RadiosQuestion( + key = "PHENOTYPES_8", + question = _("About how many hours do you usually spend each week playing a musical instrument?"), + choices = { + 1: _("None"), + 2: _("1 hour or less a week"), + 3: _("2–3 hours a week"), + 4: _("4–5 hours a week"), + 5: _("6–7 hours a week"), + 6: _("8 or more hours a week") + } + ), + RadiosQuestion( + key = "PHENOTYPES_9", + question = _("Indicate approximately how many hours per week you have played or practiced any musical instrument at all, i.e., all different instruments, on average over the last 10 years."), + choices = { + 1: _("less than 1 hour per week"), + 2: _("1 hour per week"), + 3: _("2 hours per week"), + 4: _("3 hours per week"), + 5: _("4–5 hours per week"), + 6: _("6–9 hours per week"), + 7: _("10–14 hours per week"), + 8: _("15–24 hours per week"), + 9: _("25–40 hours per week"), + 10: _("41 or more hours per week") + } ) ] diff --git a/backend/experiment/questions/other.py b/backend/experiment/questions/other.py new file mode 100644 index 000000000..1d9217b41 --- /dev/null +++ b/backend/experiment/questions/other.py @@ -0,0 +1,73 @@ +from experiment.actions.form import Question, ChoiceQuestion +from django.utils.translation import gettext_lazy as _ + + +region_choices = { + 'HD': '华东(山东、江苏、安徽、浙江、福建、江西、上海)', + 'HN': '华南(广东、广西、海南)', + 'HZ': '华中(湖北、湖南、河南、江西)', + 'HB': '华北(北京、天津、河北、山西、内蒙古)', + 'XB': '西北(宁夏、新疆、青海、陕西、甘肃)', + 'XN': '西南(四川、云南、贵州、西藏、重庆)', + 'DB': '东北(辽宁、吉林、黑龙江)', + 'GAT': '港澳台(香港、澳门、台湾)', + 'QT': '国外', + 'no_answer': '不想回答' +} + +OTHER = [ + + ChoiceQuestion( + key='dgf_region_of_origin', + view='DROPDOWN', + question=_( + "In which region did you spend the most formative years of your childhood and youth?"), + choices=region_choices, + ), + + ChoiceQuestion( + view='DROPDOWN', + key='dgf_region_of_residence', + question=_("In which region do you currently reside?"), + choices=region_choices, + ), + + ChoiceQuestion( + key='dgf_gender_identity_zh', + view='RADIOS', + question="您目前对自己的性别认识?", + choices={ + 'male': "男", + 'Female': "女", + 'Others': "其他", + 'no_answer': "不想回答" + } + ), + + ChoiceQuestion( + view='DROPDOWN', + key='dgf_genre_preference_zh', + question=_( + "To which group of musical genres do you currently listen most?"), + choices={ + 'unpretentious': _("Pop/Country/Religious"), + 'Chinese artistic': _("Folk/Mountain songs"), + 'sophisticated': _("Western classical music/Jazz/Opera/Musical"), + 'classical': _("Chinese opera"), + 'intense': _("Rock/Punk/Metal"), + 'mellow': _("Dance/Electronic/New Age"), + 'contemporary': _("Hip-hop/R&B/Funk"), + } + ), + + Question( + key='contact', + explainer=_( + "Thank you so much for your feedback! Feel free to include your contact information if you would like a reply or skip if you wish to remain anonymous." + ), + question=_( + "Contact (optional):" + ), + is_skippable=True + ) +] \ No newline at end of file diff --git a/backend/experiment/rules/base.py b/backend/experiment/rules/base.py index aa06d648e..f02f1d15d 100644 --- a/backend/experiment/rules/base.py +++ b/backend/experiment/rules/base.py @@ -6,9 +6,11 @@ from experiment.actions import Final, Form, Trial from experiment.questions.demographics import DEMOGRAPHICS -from experiment.questions.utils import unanswered_questions +from experiment.questions.goldsmiths import MSI_OTHER +from experiment.questions.utils import question_by_key, unanswered_questions from result.score import SCORING_RULES +from experiment.questions import get_questions_from_keys logger = logging.getLogger(__name__) @@ -16,9 +18,9 @@ class Base(object): """Base class for other rules classes""" contact_email = settings.CONTACT_MAIL - + def __init__(self): - self.questions = DEMOGRAPHICS + self.questions = DEMOGRAPHICS + [question_by_key('msi_39_best_instrument', MSI_OTHER)] def feedback_info(self): feedback_body = render_to_string('feedback/user_feedback.html', {'email': self.contact_email}) @@ -113,8 +115,9 @@ def get_single_question(self, session, randomize=False): def get_questionnaire(self, session, randomize=False, cutoff_index=None): ''' Get a list of questions to be asked in succession ''' + trials = [] - questions = list(unanswered_questions(session.participant, self.questions, randomize, cutoff_index)) + questions = list(unanswered_questions(session.participant, get_questions_from_keys(session.experiment.questions), randomize, cutoff_index)) open_questions = len(questions) if not open_questions: return None diff --git a/backend/experiment/rules/categorization.py b/backend/experiment/rules/categorization.py index c4a11c663..66ef5a5ed 100644 --- a/backend/experiment/rules/categorization.py +++ b/backend/experiment/rules/categorization.py @@ -354,7 +354,6 @@ def plan_experiment(self, session): def plan_phase(self, session): json_data = session.load_json_data() - print(json_data['group'], session.playlist.section_set.first().tag) if 'training' in json_data['phase']: # Retrieve training stimuli for the assigned group if json_data["group"] == 'S1': @@ -385,7 +384,6 @@ def plan_phase(self, session): section_sequence.append(sections[0].song_id) section_sequence.append(sections[1].song_id) random.shuffle(section_sequence) - print(section_sequence) json_data['sequence'] = section_sequence else: diff --git a/backend/experiment/rules/hooked.py b/backend/experiment/rules/hooked.py index f85e5d29f..680501a12 100644 --- a/backend/experiment/rules/hooked.py +++ b/backend/experiment/rules/hooked.py @@ -10,6 +10,8 @@ from experiment.actions.form import BooleanQuestion, Form from experiment.actions.playback import Playback from experiment.questions.demographics import DEMOGRAPHICS +from experiment.questions.goldsmiths import MSI_OTHER +from experiment.questions.utils import question_by_key from experiment.questions.utils import copy_shuffle from experiment.questions.goldsmiths import MSI_FG_GENERAL, MSI_ALL from experiment.questions.stomp import STOMP20 @@ -35,6 +37,7 @@ class Hooked(Base): def __init__(self): self.questions = [ *copy_shuffle(DEMOGRAPHICS), # 1. Demographic questions (7 questions) + question_by_key('msi_39_best_instrument', MSI_OTHER), *copy_shuffle(MSI_FG_GENERAL), # 2. General music sophistication *copy_shuffle(MSI_ALL), # 3. Complete music sophistication (20 questions) *copy_shuffle(STOMP20), # 4. STOMP (20 questions) diff --git a/backend/experiment/rules/huang_2022.py b/backend/experiment/rules/huang_2022.py index b64eda68e..d4ddfcfd4 100644 --- a/backend/experiment/rules/huang_2022.py +++ b/backend/experiment/rules/huang_2022.py @@ -8,7 +8,8 @@ from experiment.actions.form import BooleanQuestion, ChoiceQuestion, Form, Question from experiment.actions.playback import Playback from experiment.questions.demographics import EXTRA_DEMOGRAPHICS -from experiment.questions.goldsmiths import MSI_ALL +from experiment.questions.goldsmiths import MSI_ALL, MSI_OTHER +from experiment.questions.other import OTHER from experiment.questions.utils import question_by_key from experiment.actions.styles import STYLE_BOOLEAN_NEGATIVE_FIRST from result.utils import prepare_result @@ -16,80 +17,6 @@ logger = logging.getLogger(__name__) -region_choices = { - 'HD': '华东(山东、江苏、安徽、浙江、福建、江西、上海)', - 'HN': '华南(广东、广西、海南)', - 'HZ': '华中(湖北、湖南、河南、江西)', - 'HB': '华北(北京、天津、河北、山西、内蒙古)', - 'XB': '西北(宁夏、新疆、青海、陕西、甘肃)', - 'XN': '西南(四川、云南、贵州、西藏、重庆)', - 'DB': '东北(辽宁、吉林、黑龙江)', - 'GAT': '港澳台(香港、澳门、台湾)', - 'QT': '国外', - 'no_answer': '不想回答' -} - - -def origin_question(): - return ChoiceQuestion( - key='dgf_region_of_origin', - view='DROPDOWN', - question=_( - "In which region did you spend the most formative years of your childhood and youth?"), - choices=region_choices, - ) - - -def residence_question(): - return ChoiceQuestion( - view='DROPDOWN', - key='dgf_region_of_residence', - question=_("In which region do you currently reside?"), - choices=region_choices, - ) - - -def gender_question(): - return ChoiceQuestion( - key='dgf_gender_identity', - view='RADIOS', - question="您目前对自己的性别认识?", - choices={ - 'male': "男", - 'Female': "女", - 'Others': "其他", - 'no_answer': "不想回答" - } - ) - -def genre_question(): - return ChoiceQuestion( - view='DROPDOWN', - key='dgf_genre_preference', - question=_( - "To which group of musical genres do you currently listen most?"), - choices={ - 'unpretentious': _("Pop/Country/Religious"), - 'Chinese artistic': _("Folk/Mountain songs"), - 'sophisticated': _("Western classical music/Jazz/Opera/Musical"), - 'classical': _("Chinese opera"), - 'intense': _("Rock/Punk/Metal"), - 'mellow': _("Dance/Electronic/New Age"), - 'contemporary': _("Hip-hop/R&B/Funk"), - } - ) - -def contact_question(): - return Question( - key='contact', - explainer=_( - "Thank you so much for your feedback! Feel free to include your contact information if you would like a reply or skip if you wish to remain anonymous." - ), - question=_( - "Contact (optional):" - ), - is_skippable=True - ) class Huang2022(Hooked): """Rules for the Chinese version of the Hooked experiment.""" @@ -101,17 +28,17 @@ class Huang2022(Hooked): def __init__(self): self.questions = MSI_ALL + [ - question_by_key('msi_39_best_instrument'), - genre_question(), + question_by_key('msi_39_best_instrument', MSI_OTHER), + question_by_key('dgf_genre_preference_zh', OTHER), question_by_key('dgf_generation'), question_by_key('dgf_education', drop_choices=['isced-5']), question_by_key( 'dgf_highest_qualification_expectation', EXTRA_DEMOGRAPHICS), question_by_key('dgf_occupational_status', EXTRA_DEMOGRAPHICS), - origin_question(), - residence_question(), - gender_question(), - contact_question() + question_by_key('dgf_region_of_origin', OTHER), + question_by_key('dgf_region_of_residence', OTHER), + question_by_key('dgf_gender_identity_zh', OTHER), + question_by_key('contact', OTHER), ] def first_round(self, experiment): diff --git a/backend/experiment/rules/musical_preferences.py b/backend/experiment/rules/musical_preferences.py index a41d65d66..1d265cbeb 100644 --- a/backend/experiment/rules/musical_preferences.py +++ b/backend/experiment/rules/musical_preferences.py @@ -6,6 +6,7 @@ from experiment.questions.utils import question_by_key from experiment.questions.demographics import EXTRA_DEMOGRAPHICS from experiment.questions.goldsmiths import MSI_F1_ACTIVE_ENGAGEMENT +from experiment.questions.other import OTHER from experiment.actions import Consent, Explainer, Final, HTML, Playlist, Redirect, Step, StartSession, Trial from experiment.actions.form import BooleanQuestion, ChoiceQuestion, Form, LikertQuestionIcon @@ -18,15 +19,16 @@ from section.models import Section from .base import Base -from .huang_2022 import gender_question, genre_question, get_test_playback, origin_question, residence_question +from .huang_2022 import get_test_playback class MusicalPreferences(Base): ID = 'MUSICAL_PREFERENCES' - preference_offset = 4 #20 - knowledge_offset = 6 #42 + consent_file = 'consent_musical_preferences.html' + preference_offset = 20 + knowledge_offset = 42 round_increment = 1 - play_method = 'EXTERNAL' + contact_email = 'musicexp_china@163.com' know_score = { 'yes': 2, @@ -37,20 +39,32 @@ class MusicalPreferences(Base): def __init__(self): self.questions = [ question_by_key('msi_38_listen_music', MSI_F1_ACTIVE_ENGAGEMENT), - genre_question(), - gender_question(), + question_by_key('dgf_genre_preference_zh', OTHER), + question_by_key('dgf_gender_identity_zh', OTHER), question_by_key('dgf_age', EXTRA_DEMOGRAPHICS), - origin_question(), - residence_question() + question_by_key('dgf_region_of_origin', OTHER), + question_by_key('dgf_region_of_residence', OTHER) ] def first_round(self, experiment): - consent = Consent() + rendered = render_to_string('consent/{}'.format(self.consent_file) + ) + consent = Consent( + text=rendered, title=_('Informed consent'), confirm=_('I consent and continue.'), deny=_('I do not consent.') + ) playlist = Playlist(experiment.playlists.all()) + explainer = Explainer( + instruction=_('Welcome to the Musical Preferences experiment!'), + steps=[ + Step(_('Please start by checking your connection quality.')) + ], + button_label=_('OK') + ) start_session = StartSession() return [ consent, playlist, + explainer, start_session ] @@ -93,7 +107,7 @@ def next_round(self, session, request_session=None): else: session.decrement_round() if last_result.question_key == 'audio_check1': - playback = get_test_playback() + playback = get_test_playback('EXTERNAL') html = HTML(body=render_to_string('html/huang_2022/audio_check.html')) form = Form(form=[BooleanQuestion( key='audio_check2', @@ -112,7 +126,7 @@ def next_round(self, session, request_session=None): return Redirect(settings.HOMEPAGE) else: session.decrement_round() - playback = get_test_playback(self.play_method) + playback = get_test_playback('EXTERNAL') html = HTML(body='

{}

'.format(_('Do you hear the music?'))) form = Form(form=[BooleanQuestion( key='audio_check1', @@ -129,8 +143,8 @@ def next_round(self, session, request_session=None): like_results = session.result_set.filter(question_key='like_song') feedback = Trial( html=HTML(body=render_to_string('html/musical_preferences/feedback.html', { - 'unlocked': _("Love "), - 'n_songs': n_songs, + 'unlocked': _("Love unlocked"), + 'n_songs': n_songs - 1, 'top_participant': self.get_preferred_songs(like_results, 3) })) ) @@ -140,8 +154,8 @@ def next_round(self, session, request_session=None): known_songs = session.result_set.filter(question_key='know_song', score=2).count() feedback = Trial( html=HTML(body=render_to_string('html/musical_preferences/feedback.html', { - 'unlocked': _("Knowledge "), - 'n_songs': n_songs, + 'unlocked': _("Knowledge unlocked"), + 'n_songs': n_songs - 1, 'top_participant': self.get_preferred_songs(like_results, 3), 'n_known_songs': known_songs })) @@ -151,20 +165,28 @@ def next_round(self, session, request_session=None): like_results = session.result_set.filter(question_key='like_song') known_songs = session.result_set.filter(question_key='know_song', score=2).count() all_results = Result.objects.filter( - comment='like_song' + question_key='like_song' ) + top_participant = self.get_preferred_songs(like_results, 3) + top_all = self.get_preferred_songs(all_results, 3) feedback = Trial( html=HTML(body=render_to_string('html/musical_preferences/feedback.html', { - 'unlocked': _("Connection "), - 'n_songs': n_songs, - 'top_participant': self.get_preferred_songs(like_results, 3), + 'unlocked': _("Connection unlocked"), + 'n_songs': n_songs - 1, + 'top_participant': top_participant, 'n_known_songs': known_songs, - 'top_all': self.get_preferred_songs(all_results, 3) + 'top_all': top_all })) ) session.finish() session.save() - return [feedback, self.get_final_view(session)] + return [feedback, self.get_final_view( + session, + top_participant, + known_songs, + n_songs-1, + top_all + )] section = session.playlist.get_section() like_key = 'like_song' @@ -191,8 +213,8 @@ def next_round(self, session, request_session=None): view = Trial( playback=playback, feedback_form=form, - title=_('Song %(round)i out of %(total)i' %{ - 'round': n_songs, 'total': session.experiment.rounds}), + title=_('Song %(round)s/%(total)s') %{ + 'round': n_songs, 'total': session.experiment.rounds}, config={ 'response_time': section.duration + .1, } @@ -206,9 +228,33 @@ def calculate_score(self, result, data): else: return super().calculate_score(result, data) - def get_final_view(self, session): + def social_media_info(self, experiment, top_participant, known_songs, n_songs, top_all): + current_url = "{}/{}".format(settings.RELOAD_PARTICIPANT_TARGET, + experiment.slug + ) + format_songs = lambda songs: ', '.join([song['name'] for song in songs]) + return { + 'apps': ['weibo', 'share'], + 'message': _("I explored musical preferences on %(url)s! My top 3 favorite songs: %(top_participant)s. I know %(known_songs)i out of %(n_songs)i songs. All players' top 3 songs: %(top_all)s") % { + 'url': current_url, + 'top_participant': format_songs(top_participant), + 'known_songs': known_songs, + 'n_songs': n_songs, + 'top_all': format_songs(top_all) + }, + 'url': experiment.url or current_url, + 'hashtags': [experiment.hashtag or experiment.slug, "amsterdammusiclab", "citizenscience"] + } + + def get_final_view(self, session, top_participant, known_songs, n_songs, top_all): # finalize experiment - social_info = self.social_media_info(session.experiment, session.final_score) + social_info = self.social_media_info( + session.experiment, + top_participant, + known_songs, + n_songs, + top_all + ) social_info['apps'] = ['weibo', 'share'] view = Final( session, @@ -218,6 +264,11 @@ def get_final_view(self, session): social=social_info ) return view + + def feedback_info(self): + info = super().feedback_info() + info['header'] = _("Any remarks or questions (optional):") + return info def get_preferred_songs(self, result_set, n=5): top_songs = result_set.values('section').annotate( diff --git a/backend/experiment/templates/add-sections.html b/backend/experiment/templates/add-sections.html index a86b3b32a..67c8d1a66 100644 --- a/backend/experiment/templates/add-sections.html +++ b/backend/experiment/templates/add-sections.html @@ -10,13 +10,23 @@ .select-fields p { display: inline-block; } + + .help-text { + color: var(--body-quiet-color); + font-size: 12px; + } + + .text-red { + color: var(--error-fg); + font-size: 13px; + } + .song-help { position: relative; - top: 7.3rem; - color: var(--body-quiet-color); + top: 7.3rem; margin-left: 5rem; - font-size: 12px; } + p label { display: block; } @@ -49,7 +59,7 @@

Add sections to playlist: {{playlist.name}}

-
* Fill out both the artist and name fields to create a new song object
+
* Fill out both the artist and name fields to create a new song object
{% csrf_token %} {{ form.as_p }} {% render_inline_action_fields %} {% if form.errors %}
@@ -60,7 +70,7 @@

Add sections to playlist: {{playlist.name}}

{% endif %}
- +
* Allowed audio file formats: WAV, MP3, FLAC, OGG
@@ -69,4 +79,27 @@

Add sections to playlist: {{playlist.name}}

+ + + {% endblock %} diff --git a/backend/experiment/templates/consent/consent_musical_preferences.html b/backend/experiment/templates/consent/consent_musical_preferences.html new file mode 100644 index 000000000..a9852021a --- /dev/null +++ b/backend/experiment/templates/consent/consent_musical_preferences.html @@ -0,0 +1,70 @@ +{% load i18n %} +

{% translate "Dear participant," %}

+

+{% blocktranslate %} +You will be taking part in the Musical Preferences research project conducted by Xuan Huang under the supervision of Prof. Henkjan Honing and Dr. John Ashley Burgoyne of the Music Cognition Group at the University of Amsterdam’s Institute for Logic, Language, and Computation. +{% endblocktranslate %} +

+ +

{% translate "Purpose of the research project" %}

+ +

+{% blocktranslate %} +Studies have shown that cultural preferences and familiarity for music start in infancy and continue throughout adolescence and adulthood. People tend to prefer music from their own cultural traditions. This research will help us understand individual and situational influences on musical preferences and investigate the factors that underly musical preferences in China. For example, do people who have preferences for classical music also have preferences for Chinese traditional music? Are there cultural-specific or universal structural features for musical preferences? +{% endblocktranslate %} +

+ +{% load i18n %} +

{% translate "Who can take part?" %}

+ +

+

    +
  1. {% translate "Legally competent participants aged 16 or older." %}
  2. +
  3. {% translate "Anybody with sufficient good hearing, natural or corrected, to enjoy music listening is welcome to participate in this research." %}
  4. +
+

+ +

{% translate "Instructions" %}

+

+{% blocktranslate %} +This study is a music preference experiment in which you will hear 64 music clips throughout the experiment, you either wear headphones or use your device's speakers to listen to the clips. Adjust the volume level of your device before the experiment begins. +{% endblocktranslate %} +

+ +

+{% blocktranslate %} +The experiment has two parts. The first part is a questionnaire with 6 questions. The second part is a music preference test, where you will listen to a music clip and answer questions about it. The results of your music preferences will be available after the experiment is completed. +{% endblocktranslate %} +

+ +

{% translate "Voluntary participation & risks" %}

+ +

+{% blocktranslate %} +You will be participating in this research on a voluntary basis. This means you are free to stop taking part at any stage without consequences or penalty. If you decide to stop or withdraw your consent, all the information gathered up until then will be permanently deleted. This research has no known risks. +{% endblocktranslate %} +

+ +

{% translate "Privacy" %}

+ +

+{% blocktranslate %} +The information gathered will be used for publication in scientific journals only. Fully anonymized data may be available online in tandem with these scientific publications. We guarantee that you will remain anonymous under all circumstances. Your personal information will not be viewed by third parties without your express permission. +{% endblocktranslate %} +

+ +{% load i18n %} +

{% translate "Further Information" %}

+ +

+ {% blocktranslate %} For further information, please contact Xuan Huang (x.huang@uva.nl) or Dr. John Ashley Burgoyne (j.a.burgoyne@uva.nl). If you have any complaints regarding this project, you can contact the Secretary of the Ethics Committee of the Faculty of Humanities of the University of Amsterdam (commissie-ethiek-fgw@uva.nl). + {% endblocktranslate %} +

+ +

{% translate "Informed consent" %}

+ +

+ {% blocktranslate %} + I have been clearly informed about the research project and I consent to participate in this research. I retain the right to revoke this consent without having to provide any reasons for my decision. I am aware that I am entitled to discontinue the research at any time and can withdraw my participation. {% endblocktranslate %} +

+ diff --git a/backend/experiment/templates/final/musical_preferences.html b/backend/experiment/templates/final/musical_preferences.html deleted file mode 100644 index 434ba1694..000000000 --- a/backend/experiment/templates/final/musical_preferences.html +++ /dev/null @@ -1,20 +0,0 @@ -{% load i18n %} -

{% translate "Thank you for your participation and contribution to science!" %}

-
-
-

{% translate "Your Top 5 favorite songs:" %}

-
    - {% for song in top_participant %} -
  • {{song.name}} - {{song.score}} points
  • - {% endfor %} -
-
-
-

{% translate "Top 5 favorite songs:" %}

-
    - {% for song in top_all %} -
  • {{song.name}} - {{song.score}} points
  • - {% endfor %} -
-
-
\ No newline at end of file diff --git a/backend/experiment/templates/html/musical_preferences/feedback.html b/backend/experiment/templates/html/musical_preferences/feedback.html index 98fc917da..500631c46 100644 --- a/backend/experiment/templates/html/musical_preferences/feedback.html +++ b/backend/experiment/templates/html/musical_preferences/feedback.html @@ -1,5 +1,5 @@ {% load i18n %} -

{{unlocked}}{% translate "Unlocked" %}

+

{{unlocked}}

diff --git a/backend/experiment/tests/test_admin_experiment.py b/backend/experiment/tests/test_admin_experiment.py index 2446bb027..0ca0baef6 100644 --- a/backend/experiment/tests/test_admin_experiment.py +++ b/backend/experiment/tests/test_admin_experiment.py @@ -8,7 +8,7 @@ from session.models import Session # Expected field count per model -EXPECTED_EXPERIMENT_FIELDS = 12 +EXPECTED_EXPERIMENT_FIELDS = 13 EXPECTED_SESSION_FIELDS = 9 EXPECTED_RESULT_FIELDS = 12 EXPECTED_PARTICIPANT_FIELDS = 5 diff --git a/backend/locale/zh/LC_MESSAGES/django.mo b/backend/locale/zh/LC_MESSAGES/django.mo index 29402aee6..af67e9e85 100644 Binary files a/backend/locale/zh/LC_MESSAGES/django.mo and b/backend/locale/zh/LC_MESSAGES/django.mo differ diff --git a/backend/locale/zh/LC_MESSAGES/django.po b/backend/locale/zh/LC_MESSAGES/django.po index ac433bcc0..52bd069e9 100755 --- a/backend/locale/zh/LC_MESSAGES/django.po +++ b/backend/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-10-02 12:48+0200\n" +"POT-Creation-Date: 2023-11-20 14:03+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -49,8 +49,8 @@ msgstr "最终得分" msgid "points" msgstr "分" -#: experiment/actions/final.py:59 experiment/rules/hooked.py:107 -#: experiment/rules/thats_my_song.py:81 +#: experiment/actions/final.py:59 experiment/rules/hooked.py:108 +#: experiment/rules/thats_my_song.py:87 msgid "Play again" msgstr "再玩一次" @@ -62,17 +62,17 @@ msgstr "我的结果" msgid "All experiments" msgstr "实验结束" -#: experiment/actions/form.py:67 experiment/actions/song_sync.py:46 -#: experiment/rules/eurovision_2020.py:157 experiment/rules/hooked.py:319 -#: experiment/rules/huang_2022.py:159 experiment/rules/kuiper_2020.py:150 -#: experiment/rules/musical_preferences.py:118 +#: experiment/actions/form.py:67 experiment/actions/song_sync.py:51 +#: experiment/rules/eurovision_2020.py:159 experiment/rules/hooked.py:321 +#: experiment/rules/huang_2022.py:160 experiment/rules/kuiper_2020.py:150 +#: experiment/rules/musical_preferences.py:132 msgid "Yes" msgstr "是" -#: experiment/actions/form.py:68 experiment/actions/song_sync.py:47 -#: experiment/rules/eurovision_2020.py:156 experiment/rules/hooked.py:318 -#: experiment/rules/huang_2022.py:159 experiment/rules/kuiper_2020.py:149 -#: experiment/rules/musical_preferences.py:118 +#: experiment/actions/form.py:68 experiment/actions/song_sync.py:52 +#: experiment/rules/eurovision_2020.py:158 experiment/rules/hooked.py:320 +#: experiment/rules/huang_2022.py:160 experiment/rules/kuiper_2020.py:149 +#: experiment/rules/musical_preferences.py:132 msgid "No" msgstr "否" @@ -114,8 +114,8 @@ msgid "Completely Agree" msgstr "完全同意" #: experiment/actions/form.py:177 experiment/actions/trial.py:50 -#: experiment/actions/utils.py:25 experiment/rules/hooked.py:169 -#: experiment/rules/huang_2022.py:217 +#: experiment/actions/utils.py:25 experiment/rules/hooked.py:170 +#: experiment/rules/huang_2022.py:218 #: experiment/rules/rhythm_experiment_series.py:36 #: experiment/rules/rhythm_experiment_series.py:72 #: experiment/rules/rhythm_experiment_series_mri.py:29 @@ -137,7 +137,7 @@ msgstr "请选择一个曲库" msgid "Total Score" msgstr "总得分" -#: experiment/actions/score.py:42 experiment/rules/musical_preferences.py:99 +#: experiment/actions/score.py:42 experiment/rules/musical_preferences.py:113 msgid "Next" msgstr "下一首" @@ -161,27 +161,27 @@ msgstr "不正确" msgid "Correct" msgstr "正确" -#: experiment/actions/song_sync.py:38 +#: experiment/actions/song_sync.py:43 msgid "Do you recognise this song?" msgstr "您是否认出了这首歌曲?" -#: experiment/actions/song_sync.py:39 +#: experiment/actions/song_sync.py:44 msgid "Keep imagining the music" msgstr "继续默唱音乐" -#: experiment/actions/song_sync.py:40 +#: experiment/actions/song_sync.py:45 msgid "Did the track come back in the right place?" msgstr "歌曲回到正确的位置了吗?" -#: experiment/actions/song_sync.py:41 experiment/rules/eurovision_2020.py:149 -#: experiment/rules/hooked.py:311 experiment/rules/kuiper_2020.py:142 +#: experiment/actions/song_sync.py:46 experiment/rules/eurovision_2020.py:151 +#: experiment/rules/hooked.py:313 experiment/rules/kuiper_2020.py:142 msgid "Get ready!" msgstr "准备" #: experiment/actions/utils.py:21 experiment/actions/utils.py:31 -#: experiment/rules/musical_preferences.py:214 +#: experiment/rules/musical_preferences.py:260 msgid "End" -msgstr "" +msgstr "完成" #: experiment/questions/demographics.py:10 msgid "Have not (yet) completed any school qualification" @@ -576,7 +576,7 @@ msgstr "11或以上" #: experiment/questions/goldsmiths.py:153 msgid "I listen attentively to music for _ per day." -msgstr "" +msgstr "我每天专心聆听音乐___。" #: experiment/questions/goldsmiths.py:155 msgid "0-15 min" @@ -640,7 +640,7 @@ msgstr "当我听到一首音乐时,我通常能确定它的流派(类型) #: experiment/questions/goldsmiths.py:210 msgid "I have had formal training in music theory for _ years." -msgstr "您接受了多少年音乐理论方面的专业培训?" +msgstr "我接受过正式的音乐理论培训__年。" #: experiment/questions/goldsmiths.py:214 #: experiment/questions/goldsmiths.py:230 @@ -655,7 +655,7 @@ msgstr "7或以上" msgid "" "I have had _ years of formal training on a musical instrument (including " "voice) during my lifetime." -msgstr "您接受了多少年乐器(包括声乐)方面的专业培训?" +msgstr "在我的人生中,我接受过__年的正规乐器训练(包括声乐)。" #: experiment/questions/goldsmiths.py:233 msgid "3-5" @@ -854,7 +854,7 @@ msgstr "提交" msgid "We appreciate your feedback!" msgstr "" -#: experiment/rules/base.py:109 experiment/rules/musical_preferences.py:67 +#: experiment/rules/base.py:109 experiment/rules/musical_preferences.py:81 msgid "Questionnaire" msgstr "问卷调查" @@ -926,7 +926,7 @@ msgid "" msgstr "" #: experiment/rules/beat_alignment.py:91 -#: experiment/rules/musical_preferences.py:89 +#: experiment/rules/musical_preferences.py:103 #: experiment/rules/speech2song.py:48 experiment/rules/util/practice.py:112 msgid "Start" msgstr "开始" @@ -1081,7 +1081,7 @@ msgid "" "tone, or LONGER." msgstr "" -#: experiment/rules/eurovision_2020.py:159 experiment/rules/hooked.py:321 +#: experiment/rules/eurovision_2020.py:161 experiment/rules/hooked.py:323 #: experiment/rules/kuiper_2020.py:152 msgid "Did you hear this song in previous rounds?" msgstr "您是否在之前的识别环节里听到过这首歌曲?" @@ -1208,7 +1208,7 @@ msgid "" "cultures, much more complex meters also exist!" msgstr "" -#: experiment/rules/hooked.py:49 experiment/rules/huang_2022.py:198 +#: experiment/rules/hooked.py:50 experiment/rules/huang_2022.py:199 msgid "" "Do you recognise the song? Try to sing along. The faster you recognise " "songs, the more points you can earn." @@ -1217,7 +1217,7 @@ msgstr "" "能识别出该音乐”,同时请在大脑中跟唱这段音乐。您在15秒内识别出歌曲的速度越快," "您就能获得更多的分数。" -#: experiment/rules/hooked.py:51 experiment/rules/huang_2022.py:200 +#: experiment/rules/hooked.py:52 experiment/rules/huang_2022.py:201 msgid "" "Do you really know the song? Keep singing or imagining the music while the " "sound is muted. The music is still playing: you just can’t hear it!" @@ -1225,55 +1225,57 @@ msgstr "" "当您识别出某首歌曲且点击'是'的瞬间,音乐声从这一秒开始会被静音。请您继续将静" "音前的音乐在脑海中接唱下去直到该音乐再次播放为止。" -#: experiment/rules/hooked.py:53 experiment/rules/huang_2022.py:202 +#: experiment/rules/hooked.py:54 experiment/rules/huang_2022.py:203 msgid "" "Was the music in the right place when the sound came back? Or did we jump to " "a different spot during the silence?" msgstr "当您再次听到声音时,您需要判断出此音乐与您脑海中的音乐是否同步。" -#: experiment/rules/hooked.py:56 experiment/rules/huang_2022.py:205 -#: experiment/rules/huang_2022.py:256 -#: experiment/rules/musical_preferences.py:75 +#: experiment/rules/hooked.py:57 experiment/rules/huang_2022.py:206 +#: experiment/rules/huang_2022.py:257 +#: experiment/rules/musical_preferences.py:89 msgid "Let's go!" msgstr "开始吧!" -#: experiment/rules/hooked.py:61 experiment/rules/huang_2022.py:123 +#: experiment/rules/hooked.py:62 experiment/rules/huang_2022.py:124 #: experiment/rules/matching_pairs.py:32 +#: experiment/rules/musical_preferences.py:52 #: experiment/rules/rhythm_experiment_series.py:45 #: experiment/rules/speech2song.py:55 #: experiment/templates/consent/consent_categorization.html:15 #: experiment/templates/consent/consent_hooked.html:79 #: experiment/templates/consent/consent_huang2021.html:88 +#: experiment/templates/consent/consent_musical_preferences.html:64 msgid "Informed consent" msgstr "知情同意声书" -#: experiment/rules/hooked.py:61 experiment/rules/huang_2022.py:123 +#: experiment/rules/hooked.py:62 experiment/rules/huang_2022.py:124 #: experiment/rules/matching_pairs.py:32 #: experiment/rules/rhythm_experiment_series.py:45 #: experiment/rules/speech2song.py:55 msgid "I agree" msgstr "同意" -#: experiment/rules/hooked.py:61 experiment/rules/huang_2022.py:123 +#: experiment/rules/hooked.py:62 experiment/rules/huang_2022.py:124 #: experiment/rules/matching_pairs.py:32 #: experiment/rules/rhythm_experiment_series.py:45 #: experiment/rules/speech2song.py:55 msgid "Stop" msgstr "停止" -#: experiment/rules/hooked.py:163 +#: experiment/rules/hooked.py:164 msgid "Bonus Rounds" msgstr "奖励环节" -#: experiment/rules/hooked.py:165 +#: experiment/rules/hooked.py:166 msgid "Listen carefully to the music." msgstr "请仔细地听音乐。" -#: experiment/rules/hooked.py:166 +#: experiment/rules/hooked.py:167 msgid "Did you hear the same song during previous rounds?" msgstr "您是否在之前的音乐识别环节里听到过同一首歌曲?" -#: experiment/rules/hooked.py:209 +#: experiment/rules/hooked.py:210 #, python-format msgid "Round %(number)d / %(total)d" msgstr "%(number)d / %(total)d轮" @@ -1313,42 +1315,43 @@ msgstr "" msgid "Contact (optional):" msgstr "微信号、手机、邮箱等(选填):" -#: experiment/rules/huang_2022.py:136 +#: experiment/rules/huang_2022.py:137 +#: experiment/rules/musical_preferences.py:269 msgid "Any remarks or questions (optional):" -msgstr "请写下您的意见或建议:" +msgstr "建议或意见反馈,如技术问题(选填):" -#: experiment/rules/huang_2022.py:137 +#: experiment/rules/huang_2022.py:138 msgid "Thank you for your feedback!" msgstr "感谢您的反馈!" -#: experiment/rules/huang_2022.py:156 -#: experiment/rules/musical_preferences.py:115 +#: experiment/rules/huang_2022.py:157 +#: experiment/rules/musical_preferences.py:129 msgid "Do you hear the music?" msgstr "您听到音乐了吗?" -#: experiment/rules/huang_2022.py:166 -#: experiment/rules/musical_preferences.py:125 +#: experiment/rules/huang_2022.py:167 +#: experiment/rules/musical_preferences.py:139 msgid "Audio check" msgstr "音频测试" -#: experiment/rules/huang_2022.py:175 -#: experiment/rules/musical_preferences.py:99 +#: experiment/rules/huang_2022.py:176 +#: experiment/rules/musical_preferences.py:113 msgid "Quit" msgstr "退出" -#: experiment/rules/huang_2022.py:175 +#: experiment/rules/huang_2022.py:176 msgid "Try" msgstr "运行" -#: experiment/rules/huang_2022.py:182 +#: experiment/rules/huang_2022.py:183 msgid "Ready to experiment" msgstr "调试阶段" -#: experiment/rules/huang_2022.py:195 +#: experiment/rules/huang_2022.py:196 msgid "How to Play" msgstr "实验介绍" -#: experiment/rules/huang_2022.py:207 +#: experiment/rules/huang_2022.py:208 msgid "" "You can use your smartphone, computer or tablet to participate in this " "experiment. Please choose the best network in your area to participate in " @@ -1362,12 +1365,12 @@ msgstr "" "网络环境不佳,有可能会导致音乐加载失败或实验运行不流畅等情况出现。您可以通过" "以下的渠道打开实验页面:" -#: experiment/rules/huang_2022.py:210 +#: experiment/rules/huang_2022.py:211 msgid "" "Directly click the link on WeChat (smart phone or PC version, or WeChat Web)" msgstr "通过手机微信或电脑微信客户端/网页版的链接直接点开进入到实验页面;" -#: experiment/rules/huang_2022.py:213 +#: experiment/rules/huang_2022.py:214 msgid "" "If the link to load the experiment page through the WeChat app on your cell " "phone fails, you can copy and paste the link in the browser of your cell " @@ -1378,29 +1381,29 @@ msgstr "" "通过复制黏贴实验链接到浏览器参与实验。您可以使用市面上目前的任何一种浏览器," "如Safari、火狐、360等等。" -#: experiment/rules/huang_2022.py:252 +#: experiment/rules/huang_2022.py:253 msgid "" "Please answer some questions on your musical " "(Goldsmiths-MSI) and demographic background" msgstr "接下来是《金史密斯音乐素养》水平测试与人口统计特征问卷。" -#: experiment/rules/huang_2022.py:296 +#: experiment/rules/huang_2022.py:297 msgid "Thank you for your contribution to science!" msgstr "感谢您的参与以及对科学的贡献!" -#: experiment/rules/huang_2022.py:298 +#: experiment/rules/huang_2022.py:299 msgid "Well done!" msgstr "太棒了!" -#: experiment/rules/huang_2022.py:298 +#: experiment/rules/huang_2022.py:299 msgid "Too bad!" msgstr "有点糟哦!" -#: experiment/rules/huang_2022.py:300 +#: experiment/rules/huang_2022.py:301 msgid "You did not recognise any songs at first." msgstr "您起初并没有识别出任何歌曲。" -#: experiment/rules/huang_2022.py:302 +#: experiment/rules/huang_2022.py:303 #, python-format msgid "" "It took you %(n_seconds)d s to recognise a song on average, " @@ -1410,7 +1413,7 @@ msgstr "" "您平均花了 %(n_seconds)d 秒识别出一首歌曲,并且在您认为您知道的 %(n_total)d " "首歌曲里, 您正确地识别出了 %(n_correct)d 首。" -#: experiment/rules/huang_2022.py:308 +#: experiment/rules/huang_2022.py:309 #, python-format msgid "" "During the bonus rounds, you remembered %(n_correct)d of the %(n_total)d " @@ -1485,6 +1488,7 @@ msgid "" msgstr "" #: experiment/rules/listening_conditions.py:113 +#: experiment/rules/musical_preferences.py:60 #: experiment/rules/speech2song.py:94 msgid "OK" msgstr "好" @@ -1524,7 +1528,23 @@ msgstr "" msgid "Enter a name to enter the ICMPC hall of fame" msgstr "" -#: experiment/rules/musical_preferences.py:70 +#: experiment/rules/musical_preferences.py:52 +msgid "I consent and continue." +msgstr "同意" + +#: experiment/rules/musical_preferences.py:52 +msgid "I do not consent." +msgstr "退出" + +#: experiment/rules/musical_preferences.py:56 +msgid "Welcome to the Musical Preferences experiment!" +msgstr "欢迎参加音乐偏好实验!" + +#: experiment/rules/musical_preferences.py:58 +msgid "Please start by checking your connection quality." +msgstr "请先检查您的网络连接质量。" + +#: experiment/rules/musical_preferences.py:84 msgid "" "To understand your musical preferences, we have {} questions for you before " "the experiment begins. The first two " @@ -1535,63 +1555,73 @@ msgstr "" "为了了解您的音乐偏好,在实验开始前请您回答{}个问题。前两个问题是关于您的音乐" "聆听经验,其他四个问题是人口统计学问题。答题需要2-3分钟左右。" -#: experiment/rules/musical_preferences.py:73 #: experiment/rules/musical_preferences.py:87 +#: experiment/rules/musical_preferences.py:101 msgid "Have fun!" msgstr "祝答题愉快!" -#: experiment/rules/musical_preferences.py:81 +#: experiment/rules/musical_preferences.py:95 msgid "How to play" msgstr "实验介绍" -#: experiment/rules/musical_preferences.py:83 +#: experiment/rules/musical_preferences.py:97 msgid "" "You will hear 64 music clips and have to answer two questions for each clip." msgstr "在整个实验过程中,你将听到64个音乐片段并回答与之相关的问题。" -#: experiment/rules/musical_preferences.py:84 +#: experiment/rules/musical_preferences.py:98 msgid "It will take 20-30 minutes to complete the whole experiment." msgstr "整个实验需要20至30分钟。" -#: experiment/rules/musical_preferences.py:85 +#: experiment/rules/musical_preferences.py:99 msgid "Either wear headphones or use your device's speakers." msgstr "请佩戴耳机或使用设备扬声器。" -#: experiment/rules/musical_preferences.py:86 +#: experiment/rules/musical_preferences.py:100 msgid "Your final results will be displayed at the end." msgstr "您的实验结果将在最后显示。" -#: experiment/rules/musical_preferences.py:106 +#: experiment/rules/musical_preferences.py:120 msgid "Tech check" msgstr "调试阶段" -#: experiment/rules/musical_preferences.py:131 -msgid "Love " -msgstr "乐" +#: experiment/rules/musical_preferences.py:145 +msgid "Love unlocked" +msgstr "解锁乐之爱" -#: experiment/rules/musical_preferences.py:142 -msgid "Knowledge " -msgstr "识" +#: experiment/rules/musical_preferences.py:156 +msgid "Knowledge unlocked" +msgstr "解锁乐之识" -#: experiment/rules/musical_preferences.py:157 -msgid "Connection " -msgstr "友" +#: experiment/rules/musical_preferences.py:173 +msgid "Connection unlocked" +msgstr "解锁乐之友" -#: experiment/rules/musical_preferences.py:171 +#: experiment/rules/musical_preferences.py:193 msgid "2. How much do you like this song?" msgstr "2. 您对这首歌的喜欢程度是?" -#: experiment/rules/musical_preferences.py:177 +#: experiment/rules/musical_preferences.py:199 msgid "1. Do you know this song?" msgstr "1. 您知道这首歌吗?" -#: experiment/rules/musical_preferences.py:193 +#: experiment/rules/musical_preferences.py:215 #, python-format -msgid "Song %(round)i out of %(total)i" -msgstr "%(round)i/%(total)i 首" +msgid "Song %(round)s/%(total)s" +msgstr "%(round)s/%(total)s首歌" -#: experiment/rules/musical_preferences.py:215 -#: experiment/templates/final/musical_preferences.html:2 +#: experiment/rules/musical_preferences.py:237 +#, python-format +msgid "" +"I explored musical preferences on %(url)s! My top 3 favorite songs: " +"%(top_participant)s. I know %(known_songs)i out of %(n_songs)i songs. All " +"players' top 3 songs: %(top_all)s" +msgstr "" +"一起探索音乐喜好%(url)s! 我最喜欢的三首歌曲:%(top_participant)s;我知" +"道%(n_songs)i首歌曲中的%(known_songs)i首;其他人最喜爱的三首歌曲:" +"%(top_all)s。" + +#: experiment/rules/musical_preferences.py:261 msgid "Thank you for your participation and contribution to science!" msgstr "感谢您的参与以及对科学的贡献!" @@ -1869,11 +1899,11 @@ msgstr "听起来完全像音乐" msgid "Listen carefully" msgstr "请认真聆听" -#: experiment/rules/thats_my_song.py:103 +#: experiment/rules/thats_my_song.py:109 msgid "Choose two or more decades of music" msgstr "" -#: experiment/rules/thats_my_song.py:116 +#: experiment/rules/thats_my_song.py:122 msgid "Playlist selection" msgstr "" @@ -2084,6 +2114,7 @@ msgstr "" #: experiment/templates/consent/consent_categorization.html:13 #: experiment/templates/consent/consent_hooked.html:66 #: experiment/templates/consent/consent_huang2021.html:76 +#: experiment/templates/consent/consent_musical_preferences.html:57 #: experiment/templates/consent/consent_rhythm.html:17 #: experiment/templates/consent/consent_rhythm_unpaid.html:15 #: experiment/templates/consent/consent_speech2song.html:62 @@ -2281,6 +2312,7 @@ msgstr "" #: experiment/templates/consent/consent_hooked.html:8 #: experiment/templates/consent/consent_huang2021.html:11 +#: experiment/templates/consent/consent_musical_preferences.html:9 #: experiment/templates/consent/consent_speech2song.html:11 msgid "Purpose of the research project" msgstr "本研究目的" @@ -2703,6 +2735,146 @@ msgstr "" "销我的参与,且无需说明任何理由。如果我决定终止或撤销我的参与,那么在此之前收" "集的所有我的资料将会被永久删除。" +#: experiment/templates/consent/consent_musical_preferences.html:2 +msgid "Dear participant," +msgstr "尊敬的参与者:" + +#: experiment/templates/consent/consent_musical_preferences.html:4 +msgid "" +"\n" +"You will be taking part in the Musical Preferences research project " +"conducted by Xuan Huang under the supervision of Prof. Henkjan Honing and " +"Dr. John Ashley Burgoyne of the Music Cognition Group at the University of " +"Amsterdam’s Institute for Logic, Language, and Computation.\n" +msgstr "" +"\n" +" 您即将参加由阿姆斯特丹大学逻辑、语言和计算研究所的音乐认知实验组批准开展的" +"《音乐偏好》课题研究。该课题由博士研究生Xuan Huang主持并在Honing教授以及" +"Burgoyne博士指导下开展。\n" + +#: experiment/templates/consent/consent_musical_preferences.html:12 +msgid "" +"\n" +"Studies have shown that cultural preferences and familiarity for music start " +"in infancy and continue throughout adolescence and adulthood. People tend to " +"prefer music from their own cultural traditions. This research will help us " +"understand individual and situational influences on musical preferences and " +"investigate the factors that underly musical preferences in China. For " +"example, do people who have preferences for classical music also have " +"preferences for Chinese traditional music? Are there cultural-specific or " +"universal structural features for musical preferences?\n" +msgstr "" +"\n" +"研究表明,人们对音乐的文化偏好和熟悉程度从婴儿期开始显现,并持续到整个青春期" +"和成年期。人们会偏好他们文化上熟悉的音乐。这项研究将帮助我们了解个人和情景对" +"音乐偏好的影响,以及构成中国听众音乐偏好的潜在因素。例如,对西方古典音乐有偏" +"好的人是否也对中国传统音乐有偏好?音乐偏好是否存在特定的文化或普遍的结构特" +"征?\n" + +#: experiment/templates/consent/consent_musical_preferences.html:18 +msgid "Who can take part?" +msgstr "谁能参与该研究?" + +#: experiment/templates/consent/consent_musical_preferences.html:22 +msgid "Legally competent participants aged 16 or older." +msgstr "法定年龄满十六周岁。" + +#: experiment/templates/consent/consent_musical_preferences.html:23 +msgid "" +"Anybody with sufficient good hearing, natural or corrected, to enjoy music " +"listening is welcome to participate in this research." +msgstr "拥有先天良好听力或通过矫正听力可欣赏音乐的个体。" + +#: experiment/templates/consent/consent_musical_preferences.html:27 +msgid "Instructions" +msgstr "研究说明与过程" + +#: experiment/templates/consent/consent_musical_preferences.html:29 +msgid "" +"\n" +"This study is a music preference experiment in which you will hear 64 music " +"clips throughout the experiment, you either wear headphones or use your " +"device's speakers to listen to the clips. Adjust the volume level of your " +"device before the experiment begins.\n" +msgstr "" +"\n" +"该研究是一个音乐偏好实验,在整个实验里您将听到64个音乐片段,您可以佩戴耳机或" +"使用设备的扬声器来聆听片段。在实验正式开始前调整好您的设备音量的大小。\n" + +#: experiment/templates/consent/consent_musical_preferences.html:35 +msgid "" +"\n" +"The experiment has two parts. The first part is a questionnaire with 6 " +"questions. The second part is a music preference test, where you will listen " +"to a music clip and answer questions about it. The results of your music " +"preferences will be available after the experiment is completed.\n" +msgstr "" +"\n" +"该实验有两个部分。 第一部分为调查问卷,包含6个问题。 第二部分为音乐偏好测试," +"您将聆听音乐片段并回答相关问题。您的音乐偏好结果将在整个实验完成后获得。\n" + +#: experiment/templates/consent/consent_musical_preferences.html:40 +msgid "Voluntary participation & risks" +msgstr "自愿参加与不适" + +#: experiment/templates/consent/consent_musical_preferences.html:43 +msgid "" +"\n" +"You will be participating in this research on a voluntary basis. This means " +"you are free to stop taking part at any stage without consequences or " +"penalty. If you decide to stop or withdraw your consent, all the " +"information gathered up until then will be permanently deleted. This " +"research has no known risks.\n" +msgstr "" +"\n" +"参加本研究是完全自愿的。您可以拒绝参加研究,或者在研究过程中的任何时候选择退" +"出研究,不需任何理由,且您的数据将被永久删除。 这项研究没有已知的风险。 \n" + +#: experiment/templates/consent/consent_musical_preferences.html:48 +msgid "Privacy" +msgstr "隐私问题" + +#: experiment/templates/consent/consent_musical_preferences.html:51 +msgid "" +" \n" +"The information gathered will be used for publication in scientific journals " +"only. Fully anonymized data may be available online in tandem with these " +"scientific publications. We guarantee that you will remain anonymous under " +"all circumstances. Your personal information will not be viewed by third " +"parties without your express permission.\n" +msgstr "" +" \n" +"在此研究过程中所搜集的信息仅用于科学研究。数据完全匿名,可能会随着研究结果发" +"表一同展示。我们保证您在任何情况下都将保持匿名。此外,未经您的明确许可,您的" +"个人信息将不会被第三方查看。\n" + +#: experiment/templates/consent/consent_musical_preferences.html:60 +msgid "" +" For further information, please contact Xuan Huang (x.huang@uva.nl) or Dr. " +"John Ashley Burgoyne (j.a.burgoyne@uva.nl). If you have any complaints " +"regarding this project, you can contact the Secretary of the Ethics " +"Committee of the Faculty of Humanities of the University of Amsterdam " +"(commissie-ethiek-fgw@uva.nl).\n" +" " +msgstr "" +"如您需了解关于此研究项目的更多信息,请联系Xuan Huang(邮箱:x.huang@uva.nl)或" +"Burgoyne博士(邮箱:j.a.burgoyne@uva.nl)。如果您对此研究项目有任何投诉,请联系" +"阿姆斯特丹大学人文学院伦理委员会秘书(邮箱:commissie-ethiek-fgw@uva.nl)。\n" +" " + +#: experiment/templates/consent/consent_musical_preferences.html:67 +msgid "" +" \n" +" I have been clearly informed about the research project and I consent to " +"participate in this research. I retain the right to revoke this consent " +"without having to provide any reasons for my decision. I am aware that I am " +"entitled to discontinue the research at any time and can withdraw my " +"participation. " +msgstr "" +" \n" +"我已经阅读了知情同意书,我同意参与该项研究。我有权撤销这一同意而无须提供任何 " +"理由。我知道我有权在任何时候中止研究,可以撤回我的参与。" + #: experiment/templates/consent/consent_rhythm.html:2 #: experiment/templates/consent/consent_rhythm_unpaid.html:2 msgid "" @@ -3084,14 +3256,6 @@ msgstr "" msgid "Did you know..." msgstr "" -#: experiment/templates/final/musical_preferences.html:5 -msgid "Your Top 5 favorite songs:" -msgstr "" - -#: experiment/templates/final/musical_preferences.html:13 -msgid "Top 5 favorite songs:" -msgstr "" - #: experiment/templates/html/huang_2022/audio_check.html:3 msgid "Check volume" msgstr "检查设备音量大小。" @@ -3104,17 +3268,15 @@ msgstr "检查网络连接。" msgid "Or try at another time when you are ready" msgstr "或者一切准备就绪后换其它时间再尝试。" -#: experiment/templates/html/musical_preferences/feedback.html:2 -msgid "Unlocked" -msgstr "解锁乐之" - #: experiment/templates/html/musical_preferences/feedback.html:11 +#, python-format msgid " Your top 3 favourite songs out of %(n_songs)s:" msgstr "在%(n_songs)s首歌曲里,您最喜欢的3首歌曲是:" #: experiment/templates/html/musical_preferences/feedback.html:30 +#, python-format msgid " Of %(n_songs)s songs, you know %(n_known_songs)s" -msgstr "在%(n_songs)s首歌曲里,您知道 %(n_known_songs)s的歌曲。" +msgstr "在%(n_songs)s首歌曲里,您知道 %(n_known_songs)s首。" #: experiment/templates/html/musical_preferences/feedback.html:44 msgid "All players' top 3 favourite songs:" @@ -3145,6 +3307,26 @@ msgstr "您可以复制以下您参与实验的用户信息链接以便下次继 msgid "copy" msgstr "复制" +#: section/admin.py:92 +msgid "Cannot upload {}: {}" +msgstr "" + +#~ msgid "" +#~ "\n" +#~ " If you have any complaints regarding this research project, you can " +#~ "contact the secretary of the Ethics Committee of the Faculty of " +#~ "Humanities of the University of Amsterdam (phone number: +31 20 525 3054; " +#~ "e-mail: commissie-ethiek-fgw@uva.nl; Kloveniersburgwal 48, 1012 CX " +#~ "Amsterdam)." +#~ msgstr "" +#~ "\n" +#~ "如果我对该研究有投诉,我可以联系阿姆斯特丹大学人文学院伦理委员会秘书 (电" +#~ "话:+31 20 525 3054;电子邮件:commissie-ethiek-fgw@uva.nl ; 地址:" +#~ "Kloveniersburgwal 48, 1012 CX Amsterdam)。" + +#~ msgid " Love" +#~ msgstr "乐" + #~ msgid "Score" #~ msgstr "得分" diff --git a/backend/requirements/dev.txt b/backend/requirements/dev.txt index c96f47cc6..caf4f14c7 100644 --- a/backend/requirements/dev.txt +++ b/backend/requirements/dev.txt @@ -16,7 +16,7 @@ certifi==2023.7.22 # via requests charset-normalizer==2.1.0 # via requests -django==3.2.20 +django==3.2.23 # via # -r requirements.in/base.txt # django-cors-headers diff --git a/backend/requirements/prod.txt b/backend/requirements/prod.txt index 0b8766f65..1ffad430a 100644 --- a/backend/requirements/prod.txt +++ b/backend/requirements/prod.txt @@ -8,7 +8,7 @@ asgiref==3.7.2 # via django audioread==3.0.0 # via -r requirements.in/base.txt -django==3.2.20 +django==3.2.23 # via # -r requirements.in/base.txt # django-cors-headers diff --git a/backend/section/forms.py b/backend/section/forms.py index c68dca51d..ebe1784af 100644 --- a/backend/section/forms.py +++ b/backend/section/forms.py @@ -10,4 +10,5 @@ class AddSections(forms.Form): name = forms.CharField(max_length=128, required=False) tag = forms.CharField(max_length=128, required=False) group = forms.CharField(max_length=128, required=False) - files = forms.FileField(widget=MultipleFileInput, validators=[audio_file_validator()]) + files = forms.FileField(widget=MultipleFileInput(attrs={'accept':'.wav,.mp3,.aiff,.flac,.ogg'}), + validators=[audio_file_validator()]) diff --git a/backend/section/models.py b/backend/section/models.py index 56682244e..8908c50b3 100644 --- a/backend/section/models.py +++ b/backend/section/models.py @@ -213,7 +213,6 @@ def update_admin_csv(self): section.tag, section.group]) csv_string = csvfile.csv_string - print(csv_string) return ''.join(csv_string) class Song(models.Model): diff --git a/frontend/package.json b/frontend/package.json index 66f31a7f1..4f721a523 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -7,7 +7,7 @@ "@testing-library/jest-dom": "^5.16.1", "@testing-library/react": "^12.1.2", "@testing-library/user-event": "^13.5.0", - "axios": ">=0.25.0", + "axios": ">=1.6.0", "classnames": "^2.2.6", "email-validator": "^2.0.4", "file-saver": "^2.0.5", diff --git a/frontend/src/components/HTML/HTML.scss b/frontend/src/components/HTML/HTML.scss index a5a6d2ed5..a538d1ed2 100644 --- a/frontend/src/components/HTML/HTML.scss +++ b/frontend/src/components/HTML/HTML.scss @@ -40,7 +40,7 @@ } .card.bg-blue { - height: 20vh; + height: 21vh; background-color: $blue; span { @@ -55,6 +55,19 @@ .card-body { text-align: left; + padding-top: 1vh; + ul { + padding: 0; + } + } + + .card-title { + padding: 0; + font-size: 2.5vh; + } + + .card-text { + font-size: 2vh; } } diff --git a/frontend/src/components/Question/_TextRange.js b/frontend/src/components/Question/_TextRange.js index a562f8fb2..0206de9fe 100644 --- a/frontend/src/components/Question/_TextRange.js +++ b/frontend/src/components/Question/_TextRange.js @@ -5,7 +5,11 @@ import classNames from "classnames"; import RangeLimits from "./_RangeLimits"; import RangeTitle from "./_RangeTitle"; -// TextRange is a question view that makes you select a value within the given range, using a slider from a list of choices +/** + * TextRange is a question view that makes you select a value within the given range, using a slider from a list of choices + * Values are multiplied by 10 to be displayed as a slider. + * This to ensure that the slider is centered initially, even if we don't have a center value + * */ const TextRange = ({ question, value, onChange, emphasizeTitle }) => { const emptyValue = !value; @@ -13,14 +17,14 @@ const TextRange = ({ question, value, onChange, emphasizeTitle }) => { const choices = Object.values(question.choices); const onSliderChange = (index) => { - onChange(keys[index]); + onChange(keys[Math.round(index/10)]); }; let sliderValue = 0; if (emptyValue) { - sliderValue = Math.round(keys.length / 2) - 1; + sliderValue = Math.round(keys.length * 5) - 5; } else { - sliderValue = keys.indexOf(value); + sliderValue = keys.indexOf(value) * 10; } return ( @@ -38,7 +42,7 @@ const TextRange = ({ question, value, onChange, emphasizeTitle }) => { value={sliderValue} onChange={onSliderChange} min={0} - max={choices.length - 1} + max={(choices.length * 10) - 10} tooltip={false} /> diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 1dd4e656b..52f18c401 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2960,10 +2960,10 @@ axe-core@^4.6.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0" integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g== -axios@>=0.25.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267" - integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ== +axios@>=1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102" + integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" diff --git a/package.json b/package.json index 9696ec6cf..96baedfeb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aml-experiments", - "version": "1.4.0", + "version": "1.6.0", "private": true, "__comment1__": "private set to true to suppress 'warning package.json: No license field'",