feat(gui): markens lagervalg viser markørnavn og afstand, marksilo/gæringssilo først, kun de 8 nærmeste (34 ens Farma-rækker) (v1.29.5.0)

This commit is contained in:
2026-09-26 17:37:10 +02:00
parent 1b0a2c152b
commit 77253b5d2b
6 changed files with 83 additions and 8 deletions
+33
View File
@@ -46,3 +46,36 @@ function ADFieldView.cropText(info, getText)
if info.kind == "bare" then return getText("spu_field_bare") end if info.kind == "bare" then return getText("spu_field_bare") end
return tostring(info.cropTitle or "-") return tostring(info.cropTitle or "-")
end 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
+30 -7
View File
@@ -185,6 +185,9 @@ function SmartPickupFrame:fillFieldRows(adEnv)
self:fillFleetRows(adEnv) self:fillFleetRows(adEnv)
end end
-- lagervalget viser de nærmeste siloer (plus valgte, marksiloer og gæringssiloer)
SmartPickupFrame.FIELD_STORE_ROWS = 8
function SmartPickupFrame:fillFieldDetail(adEnv, info) function SmartPickupFrame:fillFieldDetail(adEnv, info)
local i18n = self.i18n local i18n = self.i18n
local field = ADFieldJobs.getField(info.id) local field = ADFieldJobs.getField(info.id)
@@ -284,18 +287,38 @@ function SmartPickupFrame:fillFieldStoreRows(adEnv, info, field)
if info.kind == "mowable" and product == "silage" then 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 for _, building in ipairs(ADFieldJobs.getFermenters(adEnv, farmId, fillType, info.x, info.z)) do fermenterIds[building.id] = true end
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 for _, building in ipairs(ADBuildings.list(adEnv, farmId)) do
local isSilo = building.kind == "silo" and ADRunsController.canStoreAt(adEnv, building, {{fillType = fillType, isPallet = false}}) 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 if chosen[building.id] or isSilo or fermenterIds[building.id] then
count = count + 1 local distance = nil
local row = self:addRow(self.ingredientPrefab, {kind = "fieldStore", buildingId = building.id}) local node = building.placeable ~= nil and building.placeable.rootNode or nil
local suffix = fieldSilos[building.id] ~= nil and (" (" .. i18n:getText("spu_field_fieldSilo") .. ")") or "" if node ~= nil and info.x ~= nil then
if fermenterIds[building.id] then suffix = suffix .. " (" .. i18n:getText("spu_field_fermenter") .. ")" end local bx, _, bz = getWorldTranslation(node)
row:getDescendantByName("title"):setText(" " .. tostring(building.name) .. suffix) distance = math.sqrt((bx - info.x) ^ 2 + (bz - info.z) ^ 2)
row:getDescendantByName("option"):setState(chosen[building.id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false) 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
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 if count == 0 then
self:addTextRow(" " .. i18n:getText("spu_field_noStore")) self:addTextRow(" " .. i18n:getText("spu_field_noStore"))
elseif #field.plan.storeBuildingIds == 0 then elseif #field.plan.storeBuildingIds == 0 then
+1
View File
@@ -81,6 +81,7 @@
<text name="spu_field_mowWidth" text=" Slået med %.1f m — opsamling skal være mindst lige så bred"/> <text name="spu_field_mowWidth" text=" Slået med %.1f m — opsamling skal være mindst lige så bred"/>
<text name="spu_field_section_store" text="— Tving lager (ellers nærmeste silo med plads) —"/> <text name="spu_field_section_store" text="— Tving lager (ellers nærmeste silo med plads) —"/>
<text name="spu_field_fieldSilo" text="marksilo"/> <text name="spu_field_fieldSilo" text="marksilo"/>
<text name="spu_field_storeHidden" text="+ %d siloer længere væk vises ikke"/>
<text name="spu_field_noStore" text="ingen silo tager markens vare"/> <text name="spu_field_noStore" text="ingen silo tager markens vare"/>
<text name="spu_field_storeAuto" text="intet valgt: nærmeste silo med plads bruges"/> <text name="spu_field_storeAuto" text="intet valgt: nærmeste silo med plads bruges"/>
<text name="spu_field_fieldSiloNotEmptied" text="! Marksilo %s tømmes ikke hjem — lav et Ud fra bygning-flow"/> <text name="spu_field_fieldSiloNotEmptied" text="! Marksilo %s tømmes ikke hjem — lav et Ud fra bygning-flow"/>
+1
View File
@@ -81,6 +81,7 @@
<text name="spu_field_mowWidth" text=" Mowed at %.1f m — collecting must be at least as wide"/> <text name="spu_field_mowWidth" text=" Mowed at %.1f m — collecting must be at least as wide"/>
<text name="spu_field_section_store" text="— Force storage (else nearest silo with room) —"/> <text name="spu_field_section_store" text="— Force storage (else nearest silo with room) —"/>
<text name="spu_field_fieldSilo" text="field silo"/> <text name="spu_field_fieldSilo" text="field silo"/>
<text name="spu_field_storeHidden" text="+ %d silos further away not shown"/>
<text name="spu_field_noStore" text="no silo takes this field's goods"/> <text name="spu_field_noStore" text="no silo takes this field's goods"/>
<text name="spu_field_storeAuto" text="none chosen: nearest silo with room is used"/> <text name="spu_field_storeAuto" text="none chosen: nearest silo with room is used"/>
<text name="spu_field_fieldSiloNotEmptied" text="! Field silo %s is not emptied home — create an Out of building flow"/> <text name="spu_field_fieldSiloNotEmptied" text="! Field silo %s is not emptied home — create an Out of building flow"/>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?> <?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107"> <modDesc descVersion="107">
<author>masterdraco</author> <author>masterdraco</author>
<version>1.29.4.0</version> <version>1.29.5.0</version>
<title> <title>
<en>AD Smart Pickup</en> <en>AD Smart Pickup</en>
</title> </title>
+17
View File
@@ -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 bar", ADFieldView.cropText({kind = "bare"}, T), "bar jord")
check("FVcrop afgrøde", ADFieldView.cropText({kind = "harvest", cropTitle = "Majs"}, T), "Majs") 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")) print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1) os.exit(failures == 0 and 0 or 1)