# Environment

A river gauge reports the water level every 15 minutes; the report at 20 h is missing. Here the level rises 20 cm/h to a crest after 12 h and then falls 10 cm/h. The rate is taken of the average of the last 4 reports, so a noisy gauge would not make the warning flicker.

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

- Warning above (`warning`): 220 to 420 cm in steps of 10, default 300
- Rising faster than (`rising`): 0 to 30 cm/h in steps of 1, default 10
- Lifted below (`lift`): 200 to 300 cm in steps of 10, default 250
- Lifted after (`liftHours`): 0 to 6 h in steps of 1, default 2
- Interrupted by a gap over (`gapMinutes`): 15 to 240 min in steps of 15, default 120

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 level = Channel.named("level");

Rule floodWarning = Rule.named("FloodWarning")
    .when(level.above(300)
        .and(level.averageOverSamples(4).rate().above(10 / 3600.0)))  // cm/h, as cm/s: rate() is per second
    .forDuration(Duration.ofMinutes(30))
    .endWhen(level.below(250)).forDuration(Duration.ofHours(2))
    .maxGap(Duration.ofMinutes(120));
Rule receding = Rule.named("Receding")
    .when(level.falling().and(level.above(300)));
Detector detector = Detector.builder()
    .rules(floodWarning, receding)
    .build();

for (int quarter = 0; quarter < 72 * 4; quarter++) {   // every 15 minutes for 72 h
  if (quarter == 20 * 4) continue;                       // the report at 20 h is missing
  double h = quarter / 4.0;
  double cm = h <= 12 ? 200 + 20 * h : Math.max(200, 440 - 10 * (h - 12));
  detector.push(quarter * 900_000L, Map.of(level, cm));
}
detector.close();
```

## The Rules

- **FloodWarning**: above 300 cm and still rising faster than 10 cm/h, for 30 minutes; lifted only once below 250 cm for 2 hours. Reports more than 2 hours apart interrupt it.
- **Receding**: falling while still above 300 cm.

At the defaults, `FloodWarning` starts at 5.25 h (305 cm), is Confirmed at 5.75 h and Ends at 31.25 h (247.5 cm), the missing report at 20 h being well within 2 hours. `Receding` runs from 12.25 h (437.5 cm) to 26 h, where the level is exactly 300 cm.

### Things to try

- Set *Interrupted by a gap over* to 15 min, below the 30 minutes between the reports around 20 h: the missing report interrupts the warning, which Ends Truncated at 19.75 h.

## Reference

The example is [FloodWarningExample](https://github.com/romanhaendler/rbed/blob/main/src/test/java/io/github/romanhaendler/rbed/examples/FloodWarningExample.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), [`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), [`ChannelExpression.averageOverSamples`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/ChannelExpression.html#averageOverSamples%28int%29), [`ChannelExpression.rate`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/ChannelExpression.html#rate%28%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), [`Rule.maxGap`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Rule.html#maxGap%28java.time.Duration%29), [`ChannelExpression.falling`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/ChannelExpression.html#falling%28%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.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).

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