docs: maskinpulje — design (traktorer og redskaber som fælles pulje, kø, hent/arbejd/parkér/hjem)
This commit is contained in:
@@ -0,0 +1,149 @@
|
|||||||
|
# Maskinpulje — design
|
||||||
|
|
||||||
|
Dato: 2026-09-28 · Status: godkendt i chat (afsnit 1–4), afventer review af denne spec
|
||||||
|
|
||||||
|
## Formål
|
||||||
|
|
||||||
|
Plove, harver, kultivatorer, såmaskiner, tømmevogne m.m. bruges kun en gang imellem. I dag skal hvert af dem have
|
||||||
|
en traktor koblet fast på hele året, fordi markarbejdet kun kan sende en traktor, der allerede har det rigtige
|
||||||
|
redskab bag sig. Maskinpuljen gør traktorer og redskaber til fælles puljer: et job venter i kø, til en traktor er
|
||||||
|
ledig; traktoren henter det redskab, jobbet kræver, udfører arbejdet, parkerer redskabet på dets plads og kører
|
||||||
|
selv hjem til sin egen parkering.
|
||||||
|
|
||||||
|
**Succes:** med fx 3 ledige traktorer, 2 plove og 1 kultivator bliver markernes arbejde udført uden at nogen
|
||||||
|
traktor står låst til et redskab — færre køretøjer at købe og vedligeholde. Flows, der kører hele tiden (fodring,
|
||||||
|
slurry, mælk …), påvirkes ikke.
|
||||||
|
|
||||||
|
## Brugerens valg (fra brainstorm)
|
||||||
|
|
||||||
|
| Spørgsmål | Valg |
|
||||||
|
|---|---|
|
||||||
|
| Hvordan findes redskabets Connect-markør? | Navneregel: AD-parkering "X" ↔ markør "Connect X" |
|
||||||
|
| Hvem er i puljen? | Automatisk ud fra opsætningen — ingen afkrydsning |
|
||||||
|
| Hvilken traktor henter? | Nærmeste ledige med nok hk |
|
||||||
|
| Omfang | Markarbejde + tømmevogne ved høst + marksilo-flowet. Flows er undtaget |
|
||||||
|
| Tømmevogne ved høst | Også fra puljen, men dedikeret til marken, til høsten dér er færdig |
|
||||||
|
| Arkitektur | Udvid markarbejdets eget maskinvalg (ikke en separat puljemanager) |
|
||||||
|
|
||||||
|
## Begreber
|
||||||
|
|
||||||
|
- **Puljeredskab:** et redskab eller en vogn, der holder **frakoblet**, har en AD-parkering (`advd.parkDestination`
|
||||||
|
→ markør "X"), og hvor der findes en markør "Connect X" (`ADHitch.parseMarker` = attach, navn = X; store/små
|
||||||
|
bogstaver ligegyldigt). Uden Connect-markør er redskabet ikke i puljen — det er spillerens måde at holde det
|
||||||
|
udenfor.
|
||||||
|
- **Puljevogn:** puljeredskab med rollen `unloader` (vogn med tip/snegl, `spec_trailer` + `spec_dischargeable`).
|
||||||
|
- **Puljetraktor:** motoriseret køretøj uden noget koblet bag på (`ADHitch.rearImplements` tom), ikke i et flow
|
||||||
|
(`ADRunsController.getRunForVehicle == nil`), ikke optaget (samme `busy`-regel som `getRigs`), ikke styret af
|
||||||
|
spilleren, med egen AD-parkering (`vehicle.advd.parkDestination >= 1`) og flueben i markflåden
|
||||||
|
(`ADFieldFleet.isEnabled`).
|
||||||
|
- **Færdig kombination:** det markarbejdet bruger i dag — traktor med redskabet allerede koblet på (`getRigs`).
|
||||||
|
- **Puljekombination:** {traktor, redskab, Connect-markør-id, redskabets parkering-id, traktorens parkering-id}.
|
||||||
|
|
||||||
|
AD-parkering: hver maskine har sin egen `advd.parkDestination`; AD bruger det valgte redskabs, når et er koblet på
|
||||||
|
(`AutoDriveVehicleData.lua:88-95`). Traktorens egen parkering læses derfor altid på traktoren selv.
|
||||||
|
|
||||||
|
## Komponenter
|
||||||
|
|
||||||
|
### `adPool.lua` (nyt, ren logik + tynd spil-adapter)
|
||||||
|
|
||||||
|
Ren logik (testes med luajit):
|
||||||
|
- `ADPool.roleOf(specs)` — rolle for et frakoblet redskab ud fra dets egne specs via `ADFieldFleet.ROLE_SPECS`;
|
||||||
|
vogn med `spec_trailer` + `spec_dischargeable` og intet andet → `unloader`.
|
||||||
|
- `ADPool.isPoolImplement(item)` — `item = {attached, parkMarkerName, connectMarkerId}` → frakoblet, med parkering
|
||||||
|
og Connect-markør.
|
||||||
|
- `ADPool.powerOk(tractorPower, neededPower)` — true når et af tallene mangler (nil/0), ellers `tractorPower >=
|
||||||
|
neededPower`.
|
||||||
|
- `ADPool.pairFor(role, fieldX, fieldZ, implements, tractors, reserved, accept)` — redskab med rollen nærmest marken
|
||||||
|
(ikke reserveret, `accept(implement)` sand), derefter nærmeste ledige traktor til redskabet med `powerOk`.
|
||||||
|
Returnerer `pair` eller `nil, why, args` (`noPoolImplement` / `noPoolTractor` / `tooWeak` med hk-tal).
|
||||||
|
- `ADPool.queueOrder(fields)` — markers ventende rækkefølge: `waitingSince` stigende, lige → lavest mark-id.
|
||||||
|
- `ADPool.isReturnDue(rearImplements, poolParkIds)` — traktor har et puljeredskab bag sig (dets parkering har en
|
||||||
|
Connect-markør) → hjemtur skal køres.
|
||||||
|
|
||||||
|
Spil-adapter:
|
||||||
|
- `ADPool.collect(adEnv)` → `implements, tractors` fra `g_currentMission.vehicleSystem.vehicles` (gårdens), med
|
||||||
|
position, rolle, specs til `acceptFor`, hk og parkering/Connect-id.
|
||||||
|
- hk: `g_storeManager:getItemByXMLFilename(vehicle.configFileName).specs` → traktor `power`, redskab
|
||||||
|
`neededPower`; mangler de, bruges nil (→ tilladt).
|
||||||
|
- Reservationer: `ADPool.reserve(implementId, tractorId, owner)` / `release(owner)`; i hukommelsen, ryddes ved
|
||||||
|
genindlæsning (se Genindlæsning).
|
||||||
|
- Karantæne: redskab, der ikke kunne kobles på, springes over i 10 min (`ADPool.QUARANTINE_MS = 600000`).
|
||||||
|
|
||||||
|
### `adHitch.lua` (findes, v1.47.4 — udvides let)
|
||||||
|
|
||||||
|
Udfører kørslerne: `fetch` (kør til Connect + kobl på), `route` (trin-tur, afkobling ved redskabets parkering).
|
||||||
|
Ny: `ADHitch.returnHome(adEnv, tractor, onDone)` = `route({redskabets parkering, traktorens parkering})`; ved
|
||||||
|
parkeringen kobles puljeredskabet af (samme regel som i dag i ruter).
|
||||||
|
|
||||||
|
### Markarbejdet (`adFieldWork.lua`, `adFieldJobs.lua`)
|
||||||
|
|
||||||
|
- `dispatch`: som i dag først færdige kombinationer. Returnerer `pick`/`pickMany` intet (`noRig`/`allBusy`/
|
||||||
|
`cannotDo`), forsøges `ADPool.pairFor` for de manglende. Puljekombinationens assignment får `phase = "fetching"`,
|
||||||
|
`pool = {implementId, connectId, implementParkId, tractorParkId}`, nøgle = traktorens id.
|
||||||
|
- `follow`: fase `fetching` → når `ADHitch.fetch` melder ok: bredde tjekkes med redskabet på (`checkWidth`; for
|
||||||
|
bred → hjemtur + årsag `tooWide`), derefter samme vej som i dag (`startAd` til markens markør / påfyldning,
|
||||||
|
`phase = "driving"`). Fejl → hjemtur, karantæne, markens `retryAt` som ved `noRig`.
|
||||||
|
- `finishAssignment`: har traktoren et puljeredskab bag sig (`ADPool.isReturnDue`) → `ADHitch.returnHome` i
|
||||||
|
stedet for den almindelige parkeringstur; fase `returning`; assignment slettes, når hjemturen er færdig (eller
|
||||||
|
fejler — så med advarsel).
|
||||||
|
- Kø: `tick` gennemgår ventende marker i `ADPool.queueOrder`. `waitingSince` sættes, når en mark første gang ikke
|
||||||
|
fik en maskine, og nulstilles ved udsendelse. `DISPATCH_GAP_MS` (10 s) beholdes.
|
||||||
|
- Fanen viser faserne "henter X" og "sætter X af" og årsagerne `noPoolTractor`/`tooWeak`.
|
||||||
|
|
||||||
|
### Tømning ved høst
|
||||||
|
|
||||||
|
- Helper-dispatch (`role = "unloader"`, `helper = true`) bruger samme fallback: puljevogn + puljetraktor.
|
||||||
|
- Efter `fetch`: `startUnloader` som i dag. Assignmentet bliver hos marken, til høststadiet er slut (som i dag);
|
||||||
|
først da `returnHome`. Ingen frigivelse mellem læs.
|
||||||
|
|
||||||
|
### Marksilo-flowet (`adFieldSilos.lua`, `adFieldSiloPlanner.lua`)
|
||||||
|
|
||||||
|
- `collectVehicles` tilføjer puljekombinationer (puljevogn der kan bære varen + nærmeste puljetraktor) som
|
||||||
|
kandidater med `pool = {...}`; planneren behandler dem som vogne (position = vognens).
|
||||||
|
- `withoutHarvestReserve` tæller puljevogne med, så høsten går først.
|
||||||
|
- Lån med `pool`: `ADHitch.fetch` → AD "Hent og aflever" som i dag (`enableParkAtJobFinished`) → når AD er
|
||||||
|
inaktiv: `returnHome` → lånet slettes, når traktoren er hjemme. Vagten (120 s uden fremgang) starter efter
|
||||||
|
koblingen.
|
||||||
|
|
||||||
|
## Genindlæsning
|
||||||
|
|
||||||
|
Reservationer og assignments gemmes ikke (som i dag). Efter indlæsning ser en traktor med puljeredskab ud som en
|
||||||
|
færdig kombination; når markarbejdet eller marksilo-flowet afslutter et job med den, køres `returnHome`. Reglen
|
||||||
|
afhænger kun af, hvad der hænger bag traktoren, ikke af gemt tilstand. En traktor, som ingen af vores jobs bruger,
|
||||||
|
køres aldrig hjem af sig selv (spilleren kan have koblet et puljeredskab på for at køre selv).
|
||||||
|
|
||||||
|
## Fejl
|
||||||
|
|
||||||
|
| Situation | Handling |
|
||||||
|
|---|---|
|
||||||
|
| Kobling fejler (`noAttachable`, `stoppedAway`) | Traktor hjem, redskab i karantæne 10 min, marken prøver igen (andet redskab eller venter) |
|
||||||
|
| Redskab for bredt når koblet på | Hjemtur, årsag `tooWide` i fanen |
|
||||||
|
| Spilleren sætter sig i traktoren | Assignment afbrydes som i dag; reservationer frigives |
|
||||||
|
| Ingen traktor stærk nok | Årsag `tooWeak` med hk-tal: "ingen traktor med ≥180 hk ledig til 'Plov 1'" |
|
||||||
|
| Hjemtur fejler | Advarsel i loggen; traktor og redskab frigives (spilleren må ordne det) |
|
||||||
|
|
||||||
|
## Undtaget / uden for scope
|
||||||
|
|
||||||
|
- Flows (runs) — deres køretøjer er aldrig i puljen (uændret regel i `getRigs`).
|
||||||
|
- Vogne uden Connect-markør — dedikerede som i dag.
|
||||||
|
- Genbrug af et redskab direkte til næste mark uden at parkere (senere optimering).
|
||||||
|
- Flere redskaber pr. traktor (front + bag).
|
||||||
|
- Egen GUI-side for puljen.
|
||||||
|
|
||||||
|
## Etaper
|
||||||
|
|
||||||
|
1. **v1.48.0.0 — markarbejde med pulje:** `adPool.lua`, `returnHome`, dispatch-fallback, fase fetching/returning,
|
||||||
|
kø-rækkefølge, fane-tekster. In-game: savegame4, mark der skal harves/pløjes, redskab med parkering + Connect,
|
||||||
|
solo-traktor henter → arbejder → parkerer → hjem.
|
||||||
|
2. **v1.49.0.0 — tømmevogn ved høst fra puljen.**
|
||||||
|
3. **v1.50.0.0 — marksilo med puljevogne** (inkl. høst-reserve over puljevogne).
|
||||||
|
|
||||||
|
## Test
|
||||||
|
|
||||||
|
- `tests/test_adPool.lua`: puljeredskab ja/nej (koblet på, uden parkering, uden Connect), `roleOf` inkl.
|
||||||
|
`unloader`, `powerOk` (nok/for lidt/manglende data), `pairFor` (redskab nærmest marken, traktor nærmest redskabet,
|
||||||
|
reserveret og karantæne springes over, `tooWeak`/`noPoolTractor`/`noPoolImplement`), `queueOrder`,
|
||||||
|
`isReturnDue`.
|
||||||
|
- `tests/test_adHitch.lua`: `returnHome`-rutens trin.
|
||||||
|
- `tests/test_adFieldJobs.lua`: færdig kombination foretrækkes; fallback til pulje; kø længst ventende først.
|
||||||
|
- `tests/test_adFieldSiloPlanner.lua` (etape 3): puljekandidater og høst-reserve med puljevogne.
|
||||||
Reference in New Issue
Block a user