Solutions

Contents

Solutions#

Below are the solutions belonging to the course material of Experimentation I (2023-2024)

Chapter 1 - Introduction to OpenSesame#

Stroop task in OpenSesame#

Solution tutorial Stroop task: here

Excercise 1. Change stimulus duration#

The values for response_... become empty when you do not respond within 1000 ms.

Chapter 2 - Experimental Design I#

Flanker task in OpenSesame#

Solution tutorial flanker task: here

Excercise 1. Reuse trial sequence in the flanker task#

Solution here

Excercise 2. Change the number of trials in the flanker task#

1600 observations per level of congruency / 10 participants = 160 trials. 160 trials divided over 4 test blocks = 40 trials per block per level of congruency. So we need a total of 80 trials per block = 20 (instead of 25) cycles in block_loop_1.

Chapter 3 - Experimental Design II#

Go-nogo task in OpenSesame#

Solution tutorial go-nogo task: here

Excercise 1. Counterbalancing: Even or odd participant numbers#

See files below (ignore updates in stimulus)

Excercise 2. Show mapping of correct keys on the screen#

Solution that requires copying existing objects here:

More elegant solution here:

Chapter 4 - Variables (in OpenSesame)#

Gaze cuing task in OpenSesame#

Tutorial solution: here

Exercise 1. Express the location of the cues in relative terms#

  1. Change all -300 and 300 values in the block loop to -0.1 and 0.1. These indicate the % values which will be used next to calculate the new x-coordinates.

  2. Add an inline script above the target sketchpad with the content:

# student from WG 101
# var.width stores width of the screen set in the experiment
# Calculate new positions by calculating the proportion of this width
var.target_pos = float(var.target_pos) * var.width
var.dist_pos = float(var.dist_pos) * var.width
  1. And within the target object, ensure you refer to each of these new positions using the squared-bracket notation (remains unchanged).

Note that one disadvantage of the solution above is that we OVERWRITE the original information in target_pos so this information is not logged anymore. If you want to keep the original information it is better to create a new variable (e.g. target_pos2 and use the squared-bracket notation to refer to this variable instead).

Exercise 2. Track the number of trials per block#

Solution here

Exercise 3. Calculate a running average of the accuracy#

Solution here

Exercise 4. Add a progressbar (advanced)#

Solution here

Chapter 5 - Variables (in python)#

Python Exercises: Variables#

Exercise 1. Print welcome text#

name = input("Enter your name: ")
print("Hello " + name)
Enter your name: teacher
Hello teacher

Exercise 2. Compute gross pay#

hours = float(input("Enter Hours: "))
rate = float(input("Enter Rate: "))
print("Pay: " + str(hours*rate))

# OR

hours = input("Enter Hours: ")
rate = input("Enter Rate: ")
pay = float(hours) * float(rate)
print("Pay: ", pay)
Enter Hours: 5
Enter Rate: 5
Pay: 25.0
Enter Hours: 5
Enter Rate: 5
Pay:  25.0

Exercise 3. Numeric calculations#

