From 435da7f17a68bf2beeeb949d1699d378bb49a320 Mon Sep 17 00:00:00 2001 From: Lars Date: Wed, 13 May 2026 07:38:44 +0200 Subject: [PATCH] feat(version): bump to 0.8.104 and enhance combination exercise features - Updated app version to 0.8.104, reflecting recent improvements in combination exercise handling. - Enhanced the CombinationMethodProfileEditor to support structured slot timing profiles without requiring JSON input from trainers. - Introduced quick ratio presets for circuit and interval training methods, improving user experience in setting up training profiles. - Updated documentation and changelog to reflect new features and integration details. Co-Authored-By: Claude Sonnet 4.6 --- ...e Kombinationsuebungen Spezifikation V2.md | 18 +- .../COMBINATION_TIMING_PROFILE_PLAN.md | 100 ++++++ backend/version.py | 12 +- .../CombinationMethodProfileEditor.jsx | 325 +++++++++++++++--- .../components/TrainingUnitSectionsEditor.jsx | 1 + frontend/src/pages/ExerciseFormPage.jsx | 24 +- .../src/utils/combinationMethodProfileUi.js | 145 ++++++++ 7 files changed, 560 insertions(+), 65 deletions(-) create mode 100644 .claude/docs/working/COMBINATION_TIMING_PROFILE_PLAN.md diff --git a/.claude/docs/functional/Shinkan Trainingsmodule Kombinationsuebungen Spezifikation V2.md b/.claude/docs/functional/Shinkan Trainingsmodule Kombinationsuebungen Spezifikation V2.md index 88eeceb..dd18836 100644 --- a/.claude/docs/functional/Shinkan Trainingsmodule Kombinationsuebungen Spezifikation V2.md +++ b/.claude/docs/functional/Shinkan Trainingsmodule Kombinationsuebungen Spezifikation V2.md @@ -1,7 +1,7 @@ # Trainingsmodule und Kombinationsübungen — fachliche Spezifikation V3 **Status:** fachlicher Spezifikationsentwurf -**Stand:** 2026-05-12 · **Coaching/Archetypen:** § 10.2.1, § 10.4–10.5, **§ 5.4/§ 6.3** Methoden/Archetypen/Zeitschicht · **Anhang A** (Abgleich Code vs. Spec) +**Stand:** 2026-05-12 (Anhang A **grob** App **0.8.104**; Zeit‑Pfad **`COMBINATION_TIMING_PROFILE_PLAN.md`**) · **Coaching/Archetypen:** § 10.2.1, § 10.4–10.5, **§ 5.4/§ 6.3** Methoden/Archetypen/Zeitschicht · **Anhang A** **Zweck:** Produkt- und Fachspezifikation für Trainingsmodule, Kombinationsübungen, Trainingsmethodenbezug, Planungsintegration und Coaching-Modus in Shinkan. **Wichtige Leitlinie dieser Version:** @@ -417,8 +417,12 @@ Alle diese Angaben sind **Anweisungen an den Trainer** und **Coach‑Assistenz** **Nach Einplanung in eine konkrete Trainingseinheit** muss diese Zeitschicht (oder ihr Abgleich mit der Einheitsposition) für den Trainer **bearbeitbar** bleiben, **ohne** die Bibliotheksvorlage still zu überschreiben (kopier-/instanzbasierte Anpassungen — siehe bereits § 2.5 und § 8.3). +**Umsetzung in der App (Stand 0.8.103):** Pro Übungszeile in einer Trainingseinheit kann optional ein **JSON-Snapshot** des Ablaufprofils gespeichert werden (`planning_method_profile` in der DB). **`null`** bedeutet: es wirkt das Ablaufprofil aus dem **Katalog** (`method_profile` der Übung). Ist ein Snapshot gesetzt, ersetzt er den Katalog **vollständig** für diese Platzierung (kein serverseitiges Zusammenführen). Bearbeitung in der Planungs-UI: aufklappbarer Block **„Ablaufprofil für diese Planung (Kombination)“** mit denselben geführten Feldern wie im Übungsformular. + **Coach:** soll die wirksamen Werte nach **Übernahme** und **Einheitsübersteuerungen** konsistent nachvollziehen (**§ 10.4**). +**Geplantes kanonisches Zeitmodell:** Globale Eckwerte (z. B. Anzahl der Durchläufe / Runden, optionale Gesamt-/Einführungszeit als Ziel oder Rechenhilfe) und **pro Platz (Slot)** die Dimensionen „Belastung“, „wie viele gleiche Übung hintereinander“, „kurze Pause dazwischen“, „Übergangszeit zur nächsten Übung/arbeitstation“ — dokumentiert für die technische Angleichung in **`.claude/docs/working/COMBINATION_TIMING_PROFILE_PLAN.md`** (Felder **`slot_profiles_v1`**, `timing_schema`). Archetypen können **Strukturen und typische Schnellwahlen** vorgeben (z. B. Zirkel: Relation Belastungszeit = Übergangszeit oder Erholungsanteil ≈ 2/3 der Belastung); der Archetyp **Freier Methodenblock** bildet den **Maximal‑Pfad** ohne stärkere stille Annahmen. **Pyramidale/abhängige Pausen** (Pause abhängig von vorheriger Belastung) sind **nicht Teil des aktuellen Umsetzungspfads**, können später als eigener Untertyp ergänzt werden. + ### 6.4 Slot- und Pool-Logik Slots können fest oder variabel sein. @@ -512,7 +516,7 @@ Produktregel: Nach dem Einfügen muss ein Planungsblock lokal angepasst werden können: * Dauer ändern, -* **bei Kombinationsübungen:** im Idealfall **`method_profile` (Arbeit, Erholung, Durchläufe)** und Stations-/Slot-Anpassungen des **konkreten Vorkommens**, nicht nur Gesamtzeit, +* **bei Kombinationsübungen:** Ablaufprofil **optional nur für diese Platzierung** überschreiben (aktuell: Snapshot parallel zum Katalog-`method_profile`, z. B. Arbeit-, Erholungs- und Runden-/Intervallangaben über die gleichen strukturierten Felder wie im Übungskatalog) — zusätzlich zu den **Gepl.-Min.** am Eintrag; **Stations-/Slot-Austausch** am konkreten Vorkommen weiter über die bestehende Übungs-/Planungslogik, nicht gesondert als „Kombi-Programmierung“ je Zeile, * Übung austauschen, * Station ergänzen, * Hinweise anpassen, @@ -787,7 +791,7 @@ Die Spezifikation ist daher kein technisches Pflichtenheft, sondern ein fachlich --- -## Anhang A — Implementierungsabgleich (Stand Code: App **0.8.102**, grob) +## Anhang A — Implementierungsabgleich (Stand Code: App **0.8.104**, grob) Zweck: dieselbe Tabelle für **Produkt / Architekt / Agent** beim nächsten Schritt; verhindert „wir haben X gebaut, die Spec sagt aber Y“ ohne dass es dokumentiert wird. @@ -795,10 +799,10 @@ Zweck: dieselbe Tabelle für **Produkt / Architekt / Agent** beim nächsten Schr |--------------------------------------------|-----------------|---------------------------------|-------------------------------------| | **Trainingsmodule (Bibliothek)** | Wiederverwendbare Blöcke, Kopier-Einfügen in Einheit | Bibliothek, API, Übernahme-Modal, Lineage-Spalte | **Phase 3** des Umsetzungsplans: erweiterter Übernahmemodus | | **Kombinationsübung im Katalog** | `exercise_kind=combination`, Slots, Pools (Kandidaten) | Migration 056, CRUD Übung mit `combination_slots`, GET liefert Slots + Kandidatentitel | Fachbezug Haupt-/Nebenmethoden aus § 4/§ 6 dort umsetzen, wo die Domäne es noch nicht abdeckt | -| **Archetyp + Ablaufprofil am Katalogobjekt** | `method_archetype`, JSON `method_profile` | Persistenz; Übungsformular: **geführte Felder** nach Archetyp (`CombinationMethodProfileEditor`, `combinationMethodProfileUi.js`) + eingeklapptes Roh‑JSON | Schema‑Validierung serverseitig noch offen; UI für Pflicht je Archetyp (§ 10.5) weiter schärfen | -| **Einplanbarkeit (normale Planung)** | Kombi wie Übung in Sektionen; **Zeitprofil‑Overrides** nach § 8.3 / § 10.5.1 | Picker, `exercise_kind` in Form/PUT, keine Variante bei Kombi; **Overrides von `method_profile` am Platzierungseintrag fehlen** | Planungs-UI/API: kopiertes **`method_profile` pro Einheit/item** bearbeitbar; Planungsblöcke (Phase 3) | -| **Zeitphasen (global / pro Slot)** | § 6.3 | Über `method_profile` teilweise (globale Schlüssel im Formular); **keine strukturierten slotgebundenen Zeitlisten** im UI | `slot_timing[]` oder äquivalent definieren und editieren | -| **Coaching Stufe A** | Slots + Kandidaten sichtbar, Archetyp‑Hinweis, Profil lesbar | `CombinationCoachSlots` zeigt **Key/Value** aus `method_profile`, sonst wie zuvor | Profilwerte **lesend** benutzerfreundlicher labeln (statt nur Schlüsselnamen) | +| **Archetyp + Ablaufprofil am Katalogobjekt** | `method_archetype`, JSON `method_profile` (+ Pilot **`slot_profiles_v1`** je Station in derselben JSON‑Struktur) | Persistenz; Übungsformular: **geführte globale Felder** + **pro Slot** vier Zeitreihen ohne Nutzer‑JSON‑Pflicht; Schnellwahl typische Arbeit/Pause‑Relationen (**Zirkel**, **Intervall**); Reihenfolge UX: Stationen vor Ablaufprofil | JSON‑„Experte“ weiter abschaltbar; Schema‑Pflichtfelder nach Archetyp; Konvergenz flache Schlüssel ↔ `timing_schema` (siehe Arbeitsplan) | +| **Einplanbarkeit (normale Planung)** | Kombi in Sektionen; **Zeitprofil‑Overrides** nach § 8.3 / § 10.5.1 | Picker, `exercise_kind` in Form/PUT, keine Variante bei Kombi; **Override:** DB **`planning_method_profile`** je Sektions-Item (Migration **057**), Planungseditor: Details „Ablaufprofil für diese Planung“, **„Planung wie Katalog“** / **„Aus Katalog kopieren“** | Planungsblöcke als Produktkonzept · Phase 3; serverseitige Validierung Snapshot↔Archetyp optional | +| **Zeitphasen (global / pro Slot)** | § 6.3 | Über `method_profile` / Planungs‑Snapshot (**gleiche JSON-Struktur** wie Katalogprofil): globale Schlüssel im Übungs- und Planungseditor; weiterhin **keine** eigenständigen slotgebundenen Zeitlisten im UI | `slot_timing[]` oder äquivalent definieren und editieren | +| **Coaching Stufe A** | Slots + Kandidaten sichtbar, Archetyp‑Hinweis, Profil lesbar | `CombinationCoachSlots`: wirksames Profil = **Planungs‑Snapshot wenn gesetzt, sonst Katalog**; Anzeige **Key/Value** | Profilwerte **lesend** benutzerfreundlicher labeln (statt nur Schlüsselnamen) | | **Coaching Stufe B** | Zeitleiste archetypnah (z. B. Schritt pro Station) | **Nein** — ein Coach‑Schritt = ein Planungsitem | Designentscheid: virtuelle Substeps vs. DB‑Materialisierung; Auswirkung auf Ist‑Zeit pro Item | | **Coaching Stufe C** | Timer/Wechsel/Abhaken nach Archetyp | Nur **generischer** Coach‑Timer pro Planungsitem | Pro Archetyp UI‑State + Anbindung an `method_profile` | | **Rahmenprogramm** | Gleiche Inhalte wie Einheit | Slot‑Blueprint, `from-framework-slot` | Modul-/Kombi‑UX in Rahmen wie in Einheit konsolidieren (Phase 5) | diff --git a/.claude/docs/working/COMBINATION_TIMING_PROFILE_PLAN.md b/.claude/docs/working/COMBINATION_TIMING_PROFILE_PLAN.md new file mode 100644 index 0000000..dae1862 --- /dev/null +++ b/.claude/docs/working/COMBINATION_TIMING_PROFILE_PLAN.md @@ -0,0 +1,100 @@ +# Kombinations‑Ablaufprofil — Zeitmodell, Archetyp‑Vorgaben, Umsetzung + +**Zweck:** Fach-/Technik-Brücke zwischen Wunschbild („kein Nutzer‑JSON“, globale und slotbezogene Eckwerte, Archetyp‑Strukturen) und bestehendem Speicher **`method_profile` (JSON)** + **`planning_method_profile`** auf Planungszeilen. + +**Bezüge:** `.claude/docs/functional/Shinkan Trainingsmodule Kombinationsuebungen Spezifikation V2.md` (§ 6.3 / § 8.3); Frontend `CombinationMethodProfileEditor`, `combinationMethodProfileUi.js`; Archetyp‑IDs siehe Backend `COMBINATION_ARCHETYPE_IDS` / Frontend `COMBINATION_ARCHETYPE_OPTIONS`. + +--- + +## 1. Grundprinzipien + +| Prinzip | Beschreibung | +|--------|--------------| +| **Kein Pflicht‑JSON für Trainer** | Alle trainertypischen Pflegepfade nur über geführte Felder + Archetyp‑Vorschlagsknöpfe. | +| **JSON bleibt Transport** | Persistenz geschieht weiter in `method_profile` / Kopie in `planning_method_profile`; **kanonische Schlüssel** werden hier und in Codekommentaren festgehalten. | +| **Archetyp = Struktur + Defaults** | Wechsel des Archetyps soll (optional/togglebar) Grundwerte oder typische Relationen vorbelegen können — keine stillen Überschreibungen ohne Hinweis. | +| **`free_method_block` = Maximale Freiheit** | Entspricht „maximaler Konfiguration“: alle relevanten Timing‑Dimensionen über UI, insbesondere **pro Slot**; keine impliziten stationären Constraints. | + +--- + +## 2. Kanonisches Zeit‑Schema (`timing_schema`) + +**Empfohlene Versionierung im Objekt:** + +- **`timing_schema: 1`** — sobald neue globale/strukturierte Felder aktiv genutzt werden (Pilot; UI kann ohne Migration starten durch parallele Schlüssel). + +### 2.1 Globalebene (`method_profile`) + +| Feld (Pilot) | Semantik | +|----------------|----------| +| `timing_schema` | `1` wenn Block unten aktiv | +| `intro_sec` oder bestehend `block_intro_sec` | einmalige Einführung/Demo am Block | +| `rounds` (bzw. bei Intervallen `interval_rounds` — Angleich später) | komplette Durchläufe des Musters | +| *Planned totals* nur **berechnete Anzeige** in UI, optional persistiert z. B. `planned_total_duration_min_hint` später | + +Relationen **Zwischen Arbeit und Pause** können als Schnellwahl gesetzt werden (kein eigener Persist‑Erzwing‑Typ nötig), indem konkrete Sekunden geschrieben werden. + +### 2.2 Slots (`slot_profiles_v1`) + +Array synchron zu `slot_index`; fehlende Einträge = „nicht gefüllt / aus globalen Eckdaten ableiten wo sinnvoll“. + +Objekt‑Shape (Sekunden, ganze Zahlen ≥ 0): + +```json +{ + "slot_index": 0, + "load_sec": 40, + "consecutive_reps": 1, + "intra_rep_rest_sec": 10, + "transition_after_sec": 15 +} +``` + +| Feld | Bedeutung | +|------|------------| +| `load_sec` | Belastungsdauer „an der Station“. | +| `consecutive_reps` | Übungen hintereinander ohne Wechsel zu **neuem** Stationsinhalt („oft 1“). | +| `intra_rep_rest_sec` | Pause zwischen diesen Folge‑Wiederholungen. | +| `transition_after_sec` | Pause / Wechsel **zur nächsten** Station oder zum nächsten logischen Block. | + +**Hinweis:** Bestehende Archetyp‑„flachen“ Schlüssel (`work_seconds`, `transition_seconds`, …) werden schrittweise **nicht zerstört**, sondern Slots ergänzen; Konvergenz (eine Darstellung zu v1) kann Phase 4 sein. + +--- + +## 3. Archetyp → typische Schnellwahl (Überblicks‑Matrix) + +| Archetyp | Globale Schnellwahl (Beispiele) | Slots | +|----------|---------------------------------|-------| +| `circuit_rotate_time` | Arbeit; Rotation „≈ Arbeit“ oder „Pause 2/3 Arbeit“ bezogen auf Rund‑Pausen/Rotation wo im UI dokumentiert | sinnvoll ab **timing_schema** geführt | +| `time_domain_interval` | Pause = Arbeit; Pause = 2/3 Arbeit (auf `rest_seconds`↔`work_seconds`) | optional | +| `sequence_linear` | Einführung + grobe Sek./Station | **slot_profiles_v1** priorisiert | +| `circuit_all_parallel` | Erklärzeit, gemeinsamer Start | Slots optional | +| `pair_superset` | Wechsel A↔B, Arbeit je Seite (+ später erweiterbar) | 2‑Slot‑Fokus | +| `free_method_block` | alle globalen Slots optional | **Pfad für maximale Flex** | +| `station_parcour` | Reihenfolge frei‑Flag bestehend | pro Station Verweilen sinnvoll | + +**Pyramidal (später):** neue Archetyp‑ID **`pyramid_interval`** o. ä. oder Flag `pyramid_recovery_rule` mit Regelwerk „Pause abhängig von letzter Belastung“ — **explizit out of scope** bis Regeln feststehen. + +--- + +## 4. UX‑Normen + +- **Trainingsplanung** (`plannerMode`): **keine** Roh‑JSON‑Oberfläche. +- **Übungsformular**: Roh‑JSON nur wenn `allowExpertJson === true` (Default false; später z. B. Superadmin/Dev). +- **Coaching‑Ansicht**: nur **wirksame** Zahlen aus Snapshot/Katalog darstellen, mittelfristig Labels statt Schlüsseln. + +--- + +## 5. Phasen (Implementierung) + +| Phase | Inhalt | +|-------|--------| +| **1 (jetzt)** | Slot‑Zeilen‑UI über `slot_profiles_v1`; Schnellwahl‑Ratios für `circuit_rotate_time` + `time_domain_interval`; `plannerMode` ohne JSON; `allowExpertJson` default false | +| **2** | Beim Archetypwechsel **optionales** Modal „Archetyp‑Vorlage anwenden?“ mit nicht‑destruktivem Merge | +| **3** | Geplante **Gesamtzeit** konsistent rechnerisch (Summe Slots × Runden + Global) mit Transparenz in UI | +| **4** | Konsolidierung flacher Schlüssel → **`timing_schema`** v1‑only im Editor | +| **5** | Pyramide / adaptive Recovery | + +--- + +**Pflege:** Änderungen an Schlüsseln oder Phasen hier und in Anhang A der Fachspez mitziehen. diff --git a/backend/version.py b/backend/version.py index ae392af..2988c92 100644 --- a/backend/version.py +++ b/backend/version.py @@ -1,6 +1,6 @@ # Shinkan Jinkendo Version Information -APP_VERSION = "0.8.103" +APP_VERSION = "0.8.104" BUILD_DATE = "2026-05-12" DB_SCHEMA_VERSION = "20260512057" @@ -21,7 +21,7 @@ MODULE_VERSIONS = { "groups": "0.1.0", "skills": "0.1.0", "methods": "0.1.0", - "exercises": "2.24.2", # Kombi: geführtes method_profile im Übungsformular nach Archetyp + Coach zeigt Profil als Key/Wert + "exercises": "2.25.0", # Kombi: slot_profiles_v1 + Schnellwahl Belastung/Erholung; keine Nutzer‑JSON‑Pflicht; Übungsform Stationen vor Ablaufprofil "training_units": "0.2.0", "training_programs": "0.1.0", "planning": "0.9.2", # Kombi: planning_method_profile auf Sektions-Items (Migration 057); Form-Payload + Coach-PUT @@ -35,6 +35,14 @@ MODULE_VERSIONS = { } CHANGELOG = [ + { + "version": "0.8.104", + "date": "2026-05-12", + "changes": [ + "Kombinations‑Ablaufprofil UX: Stationszeilen (slot_profiles_v1); Schnellwahlen Arbeit↔Pause (Zirkel + Intervall); Planungs‑Override ohne JSON; Übungsformular: Reihenfolge Stationen dann Ablaufprofil.", + "Arbeitspapier: `.claude/docs/working/COMBINATION_TIMING_PROFILE_PLAN.md`.", + ], + }, { "version": "0.8.103", "date": "2026-05-12", diff --git a/frontend/src/components/CombinationMethodProfileEditor.jsx b/frontend/src/components/CombinationMethodProfileEditor.jsx index f71eadf..f205fa6 100644 --- a/frontend/src/components/CombinationMethodProfileEditor.jsx +++ b/frontend/src/components/CombinationMethodProfileEditor.jsx @@ -1,10 +1,15 @@ import React, { useMemo, useState } from 'react' -import { archetypeCoachHint, combinationArchetypeLabel } from '../constants/combinationArchetypes' +import { archetypeCoachHint, combinationArchetypeLabel, sortCombinationSlotsForDisplay } from '../constants/combinationArchetypes' import { METHOD_PROFILE_GUI_FIELDS, parseProfileJson, setFullProfileRawJson, updateProfileGuided, + patchMethodProfile, + readSlotProfilesV1, + patchSlotTimingField, + applyCircuitRotateQuickRatio, + applyIntervalDomainQuickRatio, } from '../utils/combinationMethodProfileUi' function clampInt(n, min, max) { @@ -15,13 +20,31 @@ function clampInt(n, min, max) { return Math.round(x) } +/** Archetypen mit klar bezifferbarer Stationslogik · alle mit Slot-Liste sinnvoll */ +const ARCHETYPES_WITH_SLOT_TIMING = new Set([ + 'circuit_rotate_time', + 'sequence_linear', + 'station_parcour', + 'time_domain_interval', + 'circuit_all_parallel', + 'pair_superset', + 'free_method_block', +]) + /** - * Kombination: geführtes Ablaufprofil + optionales Roh-JSON. + * Kombination: geführtes method_profile (+ optional Stationszeilen, ohne JSON für Trainer). + * + * @param {boolean} [props.plannerMode] — z. B. Planungs‑Override: keine Roh‑JSON‑Sektion. + * @param {boolean} [props.allowExpertJson] — wenn true und nicht plannerMode: Roh‑JSON (Support). + * @param {{ slot_index?: number|string, title?: string }[]} [props.comboSlotsOutline] — für Slot‑Felder aus der Übung */ export default function CombinationMethodProfileEditor({ methodArchetype, methodProfileJson, onChangeMethodProfileJson, + plannerMode = false, + allowExpertJson = false, + comboSlotsOutline = null, }) { const arch = typeof methodArchetype === 'string' ? methodArchetype.trim() : '' const fieldsGui = METHOD_PROFILE_GUI_FIELDS[arch] @@ -29,20 +52,36 @@ export default function CombinationMethodProfileEditor({ const parseState = useMemo(() => parseProfileJson(methodProfileJson || '{}'), [methodProfileJson]) const [rawOpenError, setRawOpenError] = useState(null) const [rawDraft, setRawDraft] = useState(null) + const [presetHint, setPresetHint] = useState(null) const profileObj = parseState.ok ? parseState.obj : {} + const outlineSorted = useMemo(() => { + if (!comboSlotsOutline || !Array.isArray(comboSlotsOutline) || comboSlotsOutline.length === 0) return [] + return sortCombinationSlotsForDisplay(comboSlotsOutline) + }, [comboSlotsOutline]) + + const showSlotTiming = + ARCHETYPES_WITH_SLOT_TIMING.has(arch) && outlineSorted.length > 0 + + const slotRowsModel = useMemo(() => readSlotProfilesV1(profileObj), [profileObj]) + + const lookupSlotTiming = (slotIndex) => + slotRowsModel.find((r) => Number(r.slot_index) === Number(slotIndex)) || {} + const applyGuided = (key, value, kind) => { if (kind === 'bool') { const res = updateProfileGuided(arch, methodProfileJson || '{}', key, value, 'bool') if (!res.ok) return onChangeMethodProfileJson(res.json) + setPresetHint(null) return } if (value === '' || value === undefined || value === null) { const res = updateProfileGuided(arch, methodProfileJson || '{}', key, '', 'int') if (!res.ok) return onChangeMethodProfileJson(res.json) + setPresetHint(null) return } const num = typeof value === 'number' ? value : parseInt(String(value), 10) @@ -53,6 +92,36 @@ export default function CombinationMethodProfileEditor({ const res = updateProfileGuided(arch, methodProfileJson || '{}', key, c, 'int') if (!res.ok) return onChangeMethodProfileJson(res.json) + setPresetHint(null) + } + + const onSlotField = (slotIx, field, rawStr) => { + const patched = patchMethodProfile(methodProfileJson || '{}', (d) => + patchSlotTimingField(d, slotIx, field, rawStr) + ) + if (!patched.ok) return + onChangeMethodProfileJson(patched.json) + setPresetHint(null) + } + + const runCircuitPreset = (presetId) => { + const r = patchMethodProfile(methodProfileJson || '{}', (draft) => { + const pr = applyCircuitRotateQuickRatio(draft, presetId) + if (!pr.ok) setPresetHint(pr.error || '') + else setPresetHint(null) + }) + if (!r.ok) return + onChangeMethodProfileJson(r.json) + } + + const runIntervalPreset = (presetId) => { + const r = patchMethodProfile(methodProfileJson || '{}', (draft) => { + const pr = applyIntervalDomainQuickRatio(draft, presetId) + if (!pr.ok) setPresetHint(pr.error || '') + else setPresetHint(null) + }) + if (!r.ok) return + onChangeMethodProfileJson(r.json) } const archeLabel = arch ? combinationArchetypeLabel(arch) : null @@ -63,8 +132,14 @@ export default function CombinationMethodProfileEditor({ setRawDraft(p.ok ? JSON.stringify(p.obj, null, 2) : String(methodProfileJson || '')) } + const showExpertSection = allowExpertJson && !plannerMode + return (
+ {presetHint ? ( +

{presetHint}

+ ) : null} + {arch ? (

@@ -75,7 +150,8 @@ export default function CombinationMethodProfileEditor({

) : (

- Wähle einen Archetyp, um das Ablaufprofil strukturiert zu erfassen — oder nur das JSON weiter unten. + Wähle einen Methoden‑Archetyp — besonders beim freien Methodenblock stehen alle + typischen Stations‑Zeiten zur Verfügung. Ohne Archetyp keine geführten Eingaben.

)} @@ -85,6 +161,48 @@ export default function CombinationMethodProfileEditor({ {fields && fields.length > 0 ? (
+ {arch === 'circuit_rotate_time' ? ( +
+ Schnellwahl: + + + +
+ ) : null} + {arch === 'time_domain_interval' ? ( +
+ Schnellwahl: + + +
+ ) : null} + {fields.map((def) => { if (def.kind === 'bool') { const ck = !!profileObj[def.key] @@ -125,51 +243,170 @@ export default function CombinationMethodProfileEditor({ })}
) : arch && fields && fields.length === 0 ? ( -

- Für diesen Archetyp gibt es keine vorgegebenen Profilfelder — nutze die Freitexte der Kombination oder Roh‑JSON bei Bedarf. -

+
+

+ Dieser Archetyp ist für maximal flexible Stationsblöcke gedacht — die Zeit‑Eckdaten sind + unten je Station möglich. Freitexte der Kombination beschreiben alles Organisatorische, was nicht in + Sekunden gefasst wird. +

+
) : null} -
{ - if (ev.target.open) openAdvanced() - }} - > - Erweitert: JSON direkt bearbeiten -

- Zusätzliche Schlüssel (Piloten). Geführte Felder können dieselben Schlüssel beim nächsten Speichern überlagern. -

-