# Manufacturing

A machine tool's spindle temperature and load are sampled at 1 Hz without timestamps, so the Detector is built with a sampling rate and derives each Sample's timestamp from its position (sampling-rate mode). Here the spindle heats up at 1 °C/s to 100 °C under load, stays there, and cools down again.

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

- Overheat above (`overheat`): 65 to 95 °C in steps of 1, default 80
- Overheat for (`overheatSeconds`): 0 to 120 s in steps of 5, default 30
- Cooled below (`cooled`): 61 to 90 °C in steps of 1, default 70
- High load above (`highLoad`): 50 to 85 % in steps of 5, default 80
- Fast heating above (`heating`): 0.25 to 2 °C/s in steps of 0.25, default 0.5

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

Java source at the default parameters:

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

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

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

Rule highLoad = Rule.named("HighLoad")
    .when(load.above(80)).forDuration(Duration.ofSeconds(10))
    .endWhen(load.below(60));
Rule overheat = Rule.named("Overheat")
    .when(temp.above(80)).forDuration(Duration.ofSeconds(30))
    .endWhen(temp.below(70)).forDuration(Duration.ofMinutes(1));
Rule overheatUnderLoad = Rule.named("OverheatUnderLoad")
    .when(during(overheat).and(during(highLoad)));
Rule fastHeating = Rule.named("FastHeating").when(temp.rate().above(0.5)).forSamples(5);
Detector detector = Detector.builder()
    .samplingRate(1)  // 1 Hz: values without timestamps
    .rules(highLoad, overheat, overheatUnderLoad, fastHeating)
    .build();

List<Map<Channel, Double>> series = new ArrayList<>();
for (int s = 0; s < 600; s++) series.add(Map.of(temp, spindleTemp(s), load, spindleLoad(s)));
List<Event> events = detector.detectValues(series);

// In the enclosing class:
static double spindleTemp(int s) {   // °C
  if (s < 100) return 60;
  if (s < 140) return 60 + (s - 100);   // heating at 1 °C/s
  if (s < 300) return 100;
  if (s < 335) return 100 - (s - 300);  // cooling at 1 °C/s
  return 65;
}

static double spindleLoad(int s) {   // %
  return s < 100 ? 50 : s < 400 ? 90 : 40;
}
```

## The Rules

- **Overheat**: above 80 °C for 30 s, over only once below 70 °C for a minute (hysteresis).
- **HighLoad**: load above 80 % for 10 s, over below 60 %.
- **OverheatUnderLoad**: both at once, `during` combined with `and`.
- **FastHeating**: heating faster than 0.5 °C/s for 5 consecutive Samples.

At the defaults, the load is 90 % from 100 s to 400 s, so `HighLoad` runs from 100 s to 400 s, Confirmed at 110 s. The temperature rises from 101 s, and `FastHeating` runs from there, Confirmed at the fifth Sample at 105 s, to 141 s, the first Sample without a rise. It passes 80 °C at 121 s: `Overheat` is Confirmed 30 s later, at 151 s, and `OverheatUnderLoad` starts with it. The temperature falls below 70 °C at 331 s, where `Overheat` Ends.

`OverheatUnderLoad` Ends only at 391 s: `during(overheat)` stays true until Overheat's End Condition has held for its minute (391 s), although its end timestamp is where the End Condition began (331 s). A streaming Detector cannot know earlier that the Event is over.

### Things to try

- Raise *Overheat for* to 60 s: `Overheat` is Confirmed at 181 s instead of 151 s, and `OverheatUnderLoad` with it.

## Reference

The example is [MachineToolOverheatExample](https://github.com/romanhaendler/rbed/blob/main/src/test/java/io/github/romanhaendler/rbed/examples/MachineToolOverheatExample.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), [`Conditions.during`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Conditions.html#during%28io.github.romanhaendler.rbed.Rule%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.rate`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/ChannelExpression.html#rate%28%29), [`Rule.forSamples`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Rule.html#forSamples%28int%29), [`Detector.builder`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.html#builder%28%29), [`Detector.Builder.samplingRate`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.Builder.html#samplingRate%28double%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.detectValues`](https://romanhaendler.github.io/rbed/api/io.github.romanhaendler.rbed/io/github/romanhaendler/rbed/Detector.html#detectValues%28java.lang.Iterable%29).

The concepts at work, each on a page of its own: [Batch processing and sampling rates](https://romanhaendler.github.io/rbed/sampling-rate/), [Conditions and Expressions](https://romanhaendler.github.io/rbed/conditions-and-expressions/), [During another Event](https://romanhaendler.github.io/rbed/during/), [End Conditions and hysteresis](https://romanhaendler.github.io/rbed/end-conditions/).
