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:
@@ -861,7 +861,7 @@ function ADRunsController.startRun(adEnv, runId)
|
||||
local vehicle = vehiclesById[vehicleId]
|
||||
if vehicle ~= nil then
|
||||
local validation = ADRunsController.validateVehicle(adEnv, run, vehicle)
|
||||
local result = {vehicle = vehicle, ok = validation.ok, reason = validation.reason}
|
||||
local result = {vehicle = vehicle, ok = validation.ok, reason = validation.reason, missingBuilding = validation.missingBuilding}
|
||||
if not validation.ok then
|
||||
Logging.info(ADRunsController.LOG_PREFIX .. "run '%s': '%s' sprunget over (%s)", tostring(run.name), tostring(vehicle:getName()), tostring(validation.reason))
|
||||
end
|
||||
|
||||
@@ -16,6 +16,7 @@ if ADSmartPickup.dir ~= nil and source ~= nil then
|
||||
source(ADSmartPickup.dir .. "gui/SmartPickupSupplyTab.lua")
|
||||
source(ADSmartPickup.dir .. "gui/SmartPickupOutboundTab.lua")
|
||||
source(ADSmartPickup.dir .. "gui/SmartPickupStorageTab.lua")
|
||||
source(ADSmartPickup.dir .. "gui/SmartPickupFlowTab.lua")
|
||||
end
|
||||
|
||||
-- Markøren er dér hvor trækkerens næse stopper; læssetriggeren ligger et
|
||||
|
||||
@@ -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
|
||||
@@ -10,10 +10,8 @@ SmartPickupFrame.REFRESH_INTERVAL_MS = 1000
|
||||
SmartPickupFrame.STATUS_OVERRIDE_TICKS = 6
|
||||
SmartPickupFrame.LOG_PREFIX = "ADSmartPickup: "
|
||||
SmartPickupFrame.STATE_OFF, SmartPickupFrame.STATE_ON = 1, 2
|
||||
SmartPickupFrame.TAB_OVERVIEW, SmartPickupFrame.TAB_SUPPLY, SmartPickupFrame.TAB_OUTBOUND, SmartPickupFrame.TAB_STORAGE = 1, 2, 3, 4
|
||||
SmartPickupFrame.TAB_NAMES = {"spu_tab_overview", "spu_tab_supply", "spu_tab_outbound", "spu_tab_storage"}
|
||||
-- Hver fane viser kun runs af sin egen slags; Oversigt og Lagre opretter forsynings-runs.
|
||||
SmartPickupFrame.TAB_KIND = {"supply", "supply", "outbound", "supply"}
|
||||
SmartPickupFrame.TAB_FLOWS, SmartPickupFrame.TAB_STORAGE = 1, 2
|
||||
SmartPickupFrame.TAB_NAMES = {"spu_tab_flows", "spu_tab_storage"}
|
||||
SmartPickupFrame.POLICIES = {"off", "store", "sell", "sellElseStore"}
|
||||
-- Afvisningsgrunde der handler om VOGNEN (ikke run'ets opsætning): traktoren kan ikke vælges.
|
||||
SmartPickupFrame.VEHICLE_BLOCKING_REASONS = {noTrailer = true, cannotCarry = true, needsAutoload = true}
|
||||
@@ -34,7 +32,7 @@ function SmartPickupFrame.new(i18n, getAdEnv)
|
||||
self.pendingRebuild = false
|
||||
self.frameOpen = false
|
||||
self.focusLost = false
|
||||
self.currentTab = SmartPickupFrame.TAB_OVERVIEW
|
||||
self.currentTab = SmartPickupFrame.TAB_FLOWS
|
||||
self.subCategoryTabs = {}
|
||||
self.backButtonInfo = {inputAction = InputAction.MENU_BACK}
|
||||
self.startButtonInfo = {inputAction = InputAction.MENU_ACTIVATE, text = i18n:getText("spu_button_start"), callback = function() self:onClickStartStop() end}
|
||||
@@ -121,9 +119,6 @@ function SmartPickupFrame.getStepIndex(steps, value, default)
|
||||
return index
|
||||
end
|
||||
|
||||
function SmartPickupFrame:getTabKind()
|
||||
return SmartPickupFrame.TAB_KIND[self.currentTab] or "supply"
|
||||
end
|
||||
|
||||
function SmartPickupFrame:getReturnBelowIndex(run)
|
||||
local index = 1
|
||||
@@ -246,13 +241,15 @@ function SmartPickupFrame:onClickTab(state)
|
||||
self:switchTab(state)
|
||||
end
|
||||
|
||||
-- De faste rækker hører til hver sin fane: Run + Wait-pulje er fælles, Varer/Ture/tærskel er
|
||||
-- Forsyning, Sælg fra/Kør til lager/Saml op er Udkørsel. Oversigt viser ingen.
|
||||
function SmartPickupFrame:setStaticRowsVisible(tab)
|
||||
local isSupply, isOutbound = tab == SmartPickupFrame.TAB_SUPPLY, tab == SmartPickupFrame.TAB_OUTBOUND
|
||||
-- De faste rækker: Flow-vælger + Wait-pulje for alle flows; Ture/kør hjem for forsyning; Sælg fra/
|
||||
-- Kør til lager for udkørsel. Fanen Lagre viser ingen.
|
||||
function SmartPickupFrame:setStaticRowsVisible(tab, run)
|
||||
local isFlows = tab == SmartPickupFrame.TAB_FLOWS
|
||||
local hasRun = isFlows and run ~= nil
|
||||
local isSupply, isOutbound = hasRun and run.kind ~= "outbound", hasRun and run.kind == "outbound"
|
||||
local visibility = {
|
||||
{self.runOption, isSupply or isOutbound},
|
||||
{self.waitPoolOption, isSupply or isOutbound},
|
||||
{self.runOption, isFlows},
|
||||
{self.waitPoolOption, hasRun},
|
||||
{self.loopsOption, isSupply}, {self.returnBelowOption, isSupply},
|
||||
{self.sellAtOption, isOutbound}, {self.storeAboveOption, isOutbound},
|
||||
}
|
||||
@@ -264,15 +261,8 @@ function SmartPickupFrame:setStaticRowsVisible(tab)
|
||||
end
|
||||
end
|
||||
|
||||
-- Run'et der vises: kun runs af fanens slags; skifter fanen, vælges fanens første run.
|
||||
function SmartPickupFrame:getRunsForTab()
|
||||
local kind, result = self:getTabKind(), {}
|
||||
for _, run in ipairs(ADRunsController.store.runs) do
|
||||
if (run.kind or "supply") == kind then
|
||||
table.insert(result, run)
|
||||
end
|
||||
end
|
||||
return result
|
||||
return ADRunsController.store.runs
|
||||
end
|
||||
|
||||
function SmartPickupFrame:getRun()
|
||||
@@ -298,7 +288,8 @@ function SmartPickupFrame:clearRows()
|
||||
self.overviewRows = {}
|
||||
self.productRows, self.outboundStatusRows = {}, {}
|
||||
self.storageRows = {}
|
||||
self.ingredientModeRowOption, self.collectRoundRowOption = nil, nil
|
||||
self.boardRows = {}
|
||||
self.ingredientModeRowOption, self.collectRoundRowOption, self.directionRowOption = nil, nil, nil
|
||||
end
|
||||
|
||||
-- Ja/Nej-række som klon af ingredientPrefab (faste BinaryOption-elementer fra XML'en viser kun
|
||||
@@ -351,14 +342,12 @@ end
|
||||
function SmartPickupFrame:rebuild()
|
||||
local adEnv = self.getAdEnv()
|
||||
local store = ADRunsController.store
|
||||
local tabRuns = self:getRunsForTab()
|
||||
local selected = self.selectedRunId ~= nil and ADRuns.getRun(store, self.selectedRunId) or nil
|
||||
if selected == nil or (selected.kind or "supply") ~= self:getTabKind() then
|
||||
self.selectedRunId = tabRuns[1] ~= nil and tabRuns[1].id or nil
|
||||
if self.selectedRunId == nil or ADRuns.getRun(store, self.selectedRunId) == nil then
|
||||
self.selectedRunId = store.runs[1] ~= nil and store.runs[1].id or nil
|
||||
end
|
||||
self:clearRows()
|
||||
local isOverview = self.currentTab == SmartPickupFrame.TAB_OVERVIEW
|
||||
self:setStaticRowsVisible(self.currentTab)
|
||||
local run = self:getRun()
|
||||
self:setStaticRowsVisible(self.currentTab, run)
|
||||
if self.currentTab == SmartPickupFrame.TAB_STORAGE then
|
||||
if adEnv ~= nil then
|
||||
self:fillStorageRows(adEnv)
|
||||
@@ -370,39 +359,26 @@ function SmartPickupFrame:rebuild()
|
||||
self:refreshLive()
|
||||
return
|
||||
end
|
||||
if isOverview then
|
||||
if adEnv ~= nil then
|
||||
self:fillOverviewRows(adEnv)
|
||||
end
|
||||
self:addTextRow(self.i18n:getText("spu_waitPools"))
|
||||
self:fillPoolRows(adEnv)
|
||||
self.statusRow = self:addTextRow("")
|
||||
self:colorRows()
|
||||
self.boxLayout:invalidateLayout()
|
||||
self:restoreFocusIfLost()
|
||||
self:refreshLive()
|
||||
return
|
||||
end
|
||||
self:fillRunOption(adEnv)
|
||||
local run = self:getRun()
|
||||
local hasRun = run ~= nil and adEnv ~= nil
|
||||
for _, element in ipairs({self.waitPoolOption, self.loopsOption, self.returnBelowOption, self.sellAtOption, self.storeAboveOption}) do
|
||||
if element ~= nil then
|
||||
element:setDisabled(not hasRun)
|
||||
end
|
||||
end
|
||||
if adEnv ~= nil then
|
||||
self:fillBoardRows(adEnv)
|
||||
end
|
||||
if hasRun then
|
||||
self:fillWaitPoolOption(adEnv, run)
|
||||
if self.currentTab == SmartPickupFrame.TAB_OUTBOUND then
|
||||
self:rebuildOutboundTab(adEnv, run)
|
||||
else
|
||||
self:rebuildSupplyTab(adEnv, run)
|
||||
end
|
||||
self:rebuildFlowDetail(adEnv, run)
|
||||
self:addTextRow(self.i18n:getText("spu_section_vehicles"))
|
||||
self:fillVehicleRows(adEnv, run)
|
||||
self:addTextRow(self.i18n:getText("spu_section_status"))
|
||||
end
|
||||
self.statusRow = self:addTextRow("")
|
||||
self:addTextRow(self.i18n:getText("spu_waitPools"))
|
||||
self:fillPoolRows(adEnv)
|
||||
self:colorRows()
|
||||
self.boxLayout:invalidateLayout()
|
||||
self:refreshLive()
|
||||
@@ -498,7 +474,11 @@ function SmartPickupFrame:describeVehicle(adEnv, run, vehicle, isInRun)
|
||||
if validation.ok then
|
||||
table.insert(parts, "OK")
|
||||
else
|
||||
table.insert(parts, "X " .. self.i18n:getText("spu_reason_" .. tostring(validation.reason)))
|
||||
local reason = self.i18n:getText("spu_reason_" .. tostring(validation.reason))
|
||||
if validation.reason == "noMarker" and validation.missingBuilding ~= nil then
|
||||
reason = string.format(reason, tostring(validation.missingBuilding))
|
||||
end
|
||||
table.insert(parts, "X " .. reason)
|
||||
end
|
||||
return table.concat(parts, " — ")
|
||||
end
|
||||
@@ -535,6 +515,7 @@ function SmartPickupFrame:syncOptionsFromModel(adEnv, run)
|
||||
if group == run.waitPoolGroup then poolIndex = index end
|
||||
end
|
||||
sync(self.waitPoolOption, poolIndex)
|
||||
sync(self.directionRowOption, run.kind == "outbound" and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF)
|
||||
if run.kind == "outbound" then
|
||||
sync(self.sellAtOption, SmartPickupFrame.getStepIndex(self.sellAtSteps, run.sellAtPercent, ADRuns.DEFAULT_SELL_AT_PERCENT))
|
||||
sync(self.storeAboveOption, SmartPickupFrame.getStepIndex(self.storeAboveSteps, run.storeAbovePercent, ADRuns.DEFAULT_STORE_ABOVE_PERCENT))
|
||||
@@ -588,74 +569,6 @@ function SmartPickupFrame:describeActivity(adEnv, vehicle)
|
||||
return string.format("%s: %s", label, string.format(self.i18n:getText("spu_activity_driving"), place))
|
||||
end
|
||||
|
||||
-- Rækkerne klones bagest og flyttes derefter forrest i layoutet.
|
||||
function SmartPickupFrame:fillOverviewRows(adEnv)
|
||||
local rows = {}
|
||||
local function add(text)
|
||||
local title = self:addTextRow(text)
|
||||
table.insert(rows, title.parent)
|
||||
return title
|
||||
end
|
||||
self.overviewRows = {}
|
||||
for _, run in ipairs(ADRunsController.store.runs) do
|
||||
local status = ADRunsController.getRunStatus(adEnv, run)
|
||||
local statusText = status.running > 0 and string.format(self.i18n:getText("spu_status_running"), status.running, status.total)
|
||||
or string.format(self.i18n:getText("spu_status_stopped"), status.total)
|
||||
local header = add(string.format("%s — %s", run.name, statusText))
|
||||
local entry = {run = run, header = header, vehicles = {}, targets = {}}
|
||||
for _, vehicleId in ipairs(run.vehicleIds) do
|
||||
local vehicle = ADRunsController.findVehicleById(adEnv, vehicleId)
|
||||
if vehicle ~= nil then
|
||||
table.insert(entry.vehicles, {vehicle = vehicle, title = add(" " .. self:describeActivity(adEnv, vehicle))})
|
||||
end
|
||||
end
|
||||
if run.kind == "outbound" then
|
||||
entry.outbound = add(" " .. self:describeOutboundOverview(adEnv, run))
|
||||
else
|
||||
for _, target in ipairs(ADRunsController.getTargetsLevels(adEnv, run)) do
|
||||
table.insert(entry.targets, {wayPointId = target.wayPointId, title = add(" " .. self:describeTargetLevels(target))})
|
||||
end
|
||||
end
|
||||
table.insert(self.overviewRows, entry)
|
||||
end
|
||||
-- forrest i layoutet: fjern de klonede rækker bagfra og sæt dem ind i rækkefølge først
|
||||
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
|
||||
|
||||
-- Opdateres hvert sekund uden genopbygning (kun tekster).
|
||||
function SmartPickupFrame:refreshOverview(adEnv)
|
||||
for _, entry in ipairs(self.overviewRows or {}) do
|
||||
local status = ADRunsController.getRunStatus(adEnv, entry.run)
|
||||
local statusText = status.running > 0 and string.format(self.i18n:getText("spu_status_running"), status.running, status.total)
|
||||
or string.format(self.i18n:getText("spu_status_stopped"), status.total)
|
||||
entry.header:setText(string.format("%s — %s", entry.run.name, statusText))
|
||||
for _, item in ipairs(entry.vehicles) do
|
||||
item.title:setText(" " .. self:describeActivity(adEnv, item.vehicle))
|
||||
end
|
||||
if entry.outbound ~= nil then
|
||||
entry.outbound:setText(" " .. self:describeOutboundOverview(adEnv, entry.run))
|
||||
end
|
||||
local byId = {}
|
||||
for _, target in ipairs(ADRunsController.getTargetsLevels(adEnv, entry.run)) do
|
||||
byId[target.wayPointId] = target
|
||||
end
|
||||
for _, item in ipairs(entry.targets) do
|
||||
if byId[item.wayPointId] ~= nil then
|
||||
item.title:setText(" " .. self:describeTargetLevels(byId[item.wayPointId]))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fillPoolRows(adEnv)
|
||||
if adEnv == nil then
|
||||
return
|
||||
@@ -697,7 +610,9 @@ function SmartPickupFrame:refreshLive()
|
||||
self:setStatusText(self.i18n:getText("spu_status_noAd"))
|
||||
return
|
||||
end
|
||||
self:refreshOverview(adEnv)
|
||||
if self.currentTab == SmartPickupFrame.TAB_FLOWS then
|
||||
self:refreshBoard(adEnv)
|
||||
end
|
||||
self:refreshStorageRows(adEnv)
|
||||
local isRunning = false
|
||||
if run ~= nil then
|
||||
@@ -754,6 +669,10 @@ function SmartPickupFrame:onClickIngredient(state, element)
|
||||
return self:onClickIngredientMode(state)
|
||||
elseif data ~= nil and data.kind == "collectRound" then
|
||||
return self:onClickCollectRound(state)
|
||||
elseif data ~= nil and data.kind == "direction" then
|
||||
return self:onClickDirection(state)
|
||||
elseif data ~= nil and (data.kind == "sourceBuilding" or data.kind == "targetBuilding") then
|
||||
return self:onClickBuilding(state, element)
|
||||
end
|
||||
self:safe(function(frame)
|
||||
local run, data = frame:getRun(), frame.rowData[element]
|
||||
@@ -811,7 +730,11 @@ function SmartPickupFrame:onClickStartStop()
|
||||
started = started + 1
|
||||
else
|
||||
skipped = skipped + 1
|
||||
table.insert(reasons, string.format("%s: %s", tostring(result.vehicle:getName()), frame.i18n:getText("spu_reason_" .. tostring(result.reason))))
|
||||
local reasonText = frame.i18n:getText("spu_reason_" .. tostring(result.reason))
|
||||
if result.reason == "noMarker" and result.missingBuilding ~= nil then
|
||||
reasonText = string.format(reasonText, tostring(result.missingBuilding))
|
||||
end
|
||||
table.insert(reasons, string.format("%s: %s", tostring(result.vehicle:getName()), reasonText))
|
||||
end
|
||||
end
|
||||
frame.statusOverride = string.format(frame.i18n:getText("spu_status_started"), started, skipped)
|
||||
@@ -839,13 +762,11 @@ function SmartPickupFrame:onNewRunName(value, clickOk)
|
||||
if not clickOk or value == nil or not value:match("%S") then
|
||||
return
|
||||
end
|
||||
local kind = frame:getTabKind()
|
||||
local run = ADRunsController.createRun(value, kind)
|
||||
local run = ADRunsController.createRun(value, "supply")
|
||||
frame.selectedRunId = run.id
|
||||
frame.statusOverride = nil
|
||||
local tab = kind == "outbound" and SmartPickupFrame.TAB_OUTBOUND or SmartPickupFrame.TAB_SUPPLY
|
||||
frame.currentTab = tab
|
||||
frame:switchTab(tab)
|
||||
frame.currentTab = SmartPickupFrame.TAB_FLOWS
|
||||
frame:switchTab(SmartPickupFrame.TAB_FLOWS)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
@@ -101,5 +101,28 @@
|
||||
<text name="spu_source_kind_factory" text="fabrik"/>
|
||||
<text name="spu_source_kind_silo" text="silo"/>
|
||||
<text name="spu_source_kind_objectStorage" text="objektlager"/>
|
||||
<text name="spu_tab_flows" text="Flows"/>
|
||||
<text name="spu_section_flows" text="— Flows (Vare · Fra → Til · Regel · Traktorer · Status) —"/>
|
||||
<text name="spu_section_flow" text="— Ret flow: %s —"/>
|
||||
<text name="spu_section_from" text="— Fra (bygninger; markøren findes automatisk) —"/>
|
||||
<text name="spu_section_to" text="— Til (stalde og fabrikker; markøren findes automatisk) —"/>
|
||||
<text name="spu_direction" text="Retning"/>
|
||||
<text name="spu_direction_in" text="Ind til bygning"/>
|
||||
<text name="spu_direction_out" text="Ud fra bygning"/>
|
||||
<text name="spu_from_allSilos" text="alle siloer"/>
|
||||
<text name="spu_flow_needBased" text="efter behov"/>
|
||||
<text name="spu_flow_noProducts" text="(ingen varer)"/>
|
||||
<text name="spu_flow_noSource" text="(ingen kilde)"/>
|
||||
<text name="spu_flow_noTarget" text="(intet mål)"/>
|
||||
<text name="spu_flow_noVehicle" text="(ingen traktor)"/>
|
||||
<text name="spu_flow_ruleOut" text="pris ≥ %d %%, lager > %d %%"/>
|
||||
<text name="spu_flow_round" text="runde"/>
|
||||
<text name="spu_flow_ruleIn" text="behov"/>
|
||||
<text name="spu_flow_ruleInLoops" text="behov, %d ture"/>
|
||||
<text name="spu_markerAt" text="markør '%s' %d m"/>
|
||||
<text name="spu_noMarker" text="INGEN MARKØR inden for 40 m — sæt en AD-markør ved triggeren"/>
|
||||
<text name="spu_noBuildings" text="Ingen bygninger fundet"/>
|
||||
<text name="spu_buildingGone" text="bygningen findes ikke længere"/>
|
||||
<text name="spu_reason_noMarker" text="'%s' mangler en AD-markør ved triggeren"/>
|
||||
</texts>
|
||||
</l10n>
|
||||
|
||||
@@ -101,5 +101,28 @@
|
||||
<text name="spu_source_kind_factory" text="factory"/>
|
||||
<text name="spu_source_kind_silo" text="silo"/>
|
||||
<text name="spu_source_kind_objectStorage" text="object storage"/>
|
||||
<text name="spu_tab_flows" text="Flows"/>
|
||||
<text name="spu_section_flows" text="— Flows (Goods · From → To · Rule · Tractors · Status) —"/>
|
||||
<text name="spu_section_flow" text="— Edit flow: %s —"/>
|
||||
<text name="spu_section_from" text="— From (buildings; the marker is found automatically) —"/>
|
||||
<text name="spu_section_to" text="— To (barns and factories; the marker is found automatically) —"/>
|
||||
<text name="spu_direction" text="Direction"/>
|
||||
<text name="spu_direction_in" text="Into building"/>
|
||||
<text name="spu_direction_out" text="Out of building"/>
|
||||
<text name="spu_from_allSilos" text="all silos"/>
|
||||
<text name="spu_flow_needBased" text="by need"/>
|
||||
<text name="spu_flow_noProducts" text="(no goods)"/>
|
||||
<text name="spu_flow_noSource" text="(no source)"/>
|
||||
<text name="spu_flow_noTarget" text="(no target)"/>
|
||||
<text name="spu_flow_noVehicle" text="(no tractor)"/>
|
||||
<text name="spu_flow_ruleOut" text="price ≥ %d %%, storage > %d %%"/>
|
||||
<text name="spu_flow_round" text="round"/>
|
||||
<text name="spu_flow_ruleIn" text="need"/>
|
||||
<text name="spu_flow_ruleInLoops" text="need, %d loops"/>
|
||||
<text name="spu_markerAt" text="marker '%s' %d m"/>
|
||||
<text name="spu_noMarker" text="NO MARKER within 40 m — place an AD marker at the trigger"/>
|
||||
<text name="spu_noBuildings" text="No buildings found"/>
|
||||
<text name="spu_buildingGone" text="building no longer exists"/>
|
||||
<text name="spu_reason_noMarker" text="'%s' has no AD marker at its trigger"/>
|
||||
</texts>
|
||||
</l10n>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<modDesc descVersion="107">
|
||||
<author>masterdraco</author>
|
||||
<version>1.12.21.0</version>
|
||||
<version>1.13.0.0</version>
|
||||
<title>
|
||||
<en>AD Smart Pickup</en>
|
||||
</title>
|
||||
@@ -21,6 +21,7 @@
|
||||
<sourceFile filename="adPrices.lua"/>
|
||||
<sourceFile filename="adOutboundPlanner.lua"/>
|
||||
<sourceFile filename="adSources.lua"/>
|
||||
<sourceFile filename="adBuildings.lua"/>
|
||||
<sourceFile filename="adOutbound.lua"/>
|
||||
<sourceFile filename="adUnloadWait.lua"/>
|
||||
<sourceFile filename="adSmartPickup.lua"/>
|
||||
|
||||
@@ -141,6 +141,21 @@ vare valgt betyder ingen bytte-mulighed, og traktoren venter som hidtil. Wait-lo
|
||||
kun mens aflæsningsopgaven peger på AD's rigtige aflæsningsmål, så en silo-omvej (fx efter et bytte)
|
||||
aldrig fejlagtigt bliver opfattet som et fuldt mål.
|
||||
|
||||
## v1.13 — Flow-tavle (bygningsbaseret opsætning)
|
||||
|
||||
ESC-fanen har nu to under-faner: **Flows** og **Lagre**. Flows viser én række pr. flow (run):
|
||||
`> Mælk: Sukker · Kostald 1 + Kostald 2 → salg · pris ≥ 90 %, lager > 80 % · Virtus · kører (1/1) — SUGAR 78 % af top`
|
||||
og under tavlen en detail-blok for det valgte flow: **Retning** (ind til bygning / ud fra bygning),
|
||||
**Fra** (udkørsel) eller **Til** (forsyning) som afkrydsning pr. **bygning** — moden finder selv den
|
||||
AD-markør der står nærmest bygningens læsse-/aflæsningstrigger (≤ 40 m; siloer via det strenge
|
||||
opslag) og viser den: `Kostald 1 (stald) — markør 'cow 1 milk' 12 m` eller `INGEN MARKØR inden for
|
||||
40 m`. Derefter Varer, Regler, Vent ved, Traktorer og Status som før. Forsyning har "Fra = alle
|
||||
siloer" (som hidtil). Wait-puljerne står nederst.
|
||||
|
||||
Gamle runs oversættes automatisk: markører der er en bygnings markør bliver til bygningen; rå
|
||||
markører uden bygning beholdes og vises som `markør '…'`. Start afviser med `'<bygning>' mangler en
|
||||
AD-markør ved triggeren`, når en valgt bygning ingen markør har. Runs gemmes som XML version 3.
|
||||
|
||||
## v1.12 — Udkørsel af produkter
|
||||
|
||||
Et run har nu en **retning**: *Forsyning* (som hidtil) eller *Udkørsel*. ESC-fanen har tre
|
||||
|
||||
Reference in New Issue
Block a user