Files
ApiCore/ApiCore-Backend/src/automation/rule-config/season-autopilot.config.ts
T
Nick SzaunigandClaude Opus 5.5 d99a697739 feat: T4 waves 1-2 - rule configs, schema, suggestions core, season, rule forms
- Rule configs with typed parsers and registry; Berlin day helpers
- Schema: T4 enums, Suggestion table, feed vocabulary (feedStatus as
  ColonyCondition with legacy text mapping), split queen source,
  varroa sample size; migration harness for data migrations
- SuggestionsService: propose/refresh/resolve/obsolete/expire,
  accept/dismiss/reopen incl. bulk, lock order, concurrency e2e
- SeasonService: phenology-based segments, inspection/varroa due dates,
  queen age; TimeEventsStep with JobPartialFailure
- Frontend: per-rule settings forms with visible value sources

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-14 13:42:32 +02:00

103 lines
2.3 KiB
TypeScript

import {
bool,
childScope,
has,
intIn,
makeParser,
monthDay,
report,
} from './parse-helpers';
import {
AUTOPILOT_RULE_IDS,
type SeasonAutopilotConfig,
} from './rule-config.types';
export const DEFAULT_SEASON_AUTOPILOT_CONFIG: SeasonAutopilotConfig = {
honeySuperMinFrames: 8,
varroaMeasureIntervalDays: 28,
winterVarroaWindow: { from: '11-15', to: '12-20' },
queenMaxAgeYears: 2,
suggestionTtlDays: 30,
maxStepsPerColony: 3,
rules: {
A1: true,
A2: true,
A3: true,
A4: true,
A5: true,
A6: true,
A7: true,
A8: true,
A9: true,
A10: true,
},
};
export const seasonAutopilotParser = makeParser<SeasonAutopilotConfig>(
'SEASON_AUTOPILOT',
DEFAULT_SEASON_AUTOPILOT_CONFIG,
(scope) => {
const d = DEFAULT_SEASON_AUTOPILOT_CONFIG;
const windowScope = childScope(scope, 'winterVarroaWindow');
let winterVarroaWindow = {
from: monthDay(windowScope, 'from', d.winterVarroaWindow.from),
to: monthDay(windowScope, 'to', d.winterVarroaWindow.to),
};
if (winterVarroaWindow.from > winterVarroaWindow.to) {
report(
windowScope,
has(windowScope, 'from') ? 'from' : 'to',
'Das Fenster muss innerhalb eines Jahres liegen: Beginn vor Ende.',
);
winterVarroaWindow = { ...d.winterVarroaWindow };
}
const ruleScope = childScope(scope, 'rules');
const rules = { ...d.rules };
for (const id of AUTOPILOT_RULE_IDS) {
rules[id] = bool(ruleScope, id, d.rules[id]);
}
return {
honeySuperMinFrames: intIn(
scope,
'honeySuperMinFrames',
d.honeySuperMinFrames,
1,
40,
),
varroaMeasureIntervalDays: intIn(
scope,
'varroaMeasureIntervalDays',
d.varroaMeasureIntervalDays,
7,
90,
),
winterVarroaWindow,
queenMaxAgeYears: intIn(
scope,
'queenMaxAgeYears',
d.queenMaxAgeYears,
1,
10,
),
suggestionTtlDays: intIn(
scope,
'suggestionTtlDays',
d.suggestionTtlDays,
1,
365,
),
maxStepsPerColony: intIn(
scope,
'maxStepsPerColony',
d.maxStepsPerColony,
1,
3,
),
rules,
};
},
);