docs: plan for flow-tavle
This commit is contained in:
@@ -0,0 +1,78 @@
|
|||||||
|
# Flow-tavle — implementeringsplan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Én tavle med ét flow pr. række (Vare · Fra · Til · Regel · Traktorer · Status); Fra/Til vælges som bygninger, markører findes automatisk. Faner: Flows · Lagre.
|
||||||
|
|
||||||
|
**Architecture:** Ny spil-adapter `adBuildings.lua` (bygninger + markør-opslag + cache). Modellen får bygnings-id-lister; controlleren udleder waypoint-lister fra dem (`resolveMarkers`) så planlægger/hooks er uændrede. GUI omskrives: `SmartPickupFrame.lua` (faner, tavle, fælles), `SmartPickupFlowTab.lua` (detail-blok), `SmartPickupStorageTab.lua` (uændret).
|
||||||
|
|
||||||
|
**Tech Stack:** FS25 Lua, AutoDrive-globaler via `FS25_AutoDrive`, luajit-tests.
|
||||||
|
|
||||||
|
**Spec:** `docs/superpowers/specs/2026-09-23-flow-tavle-design.md`
|
||||||
|
|
||||||
|
## Global Constraints
|
||||||
|
|
||||||
|
- Motoren (adOutbound, adOutboundPlanner, adSupplyPlanner, adUnloadWait, adSmartPickup-hooks) røres ikke.
|
||||||
|
- Byg kun når alle tests er grønne (`for t in tests/test_*.lua; do luajit $t|tail -1; done`), derefter zip → `~/FS25-data/mods/` → commit → push gitea main.
|
||||||
|
- Version 1.13.0.0. XML-version 3; v1/v2 læses.
|
||||||
|
- Wait-markører er aldrig bygningsmarkører. Siloers læssemarkør = strengt opslag; alt andet = nærmeste ≤ 40 m.
|
||||||
|
|
||||||
|
## Review Focus
|
||||||
|
|
||||||
|
1. Run med bygning der er solgt siden sidst: rækken viser "(mangler)", Start afviser med noMarker, intet crash. (Task 3 test)
|
||||||
|
2. v2-fil med markør der ikke kan oversættes til en bygning: markøren beholdes rå og virker som før. (Task 2 test)
|
||||||
|
3. To bygninger med markører inden for 40 m af hinanden (silo-rækker): hver silo får sin egen markør (strengt opslag). (Task 1 test)
|
||||||
|
4. Forsynings-run: Fra vises som "alle siloer" og sources-listen røres ikke. (Task 3 test)
|
||||||
|
5. Fanen rebuild'es mens et run kører: Start/Stop-knappen og status følger `isRunning`. (in-game)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: adBuildings
|
||||||
|
|
||||||
|
**Files:** Create `FS25_ADSmartPickup/adBuildings.lua`; Test `tests/test_adBuildings.lua`.
|
||||||
|
|
||||||
|
**Produces:**
|
||||||
|
```lua
|
||||||
|
ADBuildings.MAX_MARKER_DISTANCE = 40; ADBuildings.CACHE_MS = 1000
|
||||||
|
ADBuildings.list(adEnv, farmId) -- {building...} sorteret kind, navn (cachet)
|
||||||
|
ADBuildings.find(adEnv, farmId, id) -- building | nil
|
||||||
|
ADBuildings.byMarker(adEnv, farmId, wayPointId, role) -- role "load"|"unload": building hvis markøren er dens markør, ellers nil
|
||||||
|
ADBuildings.getId(placeable) -- uniqueId eller "pos:x:z"
|
||||||
|
ADBuildings.invalidate()
|
||||||
|
building = {id, name, kind, placeable, loadMarker={id,name,distance}|nil, unloadMarker=…|nil, canBeSource, canBeTarget, canSell}
|
||||||
|
```
|
||||||
|
Kilder til bygninger: `g_currentMission.placeableSystem.placeables` (ejet af farm eller sell) — kind: factory (spec_productionPoint), silo (spec_silo), husbandry (getHusbandryFillLevel), objectStorage (spec_objectStorage), sell (ADPrices.isSellingStation på placeable.spec_sellingPoint / unloadingStation via storageSystem). Læssetriggere: `productionPoint.loadingStation.loadTriggers`, `spec_silo.loadingStation.loadTriggers`, husbandry: alle loadingStations i storageSystem med owningPlaceable == placeable. Aflæsningstriggere: unloadingStations med owningPlaceable == placeable. Objektlager/pallespawner: rootNode/spawnPlaces[1].startNode.
|
||||||
|
Markørvalg: nærmeste markør (ikke Wait) til en trigger-node ≤ 40 m; for silo-load: kun markører hvor `ADSmartPickup.getLoadStationAtWayPointId(marker.id)` == siloens station.
|
||||||
|
|
||||||
|
- [ ] Tests B1–B7 (kind, markører, silo strengt, Wait udelukket, byMarker, id-fallback, cache-invalidering) → RED → implementér → GREEN → commit `feat: adBuildings`.
|
||||||
|
|
||||||
|
### Task 2: Model v3
|
||||||
|
|
||||||
|
**Files:** Modify `adRuns.lua`, `adRunsStorage.lua`; Test `tests/test_adRuns.lua`.
|
||||||
|
|
||||||
|
**Produces:** run-felter `sourceBuildingIds`, `targetBuildingIds` (lister af strenge); `ADRuns.toggleSourceBuilding/toggleTargetBuilding(store, runId, id)`; XML v3 `#sourceBuildings`/`#targetBuildings` (mellemrumsadskilte). `ADRuns.XML_VERSION = 3`. Migration sker i controlleren (Task 3), ikke i modellen.
|
||||||
|
|
||||||
|
- [ ] Tests R-v3 → RED → implementér → GREEN → commit.
|
||||||
|
|
||||||
|
### Task 3: Controller — resolve + migration + validering
|
||||||
|
|
||||||
|
**Files:** Modify `adRunsController.lua`; Test `tests/test_adRunsController.lua`.
|
||||||
|
|
||||||
|
**Produces:**
|
||||||
|
```lua
|
||||||
|
ADRunsController.resolveMarkers(adEnv, run) -- udfylder run.sourceWayPointIds (outbound) / targetWayPointIds (supply) fra bygninger; rå markører (uden bygning) bevares; returnerer {missing = {buildingName...}}
|
||||||
|
ADRunsController.migrateBuildings(adEnv) -- ved load: markører → bygnings-id via byMarker; logger
|
||||||
|
ADRunsController.getFlowRow(adEnv, run) -- {product, from, to, rule, vehicles, status, warning} tekster til tavlen
|
||||||
|
validateVehicle: ny grund "noMarker" når en valgt bygning mangler markør
|
||||||
|
```
|
||||||
|
Start/plan: `startRun` og `ADOutbound.buildPlanInput` kalder resolveMarkers først (buildPlanInput via ADRunsController.getRunForVehicle → resolve i getRunForVehicle? nej: i `ADSmartPickup.choosePickup`/`ADOutbound.choosePickup` kaldes `ADRunsController.resolveMarkers(adEnv, run)` én gang pr. plan).
|
||||||
|
|
||||||
|
- [ ] Tests C-flow → RED → implementér → GREEN → commit.
|
||||||
|
|
||||||
|
### Task 4: GUI — Flows-fane
|
||||||
|
|
||||||
|
**Files:** Rewrite `gui/SmartPickupFrame.lua` (faner Flows/Lagre, tavle, fælles rækker, knapper), Create `gui/SmartPickupFlowTab.lua` (detail-blok, callbacks), delete `SmartPickupSupplyTab.lua`/`SmartPickupOutboundTab.lua` (indhold flyttes), Modify `gui/SmartPickupFrame.xml` (statiske rækker: runOption "Flow", waitPool, loops, returnBelow, sellAt, storeAbove; prefabs som i dag), l10n da/en (`spu_tab_flows`, `spu_flow_*`, `spu_direction_in/out`, `spu_from_allSilos`, `spu_noMarker`, `spu_reason_noMarker`, `spu_section_*`), `adSmartPickup.lua` (source()).
|
||||||
|
|
||||||
|
- [ ] Implementér; syntaks- og definitions-tjek; in-game.
|
||||||
|
|
||||||
|
### Task 5: README, version, byg, deploy, push, memory.
|
||||||
Reference in New Issue
Block a user