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='