# The instructor

Day 2, hours 4 and 5 of the [training path](TRAINING.md). The trainee drives. The instructor runs the session from
a browser page, the **instructor console**: watching, pausing, sending hazards, changing the environment, and taking
over a vehicle. Everything the instructor does is recorded with the run, so the review shows it and a playback
repeats it.

You need [Events, metrics and scorecards](TRAINING-EVENTS-SCORECARDS.md): the Training plugin added, and at least
one injectable kind declared. Crossing Drive's is `send-pedestrian`.

## 1. Open the console

Run the scenario with its session server, from a terminal in the project folder:

```sh
argus run . --window --serve --port 7795 --ws-port 7796
```

The trainee drives in the window. The run prints the session's address
(`serving the raw query API on http://127.0.0.1:7795`). Open the console in a web browser on the same PC at that
address plus `/plugins/training/`:

```text
http://127.0.0.1:7795/plugins/training/
```

The console is reachable from this PC only. It needs a run that draws: `--window` (or, with no window,
`--render-on-request`). A `--headless` run has no picture for its view. Several consoles can be open at once, a
lead instructor and a role-player for example. Each one's commands are recorded with its name.

**Coming later:** an **Open instructor console** button in the editor, and a one-time sign-in code for the address.

## 2. What the console shows

| Where | What |
|---|---|
| Top bar | the scenario, **LIVE**, the session clock and tick, **Pause**, step, the speed (×0.25 to ×4), **Report** |
| Left | the trainee: their live score against the pass mark, and the live scorecard, item by item |
| Centre | the trainee's view; under it, **Telemetry**: the scorecard's graphs (speed against the limit) and numbers (reaction, time over the limit) |
| Centre right | the **Map**, drawn from the scene's roads, with the trainee, others and people; under it the **Event log** |
| Right | three tabs: **Inject**, **Take over**, **Environment**; under them, **Your actions** |
| Bottom | the **Session timeline**: every event as a marker, in lanes (injected, instructor, scenario, session) |

The scorecard's `display` block decides what the gauge, graphs and map show
([Events, metrics and scorecards](TRAINING-EVENTS-SCORECARDS.md), section 5). While the run is live the score is
provisional: an item with no data yet is pending, and the report says "so far" until the end.

## 3. Pause, step and slow down

| Do | How | What happens |
|---|---|---|
| Pause, resume | **Pause**, or Space | the whole simulation holds, the trainee's too |
| Step | the step button, or `.` while paused | one tick (1/60 s) at a time |
| Slow down, speed up | ×0.25, ×0.5, ×1, ×2, ×4 | the clock's rate. The simulation is the same, only faster or slower to watch |

Pause, step and the speed change how fast the simulation runs against the clock on the wall. They never change what
happens in it. They are still recorded, so the review shows when the instructor paused.

## 4. Inject an event

The **Inject** tab lists what this scenario lets you send: the kinds its `journal.json` marks `injectable`, with
their settings. Crossing Drive has one, **Send the pedestrian**.

- **Inject now** sends it at the next tick. **In 10 s** sends it ten seconds from now.
- An injected event reaches the scenario's behaviours like any event: Crossing Drive's pedestrian listens for
  `send-pedestrian` and steps out. **What an injected event does is the scenario's own code.** A kind nothing listens
  for appears in the log and does nothing else.
- To make your own: declare a kind with `"injectable": true` (and its `fields`, which the palette turns into
  settings), and have a behaviour react to it in `onEvent`.

```json
{ "kind": "send-pedestrian", "label": "Send the pedestrian", "severity": "critical", "injectable": true, "target": "world", "fields": {} }
```

A kind with `"target": "entity"` asks which entity it is for (a tyre blowout on one car, say). The behaviour reads
the choice as `target` in the event's data.

**The scenario can still send it itself.** In Crossing Drive the hazard zone sends the pedestrian if the instructor
has not. Set the car's `autoHazard` prop to `false` to leave it to the instructor.

## 5. Change the environment

The **Environment** tab sets the time of day, the visibility (fog), the rain and how wet the road is. Each change is
a command at a tick, so the review shows the dusk coming in exactly when it did. The event log spells out each change
("visibility 300 m", "fog cleared", "rain 40 %").

- **Time of day** is in hours (0 to 24) and moves the sun: drag its slider, or pick **Dawn**, **Morning**, **Noon**,
  **Afternoon**, **Dusk** or **Night**.
- **Visibility** is **Clear** (no fog), a preset (**Light haze**, **Aerial**, **Morning mist**, **Valley mist**,
  **Dense**), or a distance on its slider, 30 to 1000 m, for a scene whose presets read too light or too heavy at
  its scale.
- **Sea state** (Beaufort 0 to 12) works in a scene with a sea. A scene with none refuses it, and the console then
  hides the slider.

