Expect cycle days, not numbers, in getTemperatureStatus
This commit is contained in:
+74
-86
@@ -1,118 +1,106 @@
|
||||
export default function getTemperatureStatus(temperaturesOfCycle) {
|
||||
// sensiplan rounds temps to the nearest 0.05
|
||||
const tempValues = temperaturesOfCycle.map(val => rounded(val, 0.05))
|
||||
export default function getTemperatureStatus(cycleDays) {
|
||||
const temperatureDays = cycleDays
|
||||
.filter(day => day.temperature && !day.temperature.exclude)
|
||||
.map(day => {
|
||||
return {
|
||||
originalCycleDay: day,
|
||||
temp: rounded(day.temperature.value, 0.05)
|
||||
}
|
||||
})
|
||||
|
||||
function getLtl(i) {
|
||||
const sixTempsBefore = getSixTempsBefore(i)
|
||||
return Math.max(...sixTempsBefore)
|
||||
}
|
||||
function getSixTempsBefore(i) {
|
||||
return tempValues.slice(0, i).slice(-6)
|
||||
const daysBefore = temperatureDays.slice(0, i).slice(-6)
|
||||
const temps = daysBefore.map(day => day.temp)
|
||||
return Math.max(...temps)
|
||||
}
|
||||
|
||||
return tempValues.reduce((acc, temp, i) => {
|
||||
for (let i = 0; i < temperatureDays.length; i++) {
|
||||
// need at least 6 low temps before we can detect a first high measurement
|
||||
if (i < 6) return acc
|
||||
|
||||
// if we've already detected a shift, we put it with the other high level temps
|
||||
if(acc.detected) {
|
||||
acc.high.push(temp)
|
||||
return acc
|
||||
}
|
||||
if (i < 6) continue
|
||||
|
||||
// is the temp a candidate for a first high measurement?
|
||||
const ltl = getLtl(i)
|
||||
if (temp <= ltl) return acc
|
||||
const temp = temperatureDays[i].temp
|
||||
if (temp <= ltl) continue
|
||||
|
||||
const checkResult = checkIfFirstHighMeasurement(temp, i, tempValues, ltl)
|
||||
// if we don't have a winner, keep move on to the next candidates
|
||||
if (!checkResult.isFirstHighMeasurement) return acc
|
||||
const checkResult = checkIfFirstHighMeasurement(temp, i, temperatureDays, ltl)
|
||||
|
||||
// if we do, remember the details and start collecting the high level temps
|
||||
acc.detected = true
|
||||
acc.high = [temp]
|
||||
acc.rule = checkResult.rule
|
||||
acc.ltl = ltl
|
||||
acc.low = getSixTempsBefore(i)
|
||||
if (checkResult.detected) {
|
||||
checkResult.firstHighMeasurementDay = temperatureDays[i].originalCycleDay
|
||||
return checkResult
|
||||
}
|
||||
}
|
||||
|
||||
return acc
|
||||
}, {
|
||||
detected: false
|
||||
})
|
||||
return { detected: false }
|
||||
}
|
||||
|
||||
function rounded(val, step) {
|
||||
// we round the difference because of JS decimal weirdness
|
||||
const inverted = 1 / step
|
||||
return Math.round(val * inverted) / inverted
|
||||
}
|
||||
|
||||
function checkIfFirstHighMeasurement(temp, i, temps, ltl) {
|
||||
function checkIfFirstHighMeasurement(temp, i, temperatureDays, ltl) {
|
||||
// need at least 3 high temps to form a high temperature level
|
||||
if (i > temps.length - 3) {
|
||||
return { isFirstHighMeasurement: false }
|
||||
if (i > temperatureDays.length - 3) {
|
||||
return { detected: false }
|
||||
}
|
||||
const nextTemps = temps.slice(i + 1, i + 4)
|
||||
const nextDays = temperatureDays.slice(i + 1, i + 4)
|
||||
|
||||
if (regularRuleApplies(temp, nextTemps, ltl)) {
|
||||
return {
|
||||
isFirstHighMeasurement: true,
|
||||
rule: 0,
|
||||
ltl
|
||||
}
|
||||
}
|
||||
|
||||
if (firstExceptionRuleApplies(temp, nextTemps, ltl)) {
|
||||
return {
|
||||
isFirstHighMeasurement: true,
|
||||
rule: 1,
|
||||
ltl
|
||||
}
|
||||
}
|
||||
|
||||
if (secondExceptionRuleApplies(temp, nextTemps, ltl)) {
|
||||
return {
|
||||
isFirstHighMeasurement: true,
|
||||
rule: 2,
|
||||
ltl
|
||||
}
|
||||
}
|
||||
return (
|
||||
getResultForRegularRule(nextDays, ltl)) ||
|
||||
getResultForFirstExceptionRule(nextDays, ltl) ||
|
||||
getResultForSecondExceptionRule(nextDays, ltl) ||
|
||||
{ detected: false }
|
||||
}
|
||||
|
||||
function getResultForRegularRule(nextDays, ltl) {
|
||||
if (!nextDays.every(day => day.temp > ltl)) return false
|
||||
const thirdDay = nextDays[1]
|
||||
if (rounded(thirdDay.temp - ltl, 0.1) < 0.2) return false
|
||||
return {
|
||||
isFirstHighMeasurement: false
|
||||
detected: true,
|
||||
rule: 0,
|
||||
ltl,
|
||||
evaluationCompleteDay: thirdDay.originalCycleDay
|
||||
}
|
||||
}
|
||||
|
||||
function regularRuleApplies(temp, nextTemps, ltl) {
|
||||
if (!nextTemps.every(temp => temp > ltl)) return false
|
||||
const thirdTemp = nextTemps[1]
|
||||
if (rounded(thirdTemp - ltl, 0.1) < 0.2) return false
|
||||
return true
|
||||
function getResultForFirstExceptionRule(nextDays, ltl) {
|
||||
if (nextDays.length < 3) return false
|
||||
if (!nextDays.every(day => day.temp > ltl)) return false
|
||||
const fourthDay = nextDays[2]
|
||||
if (fourthDay.temp <= ltl) return false
|
||||
return {
|
||||
detected: true,
|
||||
rule: 1,
|
||||
ltl,
|
||||
evaluationCompleteDay: fourthDay.originalCycleDay
|
||||
}
|
||||
}
|
||||
|
||||
function firstExceptionRuleApplies(temp, nextTemps, ltl) {
|
||||
if (nextTemps.length < 3) return false
|
||||
if (!nextTemps.every(temp => temp > ltl)) return false
|
||||
const fourthTemp = nextTemps[2]
|
||||
if (fourthTemp > ltl) return true
|
||||
return false
|
||||
}
|
||||
|
||||
function secondExceptionRuleApplies(temp, nextTemps, ltl) {
|
||||
if (nextTemps.length < 3) return false
|
||||
if (secondOrThirdTempIsAtOrBelowLtl(nextTemps, ltl)) {
|
||||
const fourthTemp = nextTemps[2]
|
||||
if (rounded(fourthTemp - ltl, 0.1) >= 0.2) return true
|
||||
function getResultForSecondExceptionRule(nextDays, ltl) {
|
||||
if (nextDays.length < 3) return false
|
||||
if (secondOrThirdTempIsAtOrBelowLtl(nextDays, ltl)) {
|
||||
const fourthDay = nextDays[2]
|
||||
if (rounded(fourthDay.temp - ltl, 0.1) >= 0.2) {
|
||||
return {
|
||||
detected: true,
|
||||
rule: 2,
|
||||
ltl,
|
||||
evaluationCompleteDay: fourthDay.originalCycleDay
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function secondOrThirdTempIsAtOrBelowLtl(nextTemps, ltl) {
|
||||
const secondIsLow = nextTemps[0] <= ltl
|
||||
const thirdIsLow = nextTemps[1] <= ltl
|
||||
function secondOrThirdTempIsAtOrBelowLtl(nextDays, ltl) {
|
||||
const secondIsLow = nextDays[0].temp <= ltl
|
||||
const thirdIsLow = nextDays[1].temp <= ltl
|
||||
if ((secondIsLow || thirdIsLow) && !(secondIsLow && thirdIsLow)) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function rounded(val, step) {
|
||||
const inverted = 1 / step
|
||||
// we round the difference because of JS decimal weirdness
|
||||
return Math.round(val * inverted) / inverted
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user