# Automotive

A vehicle reports its speed (m/s) and engine rpm at 1 Hz. Here the engine runs while the vehicle stands, then the vehicle accelerates at 2 m/s² to 20 m/s, drives, brakes at 5 m/s² to a stop and stands again with the engine running.

Parameters (in the page address as ?moving=…):

- Moving above (`moving`): 0.5 to 10 m/s in steps of 0.5, default 1
- Trip over after standing (`stopMinutes`): 1 to 10 min in steps of 1, default 3
- Harsh braking above (`braking`): 1 to 8 m/s² in steps of 0.5, default 4
- Idling above (`idlingRpm`): 300 to 1000 rpm in steps of 50, default 600
- Idling for (`idlingMinutes`): 1 to 10 min in steps of 1, default 2

The site cannot run the default parameters: (JavaScript) TypeError: Cannot read properties of undefined (reading 'length')

Java source at the default parameters:

```java
import io.github.romanhaendler.rbed.*;
import java.time.Duration;
import java.util.Map;

Channel rpm = Channel.named("rpm");
Channel speed = Channel.named("speed");

Rule trip = Rule.named("Trip")
    .when(speed.above(1)).forDuration(Duration.ofSeconds(10))
    .endWhen(speed.below(0.5)).forDuration(Duration.ofMinutes(3));
Rule harshBraking = Rule.named("HarshBraking").when(speed.rate().below(-4));
Rule idling = Rule.named("Idling")
    .when(speed.below(0.5).and(rpm.above(600)))
    .forDuration(Duration.ofMinutes(2));
Detector detector = Detector.builder()
    .rules(trip, harshBraking, idling)
    .listener(new EventListener() {
      @Override public void onEnded(Event e) {
        if (e.is(trip)) System.out.println("a trip of " + km(e, speed) + " km");
      }
    })
    .build();

for (int s = 0; s < 1_500; s++) {   // at 1 Hz
  detector.push(s * 1_000L, Map.of(speed, speedAt(s), rpm, s < 60 ? 0.0 : 800.0));
}
detector.close();

// In the enclosing class:
// Distance of a Trip in km: the integral of speed (m/s) over time
static double km(Event trip, Channel speed) {
  return trip.aggregates(speed).integral() / 1000;
}

static double speedAt(int s) {   // m/s
  if (s < 300) return 0;
  if (s < 310) return 2 * (s - 300);       // accelerating at 2 m/s²
  if (s < 900) return 20;
  if (s < 904) return 20 - 5 * (s - 900);  // braking at 5 m/s²
  return 0;
}
```

## The Rules

- **Trip**: moving faster than 1 m/s for 10 s, over after standing still (below 0.5 m/s) for 3 minutes. Its distance, the integral of speed over time, is computed by a plain method that the listener calls for each Ended Trip, and shown as a note in the table.
- **HarshBraking**: decelerating faster than 4 m/s², a `rate` below -4.
- **Idling**: standing (below 0.5 m/s) with the engine above 600 rpm for 2 minutes.

At the defaults, the engine starts at 60 s, and the standing vehicle is `Idling` from 60 s, Confirmed at 180 s, until it moves off at 301 s. The `Trip` runs from 301 s, Confirmed at 311 s, to 904 s, where the vehicle stands still: each speed from 301 to 903 s holds for 1 s, 11.94 km in all. Braking at 5 m/s² is `HarshBraking` from 901 s to 905 s. From 904 s the vehicle is `Idling` again, Confirmed at 1024 s; it still runs when the data ends at 1499 s, so its end is Truncated.

### Things to try

- Raise *Trip over after standing* to 10 minutes: the vehicle stands for less than that before the data ends, so the `Trip` runs to the end with a Truncated end.

## Reference

The example is [FleetTelematicsExample](https://github.com/romanhaendler/rbed/blob/main/src/test/java/io/github/romanhaendler/rbed/examples/FleetTelematicsExample.java), a test with its expected Events, listed in the README's [Examples](https://github.com/romanhaendler/rbed#examples).

Methods used: [`Channel.named`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Channel.html#named%28java.lang.String%29), [`Rule.named`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Rule.html#named%28java.lang.String%29), [`Rule.when`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Rule.html#when%28io.github.romanhaendler.rbed.Condition%29), [`Expression.above`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Expression.html#above%28double%29), [`Rule.forDuration`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Rule.html#forDuration%28java.time.Duration%29), [`Rule.endWhen`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Rule.html#endWhen%28io.github.romanhaendler.rbed.Condition%29), [`Expression.below`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Expression.html#below%28double%29), [`ChannelExpression.rate`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/ChannelExpression.html#rate%28%29), [`Condition.and`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Condition.html#and%28io.github.romanhaendler.rbed.Condition%29), [`Detector.builder`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.html#builder%28%29), [`Detector.Builder.rules`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.Builder.html#rules%28io.github.romanhaendler.rbed.Rule...%29), [`Detector.Builder.listener`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.Builder.html#listener%28io.github.romanhaendler.rbed.EventListener%29), [`EventListener.onEnded`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/EventListener.html#onEnded%28io.github.romanhaendler.rbed.Event%29), [`Event.is`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Event.html#is%28io.github.romanhaendler.rbed.Rule%29), [`Detector.Builder.build`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.Builder.html#build%28%29), [`Detector.push`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.html#push%28long,java.util.Map%29), [`Detector.close`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.html#close%28%29), [`Event.aggregates`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Event.html#aggregates%28io.github.romanhaendler.rbed.Channel%29), [`Aggregates.integral`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Aggregates.html#integral%28%29).

The concepts at work, each on a page of its own: [Conditions and Expressions](https://romanhaendler.github.io/rbed/conditions-and-expressions/), [Aggregates](https://romanhaendler.github.io/rbed/aggregates/), [End Conditions and hysteresis](https://romanhaendler.github.io/rbed/end-conditions/).
