# How Rules Work

It may help, when building complex experiences, to note the following properties about Rules in GMetri.

## Order Matters

* Rules are executed in order of definition. So on the rules page if you have these rules in the following order, then Video1 would end up in a paused state, as that executes last:
  * **First Rule**: "`When Video1 is clicked, Then Video1 should play`"
  * **Second Rule:** "`When Video1 is clicked, Then Video1 should pause`"
* Within a single rule, the "When Events" are **checked in order**&#x20;
* Within a single rule, the "Then Actions" are **executed in order**. So if you have a rule like the following, the image would end up hidden.
  * "`When something is clicked, Then Image1 should show AND Image1 should hide`"

## The Mental Model for Rules

It is helpful to think of the "When" side of rules as a series of pipes, that are either <mark style="color:green;">green</mark> or <mark style="color:red;">red</mark> in color. If any of the When events get triggered, the system decides if its a hit or a miss, and paints the pipe either <mark style="color:red;">red</mark> (No go) or <mark style="color:green;">green</mark> (Good to go).

*The reason the paint analogy works, is because the when event states persist.*

**"is clicked"** is a special rule that paints the pipe <mark style="color:green;">green</mark> for exactly *one Rules check*, and then paints it <mark style="color:red;">red</mark> again.

**"has been clicked"**, in contrast to "is clicked", paints the pipe <mark style="color:green;">green</mark>, forever. However, these events do trigger and check if the rule should be executed everytime.

#### Example:

Let's say we have the following rule, based on a "count" integer variable:

`When (count is = 2 AND Image1 is clicked)`\
`Then (you_have_passed_text should appear)`

* Let's say count becomes 1. Then the "`count is = 2`" when event is checked - it's obviously not true, so the system paints "`count is = 2`" pipe <mark style="color:red;">red</mark>. Whenever the image is clicked, its counter part is <mark style="color:red;">red</mark>, so this rule wont trigger.
* When count becomes 2, the first pipe is painted <mark style="color:green;">green</mark>, and clicking on Image1 *will* trigger the rule.
* Again, once count become 3, the first pipe is painted back <mark style="color:red;">red</mark>.

### Implications of the Rules Mental Model

This mental model also makes clear a few important points:

* If a pipe is already green, painting it green again will have no impact.
  * Example, for the rule "`When a > 2, then ...`", when a goes above 2 and becomes 3, this rule gets triggered once. But after that, a becoming 4, 5, 6 etc will have no impact (as the pipe is  already <mark style="color:green;">green</mark>).
* **Variable When Events trigger when they change:** "`When variable_a changes`" when event is triggered ONLY if the value stored in variable\_a changes. Lets say its value is "hello", and we set it to "hello" once again, this rule isn't triggered again. Because truly, the variable\_a did not change.
* **Click based When Events trigger every time.**
* If you have a rule that says "`When Image1 is clicked AND Image2 is clicked`", it would very likely never trigger. This is because "is clicked" makes the pipe <mark style="color:green;">green</mark> for excely one Rules check and then paints it <mark style="color:red;">red</mark> again. For this rule to trigger, the user would have to click both the images at the same instant. What you more likely want in a scenario like this is "`When Image1 has been clicked AND Image2 has been clicked`"

## When do Rules Run?

* Rules require a **trigger** to run. Any of the "When Events" can provide the trigger. A trigger needs either a single green pipe (in case of **OR**) or all green pipes (in case of **AND**) to flow through successfully and fire the rule.
* In case of "**AND**" linked when events, all "pipes" (When Events") need to be <mark style="color:green;">green</mark> for the trigger to actually run (fire) the rule.
* In case of "**OR**" linked when events, any single pipe being <mark style="color:green;">green</mark>, and the generation of a trigger (in that pipe) is enough to actually run (fire) the rule.

### Common Rule Triggers

* An "`on click`" when event *always* generates a trigger. However for "`on click`" the pipe becomes <mark style="color:red;">red</mark> immediately after the trigger. If there's any other pipe (i.e. when event) linked to it using an "**AND**" condition, and the pipe is <mark style="color:red;">red</mark> ***at that instant***, the rule won't fire.
* A "`has been clicked`" when event also generates a trigger. But there's no negation happening here - once the pipe is <mark style="color:green;">green</mark>, it stays <mark style="color:green;">green</mark>, until the scene changes.
* A `"variable_a changes"` when event is similar to "`has been clicked`". Once the variable changes because of any rule, the pipe stays <mark style="color:green;">green</mark>. You may want to use this event as a trigger generator on every value change of a variable.
* A `"variable_a > 5"` (or any other variable comparison) based when event generates a trigger at the instant the condition becomes true. If the condition is already true and the variable changes again in a way that keeps the condition true, no new trigger is generated. **Note:** A variable pipe that is already <mark style="color:green;">green</mark>, won't trigger again unless it goes <mark style="color:red;">red</mark> (i.e. condition becomes false) and then becomes <mark style="color:green;">green</mark> again (only a color change qualifies as a trigger for variable comparison when events).

## Recreated per Scene

Rules are defined per scene at a time.

When a viewer enters a GMetri experience, the Rules are initialized for the scene that the viewer is in. On every scene change, the older engine is dismantled and a new one is created for that scene. So when you go from Scene1 to Scene2 and back to Scene1, all the "is clicked" when events get reset back to the initial state (of not being clicked yet).

### Initialization of  a Scene

Whenever a viewer enters a new scene, the following things happen, in order:

* The scene's **preload** event is fired. You can use this event to show/hide videos or audios that you want to autoplay on scene start. Any rules defined with the when event "`When scene preloads`" get triggered here.
* Any elements that are set to "**autostart**" (like any audios), autostart at this time.
* All variables based rules are checked with their current values. So if you have any when events like "`When variable_a is = 2 then ...`", they are triggered at this point.
* The scene's **load** event is fired. Any rules defined with the when event "`When scene loads`" get triggered here.

## Checking if a Variable is Equal to Another

You can use variable substitution to check if a variable is equal to another. Example:

`When variable_a is = {{variable_b}}`

However, this check will be triggered only whenever variable\_a changes, and not when variable\_b changes. So to check for variable equality, we need to use the following rule:

`When variable_a is = {{variable_b}} OR variable_b is = {{variable_a}}`

<figure><img src="https://2186043722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Mgll1jjQMRTVj7p6n7g%2Fuploads%2FUDuc0aOQwNbQLzlfq7V9%2Fimage.png?alt=media&#x26;token=ae75a622-ed86-4f4e-a9ac-d6818cc03e10" alt=""><figcaption><p>Checking for variable equality</p></figcaption></figure>