**Rain** and **Road wetness** go from 0 to 1, and they change how the tyres grip:
- The rain wets the road gradually: most of the way in two or three minutes. Once the rain eases, the road dries
  about ten times as slowly.
- **Road wetness** makes the road that wet at once.
- A wet road grips less. On a soaked road, Crossing Drive's car brakes at about three quarters of its dry rate, and
  it picks up speed more slowly. From about 80 km/h, a car on a soaked road starts to aquaplane.
- For now the weather is felt, not seen: nothing draws the rain or the wet road.

A scene sets how fast its road wets and dries: `wetTime` and `dryTime` in its `environment.weather`, 60 s and 600 s
unless it says otherwise ([Vehicles](VEHICLES.md), "Surfaces and weather").

## 6. Take over

On the **Take over** tab, pick a vehicle or character, or click it on the map, and drive it yourself.

- The console turns your keys into the scene's own input actions: W, S, A and D drive Crossing Drive's car, as they
  do for the trainee. The view says **You have control of** and the entity's name (**Sam Taylor** in Crossing Drive).
  **Hand back** (or Esc) returns it.
- Every console's trainee card says **An instructor has taken over from** and the trainee's name while it is held.
- While you hold it, the trainee's input to it is ignored, and the trainee's screen says **Instructor has control**
  (with the Training plugin's panel, section 7). On hand-back the
  entity's input starts again from neutral, so a key the trainee is still holding counts only once released and
  pressed again.
- One instructor at a time: a vehicle another console holds cannot be taken until it is handed back.
- An entity driven by another simulator (through DIS) cannot be taken over.

## 7. A message to the trainee

**Message to trainee** shows a line of text on the trainee's screen for a few seconds. It needs the Training plugin's
panel, a behaviour the plugin carries, on the trainee's entity:

```json
{ "type": "script", "module": "training:trainee-panel", "props": { "position": "top" } }
```

The same panel shows **Instructor has control** while an instructor holds the trainee's vehicle.

## 8. What gets recorded

Every action above is a **session command**: applied at a tick, kept in the session's journal with the console that
sent it, and written into the recording when the session is recorded (`--save-replay <file>` on `argus run`, or the
console's recording). In the event log, your own actions are marked **You**. Playing the recording back applies the
same commands at the same ticks, so the review is the run as it happened, instructor included.

**Without the console:** the same commands go to `POST /session/command` on the session's port, from a client
registered with `POST /session/clients`. The console registers a client so that every command it sends is recorded
with who sent it: name yours with the `x-argus-client` header. A tool may send commands with no header; they are
recorded without a name. The session API reference is `crates/query/API.md` (on the docs site,
**Query API**), sections "Session control" and "The session journal". A script or a test can therefore run a session
the way an instructor does:

```sh
P=http://127.0.0.1:7795; J='content-type: application/json'
curl -X POST $P/session/clients -H "$J" -d '{"role":"instructor","name":"Lead"}'
# {"client":"cl_1","name":"Lead","role":"instructor"}
C='x-argus-client: cl_1'
curl -X POST $P/session/command -H "$J" -H "$C" -d '{"cmd":"inject","kind":"send-pedestrian"}'
# {"applied_tick":82,"queued":true,"seq":null}
```

| Console | Body of `POST /session/command` |
|---|---|
| Pause, resume | `{"cmd":"pause"}`, `{"cmd":"resume"}` |
| Step | `{"cmd":"step","n":5}` (1 to 3600 ticks) |
| Speed | `{"cmd":"scale","x":0.5}` (0.1 to 10) |
| Inject now | `{"cmd":"inject","kind":"send-pedestrian"}` (with `"params"` for the kind's fields) |
| In 10 s | the same with `"at_tick"`: the session's tick (from `GET /session/control`) plus 600 |
| Take over | `{"cmd":"possess","entity":"car","client":"cl_1"}`, then drive it with `POST /input` and the same header: `{"actions":[{"type":"axis","name":"throttle","value":[1,0],"frames":60}]}` |
| Hand back | `{"cmd":"release","entity":"car"}` |
| Environment | `{"cmd":"environment","timeOfDay":19.5,"fog":"morning-mist"}` (`fog` also `{"visibilityM":300}` or `null`; `seaState` 0 to 12 with a scene's sea; `rain` and `wetness` 0 to 1) |

`GET /session/control` answers the clock, whether it is paused, the queue of commands not yet applied, the
clients and who holds what.

## Where the console runs

The console is a page on the PC that runs the scenario, reachable from that PC only. Instructing from a second
machine on the network comes later. A release export does not serve the console yet, so a session with a console
runs in the editor, from `argus run`, or from a development export ([Training scenarios](TRAINING.md), "The
training room").

Next: [Reviewing a run](TRAINING-REVIEW.md).

