How to calculate the global score of a scale created with a form component?

Hello everyone!

I try to calculate automatically the global score of a Likert scale that I have created with a form component (5-point Likert scale containing 4 questions). To calculate the global score, I need to associate each response with a question-score and I need to know the number of times the subject has chosen each answer.

What I have tried :
In a Code Component, I associate each response of the scale with its value (question-score). I try to count the number of times the subject chooses each answer by creating a counter for each response ( response_count = 0) and incrementing counters each time the subject clicks on one of the answers (each frame : response_count = response_count +1 ).

The problem :
Psychopy sends me this error message: ZeroDivisionError: float division by zero This error comes from a problem with the incrementation of my counters : the counters remain at zero, so when I calculate the global score, the denominator is always zero…

The code :

#Begin Routine
from psychopy import event
mouse = event.Mouse()

#I create an empty string for each response
Tj_D = ''
Gn_D = ''
At_DG = ''
Gn_G = ''
Tj_G = ''

# I fill out each string with the title of the answer
# I associate each response with its value
Tj_D.join('Toujours la droite')
Tj_D = 2.0
Gn_D.join('Généralement la droite')
Gn_D = 1.0
At_DG.join('Autant la droite que la gauche')
At_DG = 1.0
Gn_G.join('Généralement la gauche')
Gn_G = 1.0
Tj_G.join('Toujours la gauche')
Tj_G = 2.0

# I create a counter for each response
tjD_count = 0
gnD_count = 0
atDG_count = 0
gnG_count = 0
tjG_count = 0

# Each Frame
#when the subject choses a response, I increment / update the corresponding counter
#test_edimbourgh = name of the form Component (.items = field where the Excel file is indicated in the form component parameters)
if(mouse.getPressed('Toujours la droite') in test_edimbourgh.items):
    tjD_count = tjD_count +1
elif(mouse.getPressed('Généralement la droite') in test_edimbourgh.items):
    gnD_count = gnD_count +1
elif(mouse.getPressed('Autant la droite que la gauche') in test_edimbourgh.items):
    atDG_count = atDG_count +1
elif(mouse.getPressed('Généralement la gauche') in test_edimbourgh.items):
    gnG_count = gnG_count +1
elif(mouse.getPressed('Toujours la gauche') in test_edimbourgh.items):
    tjG_count = tjG_count +1

#End Routine:
#I convert each response into its value
int(Tj_D)
int(Gn_D)
int(At_DG)
int(Gn_G)
int(Tj_G)

#I log data to check the incrementation and asoociation response-value
thisExp.addData('Toujours D', Tj_D)
thisExp.addData('Généralement D', Gn_D)
thisExp.addData('Autant DG', At_DG)
thisExp.addData('Généralement G', Gn_G)
thisExp.addData('Toujours G', Tj_G)
thisExp.addData('Tj D count', tjD_count)
thisExp.addData('Gn D count', gnD_count)
thisExp.addData('Au DG count', atDG_count)
thisExp.addData('Gn G count', gnG_count)
thisExp.addData('Tj G count', tjG_count)

#I calculate the global score and log it
glob_score = (((tjD_count * Tj_D) + (gnD_count * Gn_D) + (atDG_count * At_DG)) - ((tjG_count * Tj_G) + (gnG_count * Gn_G) + (atDG_count * At_DG)) * 100) / (((tjD_count * Tj_D) + (gnD_count * Gn_D) + (atDG_count * At_DG)) + ((tjG_count * Tj_G) + (gnG_count * Gn_G) + (atDG_count * At_DG)))
thisExp.addData('edim_score', glob_score)

I have tried A LOT of different codes, but nothing worked… Does anyone have a suggestion? Maybe in the way I try to increment the counters?
Thank you very much for your help!
Romane.

Hello!
Finally, I found a solution and I post it here (it would help someone).
So, I didn’t use a form component, but several Slider components (one per question). The solution is not very ‘sexy’ but it works. This code allows me to automatically calculate the global score and to have the label of each response in my data file.

I created four Sliders named: Secrire, Slancer, Sbrosse and Scuillere.
Then, in a Code Component:

