Skip to main content Skip to navigation

Worksheet: Light in a room

Part 1. Constructing the room

Let's consider a scenario where we have a room with a lamp and a switch for the light. What happens when you press the switch? In this worksheet, we will make a simple construal representing the room and the light. After the basic functionality, we will extend the construal with a simple query as to whether the light is on or off.

First we obviously would need a room and a lightswitch. So, let's bring them to the construal. Copy the following definitions and paste them into Script Input window of the js-eden environment, and press the Submit button. The rectangle and the button should appear to the screen.

room is Rectangle(50,50, 100, 100, (lightison) ? "yellow" : @);
lightswitch is Button("lightswitch", switchlabel, 200, 50);
picture is [room, lightswitch];

In the first and second definitions above, we prepare two basic elements (a rectangle and a button) and set suitable parameters for them. You can freely alter these parameters (x and y coordinates, width and height of the rectangle, the predefined color) to match your preferences. We will use similar components also in the later parts of this tutorial so take your time to understand how they work.

Now we have a skeleton of a "room" and a button to represent the switch. The label of the button most likely appears as "undefined". You can notice from the definitions below that the button has an observable switchlabel as a parameter. Now, when we have not yet defined a value or a dependency to that observable, it appears on the screen in an undefined state. We can attach some sensible text to the button through a dependency on the observable switchlabel, as follows:

switchlabel is (lightison) ? "Turn off" : "Turn on";

As you can see, the value of the switchlabel observable depends on the state of lightison observable (which, as you may guess from the name, defines whether the light is on or off). To turn on the light we can now simply input the following definition into the Script Input Window:

lightison = true;

As a result, the room should change to yellow (visualising that the light is on). Also, you may notice that the label of the switch button changed. Now it's a good time to take a moment to explore the previously added definitions and their connections. Open an Observable List window from the New Window menu. Type room into the search box. The list should now show the details of room observable only. Insert a | symbol into the search box, followed by switch, another |, and finally lightison, as follows:

room|switch|lightison

Now you should see the current state of three key observables of the construal. Arrange the windows so that you can see the Canvas, Script Input Window and Observable List all at the same time. Change the value of the lightison observable in the Script Input Window and observe how the values change in the observable list. Pay attention also to the canvas. What happens to the room and the light switch?

lightison = not lightison;

In this definition, the keyword not is a commonly used syntax to invert a boolean value from true to false and vice versa.

Switching the light on and off from the input editor is not very convenient. Let's create an agent that can observe button clicks and modify the observable accordingly. Copy the following lines to the Script Input.

proc press_switch: lightswitch_clicked {
	if (lightswitch_clicked) {
		lightison = not lightison;
	}
}

In this definition, we are particularly interested in the event when the button lightswitch is clicked. Hence, we set an event trigger lightswitch_clicked to fire the procedure. Inside of the procedure, we still check that the event originates from the particular observable. Then, we can turn the light on and off in a similar manner that we did earlier directly in the Script Input window.

Now you can try to press the button in the construal and the light should come on! Congratulations for getting this far!

Part 2. Playing with the light

In the second part of this tutorial we will add more interaction to the construal. The next example lets you play with your mental models about when the light is on or off. It might feel very simple or even naive, but it essentially demonstrates very important and powerful techniques of construal making that make the difference between MC and traditional programming.

First we need to add a few elements to the screen. The first two are text labels with predefined parameters for location, size, and color. The second label uses the observable resulttextcolor to define what it looks like. We will return to this a bit later.

Buttons have a few extra parameters compared with the light switch button we set up earlier. The fifth parameters determine whether the button is enabled, and the sixth parameter defines the color of the button.

question is Text("Is the light on?", 50, 200, "14px","blue" );
result is Text(resulttext, 150, 230, "14px", resulttextcolor);

buttonyes is Button("buttonyes", "Yes", 60, 230, true, (myanswer == "Y") ? "lightblue" : "white");
buttonno is Button("buttonno", "No", 110, 230, true, (myanswer == "N") ? "lightblue" : "white");

picture is [room, lightswitch, question, buttonyes, buttonno, result];

As you may notice, the observable defining the color of the buttons can change according to the state of myanswer observable. We are trying to achieve here the functionality that the selected (the most recently pressed button) would appear highlighted. Now we can set up the myanswer observable in the following procedures to observe button clicks.

proc lightis_on: buttonyes_clicked {
	if (buttonyes_clicked) {
		myanswer = "Y";
	}
}

proc lightis_off: buttonno_clicked {
	if (buttonno_clicked) {
		myanswer = "N";
	}
}

Now you should see the buttons change color when you press them, but they do not yet affect anything. Also, the previously set text label result still remains undefined. Next we will set up the result text so as to reflect correctly the current situation and selections. As you remember, result observable had a parameter resulttext which will be defined in the first of the definitions listed below.

Depending on the state of myanswercorrect observable, the value of resulttext indicates a correct or incorrect answer. The notation with ? and : symbols is very commonly used in construal making, so it's a good idea to take a moment to comprehend how the definition works. In a nutshell, the first option after question mark ? will be selected when the condition before the question mark is true (in this case, when myanswercorrect has value true). If the condition is false, a value after colon : will be selected.

resulttext is (myanswercorrect) ? "Correct answer!" : "Oops.. are you sure?";
myanswercorrect is ((myanswer == "Y") and (lightison)) or ((myanswer == "N") and (!lightison));

The second row defines the dependency for myanswercorrect obervable. In this case, the value is depends on values of the observables myanswer (this was changed in the button trigger procedures) and lightison (this was set in the light switch button triggering procedure). There are some logical operations and and or that are used to define when myanswercorrect observable gets value true or false. Conditions expressed with the logical operation and will become true if and only if both conditions are true. Furthermore, conditions with the operator or become true when one of the conditions before or after becomes true. Again, take a moment to observe and comprehend how the logical operations work in this case.

Finally, we can add a nice touch to our construal by changing the color of the result text label according to whether the answer is correct or incorrect.

resulttextcolor is (myanswercorrect) ? "green" : "red";

Great, now our construal is ready! You can play with the components and see how it behaves. To observe the status of the key observables, you may want to see their values in an Observable List. You can try the following search string in the search box.

room|switch|lightison|resulttext|myanswercorrect

Summary of the elements used in this worksheet

Here is a summary of the main elements in your construal in their basic format. You may want to use these as building blocks when making further excercises and construals of your own! Note that you have to configure the content of the button procedure where "..." appears. Also, you have to place the elements on the screen by entering the last definition.

## Rectangle
myBox is Rectangle(50,50, 100, 100, "yellow");

## Text label
myQuestion is Text("Is the light on?", 50, 200, "14px","blue" );

## Button and procedure to fire the button
myButton is Button("mybutton", "Press me!", 400, 50);
proc click_button: mybutton_clicked {
	if (mybutton_clicked) {
		...
	}
}

## Place the elements to the screen
picture is [myBox, myQuestion, myButton];