# Runs-UI ("Cow Feed") — design Dato: 2026-09-22 · Status: godkendt af bruger (sektion 1–3) · Version: v1.8 ## Problem Al opsætning sker i dag pr. traktor i AutoDrives HUD: mål, multi-valg af varer (tændknap for behovsstyring), mapper + rotation, loop-tæller. Med fire ens "Fastrac 2135" til to stalde og flere Wait-puljer på vej (Cow/Pig/Sheep Wait) mangler overblik og central kontrol: *hvad* kører *hvor* med *hvilke varer*, og hvor venter de. ## Løsning Et **run** er den centrale enhed: navn, aflæsningsmål, varer, Wait-pulje, tildelte traktorer, loop-tæller. En ESC-menu-fane ("Smart Pickup") viser og redigerer runs og starter/stopper dem. "Start" skriver run'et ind i hver traktors AutoDrive-tilstand og kalder AD's start — alt det eksisterende (behovsstyring, fabriks-inputs, Wait-punkter) virker uændret ovenpå, fordi det læser præcis den tilstand. Traktorer uden run kører som i dag. Valgt tilgang: **run-lag oven på AutoDrives tilstand** (fravalgt: egen dispatcher der kalder AD's lav-niveau-opgaver — genopfinder P&D og knækker ved AD-opdateringer; konfig-fil uden UI — ikke det brugeren bad om). ## 1. Datamodel og lagring ``` Run id løbenummer (stabilt, unikt i savegame) name "Cow Feed" targetWayPointId AD-waypoint-id for mål-markøren (stald/fabrik); vises som markørnavn ingredientMode "auto" | "manual" ingredients liste af fillType-NAVNE (kun ved manual), fx {"STRAW","FORAGE"} waitPoolGroup AD-mappenavn (fx "Cow Wait"); tom streng = alle Wait-mapper, nærmeste ledige loops 0 = uendeligt, N = antal ture (AD's loop-tæller) vehicleIds liste af køretøjs-referencer (se nedenfor) Runtime (ikke gemt): isRunning afledt: mindst én tildelt traktor har AD aktiv og run-medlemskab runMembership vehicle -> run.id (svagt nøglet tabel) ``` - **Køretøjs-reference:** AD's `uniqueId` (streng) når den findes på køretøjet, ellers savegame-id (`vehicle.currentSavegameId`). Navne bruges aldrig som nøgle (fire hedder "Fastrac 2135 4WS"). - **WaitPool** er afledt, ikke gemt: alle AD-mapper med ordet "Wait" i navnet (`ADSupplyPlanner.isWaitMarker`). Omdøbning sker i AutoDrive; vi læser kun. - **Fil:** `savegameN/ADSmartPickup_runs.xml`, samme mappe som `AutoDrive_config.xml`. Skrives i spillets gem-hook (som AD), læses ved `loadMap`. Ukendte køretøjs-referencer droppes med loglinje; run'et beholdes. Runs der kørte ved gem genstartes IKKE ved load (AD gendanner selv aktive køretøjer). - **Regler:** en traktor kan kun være i ét run (tildeles den et andet, flyttes den — UI'et siger det). Singleplayer først; multiplayer kræver events og er uden for scope. XML-format: ```xml ``` ## 2. UI — ESC-fane "Smart Pickup" Forbillede: FarmOperationsDashboard (`TabbedMenuFrameElement`, XML-layout med `SmoothList`, `MultiTextOption`, `Button`; registreret via `g_gui:loadGui` + indsættelse i `InGameMenu.pagingElement`). ``` ┌ Smart Pickup ─────────────────────────────────────────────────────────────┐ │ [Runs] [Wait-puljer] (under-faner) │ ├──────────────────┬────────────────────────────────────────────────────────┤ │ RUNS │ RUN: Cow Feed ● Kører (2/2) │ │ ▶ Cow Feed 2/2 │ Mål: [Cow 1 Food ▼] (AD-markør) │ │ Cow 2 Feed 1/2 │ Varer: (•) Auto: alt målet tager / fabrikken │ │ TMR Fabrik 1/1 │ ( ) Vælg: [x] Halm [x] TMR [ ] Vand │ │ │ Wait-pulje: [Cow Wait ▼] (6 punkter)│ │ [+ Nyt run] │ Ture (loop): [0 = uendeligt ◄►] │ │ [Slet run] │ Traktorer: │ │ │ Fastrac 2135 (#1) vogn: 1.000.000 l halm+TMR ✔ │ │ │ Fastrac 2135 (#2) vogn: — INGEN VOGN ✖ │ │ │ [+ Tilføj traktor ▼] [Fjern] │ │ │ [▶ Start run] [■ Stop run] Status: 1 advarsel │ └──────────────────┴────────────────────────────────────────────────────────┘ ``` - **Runs-liste (venstre):** alle runs med "kører X af Y". Valg → detaljer til højre. `+ Nyt run` opretter "Run N" (navn redigeres via AD-lignende tekstdialog). `Slet run` spørger ja/nej. - **Mål:** dropdown over AD-markører der ligger ved en aflæsningsstation (`getUnloadStationAtMarker` ≠ nil) — ikke alle markører. - **Varer:** *Auto* = det eksisterende: fabrik → ønskede produktioners inputs (v1.6); stald → alle varer stalden tager (`getHusbandryIsFillTypeSupported`); andet mål → stationens understøttede varer. *Vælg* = afkrydsning blandt målets mulige varer. - **Wait-pulje:** dropdown "Alle (nærmeste ledige)" + hver mappe med "Wait" i navnet (antal punkter). - **Ture:** 0–99. - **Traktorer:** dropdown over farmens køretøjer med `vehicle.ad` (navn + `#løbenummer`). Pr. række: vogn-kapacitet (AD `getAllFillLevels`), hvilke af run'ets varer vognen kan bære, og ✔/✖ med tekst: "ingen vogn", "kan ikke bære: TMR", "N m fra vejnettet", "i run X (flyttes)". - **Start/Stop** gælder hele run'et; ✖-traktorer springes over med besked i rækken. - **Wait-puljer-fanen:** liste over Wait-mapper: antal punkter, hvilke traktorer holder hvor lige nu (fra `adUnloadWait`'s reservationer). Kun visning. - Live-opdatering hvert sekund mens siden er åben. Dansk + engelsk l10n. Ingen nye tastaturgenveje. ## 3. Start/Stop, integration, fejl og test **Start run** (pr. tildelt traktor): 1. Validér: vogn tilkoblet og kan bære ≥1 af run'ets varer (`AutoDrive.getSupportedFillTypesOfAllUnitsAlphabetically`); ≤ 30 m fra vejnettet (`ADGraphManager:getDistanceFromNetwork`); mål-markør findes. Fejl → ✖ på rækken, traktoren springes over, run'et fortsætter med de andre. 2. Skriv AD-tilstand: `stateModule:setMode(AutoDrive.MODE_PICKUPANDDELIVER)`; `setSecondMarkerByWayPointId(target)`; `setFirstMarkerByWayPointId(nærmeste markør med læssestation)` (kun en gyldig start — moden vælger reel kilde pr. tur); `selectedFillTypes` = run'ets varer (Auto: udledt liste) + `raiseDirtyFlag`; loop-tæller; per-køretøj `vehicle.ad.settings.useFolders` = til og `rotateTargets` = kun pålæsning (`current` og `new`). 3. `vehicle:startAutoDrive()`. 4. `runMembership[vehicle] = run.id`. **Stop run:** `vehicle:stopAutoDrive()` pr. tildelt traktor; medlemskab bevares (konfigureret, ikke kørende). **Integration:** de eksisterende hooks læser AD-tilstanden uændret. Run'et læses to steder: (a) `adUnloadWait`: Wait-kandidater begrænses til run'ets mappe, hvis sat; (b) `choosePickup`: for run-traktorer tages ingredienslisten fra run'et (Auto/manual) i stedet for "≥2 valgt i dropdown", så tændknappen ikke længere kræves. Traktorer uden run: præcis som i dag. **Fejlhåndtering:** al UI-kode og Start/Stop i `pcall`; fejl vises i status-linjen og logges med `ADSmartPickup:`-præfiks; aldrig crash. Manglende AD-API → fanen viser "AutoDrive-API ikke fundet", resten af moden upåvirket. **Test:** rene funktioner i luajit (run-model: opret/omdøb/tildel/flyt; validering; Auto-vareliste; XML ↔ tabel; kandidat-filtrering pr. Wait-pulje). GUI og AD-skrivning verificeres in-game efter tjekliste: opret run → tildel 2 traktorer (én uden vogn) → Start (én ✖) → Stop → gem/load → run bevaret. **Afgrænsning (YAGNI):** singleplayer; ingen kilde-begrænsning pr. run; ingen omdøbning af Wait-mapper; ingen auto-genstart ved load; ingen genvejstast-dialog. ## Filer (forventet) - `FS25_ADSmartPickup/adRuns.lua` — run-model + XML (rene funktioner hvor muligt) - `FS25_ADSmartPickup/adRunsController.lua` — Start/Stop, validering mod AD/spil-API, medlemskab - `FS25_ADSmartPickup/gui/SmartPickupFrame.lua` + `gui/SmartPickupFrame.xml` + `gui/guiProfiles.xml` - `FS25_ADSmartPickup/l10n/l10n_da.xml`, `l10n_en.xml` - `tests/test_adRuns.lua` - Tilpasninger i `adSmartPickup.lua` (ingredienser fra run) og `adUnloadWait.lua` (pulje-filter) ## Efterfølgende (ikke i v1.8): læs-bytte fra Wait In-game 2026-09-22 21:55: begge stalde fulde af halm, mangler TMR; alle fire traktorer venter ved Cow Wait med vognene fulde af halm → ingen kan hente TMR (deadlock). Design: mens en traktor venter, tjekkes målets behov. Hvis målet er fuldt for vognens vare, og en ANDEN vare i traktorens ingrediensliste mangler så meget at et fuldt læs passer (hysterese), og vognen kan bære den: find en silo (lager-placeable med aflæsningstrigger ved en AD-markør, fri plads ≥ rest, rute til/fra) — foretræk den moden ellers henter varen fra — og omdiriger aflæsningsopgaven dertil. AD læsser af, vognen er tom, næste tur vælger moden den manglende vare efter behov. Log: "bytter læs: N l STRAW tilbage i , målet mangler FORAGE". Ingen silo → bliv ved Wait. Kræver at traktoren har begge varer i sin liste (run eller multi-valg).