Begin Routine:

#incrementation of my counters for each type of response in my Sliders
awr_count = 0  # "awr" for the "always right" response
usr_count = 0  # usually right
brl_count = 0  # both right and left
usl_count = 0  # usually left
awl_count = 0  # always left

End Routine:

#I create a list containing the rating of each slider
resp_edim = [Secrire.getRating(), Slancer.getRating(), Sbrosse.getRating(), Scuillere.getRating()]

#I use a loop to update the counter of each type of response depending of the rating on each slider
#And I log the label of the corresponding response 
for i in resp_edim:
    if i == 1: #if the subject chooses the first response 'always right' in the slider
        awr_count = awr_count+1 #I update the counter of 'always right'
        if i is resp_edim[0]: # if it's right when i takes the value of 'Secrire.getRating()' into the list...
            thisExp.addData('Resp_ecrire', 'always right') #... I log the label for this slider
        elif i is resp_edim[1]:
            thisExp.addData('Resp_lancer', 'always right')
        elif i is resp_edim[2]:
            thisExp.addData('Resp_brosse', 'always right')
        elif i is resp_edim[3]:
            thisExp.addData('Resp_cuillere', 'always right')
        continue
    elif i == 2:
        usr_count = usr_count+1
        if i is resp_edim[0]:
            thisExp.addData('Resp_ecrire', 'usually right')
        elif i is resp_edim[1]:
            thisExp.addData('Resp_lancer', 'usually right')
        elif i is resp_edim[2]:
            thisExp.addData('Resp_brosse', 'usually right')
        elif i is resp_edim[3]:
            thisExp.addData('Resp_cuillere', 'usually right')
        continue
    elif i == 3:
        brl_count = brl_count+1
        if i is resp_edim[0]:
            thisExp.addData('Resp_ecrire', 'Both right and left')
        elif i is resp_edim[1]:
            thisExp.addData('Resp_lancer', 'Both right and left')
        elif i is resp_edim[2]:
            thisExp.addData('Resp_brosse', 'Both right and left')
        elif i is resp_edim[3]:
            thisExp.addData('Resp_cuillere', 'Both right and left')
        continue
    elif i == 4:
        usl_count = usl_count+1
        if i is resp_edim[0]:
            thisExp.addData('Resp_ecrire', 'usually left')
        elif i is resp_edim[1]:
            thisExp.addData('Resp_lancer', 'usually left')
        elif i is resp_edim[2]:
            thisExp.addData('Resp_brosse', 'usually left')
        elif i is resp_edim[3]:
            thisExp.addData('Resp_cuillere', 'usually left')
        continue
    elif i == 5:
        awl_count = awl_count+1
        if i is resp_edim[0]:
            thisExp.addData('Resp_ecrire', 'Always left')
        elif i is resp_edim[1]:
            thisExp.addData('Resp_lancer', 'Always left')
        elif i is resp_edim[2]:
            thisExp.addData('Resp_brosse', 'Always left')
        elif i is resp_edim[3]:
            thisExp.addData('Resp_cuillere', 'Always left')

#I calculate each score that I need to calculate the global score
score_right = (awr_count*2) + (usr_count*1) + (brl_count*1)
score_left = (brl_count*1) + (usl_count*1) + (awl_count*2)
score_global = ((score_right - score_left)*100)/(score_right + score_left)

#I log them
thisExp.addData('score_right', score_right)
thisExp.addData('score_left', score_left)
thisExp.addData('score_global', score_global)

#then I log directly the manual dominance of the subject according to his global score
if score_global < 150:
    if score_global > 33.334:
        thisExp.addData('dominance', 'right hander')
    elif score_global <= 33.334 and score_global >= -33.334:
        thisExp.addData('dominance', 'ambidextrous')
    elif score_global < -33.334:
        thisExp.addData('dominance', 'left hander')

If anyone has suggestions to improve this code (lighten/condense…), I’m interested!
I hope it helps.

Romane.

Thank you for posting your solution! I will need to do something similar for a study I am designing.

Balbir Singh