width = 17
height = 12.0
print(width//2)
print(type(width//2))
print(width/2.0)
print(type(width/2.0))
print(height/3)
print(type(height/3))
print(1 + 2 * 5)
print(type(1 + 2 * 5))
8
<class 'int'>
8.5
<class 'float'>
4.0
<class 'float'>
11
<class 'int'>

Exercise 4. Convert temperature#

celsius = float(input("Enter temperature in Celsius: "))
print("Temperature in Fahrenheit: " + str((celsius * 9/5) + 32))
Enter temperature in Celsius: 30
Temperature in Fahrenheit: 86.0

Exercise 5. Convert reaction time#

import math
RT = int(input("Enter reaction time value in ms (between 1 and 2000 ms): "))
RTinv = round(-1000 / RT,2)
RTlog = round(math.log(RT),2)
print("Inverse RT is: " + str(RTinv) + "; Log RT is: " + str(RTlog) + ".")

Exercise 6. Combine reaction time and accuracy information#

RT = int(input("Enter average reaction time value in ms (between 1 and 2000 ms): "))
ACC = float(input("Enter average accuracy score as proportion (between 0 and 1): "))
IES = round(RT/ACC)
PEp = round((1-ACC)*100,2)
print("When combining an RT of " + str(RT) + " ms and an ACC of " + str(ACC) + " (= " +  str(PEp) + "% errors), the IES score is " + str(IES) + " ms.")
Enter average reaction time value in ms (between 1 and 2000 ms): 45
Enter average accuracy score as proportion (between 0 and 1): 0.5
When combining an RT of 45 ms and an ACC of 0.5 (= 50.0% errors), the IES score is 90 ms.

Exercise 8-12. Repeat in OpenSesame#

Exercise 8 (Print welcome text) solution: here

Exercise 9 (Compute gross pay) solution: here

Exercise 10 (Convert temperature) solution: here

Exercise 11 (Convert reaction time) solution: here

Exercise 12 (Combine reaction time and accuracy information) solution: here

Chapter 6 - Conditionals#

The Wiconsin Card Sorting Task in OpenSesame#

You can download the full experiment, including the solutions to the extra assignments, here:

https://osf.io/f5er2/

Exercise 1. Calculate average performance#

We want to present proportion of accurate, incorrect and missing responses to the participants in the feedback object.

For this, first, we would like to count the number of missing trials to calculate the proportion of missed responses.

We add a var_init python inline object right before the block_loop to initialize the value for the variable var.missing. Setting this variable outide the block loop avoids resetting it to 0 each time the loop runs.

var.missing = 0

We then want to update this value if participants did not respond on a given trial. Otherwise, the value remains unchanged.

  1. We add a new python inline object checkMissing inside the trial_sequence below the incorrect_sound. And we make sure that this python inline runs only when the [response] = “None”.

  2. Calculate the proportion of missing trials compared to all trials seen so far. We do this in a new python inline calculate_rates we add before the feedback object.

  3. Calculate the current error rate, Error = 1 - (Accurate + Missing).

## checkMissing inline should contain the following:
var.missing = var.missing + 1 # one more missing trial
## calculate_rates inline should contain the following:
var.missing_rate = (var.missing/(var.count_trial_sequence + 1)*100)
# notice that we needed to add 1 to the count of trials. This is because the OpenSesame counts trials starting at 0.

var.err_rate = 100 - (var.missing_rate + var.acc)
  1. At the end of each block, the feedback item displays the final proportions of correct, incorrect and missed trials. The structure of the experiment and the feedback item are shown below.

MicrosoftTeams-image.png

Exercise 2. Counterbalancing using python script#

Adapt the correct responses in the correct position in the triallist using the values: [corresp_red] [corresp_green] [corresp_blue] and [corresp_yellow]

e.g. [corresp_red] replaces all values “r”, etc.

also refer to these four variables with squared bracket notation in the instruction.

Then, somewhere before you present the trials (e.g. beginning of the experiment) add the following inline script:

# EITHER method 1
if var.subject_parity == "odd":
  var.version = "version 1"
  var.corresp_red = "1"
  var.corresp_green = "2"
  var.corresp_blue = "3"
  var.corresp_yellow = "4"
else:
  var.version = "version 2"
  var.corresp_red = "3"
  var.corresp_green = "4"
  var.corresp_blue = "1"
  var.corresp_yellow = "2"

# OR method 2, only the first line needs to change:
if var.subject_nr % 2 == 1:
  var.version = "version 1"
  var.corresp_red = "1"
  var.corresp_green = "2"
  var.corresp_blue = "3"
  var.corresp_yellow = "4"
else:
  var.version = "version 2"
  var.corresp_red = "3"
  var.corresp_green = "4"
  var.corresp_blue = "1"
  var.corresp_yellow = "2"

Exercise 3. Create flanker arrows using Canvas commands (advanced)#

Solution can be downloaded here

Optional Study Material - Python lessons: Conditionals#

Exercise 1. Advanced pay computation (1)#

solution can be found here

Exercise 2. Advanced pay computation (2)#

je hours = input('Enter Hours: ')
rate = input('Enter Rate: ')
try:
  if float(hours) > 40:
    extra_rate = float(rate)*1.5
    normal_hours = 40
  else:
    extra_rate = 0
    normal_hours = float(hours)
  pay = normal_hours*float(rate) + ((float(hours) - 40)*extra_rate)
  print('Pay: ', pay)
except:
  print('Error, please enter numeric input')
Enter Hours: 30
Enter Rate: 10
Pay:  300.0

Alternatively, substituting using raise to quit the script:

try:
    hours = int(input("Enter hours: "))
    rate = float(input("Enter rate: "))
except:
    print("Error, please enter numeric input!")
    raise

if hours > 40:
    pay = (hours - 40)*rate*1.5 + 40 * rate
else:
    pay = hours * rate

print("Pay: ", pay)

ADVANCED: If you want to quit the script after an except without an error function you will need to import the sys module:

import sys

try:
    hours = int(input("Enter hours: "))
    rate = float(input("Enter rate: "))
except:
    print("Error, please enter numeric input!")
    sys.exit(1)

if hours > 40:
    pay = (hours - 40)*rate*1.5 + 40 * rate
else:
    pay = hours * rate

print("Pay: ", pay)

Exercise 3. Convert scores to grades#

score = input('Enter your score (between 0.0 and 1.0): ')
try:
  if float(score) > 1 or float(score) < 0:
    print('Bad score')
  elif float(score) >= 0.9:
    print('A')
  elif float(score) >= 0.8:
    print('B')
  elif float(score) >= 0.7:
    print('C')
  elif float(score) >= 0.6:
    print('D')
  else:
    print('F')
except:
  print('Bad score')

Alternatively, using raise:

try:
    grade = float(input("Enter score: "))
except:
    print("Bad score")
    raise

if grade < 0 or grade > 1.0:
    print("Score is out of range!")
elif grade >= 0.9:
    print("A")
elif grade >= 0.8:
    print("B")
elif grade >= 0.7:
    print("C")
elif grade >= 0.6:
    print("D")
else:
    print("F")

Or again using sys.exit():

import sys

try:
    grade = float(input("Enter score: "))
except:
    print("Bad score")
    sys.exit(1)

if grade < 0 or grade > 1.0:
    print("Score is out of range!")
elif grade >= 0.9:
    print("A")
elif grade >= 0.8:
    print("B")
elif grade >= 0.7:
    print("C")
elif grade >= 0.6:
    print("D")
else:
    print("F")

Exercise 4. Check the age of your participant#

name = input('Your name: ')
age = input('Your age in years: ')
try:
  if float(age) < 18:
    print('Wow you are too young!')
  elif float(age) > 30:
    print('Wow you are too old!')
  else:
    print('Hello', name, ', welcome to this experiment!')
except:
  print('Invalid input, try again!')

Chapter 7 - Functions#

The Ultimatum Game in OpenSesame#

A solution can be downloaded by clicking this link

Optional Study Material - Python exercises: Functions#

Exercise 1. Sequence of function calls#

Correct answer: D

Exercise 2. Pay computation with a function#

solution can be found here

Exercise 3. Grade calculation using a function#

solution can be found here

Exercise 4. Check age of your participant#

def check_age(age, name):
  if age < 18:
    return "You are too young for this experiment."
  elif age > 30:
    return "You are too old for this experiment."
  else:
    return f"Hello {name}, welcome to this experiment."

name = input("Please enter your name: ")
age = int(input("Please enter your age: "))
message = check_age(age, name)
print(message)

Chapter 8 - Loops#

The Cyberball game in OpenSesame#

Solution to the first part of the tutorial can be downloaded here

Solution to the second part of the tutorial (with the custom code) can be downloaded here

Exercise 1. Loop the countdown timer using code#

Solution can be downloaded here

Exercise 2. Create a function of the countdown timer#

Solution can be downloaded here

Exercise 3. Fixing the issue of incorrect number of trials#

There are multiple throws in one trial! So there are likely more than 60 throws presented in this experiment. If you set the number of trials to 1 you see that this trial first let player 1 throw the ball, and after that 2 or 3 throws the ball in the same trial. This happens because each for each player_loop it is checked, independently of each other (!), whether current_player equals the values 1, 2, and 3 respectively. Because player_loop2 and player_loop3 will be run after player_loop1, the first trial will already present two throws (1>2 then 2>3, or 1>3 then 3>2) or even three or more throws (e.g. 1>2, then 2>1, then 1>2 or 3 etc.).

The full solution for this step can be downloaded [here] (https://downgit.github.io/#/home?url=https://github.com/henkvs/experimentation_i_2324/blob/main/content/solutions/Cyberball_loops05_2_Exercise1-rev1.osexp)

Exercise 4. Present video at the center of the screen#

The full solution for this step can be downloaded here

play_movie inline is changed to include the following:

import cv2
import numpy
import pygame
# Full path to the video file in file pool
          
path = pool[var.movie_filename]
# Open the video
video = cv2.VideoCapture(path)
# A loop to play the video file. This can also be a while loop until a key
# is pressed. etc.
videowidth = video.get(cv2.CAP_PROP_FRAME_WIDTH)
videoheight = video.get(cv2.CAP_PROP_FRAME_HEIGHT)
          
for i in range(100):
    # Get a frame
    try:
        retval, frame = video.read()
        # Rotate it, because for some reason it otherwise appears flipped.
        frame = numpy.rot90(frame)
        # Flip it (vertically?!), because for some reason it otherwise appears horizontally (!) flipped.
        frame = numpy.flipud(frame)
        # The video uses BGR colors and PyGame needs RGB

        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        # Create a PyGame surface
        surf = pygame.surfarray.make_surface(frame)
    except:
        #end of movie
        break

    # Show the PyGame surface!
    exp.surface.blit(surf, ((var.width - videowidth) / 2, (var.height - videoheight) / 2))
    pygame.display.flip()

Exercise 5. Change the speed of the video#

The full solution for this step can be downloaded here

In the Run tab of the play_movie:

import cv2
import numpy
import pygame
# Full path to the video file in file pool
          
path = pool[var.movie_filename]
# Open the video
video = cv2.VideoCapture(path)
# A loop to play the video file. This can also be a while loop until a key
# is pressed. etc.
videowidth = video.get(cv2.CAP_PROP_FRAME_WIDTH)
videoheight = video.get(cv2.CAP_PROP_FRAME_HEIGHT)

fps =  video.get(cv2.CAP_PROP_FPS)
print(fps)

for i in range(100):
    # Get a frame
    try:
        retval, frame = video.read()
        # Rotate it, because for some reason it otherwise appears flipped.
        frame = numpy.rot90(frame)
        # Flip it (vertically?!), because for some reason it otherwise appears horizontally (!) flipped.
        frame = numpy.flipud(frame)
        # The video uses BGR colors and PyGame needs RGB

        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        # Create a PyGame surface
        surf = pygame.surfarray.make_surface(frame)
    except:
        #end of movie
        break

    # Show the PyGame surface!
    exp.surface.blit(surf, ((var.width - videowidth) / 2, (var.height - videoheight) / 2))
    pygame.display.flip()
    # clock.sleep(1000/fps)
    myclocktick(fps)

In the Prepare tab of the play_movie:

def myclocktick(foo):
  #inspired by clock.tick
  #see https://stackoverflow.com/questions/34383559/pygame-clock-tick-vs-framerate-in-game-main-loop
  if var.has(u'prevt'):
        diff = ((1000/foo) - (clock.time() - var.prevt) ) - 10
        if diff>0:
            clock.sleep(diff)

  var.prevt = clock.time()

Exercise 6. Manipulate the level of social exclusion#

The full solution for this step can be downloaded here

Exercise 7. Alternatives to manually prepare an OpenSesame object#

The full solution for the step 1 can be downloaded here

The full solution for the step 2 can be downloaded here

Optional Study Material - Python exercises: Loops#

Exercise 1. Print total, count, and average#

solution can be found here without the try..except structure

Exercise 2. Print total, count, and average and check incorrect inputs#

solution can be found here

count = 0
total = 0

while True:
    str_val = input("Enter a number:")
    if str_val == 'done':
        break
    try:
        val = float(str_val)
    except:
        print("Invalid input")
        continue
    total = total + val
    count = count + 1

print(total, count, total/count)
Enter a number:56
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-1-8eaacffe244b> in <module>
      3 
      4 while True:
----> 5     str_val = input("Enter a number:")
      6     if str_val == 'done':
      7         break

/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py in raw_input(self, prompt)
    858                 "raw_input was called, but this frontend does not support input requests."
    859             )
--> 860         return self._input_request(str(prompt),
    861             self._parent_ident,
    862             self._parent_header,

/usr/local/lib/python3.8/dist-packages/ipykernel/kernelbase.py in _input_request(self, prompt, ident, parent, password)
    902             except KeyboardInterrupt:
    903                 # re-raise KeyboardInterrupt, to truncate traceback
--> 904                 raise KeyboardInterrupt("Interrupted by user") from None
    905             except Exception as e:
    906                 self.log.warning("Invalid Message:", exc_info=True)

KeyboardInterrupt: Interrupted by user

Exercise 3. Print maximum and minimum#

solution can be found here

Exercise 4. Print moving text#

fill = ""
import time
for i in range(1,41):
    fill = fill + " "
    print("\r",fill + 'Hello world',end='')
    time.sleep(0.5)
                                         Hello world

Exercise 5. Print a Christmas tree#

def print_tree(height):
    # Loop through the rows of the tree
    for row in range(height):
        # Print spaces before the asterisks to center the tree
        for space in range(height-row-1):
            print(" ", end="")
        
        # Print the asterisks for the current row
        for asterisk in range(row*2+1):
            print("*", end="")
        
        # Move to the next row
        print()

# Test the function with different values for the height
print_tree(5)
print_tree(7)
print_tree(10)

Chapter 9 - Strings and lists#

Memory Span Task in OpenSesame#

Solution to the tutorial can be downloaded here

Exercise 1. Abort the experiment when four trials in a row are incorrect#

Step 1: Initialize two variables and set the break-if statement

var.stop = 0 # abort the Conditions loop when the value is 1
incorrect = 0 # record the number of successive incorrect trials

exerciese1_1.png

Step 2: Update variables based on the response of current trial

# insert these codes into inline_script item "process_trial"
if var.num_correct != var.num_total: 
    incorrect = incorrect + 1
    if incorrect == 4:
        var.stop = 1
else:
    incorrect = 0

Step 3: When var.stop has changed to 1, skip the following Sketchpad item “Next” and the Keyboard_response item SPACE_BAR” (Because there’s no next trial)

exerciese1_2.png

Exercise 2. Recollect the sequence in reversed order#

**Add and modify some codes in “process_trial”: **

Step 1: Create a new variable “var.seq_reversed” to store the reversed sequence

# (1) This can be achieved by iteratively adding each character in var.seq_presented into var.seq_reversed in reversed order
var.seq_reversed = ''
for i in range(1,len(var.seq_presented)+1):
    var.seq_reversed = var.seq_reversed + var.seq_presented[len(var.seq_presented)-i]
# (2)	A much easier solution is to use negative slicing
var.seq_reversed = var.seq_presented[::-1]

Step 2: Modify the conditional and loop statements related to feedbacks

if (var.response == var.seq_reversed): 
    var.fbtext = "Correct sequence"
else:
    var.fbtext = "Incorrect sequence"
for i in range(len(var.response)):
    if var.response[i] == var.seq_reversed[i]: 
        var.num_correct = var.num_correct + 1

Exercise 3. Ignore duplicates in the answer#

The following code counts number of correct letters while ignoring duplicates. Note, when combining this with Exercise 2, you might have to use ‘var.seq_reversed’.

seq_check = var.seq_presented 
for char in var.response: 
    if (seq_check.find(char)) > -1: 
        var.num_correct = var.num_correct + 1
        seq_check = seq_check.replace(char,'') 

Note: If you generally wish to remove duplicates in a string while ensuring that letter order is preserved, you can use one of the following options. Also note that the set function is often used in Python to remove duplicates, but it does not preserve order.

Option 1.

# code builds a new string t using unique letters within a string str. It does this in the order of letters found in str. 

str = "abdb"
t = "" # empty
for i in str: # for each letter in str
    if (i in t): # if the letter is already in t
        pass # do nothing
    else: # if the letter is not in t
        t = t + i # add that to t
    
print (t) # outputs abd

------------
Option 2.
 

from collections import OrderedDict
str = "pqrqtrq" 
x = "".join(OrderedDict.fromkeys(str))
print (x) # outputs pqrt

Optional Study Material - Python exercises: Strings#

Exercise 1. Extract substring#

text1 = "X-DSPAM-Confidence:0.8475"
col_index = text1.find(":")
num = float(text1[col_index+1:])
print(num)
print(type(num))

Exercise 2. Understanding string methods#

We provide 3 solutions that handle the reduction of whitespaces between words differently

text2 = "  This is a  setece      with  a typo and   too many  spaces "

text2 = text2.strip()
text2 = text2.replace("setece", "sentence")

while "  " in text2:
  text2 = text2.replace("  ", " ")

print(text2)
This is a sentence with a typo and too many spaces
string = "  This is a  setece      with  a typo and   too many  spaces "
string = string.strip()
string = string.replace('setece', 'sentence')
string = string.replace('   ', ' ') # first reduce 3 whitespaces to 2
string = string.replace('  ', ' ') # second reduce 2 whitespaces to 1

print(string)
This is a sentence with a typo and too many spaces
string = "  This is a  setece      with  a typo and   too many  spaces "

string = string.strip()
string = string.replace('setece', 'sentence')
string = ' '.join(string.split()) # split the string (removes spaces) and rejoin it (around 1 space)

print(string)
This is a sentence with a typo and too many spaces
string = "  This is a  setece      with  a typo and   too many  spaces "
" ".join(string.split())
'This is a setece with a typo and too many spaces'

Exercise 3. Create a looping text#

#s = "1234"
s = "Look at this moving text!!!!!!!!!!!!!!!!"

import time
for repeat in range(0,3):
  for i in range(0,len(s)):
      print('\r',s[i:len(s)]+s[0:i],end='')
      time.sleep(0.2)
      
#end with original
print('\r',s,end='')      
      
  moving text!!!!!!!!!!!!!!!!Look at this
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-2-d5cb639a8fca> in <module>
      6   for i in range(0,len(s)):
      7       print('\r',s[i:len(s)]+s[0:i],end='')
----> 8       time.sleep(0.2)
      9 
     10 #end with original

KeyboardInterrupt: 
import time

text = "Look at this moving text!!!!!!!!!!!!!!!!"
for repeat in range(3):

  for i in range(len(text)):
    # right to left
    print('\r', text[i:] + text[:i], end = '')
    # left to right
    print('\r', text[-i:] + text[:-i], end = '')
    
    time.sleep(.2)
 !!!!!!!!!!!!Look at this moving text!!!!
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-3-a9e8e2ad0e9e> in <module>
     10     print('\r', text[-i:] + text[:-i], end = '')
     11 
---> 12     time.sleep(.2)

KeyboardInterrupt: 

Optional Study Material - Python exercises: Lists#

Exercise 1. Find all unique words in a file#

solutions can be found here

Exercise 2. Minimalist Email Client#

solutions can be found here

Exercise 3. Process list of numbers#

solutions can be found here

Exercise 4. Using tuples in the grade calculation#


def calc_grade(score):
  # define grades and scores tuples
  grades = ('A', 'B', 'C', 'D', 'E', 'F')
  scores = (0.9, 0.8, 0.7, 0.6, 0.5, 0.0)

  # loop over them, leaving out F
  for i in range(len(grades)-1):
    
    # if score is larger/equal than cutoff, assign the grade 
    if score >= scores[i]:
      grade = grades[i]
      return grade
      
  # otherwise, return F
  return 'F'
    
# Test
calc_grade(0.7)

Chapter 10 - Q&A#

Questionnaires in OpenSesame#

solution can be found here

Exercise 1. Update the OK button earlier#

TODO

Exercise 2. Create a striped color layout#

solution can be found here

Exercise 3. Make the code more compact#

TODO

Exercise 4. Radio-button layout (advanced level!)#

TODO

OpenSesame solutions - extra exercises#

Solution Exercise 1 link

Solution Exercise 2 link

Solution Exercise 3 link

Solution Exercise 4 link

Solution Exercise 5 link

Below is an Alternative approach to “performance_contingent_smiley” script in Exercises 3-5. The objective of the script is:

  1. Show Pos smiley when response is correct and <=500ms.

  2. Show Neutral smiley when response is correct but slow (>500ms).

  3. Show Negative stimuli when response is incorrect, or in the absense of a response (‘too late’ as written in the PDF).

Unlike in the solution uploaded above, it is usually better to avoid comparisons with RTs to look for missing responses.

  • Always go for checking missed responses directly like var.response_keyboard_response !='None'.

  • Sticking to RT checks is error prone. If you change the time allowed for the response elsewhere in the experiment (may be to debug or pilot the experiment), you might have to change the way you detect missed responses too.

  • Different software use different RTs for missed responses. RT for missed responses is 0 in Eprime, ‘[ ]’ in Psychopy, or a few microsenconds higher than max limit of the keyboard object (around 1000.50ms in this experiment).

Hence the following code is recommended as a form of best practice.

if var.response_keyboard_response !='None':
    if var.correct == 1 and var.response_time_keyboard_response <= 500:
        var.smiley = 1 #positive
        var.totalPoints = var.totalPoints + 20
    elif var.correct == 1 and var.response_time_keyboard_response > 500:
        var.smiley = 3 #neutral
        var.totalPoints = var.totalPoints + 0
    else:
        var.smiley = 2 #negative
        var.totalPoints = var.totalPoints - 20
else:
    var.smiley = 2 #negative
    var.totalPoints = var.totalPoints - 20


Extra Python exercises: Multiplication Table#

# 1
for i in range(1,11):
    print(i)
# 2
m = 5 # Change this to any integer you want

for i in range(1,11):
    print(i,"x",m)
# 3
m = 5 # Change this to any integer you want

for i in range(1,11):
    x = i * m
    print(i,"x",m,"=",x)
# 4
def print_multiplication_table(m):
    for i in range(1,11):
        x = i * m
        print(i,"x",m,"=",x)

print_multiplication_table(9)
# 5
for m in range(1, 11):
    print(f"The multiplication table of {m}:")
    print() # Optional for readability
    print_multiplication_table(m)
    print() # Optional for readability


# OR 
for m in range(1, 11):
    print(f"The multiplication table of {m}:\n") # Way nicer actually!
    print_multiplication_table(m)
    print()
# 6
group4 = [1,2,5,10]
group5 = [3,4,6,7,8,9]

print("The following multiplication tables are learned in group 4")
for m in group4:
    print(f"The multiplication table of {m}:")
    print()
    print_multiplication_table(m)
    print()

print("The following multiplication tables are learned in group 5")
for m in group5:
    print(f"The multiplication table of {m}:")
    print()
    print_multiplication_table(m)
    print()
# 7
group4 = [1,2,5,10]
group5 = [3,4,6,7,8,9]

def group_number_chosen(group_number):
    if group_number == 4:
        print("The following multiplication tables are learned in group 4")
        for m in group4:
            print(f"The multiplication table of {m}:")
            print()
            print_multiplication_table(m)
            print()

    elif group_number == 5:
        print("The following multiplication tables are learned in group 5")
        for m in group5:
            print(f"The multiplication table of {m}:")
            print()
            print_multiplication_table(m)
            print()

group_number_chosen(4)
# 8
def test_multiplication_table(m):
    score = 0
    for i in range(1, 11):
        answer = int(input(f"{m} x {i} = "))
        if answer == m * i:
            print("Correct!")
            score += 1
        else:
            print(f"Incorrect. The correct answer is {m*i}")
    return score / 10 * 100

# Call the function with different values of m
score = test_multiplication_table(5)
print(f"Your score is {score}%")
# 9 and 10

def test_multiplication_table(m):
    score = 0
    count = 0
    for i in range(1, 11):
        while True:
            answer = input(f"{m} x {i} = ")
            if answer.isdigit():
                answer = int(answer)
                count += 1
                break
            else:
                print("Please enter a valid number!")

        while answer != m * i:
            answer = input(f"Incorrect. Please try again. {m} x {i} = ?: ")
            if answer.isdigit():
                answer = int(answer)
                count += 1
            else:
                print("Please enter a valid number!")

        print("Correct!")
        score += 1

    return int(score / count * 100)

# Call the function with different values of m
score = test_multiplication_table(5)
print(f"Your score is {score}%")

Example output last exercise:

Correct!

Please enter a valid number!

Correct!

Correct!

Correct!

Correct!

Correct!

Correct! Correct! Correct! Correct! Your score is 83.33333333333334%