# ACT-R tutorial unit 2 assignment task.
# This experiment opens a window, displays 3 characters
# with two being the same and one different, waits for a
# keypress, and then reports whether the key that was 
# pressed matches the different letter or not.

# Import the actr module for tutorial tasks

import actr

# Load the corresponding tutorial model

actr.load_act_r_model("ACT-R:tutorial;unit2;unit2-assignment-model.lisp")

# Create a variable to store the key that was pressed.

response = False

# This is the function which we will have ACT-R call when
# a key is pressed in the experiment window which is signaled
# by the output-key action.

# That action provides two parameters to the function called.
# The first is the name of the model that performed the keypress
# or None if it wasn't generated by a model, and the second
# is a string with the name of the key that was pressed.


def respond_to_key_press (model,key):

    # just store the key that was pressed in the response variable

    global response
    response = key


# This is the function that runs the experiment for either a
# person or a model.  It has one optional parameter which if
# provided as True will run a person.
# If it is not provided or any other value is specified then
# it will run the model.

def experiment (human=False):
  
    # Reset the ACT-R system and any models that are defined to
    # their initial states.

    actr.reset()

    # Create variable for the items needed to run the exeperiment:
    #   items - a randomized list of letter strings which is randomized
    #           using the ACT-R function permute_list
    #   target - the first string from the randomized list which will be the
    #            one that is different in the display
    #   foil   - the second item from the list which will be displayed 
    #            twice
    #   window - the ACT-R window device list returned by using the ACT-R
    #            function open_exp_window to create a new window for 
    #            displaying the experiment 
    #   text# - three text items that will hold the letters to be 
    #           displayed all initialized to the foil letter to start
    #   index - a random value from 0-2 generated from the actr.random
    #           function which is used to determine which of the three
    #           text variables will be set to the target
  
    items = actr.permute_list(["B","C","D","F","G","H","J","K","L",
                               "M","N","P","Q","R","S","T","V","W",
                               "X","Y","Z"])
    target = items[0]
    foil = items[1]
    window = actr.open_exp_window("Letter difference")
    text1 = foil
    text2 = foil
    text3 = foil    
    index = actr.random(3)

    # Set the randomly chosen item to be the target letter
    
    if index == 0:
       text1 = target
    elif index == 1:
       text2 = target
    else:
       text3 = target

    # display the three letters in the window
    
    actr.add_text_to_exp_window(window, text1, x=125, y=75)
    actr.add_text_to_exp_window(window, text2, x=75, y=175)
    actr.add_text_to_exp_window(window, text3, x=175, y=175)

    # Create a command in ACT-R that corresponds to our respond_to_key_press
    # function so that ACT-R is able to use the function.

    actr.add_command("unit2-key-press",respond_to_key_press,
                      "Assignment 2 task output-key monitor")

    # Monitor the output-key action so that when an output-key happens
    # our function is called.

    actr.monitor_command("output-key","unit2-key-press")
    
    # Set the response value to '' to remove any value it may
    # have from a previous run of the experiment.

    global response
    response = ''
    
    # Here is where we actually "run" the experiment.
    # It either waits for a person to press a key or runs ACT-R
    # for up to 10 seconds giving the model a chance to do the
    # experiment.

    if human == True:

        # If a person is doing the task then for safety 
        # we make sure there is a visible window that they
        # can use to do the task, and if so, loop until the
        # response variable is not '' calling the ACT-R
        # process_events function to allow the system a 
        # chance to handle any interactions.

        if actr.visible_virtuals_available():
            while response == '':
                actr.process_events()
      
    else:

        # If it is not a human then use install_device so that
        # the features in the window will be seen by the model
        # (that will also automatically provide the model with
        # access to a virtual keyboard and mouse).  Then use
        # the ACT-R run function to run the model for up to 10
        # seconds in real-time mode.

        actr.install_device(window)
        actr.run(10,True)

    # To avoid any issues with our function for keypresses in this
    # experiment interfering with other experiments we should stop
    # monitoring output-key and then remove our command.

    actr.remove_command_monitor("output-key","unit2-key-press")
    actr.remove_command ("unit2-key-press")

    # If the response matches the target return True otherwise
    # return False.
    
    if response.lower() == target.lower():
        return True
    else:
        return False
