Rules
Inroduction:
To enable dynamic, context-sensitive behavior within the simulated smart environment, we implement a rule-based logic engine that governs the behavior of devices and the presentation of explanations. Each rule defines a set of precondition that, when satisfied, trigger one or more actions. This structure models programmable automation scenarios common in real-world smart home ecosystems.
This Rule-Based Interaction Logic is a powerful approach for experimental design, enabling the study of user interaction with smart systems. It allows designers to create scenarios with custom task logic, personalization, and even intentionally contradictory or impossible rules. This capability is crucial for researching user problem-solving, cognitive load, and frustration in response to systems that are confusing or appear to be malfunctioning. The rule-based nature of the engine also provides a foundation for explanation mechanisms and adaptive explanation systems, where the rules that drive the system's behavior also serve as triggers for transparency features that explain that behavior to the user.
JSON Schema
JSON Schema Code
Rule Schema
{
"title": "Rule",
"description": "A rule in the smart home system that defines automated behavior",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the rule"
},
"name": {
"type": "string",
"description": "The name of the rule"
},
"precondition": {
"type": "array",
"description": "The preconditions of the rule that must be satisfied to trigger the rule. All preconditions must be satisfied.",
"items": {
"oneOf": [
{
"type": "object",
"description": "Device property precondition",
"properties": {
"type": {
"type": "string",
"const": "Device",
"description": "Indicates this is a device-based precondition"
},
"device": {
"type": "string",
"description": "The device's name ID"
},
"condition": {
"type": "object",
"description": "The condition to check on the device",
"properties": {
"name": {
"type": "string",
"description": "The property name"
},
"operator": {
"type": "string",
"enum": [
"<=",
">",
"<",
">=",
"==",
"!="
],
"description": "The comparison operator"
},
"value": {
"type": [
"string",
"number",
"boolean"
],
"description": "The value to compare against"
}
},
"required": [
"name",
"operator",
"value"
]
}
},
"required": [
"type",
"device",
"condition"
]
},
{
"type": "object",
"description": "Time-based precondition",
"properties": {
"type": {
"type": "string",
"const": "Time",
"description": "Indicates this is a time-based precondition"
},
"condition": {
"type": "object",
"description": "The time condition to check",
"properties": {
"operator": {
"type": "string",
"enum": [
"<=",
">",
"<",
">=",
"==",
"!="
],
"description": "The comparison operator"
},
"value": {
"type": "string",
"description": "The value to compare against"
}
},
"required": [
"operator",
"value"
]
}
},
"required": [
"type",
"condition"
]
},
{
"type": "object",
"description": "Context-based precondition",
"properties": {
"type": {
"type": "string",
"const": "Context",
"description": "Indicates this is a context-based precondition"
},
"condition": {
"type": "object",
"description": "The context condition to check",
"properties": {
"name": {
"type": "string",
"description": "The context variable to check (e.g., 'task', ...)"
},
"operator": {
"type": "string",
"enum": [
"<=",
">",
"<",
">=",
"==",
"!="
],
"description": "The comparison operator"
},
"value": {
"type": [
"string",
"number"
],
"description": "The value to compare against"
}
},
"required": [
"name",
"operator",
"value"
]
}
},
"required": [
"type",
"condition"
]
}
]
},
"minItems": 1
},
"delay": {
"type": "number",
"description": "Optional delay in seconds before executing the action after preconditions are met",
"minimum": 0
},
"action": {
"type": "array",
"description": "The actions to be executed when the rule is triggered",
"items": {
"oneOf": [
{
"type": "object",
"description": "Device interaction action",
"properties": {
"type": {
"type": "string",
"const": "Device_Interaction",
"description": "Indicates this is a device interaction action"
},
"device": {
"type": "string",
"description": "The device's name ID to control"
},
"interaction": {
"type": "object",
"description": "The interaction to perform on the device",
"properties": {
"name": {
"type": "string",
"description": "The property name to change"
},
"value": {
"type": [
"string",
"number",
"boolean"
],
"description": "The value to set"
}
},
"required": [
"name",
"value"
]
}
},
"required": [
"type",
"device",
"interaction"
]
},
{
"type": "object",
"description": "Explanation action",
"properties": {
"type": {
"type": "string",
"const": "Explanation",
"description": "Indicates this is an explanation action"
},
"explanation": {
"type": "string",
"description": "The explanation ID which corresponds to the ID in explanation.json"
}
},
"required": [
"type",
"explanation"
]
}
]
},
"minItems": 1
}
},
"required": [
"name",
"precondition",
"action"
]
}
Top-Level Properties
Property | Type | Description |
---|---|---|
id | string | Unique identifier for the rule (optional, but recommended for traceability) |
name | string | Name/title of the rule |
precondition | array | Conditions that must all be satisfied to trigger the rule |
delay | number | (Optional) Delay in seconds before executing actions |
action | array | List of actions triggered if preconditions are met |
Each rule within the rules array is a self-contained object with several key properties that define its behavior: id, name, precondition, delay, and action.
- ID (optistring, optionaonal): A unique identifier for the rule
- Name (string, required): A human-readable name describing the rule's purpose (e.g., "Turn Off Coffee Machine Automatically").
- Delay (number, optional): The time in seconds to wait after the preconditions are met before executing the action. This allows for the modeling of system latency or the creation of more naturalistic, timed behaviors.
- Preconditions (array, required): An array of condition objects that represent the "IF" part of a rule. Preconditions specify when a rule becomes eligible for execution.
All listed preconditions must be met (logical AND). Different types of preconditions are as follows:
- Device State Conditions
- Time conditions
- Contextual Conditions (User's Context and Task)
- Actions (array, required): An array of action objects that represent the "THEN" part of a rule.
These are the events that occur once the preconditions are satisfied and the delay has elapsed. Supported actions include:
- Device Interaction: Changes a device’s internal state (e.g., turning off a coffee machine).
- Explanation Actions: Issues system-generated explanations
Property: ID and Name
Each rule is identified with two fields: a machine-readable id for programmatic tracking and a human-readable name for clarity. The optional id serves as a unique system identifier, while the required name describes the rule's purpose for easy debugging and management.
{
"id": "coffee_machine_rule",
"name": "Turn Off Coffee Machine",
// ... rest of rule
}
Property: Delay
Furthermore, a rule can include an optional delay
property. It is used to configure a latency period,
specified in seconds, that must elapse before the rule's actions are executed.
{
"name": "Turn On Lamp When Book Is Open",
"delay": 3,
"precondition": [
// ... preconditions
],
"action": [
// ... actions
]
}
Property: Precondition
An array of condition objects that represent the "IF" part of a rule. Preconditions specify when a rule becomes eligible for execution. All listed preconditions must be met (logical AND). Different types of preconditions are as follows: This framework supports a variety of condition types to create rich, context-aware triggers. Different types of preconditions are as follows:
- Device State Conditions
- Time conditions
- Contextual Conditions (User's Context and Task)
All preconditions must satisfy to trigger the rule's actions.
Device State Conditions
An interesting feature of the simulation’s rule engine is its ability to monitor and respond to real-time device states. Rules may include preconditions that inspect the internal properties of devices in the environment. This allows a rule to be triggered based on the status of any monitored device.
Each Device-based precondition is structured as follows:
type
: Must be set to "Device".device
: A unique identifier (ID) corresponding to the target device within the environment (e.g., "coffee_machine").condition
: A logical expression applied to a named device property. Thecondition
object contains three elements:name
: The property to be monitored (e.g., "Number of Coffees Made").operator
: The logical operator used for evaluation (e.g.,>=
,==
,<
).value
: The threshold or value to compare against.
{
"type": "Device",
"device": "coffee_machine",
"condition": {
"name": "Number of Coffees Made",
"operator": ">=",
"value": 3
}
}
This precondition evaluates to true when the device with ID coffee_machine has produced three or more coffees.
Time conditions
Time Conditions trigger a rule based on the absolute time of day within the environment (i.e., the "game clock"), modeling behaviors that depend on the time of day rather than the duration of interaction. This reflects how many real-world smart environments operate, for example, lights turning on after 18:00, or appliances powering down at 22:00.
Each precondition of this type consists of:
type
: "Time" that identifies the condition categorycondition
: Thecondition
object contains two elements:operator
: Comparison symbol (==
,>=
,<=
, etc.)value
: Time string in 24-hour "HH:MM" format
The following condition evaluates to True if the current time is 10:30 PM (22:30) or later.
{
"type": "Time",
"condition": {
"operator": ">=",
"value": "22:30",
}
}
Context conditions
In addition to time- and device-based triggers, the rule engine supports contextual preconditions, rules that activate based on properties of the user’s current state, such as their assigned experimental group or the task they are performing. his allows for personalization and dynamic behavior based on who the user is and what they are currently doing. This is a powerful way to create rules that adapt to individual circumstances.
Contextual conditions are specified with:
type
: "Context", indicating that the rule depends on user-related contextcondition
: Thecondition
object contains:variable
: the name of the contextual attribute to evaluateoperator
: logical comparator (==
,>=
,<=
, etc.)value
: target value to compare
Contextual variables fall into two broad categories:
System Context Variables
These refer to shared dynamic state tracked by the system itself and updated during runtime. They are global across all users change as the simulation progresses,
allowing rules to be triggered by events. A key example is the task
variable.
{
"type": "Context",
"condition": {
"variable": "task",
"operator": "==",
"value": "task_3"
}
}
For instance, here when the simulation advances to the third task, a condition checking for this becomes true for every participant. This is useful for simulating the conditions and events relevant to a specific stage of the simulation.
User-Specific Context Variables
These are externally defined attributes passed into the platform at the start of the session through the session URL. They allow fine-grained personalization of rule behavior on a per-user basis.The simulation is initialized with a base64-encoded JSON object in the session URL. This object can include arbitrary key-value pairs representing user-specific metadata such as group assignment, preferences, conditions, or cognitive load level.
{
"type": "Context",
"condition": {
"variable": "group",
"operator": "==",
"value": "1"
}
}
For example, In this case, the rule will only activate for users whose session context includes "group": "1", enabling between-subject design strategies, such as assigning different rules, device behaviors, or explanation styles to control and experimental groups.
Combined Use Case:
The flexibility of contextual preconditions allows researchers to combine both system-wide and personalized conditions in a single rule. For example:
{
"precondition": [
{
"type": "Context",
"condition": {
"variable": "task",
"operator": "==",
"value": "plant_watering"
}
},
{
"type": "Context",
"condition": {
"variable": "group",
"operator": "==",
"value": "control"
}
}
]
}
This rule triggers only when a participant from the control group reaches the plant_watering task, enabling precise targeting of rule-based interventions. By supporting both system and user-specific context variables, the platform enables:
- Between- and within-subject experimental designs
- Adaptive behavior modeling based on user group or profile
- Stage-aware feedback, only triggered during specific tasks
- Scenario tailoring across diverse participant populations
This contextual design makes the platform suitable for controlled usability studies, cognitive workload comparisons, or personalized explanation strategies in human-smart environment interaction research.
Property: Actions
Device interactions
A rule can change the state of a device by defining a Device Interaction action. To configure such an action, create an object with the following fields:
type
: must be set to "Device_Interaction"device
: the name ID of the target deviceinteraction
: an object defining:name
: the property to changevalue
: the new value to set
{
"type": "Device_Interaction",
"device": "coffee_machine",
"interaction": {
"name": "Power",
"value": false
}
}
This example turns off the coffee machine by setting its Power property to false.
Explanations
In our framework, explanations play a pivotal role in enabling transparency, trust, and usability. They are not passive byproducts, but explicitly modeled as actions within the rule system. See also Explanation.mdx for a full overview of explanation generation configurations.
Explanation generation is governed by the same rule-based mechanism as other smart home behaviors. This gives researchers fine-grained control over:
- When an explanation should be shown
- Under which preconditions it should be triggered
- What explanation (identified by ID) should be displayed
In simple terms:
Explanations are modeled as a special type of action within rules. That is: IF some preconditions are met, THEN generate a specific explanation.
This allows fully configurable, context-aware explanations, ideal for experimentation and user studies.
To create a such action, create an object with following properties :
type
: must be set to "Explanation"explanation
: a string ID referencing the explanation to show (must exist in explanation.json)
{
"type": "Explanation",
"explanation": "coffee_01"
}
This action triggers the explanation with ID_ coffee_01 (e.g., “The coffee machine was turned off to save energy”).
Example
{
"rules": [
{
"id": "coffee_machine_rule",
"name": "Turn Off Coffee Machine",
"precondition": [
{
"type": "Device",
"device": "coffee_machine",
"condition": {
"name": "Number of Coffees Made",
"operator": ">=",
"value": 3
}
},
{
"type": "Time",
"condition": {
"variable": "minute",
"operator": ">=",
"value": 10
}
}
],
"delay": 2,
"action": [
{
"type": "Device_Interaction",
"device": "coffee_machine",
"interaction": {
"name": "Power",
"value": false
}
}
]
}
]
}
Best Practices
- Design intentional contradictions if your goal is to create confusing situations
- Test rule interactions thoroughly
- Use meaningful IDs for rules to make debugging and maintenance easier
- Consider using delays for rules that should have realistic timing behavior