feat(gui): flow-tavle — faner Flows/Lagre, én række pr. flow, Fra/Til som bygninger med automatisk markør (v1.13.0.0)
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
-- Smart Pickup — fanen Flows
|
||||
-- Tavle øverst: én tekstrække pr. flow (Vare · Fra → Til · Regel · Traktorer · Status), det valgte
|
||||
-- markeret med ">". Under tavlen: detail-blok for det valgte flow — Retning, Fra/Til som BYGNINGER
|
||||
-- (markøren findes automatisk), Varer, Regler, Vent ved, Traktorer, Status — og Wait-puljerne.
|
||||
-- Funktionerne lægges på SmartPickupFrame (indlæses efter SmartPickupFrame.lua).
|
||||
|
||||
-- ---- tavlen ----
|
||||
|
||||
local function joinOr(list, empty)
|
||||
if #list == 0 then return empty end
|
||||
return table.concat(list, " + ")
|
||||
end
|
||||
|
||||
-- "Mælk · Kostald 1 + Kostald 2 → salg · pris ≥ 90 %, lager > 80 % · Virtus · kører (1/1) — SUGAR 78 % af top"
|
||||
function SmartPickupFrame:describeFlow(adEnv, run, isSelected)
|
||||
local row = ADRunsController.getFlowRow(adEnv, run)
|
||||
local i18n = self.i18n
|
||||
local products
|
||||
if row.productAuto then
|
||||
products = i18n:getText("spu_flow_needBased")
|
||||
else
|
||||
local titles = {}
|
||||
for _, name in ipairs(row.productNames) do
|
||||
local index = g_fillTypeManager:getFillTypeIndexByName(name)
|
||||
local title = index ~= nil and g_fillTypeManager.getFillTypeTitleByIndex ~= nil and g_fillTypeManager:getFillTypeTitleByIndex(index) or name
|
||||
table.insert(titles, tostring(title))
|
||||
end
|
||||
products = joinOr(titles, i18n:getText("spu_flow_noProducts"))
|
||||
end
|
||||
local missing = {}
|
||||
for _, name in ipairs(row.missing) do missing[name] = true end
|
||||
local function mark(names)
|
||||
local out = {}
|
||||
for _, name in ipairs(names) do table.insert(out, missing[name] and (name .. " !") or name) end
|
||||
return out
|
||||
end
|
||||
local from, to
|
||||
if row.kind == "outbound" then
|
||||
from = joinOr(mark(row.fromNames), i18n:getText("spu_flow_noSource"))
|
||||
local seen, policies = {}, {}
|
||||
for _, policy in ipairs(row.policies) do
|
||||
if not seen[policy] then seen[policy] = true; table.insert(policies, i18n:getText("spu_policy_" .. policy)) end
|
||||
end
|
||||
to = joinOr(policies, i18n:getText("spu_flow_noProducts"))
|
||||
else
|
||||
from = i18n:getText("spu_from_allSilos")
|
||||
to = joinOr(mark(row.toNames), i18n:getText("spu_flow_noTarget"))
|
||||
end
|
||||
local rule
|
||||
if row.kind == "outbound" then
|
||||
rule = string.format(i18n:getText("spu_flow_ruleOut"), row.sellAtPercent or 90, row.storeAbovePercent or 80)
|
||||
if row.collectRound then rule = rule .. ", " .. i18n:getText("spu_flow_round") end
|
||||
else
|
||||
rule = row.loops ~= nil and row.loops > 0 and string.format(i18n:getText("spu_flow_ruleInLoops"), row.loops) or i18n:getText("spu_flow_ruleIn")
|
||||
end
|
||||
local vehicles = joinOr(row.vehicleNames, i18n:getText("spu_flow_noVehicle"))
|
||||
local status = row.running > 0 and string.format(i18n:getText("spu_status_running"), row.running, row.total) or string.format(i18n:getText("spu_status_stopped"), row.total)
|
||||
if row.warning ~= nil then
|
||||
status = status .. " — !! " .. row.warning
|
||||
elseif row.reason ~= nil then
|
||||
status = status .. " — " .. row.reason
|
||||
end
|
||||
local prefix = isSelected and "> " or " "
|
||||
return string.format("%s%s: %s · %s → %s · %s · %s · %s", prefix, run.name, products, from, to, rule, vehicles, status)
|
||||
end
|
||||
|
||||
-- Tavlen klones bagest og flyttes derefter forrest i layoutet (foran de faste rækker).
|
||||
function SmartPickupFrame:fillBoardRows(adEnv)
|
||||
self.boardRows = {}
|
||||
local rows = {}
|
||||
local header = self:addTextRow(self.i18n:getText("spu_section_flows"))
|
||||
table.insert(rows, header.parent)
|
||||
for _, run in ipairs(ADRunsController.store.runs) do
|
||||
local title = self:addTextRow(self:describeFlow(adEnv, run, run.id == self.selectedRunId))
|
||||
table.insert(rows, title.parent)
|
||||
table.insert(self.boardRows, {run = run, title = title})
|
||||
end
|
||||
if #ADRunsController.store.runs == 0 then
|
||||
table.insert(rows, self:addTextRow(self.i18n:getText("spu_noRuns")).parent)
|
||||
end
|
||||
local elements = self.boxLayout.elements
|
||||
for index = #rows, 1, -1 do
|
||||
for position = #elements, 1, -1 do
|
||||
if elements[position] == rows[index] then
|
||||
table.remove(elements, position)
|
||||
break
|
||||
end
|
||||
end
|
||||
table.insert(elements, 1, rows[index])
|
||||
end
|
||||
end
|
||||
|
||||
function SmartPickupFrame:refreshBoard(adEnv)
|
||||
for _, entry in ipairs(self.boardRows or {}) do
|
||||
if ADRuns.getRun(ADRunsController.store, entry.run.id) ~= nil then
|
||||
entry.title:setText(self:describeFlow(adEnv, ADRuns.getRun(ADRunsController.store, entry.run.id), entry.run.id == self.selectedRunId))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ---- detail-blok ----
|
||||
|
||||
-- "Kostald 1 (stald) — markør 'cow 1 milk' 12 m" / "… — INGEN MARKØR inden for 40 m"
|
||||
function SmartPickupFrame:describeBuilding(building, role)
|
||||
local marker = role == "load" and building.loadMarker or building.unloadMarker
|
||||
local kindText = self.i18n:getText("spu_source_kind_" .. tostring(building.kind))
|
||||
if marker == nil then
|
||||
return string.format(" %s (%s) — %s", building.name, kindText, self.i18n:getText("spu_noMarker"))
|
||||
end
|
||||
return string.format(" %s (%s) — %s", building.name, kindText, string.format(self.i18n:getText("spu_markerAt"), marker.name, marker.distance))
|
||||
end
|
||||
|
||||
-- Afkrydsning pr. bygning: kilder (udkørsel, role "load") eller mål (forsyning, role "unload").
|
||||
function SmartPickupFrame:fillBuildingRows(adEnv, run, role)
|
||||
if ADBuildings == nil then
|
||||
self:addTextRow(self.i18n:getText("spu_status_noAd"))
|
||||
return
|
||||
end
|
||||
local chosen = {}
|
||||
local ids = role == "load" and run.sourceBuildingIds or run.targetBuildingIds
|
||||
for _, id in ipairs(ids or {}) do chosen[id] = true end
|
||||
local count = 0
|
||||
for _, building in ipairs(ADBuildings.list(adEnv, g_currentMission:getFarmId())) do
|
||||
local fits = (role == "load" and building.canBeSource) or (role == "unload" and building.canBeTarget)
|
||||
if fits then
|
||||
count = count + 1
|
||||
local row = self:addRow(self.ingredientPrefab, {kind = role == "load" and "sourceBuilding" or "targetBuilding", buildingId = building.id})
|
||||
row:getDescendantByName("title"):setText(self:describeBuilding(building, role))
|
||||
row:getDescendantByName("option"):setState(chosen[building.id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false)
|
||||
end
|
||||
end
|
||||
-- valgte bygninger der ikke længere findes (solgt)
|
||||
for _, id in ipairs(ids or {}) do
|
||||
if ADBuildings.find(adEnv, g_currentMission:getFarmId(), id) == nil then
|
||||
local row = self:addRow(self.ingredientPrefab, {kind = role == "load" and "sourceBuilding" or "targetBuilding", buildingId = id})
|
||||
row:getDescendantByName("title"):setText(string.format(" %s — %s", tostring(id), self.i18n:getText("spu_buildingGone")))
|
||||
row:getDescendantByName("option"):setState(SmartPickupFrame.STATE_ON, false)
|
||||
end
|
||||
end
|
||||
if count == 0 then
|
||||
self:addTextRow(self.i18n:getText("spu_noBuildings"))
|
||||
end
|
||||
end
|
||||
|
||||
function SmartPickupFrame:rebuildFlowDetail(adEnv, run)
|
||||
ADRunsController.resolveMarkers(adEnv, run)
|
||||
run = self:getRun()
|
||||
local isOut = run.kind == "outbound"
|
||||
self:addTextRow(string.format(self.i18n:getText("spu_section_flow"), run.name))
|
||||
self.directionRowOption = self:addToggleRow("direction", self.i18n:getText("spu_direction"), {self.i18n:getText("spu_direction_in"), self.i18n:getText("spu_direction_out")}, isOut)
|
||||
if isOut then
|
||||
self:addTextRow(self.i18n:getText("spu_section_from"))
|
||||
self:fillBuildingRows(adEnv, run, "load")
|
||||
self:addTextRow(self.i18n:getText("spu_section_products"))
|
||||
self:fillProductRows(adEnv, run)
|
||||
self:addTextRow(self.i18n:getText("spu_section_rules"))
|
||||
self.sellAtOption:setState(SmartPickupFrame.getStepIndex(self.sellAtSteps, run.sellAtPercent, ADRuns.DEFAULT_SELL_AT_PERCENT), false)
|
||||
self.storeAboveOption:setState(SmartPickupFrame.getStepIndex(self.storeAboveSteps, run.storeAbovePercent, ADRuns.DEFAULT_STORE_ABOVE_PERCENT), false)
|
||||
self.collectRoundRowOption = self:addToggleRow("collectRound", self.i18n:getText("spu_collectRound"), {self.i18n:getText("ui_no"), self.i18n:getText("ui_yes")}, run.collectRound == true)
|
||||
self:fillOutboundStatusRows(adEnv, run)
|
||||
else
|
||||
self:addTextRow(self.i18n:getText("spu_section_to"))
|
||||
self:fillBuildingRows(adEnv, run, "unload")
|
||||
self:addTextRow(self.i18n:getText("spu_section_targets"))
|
||||
self.ingredientModeRowOption = self:addToggleRow("ingredientMode", self.i18n:getText("spu_ingredientMode"), {self.i18n:getText("spu_mode_auto"), self.i18n:getText("spu_mode_manual")}, run.ingredientMode == "manual")
|
||||
self:fillIngredientRows(adEnv, run)
|
||||
self:fillNeedsRows(adEnv, run)
|
||||
self:addTextRow(self.i18n:getText("spu_section_rules"))
|
||||
self.loopsOption:setState(run.loops + 1, false)
|
||||
self.returnBelowOption:setState(self:getReturnBelowIndex(run), false)
|
||||
end
|
||||
end
|
||||
|
||||
-- ---- callbacks ----
|
||||
|
||||
function SmartPickupFrame:onClickDirection(state)
|
||||
self:safe(function(frame)
|
||||
local run = frame:getRun()
|
||||
if run == nil then return end
|
||||
ADRunsController.updateRun(run.id, {kind = state == SmartPickupFrame.STATE_ON and "outbound" or "supply"})
|
||||
frame:requestRebuild()
|
||||
end)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickBuilding(state, element)
|
||||
self:safe(function(frame)
|
||||
local run, data = frame:getRun(), frame.rowData[element]
|
||||
if run == nil or data == nil then return end
|
||||
if data.kind == "sourceBuilding" then
|
||||
ADRunsController.store = ADRuns.toggleSourceBuilding(ADRunsController.store, run.id, data.buildingId)
|
||||
else
|
||||
ADRunsController.store = ADRuns.toggleTargetBuilding(ADRunsController.store, run.id, data.buildingId)
|
||||
end
|
||||
local updated = ADRuns.getRun(ADRunsController.store, run.id)
|
||||
Logging.info(SmartPickupFrame.LOG_PREFIX .. "run '%s': %s=%s", tostring(run.name), data.kind == "sourceBuilding" and "sourceBuildings" or "targetBuildings", table.concat(data.kind == "sourceBuilding" and updated.sourceBuildingIds or updated.targetBuildingIds, " "))
|
||||
ADRunsController.resolveMarkers(frame.getAdEnv(), updated)
|
||||
frame:requestRebuild()
|
||||
end)
|
||||
end
|
||||
Reference in New Issue
Block a user