From 01745f12217131b756b838605a158dea57a8ee54 Mon Sep 17 00:00:00 2001
From: streuper <289489346+streuper@users.noreply.github.com>
Date: Thu, 16 Jul 2026 20:09:25 +0200
Subject: [PATCH] Blokkeer meterregel bij ongeldige start-HF
---
CHECKSUMS.sha256 | 2 +-
index.html | 138 ++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 119 insertions(+), 21 deletions(-)
diff --git a/CHECKSUMS.sha256 b/CHECKSUMS.sha256
index 7b55422..a32b7ef 100644
--- a/CHECKSUMS.sha256
+++ b/CHECKSUMS.sha256
@@ -1 +1 @@
-1ef56afddea6d292bbbccad4222f82335b1c1897418a3e13a55f9fad18d6c4ed *index.html
+725f5abfe071cd702139d9365be6e07e011ab1fcbd46832fbc73cfafe2e216b6 *index.html
diff --git a/index.html b/index.html
index 5c36383..d9eb85b 100644
--- a/index.html
+++ b/index.html
@@ -1900,13 +1900,33 @@
Duikmonitor
const resultUnits=[];
for(const arr of byDiver.values()){
arr.sort((a,b)=>a.start-b.start);
+ const pending = arr.slice();
let prev = null, chainBlocker = null;
- for(const u of arr){
+ while(pending.length){
+ const u = pending.shift();
if(chainBlocker?.surface && u.start && minsBetween(chainBlocker.surface, u.start) > 1080){
chainBlocker = null;
prev = null;
}
- const r = calcUnit(u, chainBlocker ? null : prev);
+ const calcPrev = chainBlocker ? null : prev;
+ if(u.appliedRule && u.events.length > 1){
+ const startOiMin = calcPrev?.surface && u.start ? Math.floor(minsBetween(calcPrev.surface, u.start)) : null;
+ const startHF = chainBlocker
+ ? {hf:null, label:"eerdere berekening geblokkeerd"}
+ : getHF(calcPrev?.hgAdjusted || calcPrev?.hgRaw, startOiMin);
+ if(startHF.hf !== 1){
+ const separateUnits = u.events.map(e => Object.assign(unitFromEvents([e], dataset), {
+ meterRuleStartRejected:true,
+ meterRuleStartHF:startHF.hf,
+ meterRuleStartLabel:startHF.label,
+ rejectedMeterRule:u.appliedRule
+ }));
+ pending.push(...separateUnits);
+ pending.sort((a,b)=>a.start-b.start);
+ continue;
+ }
+ }
+ const r = calcUnit(u, calcPrev, {prevBlockedByChain:!!chainBlocker});
Object.assign(u, r);
if(chainBlocker){
// De korte-OI-oorzaak draagt de code van de lege tabelcel die de keten
@@ -1996,7 +2016,7 @@ Duikmonitor
}
}
- function calcUnit(u, prev){
+ function calcUnit(u, prev, context={}){
const res = {messages:[], severity:0, codes:[], oiMin:null, hf:null, hfLabel:"-", edt:null, ndl:null, hgRaw:null, hgAdjusted:null, calcType:"", safetyStop:false, chainUnreliable:false};
if((u.events || []).some(e=>e.timerNeedsCheck)){
addMsg(res,1,"Actieve timer is langer dan 8 uur; controleer starttijd of zet de duik boven/einde.");
@@ -2017,6 +2037,16 @@ Duikmonitor
return res;
}
+ if(u.meterRuleStartRejected){
+ const rejectedRule = shallowRules[u.rejectedMeterRule];
+ const startHF = u.meterRuleStartHF == null
+ ? `niet bepaald (${u.meterRuleStartLabel || "onbekende uitgangssituatie"})`
+ : fmtHF(u.meterRuleStartHF);
+ addMsg(res,1,`${rejectedRule?.label || "Meterregel"} niet toegepast: inkomende HF bij de eerste duik van deze meterregelsessie is ${startHF} en moet 1,0 zijn; normale beoordeling gebruikt.`);
+ if(context.prevBlockedByChain) return res;
+ if(u.meterRuleStartHF == null && !prev) return res;
+ }
+
if(!u.appliedRule && u.shallowRuleKey && u.rule !== "auto"){
const selectedRule = shallowRules[u.shallowRuleKey];
if(selectedRule && u.mddMax > selectedRule.maxDepth){
@@ -2027,23 +2057,38 @@ Duikmonitor
if(u.appliedRule){
const rule = shallowRules[u.appliedRule];
- res.calcType = rule.label;
- if(u.rule !== "auto" && u.mddMax > rule.maxDepth){
- addMsg(res,2,`${rule.label} gekozen, maar MDD ${u.mddMax.toFixed(1)} m is dieper dan ${rule.maxDepth} m.`,"INVALID_INPUT");
- if(u.appliedRule === "s12") addMsg(res,1,over12PlannedGuidance);
- }
- if(u.dtTotal > rule.totalLimit){
- addMsg(res,2,`Totale duiktijd binnen meterregel ${u.dtTotal} min overschrijdt ${rule.label} (${rule.totalLimit} min).`,"BOTTOM_TIME_EXCEEDS_METER_RULE");
+ const startHF = getHF(prev?.hgAdjusted || prev?.hgRaw, res.oiMin);
+ if(startHF.hf !== 1){
+ const startHFText = startHF.hf == null ? `niet bepaald (${startHF.label})` : fmtHF(startHF.hf);
+ res.appliedRule = null;
+ res.meterRuleApplied = false;
+ res.meterRuleStartRejected = true;
+ res.meterRuleStartHF = startHF.hf;
+ res.meterRuleStartLabel = startHF.label;
+ res.rejectedMeterRule = u.appliedRule;
+ addMsg(res,1,`${rule.label} niet toegepast: inkomende HF bij de eerste duik van deze meterregelsessie is ${startHFText} en moet 1,0 zijn; normale beoordeling gebruikt.`);
+ if(startHF.hf == null && res.oiMin == null){
+ addMsg(res,2,"Inkomende HF voor de meterregelsessie kan niet betrouwbaar worden bepaald; berekening geblokkeerd.","INVALID_INPUT");
+ return res;
+ }
+ }else{
+ res.calcType = rule.label;
+ if(u.rule !== "auto" && u.mddMax > rule.maxDepth){
+ addMsg(res,2,`${rule.label} gekozen, maar MDD ${u.mddMax.toFixed(1)} m is dieper dan ${rule.maxDepth} m.`,"INVALID_INPUT");
+ if(u.appliedRule === "s12") addMsg(res,1,over12PlannedGuidance);
+ }
+ if(u.dtTotal > rule.totalLimit){
+ addMsg(res,2,`Totale duiktijd binnen meterregel ${u.dtTotal} min overschrijdt ${rule.label} (${rule.totalLimit} min).`,"BOTTOM_TIME_EXCEEDS_METER_RULE");
+ }
+ res.hf = 1;
+ res.hfLabel = "start HF 1,0";
+ res.edt = u.dtTotal;
+ res.ndl = rule.totalLimit;
+ res.hgRaw = getHG(rule.maxDepth, u.dtTotal);
+ if(!res.hgRaw) addMsg(res,2,"HG kan niet uit Airtabel 1 worden bepaald voor deze duiktijd.","BOTTOM_TIME_EXCEEDS_TABLE");
+ res.hgAdjusted = res.hgRaw;
+ return res;
}
- if(prev && res.oiMin != null && res.oiMin <= 1080) addMsg(res,1,`${rule.label} vereist start met HF 1,0; vorige HG is nog niet volledig vervallen.`);
- res.hf = 1;
- res.hfLabel = "start HF 1,0";
- res.edt = u.dtTotal;
- res.ndl = rule.totalLimit;
- res.hgRaw = getHG(rule.maxDepth, u.dtTotal);
- if(!res.hgRaw) addMsg(res,2,"HG kan niet uit Airtabel 1 worden bepaald voor deze duiktijd.","BOTTOM_TIME_EXCEEDS_TABLE");
- res.hgAdjusted = res.hgRaw;
- return res;
}
if(u.mddMax > 12){
if(u.rule === "auto") addMsg(res,2,"Dieper dan 12 meter: 6/9/12-meterregel niet toepasbaar. Gebruik DCIEM standaard en beoordeel de duiken afzonderlijk.","INVALID_INPUT");
@@ -2205,7 +2250,10 @@ Duikmonitor
arr.sort((a,b)=>(a.surface||a.start)-(b.surface||b.start));
let prev = null, period = [];
const flush = () => {
- const meter = period.filter(e => daypartRule(e.rule, e.mdd) && Number.isFinite(e.dtMin));
+ const meter = period.filter(e => {
+ const unit = unitByEvent.get(e.id);
+ return !unit?.meterRuleStartRejected && daypartRule(e.rule, e.mdd) && Number.isFinite(e.dtMin);
+ });
if(!meter.length){ period = []; return; }
const sumDt = meter.reduce((s,e)=>s+e.dtMin, 0);
const maxD = Math.max(...meter.map(e=>Number.isFinite(e.mdd)?e.mdd:0));
@@ -4683,6 +4731,56 @@ ${esc(displayDiver(d))} ${s.txt}