# 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).