rbed

Time spent in Events

totalDuration(a) is the summed duration in milliseconds of all Events of Rule a: the Ended ones in full, plus a running one up to now. It grows continuously while an Event of a runs, so a limit is detected the moment it is crossed:

Rule excursion = Rule.named("Excursion").when(temp.above(8));
Rule cumulativeLimit = Rule.named("CumulativeLimit")
    .when(totalDuration(excursion).above(Duration.ofMinutes(45).toMillis()));

A cumulative limit

A cold chain logs its temperature once a minute. It is above 8 °C from minute 20 to 40, from 80 to 95 and from 150 to 175: 20, 15 and 25 minutes, an hour in all. A single excursion is tolerable, but not more than the limit in total.

The live chart and its controls need JavaScript. The tables show the Events at the default parameters.

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

import static io.github.romanhaendler.rbed.Conditions.*;

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

Channel temp = Channel.named("temp");

Rule excursion = Rule.named("Excursion").when(temp.above(8));
Rule cumulativeLimit = Rule.named("CumulativeLimit")
    .when(totalDuration(excursion).above(Duration.ofMinutes(45).toMillis()));
Detector detector = Detector.builder()
    .rules(excursion, cumulativeLimit)
    .build();

for (int m = 0; m <= 240; m++) {   // one Sample a minute
  boolean warm = m >= 20 && m < 40 || m >= 80 && m < 95 || m >= 150 && m < 175;
  detector.push(m * 60_000L, Map.of(temp, warm ? 10.0 : 5.0));
}
detector.close();

totalDuration(excursion) rises while an Excursion runs and stays level between them: 20 minutes after the first, 35 after the second. At the default limit of 45 minutes, the sum reaches 45 at minute 160, in the middle of the third excursion, and exceeds it at minute 161, where CumulativeLimit starts. It never Ends, since the sum never decreases: it runs to the end of the data, and close() gives it a Truncated end.

Things to try

  • Raise the limit to 60 minutes: the sum reaches it at minute 175 but never exceeds it, so there is no CumulativeLimit.
  • Lower it to 30 minutes: the sum exceeds it during the second excursion, and CumulativeLimit starts at minute 91.

Reference

Methods used: Channel.named, Rule.named, Rule.when, Expression.above, Conditions.totalDuration, Detector.builder, Detector.Builder.rules, Detector.Builder.build, Detector.push, Detector.close.