Share via


Configuration

The beginning model for this example walkthrough of Point and Shoot has three actions: two stimuli and a response, declared in the following Cord configuration (from file Config.cord):

config MovementActions 
{
    action static void SailboatController.Sail(Heading heading,int hours,int knots);
    action event static void SailboatController.RunAground(int atx, int aty);
    action static void SailboatController.Rescue();

    // ... configuration switches ...
}

The most important stimulus is Sail, which commands the sailboat to move in a certain direction, at a certain speed, for a certain time. The RunAground response is emitted by the sailboat if it hits the lake shore as a result of the last Sail call. After this, the sailboat can no longer sail until it receives a Rescue stimulus, which transports it to the starting location and restores its sailing capacity.

Sail uses an enumerated type from the SUT implementation to represent possible headings. It maps each heading to a corresponding angle, in degrees, with respect to the east-west direction. The Heading enumeration is shown in the following code example (from file Implementation.cs).

public enum Heading
{
    N = 90,
    S = 270,
    E = 0,
    W = 180,
    NE = 45,
    NW = 135,
    SE = 315,
    SW = 225
}

A static class is used in the model program. Its state consists of the position of the sailboat and a flag indicated if the boat has run aground, as shown in the following model code example (from file Model.cs).

namespace Sailboat.Model
{
    public static class SailboatModel
    {
        static int x, y;
        static bool runAground = false;
        static bool agroundFired = false;

        // ...  Other Model Program Code (described in the following)
    }
}

Sail is modeled in a single rule method. Its enabling conditions require that the sailboat has not already run aground and that the time and speed parameters have positive values, as shown in the following example code (from file Model.cs).

[Rule]
static void Sail(Heading heading, int hours, int knots)
{
    // Because the Math functions will influence the parameter generation functions,
    // the parameters are explicitly expanded here to preclude that influence.
    Combination.Expand(heading, hours, knots);

    Condition.IsTrue(!runAground);
    Condition.IsTrue(hours > 0);
    Condition.IsTrue(knots > 0); 

    int miles = knots * hours;
    double radians = ((int) heading * Math.PI / 180);
    x += (int) Math.Round(miles * Math.Cos(radians));
    y += (int) Math.Round(miles * Math.Sin(radians));
    if (x < 0)
    {
        runAground = true;
        x = 0;
    }
    else if (x > 1000)
    {
        runAground = true;
        x = 1000;
    }
    if (y < 0)
    {
        runAground = true;
        y = 0;
    }
    else if (y > 1000)
    {
        runAground = true;
        y = 1000;
    }
} 

Position updates are calculated with a polar-to-rectangular conversion algorithm and rounded to the closest integer.

The Sail rule contains logic that effectively defines the size and shape of the lake by setting the runAground flag to be true if the position is negative or beyond 1000, either in latitude or in longitude.

The following example code (from file Model.cs) defines rules for the remaining actions.

[Rule]
static void RunAground(int atx, int aty)
{
    Condition.IsTrue(runAground);
    Condition.IsTrue(!agroundFired);
    Condition.IsTrue(atx == x);
    Condition.IsTrue(aty == y);
    agroundFired = true;
}

[Rule]
static void Rescue()
{
    Condition.IsTrue(runAground);
    Condition.IsTrue(agroundFired);
    x = y = 0;
    runAground = false;
    agroundFired = false;
}

RunAground sets agroundFired flag to true when the sailboat hits a lake shore, so its enabling conditions require it to be currently aground and for agroundFired not to have been set previously. Without the second condition, the event would keep firing indefinitely once the sailboat runs aground. The only effect of this rule is to set agroundFired to true.

Rescue can be performed only if the sailboat is already aground and agroundFired has been set. It resets its position to the initial location and re-enables Sail by setting runAground and agroundFired to false.

Remember that our accepting state condition requires the sailboat to be at the point of origin, as shown in the following example code (from file Model.cs).

[AcceptingStateCondition]
static bool InitialPosition()
{
   return x == 0 && y == 0;
}

See Also

Concepts

Point and Shoot
Comprehensive Testing