Files
fs25-adsmartpickup/docs/superpowers/specs/2026-09-27-marksilo-flow-design.md
T

100 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.
- **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
Ny run-type `fieldSilos` i `ADRuns.KINDS` (ved siden af `supply`/`outbound`). Højst ét marksilo-flow pr. savegame
(GUI'et tilbyder ikke at oprette et til, når det findes).
Felter (gemmes i `ADSmartPickup_runs.xml` som de øvrige):
- `storeBuildings` — gårdlagre (bygnings-id'er → markører via den eksisterende `resolveMarkers`)
- `maxVehicles` — x, 1–10, standard 2
- `minLiters` — tærskel pr. silo og vare, standard 10000
- `running` — til/fra (som de andre flows' Start/Stop)
## 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:** `ADFieldWork.getRigs(adEnv)` filtreret til `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: '<vogn>' henter <liter> l <vare> i <silo> → <lager>`.
- **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
Flow-fanen: typen "Marksiloer" kan oprettes (højst én). 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 <vare>`). 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_adRuns.lua`: ny kind gemmes/indlæses med `maxVehicles`/`minLiters`; ukendt kind → supply som før.
- 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.