Writing Goals (Python)

Overview

A Goal in Tychos is a short piece of code in a scenario which can check a student's work. Goals are written by the scenario's author, usually an instructor. To the student, the goals appear as a sentence describing something the student should do. At a time defined within the goal, the goal is "checked" and if the goal is satisfied, it turns green. Otherwise it turns red. If the goal's state has not yet been "checked" it will display a question mark.

Writing a Goal

In order to write a goal, you need to be logged in as an Instructor. Only instructors see blue pencil edit buttons at the right side of the goal. Goals can be dragged up or down to reorder the goals. This does not affect when they are checked, but just as a way for you to change how they re being presented to the students.

When you click the pencil button to edit a goal, the goal turns into three edit boxes. The blue pencil button changes to three buttons:

  • A "check" button for saving the goal

  • An "x" for closing the edit boxes without saving them.

  • A "trashcan" button for deleting the goal.

Each edit box represents the three parts of a goal - (1) a description which the student sees, (2) a when condition which specifies at what time the goal will be checked, and (3) the victory condition which specifies what value the student is supposed to create. Here is a simple Goal:

In this case the Goal is:

Description: Create a Circle object called c1 with a position of (10, 10), a radius of 5, and a color of "green"

When Condition: "frame_count == 0"

Success Condition:

def test1():
  if "c1" in globals():
    return equals(c1.pos, vec(10, 10)) and c1.radius==5 and c1.color == "green"
  else:
    return False

test1()

The above goal's when condition is fired when the frame_count is 0, which causes the success condition to be checked right after the initial state code is run, and before the first calculations code is run.

The code in the success condition first defines a function called test1. The name of the function does not matter, but the function must return either True or False.

The very last line of code calls this function. So the general format for the success condition is like this:

# Define a function
def my_function()
    if condition:
        return True
    else:
        return False

# Now call the function
my_function()

In our example, the test1() function uses a conditional statement that first tests to see if the variable c1 exists in the global scope:

if "c1" in globals():

If the variable exists, it then evaluates the following:

equals(c1.pos, vec(10, 10)) and c1.radius==5 and c1.color == "green"

If any of the comparisons do not evaluate to True, then the function will return False, but if they are all true, then the function will return True

To satisfy this goal, the student can write this:

# Intial State
c1 = circle(pos=vec(10, 10), radius=5, color="green")

The initial position of the circle is [0, 0] before the simulation begins - this is frame 0. The frame_count variable allows you to track the frame of the simulation.

In the above Goal's victory condition code, you can see that we used the function equals to see if the position of the circle is (0, 0). When comparing vectors for equivalency, you need to use equals.

If the student were to then write this code in the Calculations Pane:

# Calculations
c1.pos = vec(1, 1)

The success condition would still be met because this would change the circle's position after the initial conditions have already been tested at frame 0.

Testing Future Conditions:

Here is another goal that will check that a student has moved the circle to a new position at a time other than at the beginning of the simulation:

In this case the Goal is:

Description: "Move the circle to a new position so that it is at (20, 20) at time t = 2 seconds."

When Condition: "t == 2"

Success Condition:

def test2():
  try:
    if equals(c1.pos, vec(20,20)):
      return True
    else:
      return False
  except:
    return False

test2()

The above goal's when condition is fired when t is 2, which causes the success condition to be checked at the moment the simulation reaches a time of 2 seconds. This example demonstrates that you can choose either to trigger the Goal test using a specific frame, or a time in seconds.

You could also set the when condition using a comparison operator. This would allow you to test your goal state every frame as long as the when condition was set:

# When Condition
t > 2

Notice in the Success Condition that we use a try - except statement in order to catch any errors that might occur during the execution of the tests. This can be helpful because in this case, if they have not even defined a variable called c1, Tychos will generate an error, and the simulation will not run. Using this method, catches the error, and simply returns a False value to the goal checking mechanism which results in the goal not passing.

Tips When Writing Goals

  • Use the logical operators and and or to combine conditions. This can be helpful in making sure that something is meeting two different conditions, or could be meeting one of two (or three, etc.)

  • If you are referencing variable names, its a good idea to see if the exist first in the global scope, using the built in globals() function.

  • Use a try-except statement if you suspect the testing of the success condition might generate/throw an error.

  • Make sure that you test your own goals. You can also test your success conditions in the Calculations Pane as a way to see if the condition code is working.

  • You could also use print statements in your Success Conditions as a way to print out messages to the Console when the goal is tested. This might be used to provide hints to your students.

Last updated