# Marksilo-flow — design Dato: 2026-09-27 · Status: godkendt i chat, afventer review af denne spec ## Formål Høsten lægges ofte i siloer ude ved markerne (mellemlager). I dag skal spilleren selv huske at køre varerne hjem. Marksilo-flowet kigger jævnligt alle marksiloer igennem og sender selv op til **x** ledige vogne ud for at hente varerne hjem til gårdens lagre. **Succes:** står der varer i en marksilo, som gården kan tage, bliver de kørt hjem uden at spilleren gør noget, med højst x vogne ude ad gangen, og uden at tage vogne fra markarbejde, andre flows eller spilleren. ## Brugerens valg (fra brainstorm) | Spørgsmål | Valg | |---|---| | Hvor er "hjem"? | Nærmeste af de gårdlagre, spilleren vælger i flowet, der tager varen og har plads | | Hvad er "x vogne"? | Lånte ledige vogne fra hele gården — ingen fast tilknytning — højst x ude samtidig | | Hvilke vogne må lånes? | Samme regel og flueben som markarbejdet (`fleetMode` "all"/"ticked", `ADFieldJobs.state.fleet`) | ## Begreber - **Marksilo:** bygning af typen silo inden for `ADFields.FIELD_SILO_DISTANCE` (150 m) af en marks polygon (`ADFields.fieldSilos`), samlet over alle marker, uden dubletter. En bygning, der er valgt som gårdlager i flowet, er aldrig marksilo. Det samme gælder siloer, der er kilde, mål eller lager i et flow (tilføjet efter review 2026-09-27: ellers tømte flowet gårdsiloer, som forsyningsflows bruger, fordi de ligger under 150 m fra en mark). - **Gårdlager:** bygning spilleren vælger i flowet (samme bygningsvælger som udkørslens lagre, `storeBuildings`). - **Lån:** en vogn, flowet har sendt på én tur. Lån ligger kun i hukommelsen. ## Flowet Marksilo-flowet er ÉN fast opsætning pr. savegame — ikke en ny run-type. Beslutning (2026-09-27, under planlægning): run-editoren (`SmartPickupFrame`) er bygget til præcis to typer (forsyning/udkørsel) mange steder, og runs har faste vogne, Start/Stop pr. vogn og Wait-puljer, som intet af det passer til lånte vogne. En egen underfane + egen gemmefil giver langt færre indgreb i eksisterende kode. Opsætning (`ADSmartPickup_fieldsilos.xml` i savegame-mappen, gemmes sammen med runs): - `enabled` — til/fra, standard fra - `storeIds` — gårdlagre (bygnings-id'er fra `ADBuildings`, kun `kind == "silo"`) - `maxVehicles` — x, 1–10, standard 2 - `minLiters` — tærskel pr. silo og vare: 5000 / 10000 / 25000 / 50000, standard 10000 ## Planlægning (ren logik, nyt modul `adFieldSiloPlanner.lua`, testes med luajit) Input: marksiloer `{id, markerId|nil, stock = {[fillType] = liters}}`, gårdlagre `{id, markerId, accepts = {[fillType] = freeLiters}, x, z}`, aktive lån `{siloId, fillType, liters}`, ledige vogne `{id, x, z, capacity, carries = {[fillType] = true}}`, `maxVehicles`, `minLiters`. 1. **Kvalificerede opgaver:** pr. (silo, vare) hvor silo har markør, `liters >= minLiters`, og mindst ét gårdlager har `freeLiters >= minLiters` for varen. Resten = liters minus det aktive lån på samme (silo, vare) allerede er på vej med; kun opgaver med rest `>= minLiters` tæller. Siloer uden markør → status `noMarker`; varer intet gårdlager tager → status `noFarmStore`. 2. **Rækkefølge:** fuldeste rest først; lige → lavest silo-id (stabilt). 3. **Vogne:** ledige pladser = `maxVehicles - #aktive lån`. For hver opgave i rækkefølge, så længe der er pladser: nærmeste ledige vogn (til siloen), der kan bære varen; resten reduceres med vognens kapacitet; samme opgave får flere vogne, så længe resten stadig er `>= minLiters`. 4. **Gårdlager pr. lån:** nærmeste gårdlager (til siloen) der tager varen med `freeLiters >= min(vognens kapacitet, rest)`; ellers det med mest plads; ellers intet (opgaven springes over denne runde). Output: `{dispatch = {{vehicleId, siloId, siloMarkerId, fillType, storeMarkerId, liters}}, status = {...}}`. ## Udførelse (`adFieldSilos.lua`) - **Takt:** planlæg hvert 60. s (spiltid via `dt`), kun når flowet kører. Lagertal læses som i dag (`ADSmartPickup.getStationLevelAndCapacity` / silo-lagre). - **Ledige vogne:** kun vogne med AD-parkeringspunkt (ellers bliver de holdende på lagerets markør); `ADFieldWork.getRigs(adEnv)` filtreret til `role == "unloader"` (traktor + vogn, som Courseplay godkender som tømmevogn — ikke sprøjter/høstere med tank), `enabled and not busy and not controlled`, og vogne der har aflæsbare enheder (`AutoDrive.getAllDischargeableUnits`), der understøtter varen. `getRigs.busy` udvides med `ADFieldSilos.isLoaned(vehicle)`, så markarbejdet ikke tager en lånt vogn (flows tager allerede kun deres egne tilknyttede vogne). - **Afsend:** AutoDrive "Hent og aflever": første markør = silomarkør, anden = gårdlagerets markør, vare = lånets vare, `loopCounter = 1`, parkering ved job slut slået til (`enableParkAtJobFinished`); start som markarbejdet (`startAd` → mode:start). Log: `marksilo: '' henter l i → `. - **Frigivelse:** lånet slettes når AD ikke længere er aktivt for vognen (turen og parkeringen er færdig), når spilleren sætter sig i den, eller når flowet stoppes (stop = AD stoppes på lånte vogne). - **Vagt:** er vognen ikke kommet i gang (ingen stigning i fyldning og står stille) efter 120 s, stoppes AD, lånet slettes, og der logges én advarsel pr. (silo, vare), så samme opgave ikke fejler i ring hvert minut (opgaven får 10 min pause). - **Genindlæsning:** lån gemmes ikke. Ved indlæsning er alle vogne frie for flowet; en vogn AutoDrive selv genstarter, kører sin tur færdig som almindelig AD-tur. ## GUI Ny underfane "Marksiloer" efter "Måned". Indstillinger: gårdlagre (eksisterende vælger), "Maks. vogne ude" (1–10), "Mindste mængde" (5.000 / 10.000 / 25.000 / 50.000 l), Start/Stop. Status: `x/y vogne ude · n siloer venter`, og én række pr. marksilo med indhold: silo, vare, liter, på vej, status (`ok` / `mangler markør` / `ingen gård tager `). Tekster i `l10n_da` + `l10n_en` (`spu_fs_*`). ## Uden for scope - Salg direkte fra marksilo (kan senere bruge udkørslens prisregel). - Faste vogne i flowet (valg 1 i brainstorm) — fravalgt. - Lån der overlever genindlæsning. ## Test - `tests/test_adFieldSiloPlanner.lua`: kvalificering (tærskel, markør, gård tager varen), fuldeste først, x-loft inkl. aktive lån, flere vogne til én stor silo, vogn der ikke kan bære varen springes over, nærmeste gårdlager med plads, fallback til mest plads, intet lager → ingen afsendelse. - `tests/test_adFieldSiloConfig.lua`: standarder, grænser (x 1–10, tærskel kun de fire værdier), til/fra af gårdlager, records frem og tilbage. - In-game: silo ved en mark med 50.000 l hvede, gårdlager = Farma-silo, x = 2 → to vogne kører, afleverer, parkerer; markarbejdet tager ikke de lånte vogne imens.