From 77253b5d2be42bdb29d7f4c31a5d0af83e628e3e Mon Sep 17 00:00:00 2001 From: masterdraco Date: Sat, 26 Sep 2026 17:37:10 +0200 Subject: [PATCH] =?UTF-8?q?feat(gui):=20markens=20lagervalg=20viser=20mark?= =?UTF-8?q?=C3=B8rnavn=20og=20afstand,=20marksilo/g=C3=A6ringssilo=20f?= =?UTF-8?q?=C3=B8rst,=20kun=20de=208=20n=C3=A6rmeste=20(34=20ens=20Farma-r?= =?UTF-8?q?=C3=A6kker)=20(v1.29.5.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FS25_ADSmartPickup/adFieldView.lua | 33 +++++++++++++++++ .../gui/SmartPickupFieldTab.lua | 37 +++++++++++++++---- FS25_ADSmartPickup/l10n/l10n_da.xml | 1 + FS25_ADSmartPickup/l10n/l10n_en.xml | 1 + FS25_ADSmartPickup/modDesc.xml | 2 +- tests/test_adFieldView.lua | 17 +++++++++ 6 files changed, 83 insertions(+), 8 deletions(-) diff --git a/FS25_ADSmartPickup/adFieldView.lua b/FS25_ADSmartPickup/adFieldView.lua index 650ee2a..8950437 100644 --- a/FS25_ADSmartPickup/adFieldView.lua +++ b/FS25_ADSmartPickup/adFieldView.lua @@ -46,3 +46,36 @@ function ADFieldView.cropText(info, getText) if info.kind == "bare" then return getText("spu_field_bare") end return tostring(info.cropTitle or "-") end + +-- Lagervalget for en mark: marksilo først, så gæringssiloer, så efter afstand. Valgte, marksiloer og +-- gæringssiloer vises altid; af resten kun de `limit` nærmeste (34 ens "Farma 500"-rækker var ulæselige). +-- entries = {{id, distance, fieldSilo, fermenter, chosen}}. +function ADFieldView.storeRows(entries, limit) + local sorted = {} + for _, entry in ipairs(entries or {}) do table.insert(sorted, entry) end + local function rank(e) return e.fieldSilo and 0 or (e.fermenter and 1 or 2) end + table.sort(sorted, function(a, b) + if rank(a) ~= rank(b) then return rank(a) < rank(b) end + if (a.distance or math.huge) ~= (b.distance or math.huge) then return (a.distance or math.huge) < (b.distance or math.huge) end + return tostring(a.id) < tostring(b.id) + end) + local rows, others, hidden = {}, 0, 0 + for _, entry in ipairs(sorted) do + if entry.chosen or entry.fieldSilo or entry.fermenter then + table.insert(rows, entry) + elseif others < limit then + others = others + 1 + table.insert(rows, entry) + else + hidden = hidden + 1 + end + end + return rows, hidden +end + +-- "90 m" / "1,4 km" +function ADFieldView.distanceText(meters) + if meters == nil then return "?" end + if meters < 1000 then return string.format("%d m", math.floor(meters + 0.5)) end + return (string.gsub(string.format("%.1f km", meters / 1000), "%.", ",")) +end diff --git a/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua b/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua index f45c593..c4d8eef 100644 --- a/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua +++ b/FS25_ADSmartPickup/gui/SmartPickupFieldTab.lua @@ -185,6 +185,9 @@ function SmartPickupFrame:fillFieldRows(adEnv) self:fillFleetRows(adEnv) end +-- lagervalget viser de nærmeste siloer (plus valgte, marksiloer og gæringssiloer) +SmartPickupFrame.FIELD_STORE_ROWS = 8 + function SmartPickupFrame:fillFieldDetail(adEnv, info) local i18n = self.i18n local field = ADFieldJobs.getField(info.id) @@ -284,18 +287,38 @@ function SmartPickupFrame:fillFieldStoreRows(adEnv, info, field) if info.kind == "mowable" and product == "silage" then for _, building in ipairs(ADFieldJobs.getFermenters(adEnv, farmId, fillType, info.x, info.z)) do fermenterIds[building.id] = true end end - local count = 0 + -- kandidater med markørnavn og afstand til marken (34 ens "Farma 500 + Obi 1000" kan ellers ikke skelnes) + local entries = {} for _, building in ipairs(ADBuildings.list(adEnv, farmId)) do local isSilo = building.kind == "silo" and ADRunsController.canStoreAt(adEnv, building, {{fillType = fillType, isPallet = false}}) if chosen[building.id] or isSilo or fermenterIds[building.id] then - count = count + 1 - local row = self:addRow(self.ingredientPrefab, {kind = "fieldStore", buildingId = building.id}) - local suffix = fieldSilos[building.id] ~= nil and (" (" .. i18n:getText("spu_field_fieldSilo") .. ")") or "" - if fermenterIds[building.id] then suffix = suffix .. " (" .. i18n:getText("spu_field_fermenter") .. ")" end - row:getDescendantByName("title"):setText(" " .. tostring(building.name) .. suffix) - row:getDescendantByName("option"):setState(chosen[building.id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false) + local distance = nil + local node = building.placeable ~= nil and building.placeable.rootNode or nil + if node ~= nil and info.x ~= nil then + local bx, _, bz = getWorldTranslation(node) + distance = math.sqrt((bx - info.x) ^ 2 + (bz - info.z) ^ 2) + end + table.insert(entries, {id = building.id, building = building, distance = distance, chosen = chosen[building.id] == true, + fieldSilo = fieldSilos[building.id] ~= nil, fermenter = fermenterIds[building.id] == true}) end end + local storeRows, hiddenStores = ADFieldView.storeRows(entries, SmartPickupFrame.FIELD_STORE_ROWS) + local count = #storeRows + for _, entry in ipairs(storeRows) do + local building = entry.building + local row = self:addRow(self.ingredientPrefab, {kind = "fieldStore", buildingId = building.id}) + local markers = ADBuildings.getMarkers ~= nil and ADBuildings.getMarkers(building, "unload") or {} + -- det der skelner rækkerne først (rækken afkorter bagfra): markør, afstand, art — så bygningens navn + local label = (markers[1] ~= nil and tostring(markers[1].name) or tostring(building.name)) .. ", " .. ADFieldView.distanceText(entry.distance) + if entry.fieldSilo then label = label .. " (" .. i18n:getText("spu_field_fieldSilo") .. ")" end + if entry.fermenter then label = label .. " (" .. i18n:getText("spu_field_fermenter") .. ")" end + if markers[1] ~= nil then label = label .. " — " .. tostring(building.name) end + row:getDescendantByName("title"):setText(" " .. label) + row:getDescendantByName("option"):setState(entry.chosen and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false) + end + if hiddenStores > 0 then + self:addTextRow(" " .. string.format(i18n:getText("spu_field_storeHidden"), hiddenStores)) + end if count == 0 then self:addTextRow(" " .. i18n:getText("spu_field_noStore")) elseif #field.plan.storeBuildingIds == 0 then diff --git a/FS25_ADSmartPickup/l10n/l10n_da.xml b/FS25_ADSmartPickup/l10n/l10n_da.xml index c0f1b52..03c4caf 100644 --- a/FS25_ADSmartPickup/l10n/l10n_da.xml +++ b/FS25_ADSmartPickup/l10n/l10n_da.xml @@ -81,6 +81,7 @@ + diff --git a/FS25_ADSmartPickup/l10n/l10n_en.xml b/FS25_ADSmartPickup/l10n/l10n_en.xml index 1a0f67f..38861ec 100644 --- a/FS25_ADSmartPickup/l10n/l10n_en.xml +++ b/FS25_ADSmartPickup/l10n/l10n_en.xml @@ -81,6 +81,7 @@ + diff --git a/FS25_ADSmartPickup/modDesc.xml b/FS25_ADSmartPickup/modDesc.xml index c8db5ba..2d85c78 100644 --- a/FS25_ADSmartPickup/modDesc.xml +++ b/FS25_ADSmartPickup/modDesc.xml @@ -1,7 +1,7 @@ masterdraco - 1.29.4.0 + 1.29.5.0 <en>AD Smart Pickup</en> diff --git a/tests/test_adFieldView.lua b/tests/test_adFieldView.lua index d677f26..b41d9ff 100644 --- a/tests/test_adFieldView.lua +++ b/tests/test_adFieldView.lua @@ -45,5 +45,22 @@ check("FVcrop stub", ADFieldView.cropText({kind = "bare", stubbleOf = "Hvede", c check("FVcrop bar", ADFieldView.cropText({kind = "bare"}, T), "bar jord") check("FVcrop afgrøde", ADFieldView.cropText({kind = "harvest", cropTitle = "Majs"}, T), "Majs") +-- FVstore: marksilo først, gæringssilo, så afstand; valgte vises altid; kun de nærmeste af resten +local stores = { + {id = "fjern", distance = 3000}, + {id = "nær", distance = 200}, + {id = "mark", distance = 90, fieldSilo = true}, + {id = "valgt", distance = 5000, chosen = true}, + {id = "gær", distance = 800, fermenter = true}, + {id = "midt", distance = 1200}, +} +local storeRows, hiddenStores = ADFieldView.storeRows(stores, 2) +local order = {} +for _, e in ipairs(storeRows) do table.insert(order, e.id) end +check("FVstore rækkefølge", table.concat(order, ","), "mark,gær,nær,midt,valgt") +check("FVstore skjulte", hiddenStores, 1) +check("FVstore meter", ADFieldView.distanceText(90.4), "90 m") +check("FVstore km", ADFieldView.distanceText(1420), "1,4 km") + print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) os.exit(failures == 0 and 0 or 1)