499 lines
25 KiB
Lua
499 lines
25 KiB
Lua
-- Smart Pickup — fanen Flows: tavle + resumé, og guiden "Opsæt flow"
|
|
-- Tavlen øverst (én række pr. flow), det valgte flows resumé (klik på en linje = ret ét trin; Navn = omdøb)
|
|
-- og status. [Opsæt flow] / [Nyt flow] åbner guiden på den fælles trin-skærm (gui/SmartPickupGuide.lua).
|
|
-- Henter det spil-afhængige som `context` til ADFlowGuide og gemmer via ADRunsController.
|
|
-- Funktionerne lægges på SmartPickupFrame (indlæses efter SmartPickupFrame.lua).
|
|
|
|
function SmartPickupFrame:initFlowButtons(i18n)
|
|
self.flowSetupButtonInfo = {inputAction = InputAction.MENU_EXTRA_1, text = i18n:getText("spu_guide_flow_open"), callback = function() self:onClickFlowSetup() end}
|
|
self.flowNewButtonInfo = {inputAction = InputAction.MENU_EXTRA_2, text = i18n:getText("spu_button_new"), callback = function() self:onClickFlowNew() end}
|
|
-- Flows-fanen: [Start/Stop] [Opsæt flow] [Nyt flow] [Slet]; omdøb ligger på resuméets Navn-linje
|
|
-- v1.58: listen har Start/Stop pr. række; Opsæt/Slet ligger i redigeringsvinduet
|
|
self.flowButtons = {self.backButtonInfo, self.flowNewButtonInfo}
|
|
end
|
|
|
|
-- ---- traktor-tekst (også til guidens traktorliste) ----
|
|
|
|
-- "Fastrac 2135 4WS (#1) — 1.000.000 l — kan bære: Halm, TMR — OK" / "… — X ingen vogn".
|
|
function SmartPickupFrame:describeVehicle(adEnv, run, vehicle, isInRun)
|
|
local label = ADRunsController.getVehicleLabel(adEnv, vehicle)
|
|
local validation = ADRunsController.validateVehicle(adEnv, run, vehicle)
|
|
local parts = {label}
|
|
if validation.isAutoload and validation.capacity == nil then
|
|
table.insert(parts, self.i18n:getText("spu_capacity_pallets"))
|
|
elseif validation.capacity ~= nil then
|
|
table.insert(parts, string.format(self.i18n:getText("spu_capacity"), g_i18n:formatNumber(validation.capacity, 0)))
|
|
local carriable = self:describeCarriable(adEnv, run, vehicle, validation.carriable)
|
|
if carriable ~= nil then
|
|
table.insert(parts, carriable)
|
|
end
|
|
end
|
|
if validation.ok then
|
|
table.insert(parts, "OK")
|
|
else
|
|
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
|
|
|
|
-- Hvilke af run'ets varer vognen kan bære (titler); nil når ingen.
|
|
function SmartPickupFrame:describeCarriable(adEnv, run, vehicle, carriable)
|
|
local canCarry = {}
|
|
for _, fillType in ipairs(carriable or {}) do
|
|
canCarry[fillType] = true
|
|
end
|
|
local titles = {}
|
|
for _, fillType in ipairs(ADRunsController.getRunIngredients(adEnv, run, vehicle)) do
|
|
if canCarry[fillType] then
|
|
local title = g_fillTypeManager.getFillTypeTitleByIndex ~= nil and g_fillTypeManager:getFillTypeTitleByIndex(fillType) or nil
|
|
table.insert(titles, tostring(title or g_fillTypeManager:getFillTypeNameByIndex(fillType)))
|
|
end
|
|
end
|
|
if #titles == 0 then
|
|
return nil
|
|
end
|
|
return string.format(self.i18n:getText("spu_canCarry"), table.concat(titles, ", "))
|
|
end
|
|
|
|
-- ---- context til ADFlowGuide ----
|
|
|
|
local function trim(text)
|
|
return (string.gsub(tostring(text or ""), "^%s+", ""))
|
|
end
|
|
|
|
local function idSet(list)
|
|
local set = {}
|
|
for _, id in ipairs(list or {}) do set[id] = true end
|
|
return set
|
|
end
|
|
|
|
function SmartPickupFrame:flowBuildingContext(adEnv, draft, farmId)
|
|
local isOut = draft.kind == "outbound"
|
|
local role = isOut and "load" or "unload"
|
|
local chosen = idSet(isOut and draft.sourceBuildingIds or draft.targetBuildingIds)
|
|
local buildings, found = {}, {}
|
|
for _, building in ipairs(ADBuildings.list(adEnv, farmId)) do
|
|
local fits = (isOut and building.canBeSource) or (not isOut and building.canBeTarget)
|
|
if fits or chosen[building.id] then
|
|
local markers = ADBuildings.getMarkers ~= nil and ADBuildings.getMarkers(building, role) or {}
|
|
found[building.id] = true
|
|
table.insert(buildings, {id = building.id, name = tostring(building.name), label = markers[1] ~= nil and tostring(markers[1].name) or nil,
|
|
hasMarker = markers[1] ~= nil, text = trim(self:describeBuilding(building, role))})
|
|
end
|
|
end
|
|
-- valgte bygninger der ikke længere findes (solgt): kan fravælges
|
|
for id in pairs(chosen) do
|
|
if not found[id] then
|
|
local gone = self.i18n:getText("spu_buildingGone")
|
|
table.insert(buildings, {id = id, name = gone, hasMarker = false, text = gone})
|
|
end
|
|
end
|
|
return buildings
|
|
end
|
|
|
|
function SmartPickupFrame:flowStoreContext(adEnv, preview, farmId)
|
|
local goods = ADRunsController.getStoreGoods(adEnv, preview)
|
|
local chosen = idSet(preview.storeBuildingIds)
|
|
local result = {}
|
|
for _, building in ipairs(ADBuildings.list(adEnv, farmId)) do
|
|
local isStoreKind = building.kind == "silo" or building.kind == "factory" or building.kind == "objectStorage"
|
|
if isStoreKind and (chosen[building.id] or ADRunsController.canStoreAt(adEnv, building, goods)) then
|
|
table.insert(result, {id = building.id, name = tostring(building.name), text = trim(self:describeBuilding(building, "unload"))})
|
|
end
|
|
end
|
|
return result
|
|
end
|
|
|
|
-- Varer (fillType-indeks) flowet kører med: udkørsel = valgte produkter, forsyning = valgte/målets varer.
|
|
-- Tom liste = ukendt endnu (ingen mål valgt) -> enhver vogn med last-enheder tæller.
|
|
local function flowFillTypes(adEnv, preview)
|
|
local names = {}
|
|
if preview.kind == "outbound" then
|
|
for _, product in ipairs(preview.products or {}) do table.insert(names, product.fillType) end
|
|
elseif preview.ingredientMode == "manual" then
|
|
names = preview.ingredients or {}
|
|
else
|
|
for _, fillType in ipairs(ADRunsController.getTargetAcceptedFillTypes(adEnv, preview)) do table.insert(names, fillType.name) end
|
|
end
|
|
local result = {}
|
|
for _, name in ipairs(names) do
|
|
local index = g_fillTypeManager:getFillTypeIndexByName(tostring(name))
|
|
if index ~= nil then table.insert(result, index) end
|
|
end
|
|
return result
|
|
end
|
|
|
|
local function carriesAny(carriable, wanted)
|
|
if #carriable == 0 then return false end
|
|
if #wanted == 0 then return true end
|
|
for _, a in ipairs(carriable) do
|
|
for _, b in ipairs(wanted) do if a == b then return true end end
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Ledige vogne til solo-traktorer: frakoblet, egen AD-parkering med "Connect"-markør, ikke holdt af et andet flow
|
|
-- og kan bære flowets varer. Bedste først (navnematch, så "Disponibel"). In-game 29/9: flowet kunne ikke oprettes
|
|
-- uden at omdøbe en vogns parkering til flowets navn.
|
|
function SmartPickupFrame:flowWagonContext(adEnv, preview)
|
|
local farmId = g_currentMission:getFarmId()
|
|
local markers = adEnv.ADGraphManager:getMapMarkers()
|
|
local wanted = flowFillTypes(adEnv, preview)
|
|
local candidates = {}
|
|
for _, any in pairs(g_currentMission.vehicleSystem.vehicles) do
|
|
local ok, entry = pcall(function()
|
|
local index = any.advd ~= nil and any.advd.parkDestination or nil
|
|
if any.spec_motorized ~= nil or any.spec_attachable == nil or type(index) ~= "number" or index < 1 then return nil end
|
|
if any.getAttacherVehicle ~= nil and any:getAttacherVehicle() ~= nil then return nil end
|
|
if any.getOwnerFarmId == nil or any:getOwnerFarmId() ~= farmId then return nil end
|
|
local id = ADRunsController.getVehicleId(any)
|
|
local park = adEnv.ADGraphManager:getMapMarkerById(index)
|
|
if id == nil or park == nil or ADPool.connectFor(park.name, markers) == nil then return nil end
|
|
local owner = ADFlowWagons.ownerOf(ADRunsController.store.runs, id)
|
|
if owner ~= nil and owner.id ~= preview.id then return nil end
|
|
if not carriesAny(ADRunsController.getCarriableFillTypes(adEnv, any), wanted) then return nil end
|
|
return {id = id, label = tostring(park.name)}
|
|
end)
|
|
if ok and entry ~= nil then table.insert(candidates, entry) end
|
|
end
|
|
return ADFlowWagons.rankWagons(preview.name, candidates)
|
|
end
|
|
|
|
function SmartPickupFrame:flowVehicleContext(adEnv, preview, wagons)
|
|
local result = {}
|
|
local hasWagons = wagons ~= nil and #wagons > 0
|
|
for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
|
|
local ok, entry = pcall(function()
|
|
local text = self:describeVehicle(adEnv, preview, vehicle, false)
|
|
local validation = ADRunsController.validateVehicle(adEnv, preview, vehicle)
|
|
local other = ADRunsController.getRunForVehicle(vehicle)
|
|
local label = ADRunsController.getVehicleLabel(adEnv, vehicle)
|
|
-- solo-traktor (ingen vogn bagpå, kan trække): valgbar når en ledig vogn findes — den hentes ved Connect
|
|
local solo = validation.reason == "noTrailer" and ADPool.canPull(ADPool.ownRole(vehicle))
|
|
if solo and hasWagons then text = string.format(self.i18n:getText("spu_guide_flow_soloText"), tostring(label)) end
|
|
local blocked = SmartPickupFrame.VEHICLE_BLOCKING_REASONS[validation.reason] == true and not (solo and hasWagons)
|
|
return {id = ADRunsController.getVehicleId(vehicle), text = text, label = label, otherRunId = other ~= nil and other.id or nil,
|
|
otherRunName = other ~= nil and other.name or nil, blocked = blocked, solo = solo}
|
|
end)
|
|
if ok and entry.id ~= nil then
|
|
table.insert(result, entry)
|
|
elseif not ok then
|
|
Logging.warning(SmartPickupFrame.LOG_PREFIX .. "traktor '%s' kunne ikke vises i flowets traktorliste: %s",
|
|
tostring(vehicle.getName ~= nil and vehicle:getName() or "?"), tostring(entry))
|
|
end
|
|
end
|
|
return result
|
|
end
|
|
|
|
-- draft: kladden (eller selve run'et — samme feltnavne).
|
|
function SmartPickupFrame:flowGuideContext(adEnv, draft)
|
|
local farmId = g_currentMission:getFarmId()
|
|
local preview = ADFlowGuide.previewRun(draft, function(buildingId, role)
|
|
local building = ADBuildings.find(adEnv, farmId, buildingId)
|
|
local ids = {}
|
|
for _, marker in ipairs(building ~= nil and ADBuildings.getMarkers ~= nil and ADBuildings.getMarkers(building, role) or {}) do
|
|
table.insert(ids, marker.id)
|
|
end
|
|
return ids
|
|
end)
|
|
local context = {buildings = self:flowBuildingContext(adEnv, draft, farmId), fillTypes = {}, products = {}, storeBuildings = {},
|
|
waitPools = ADRunsController.getWaitPools(adEnv)}
|
|
context.wagons = self:flowWagonContext(adEnv, preview)
|
|
context.vehicles = self:flowVehicleContext(adEnv, preview, context.wagons)
|
|
if draft.kind == "outbound" then
|
|
for _, product in ipairs(ADRunsController.getRunProducts(adEnv, preview)) do
|
|
local title = tostring(product.title)
|
|
table.insert(context.products, {name = product.name, title = title,
|
|
text = string.format("%s — %s l", title, SmartPickupFrame.formatCompact(product.available or 0))})
|
|
end
|
|
context.storeBuildings = self:flowStoreContext(adEnv, preview, farmId)
|
|
else
|
|
for _, fillType in ipairs(ADRunsController.getTargetAcceptedFillTypes(adEnv, preview)) do
|
|
table.insert(context.fillTypes, {name = fillType.name, title = tostring(fillType.title)})
|
|
end
|
|
end
|
|
return context
|
|
end
|
|
|
|
-- ---- fanen: tavle + resumé ----
|
|
|
|
-- Flows: det valgte flow øverst (indstillinger som "ret"-linjer + status), derunder en kort liste til at vælge
|
|
-- et andet flow. Tavlen med alle flows står i Oversigt (in-game 27/9: de to faner så ens ud).
|
|
function SmartPickupFrame:fillFlowTabRows(adEnv)
|
|
if not self.editPanelOpen and self:hasGuideOn(SmartPickupFrame.TAB_FLOWS) and self:fillGuideRows(adEnv) then return end
|
|
self.flowListRows = {}
|
|
local i18n = self.i18n
|
|
if #ADRunsController.store.runs == 0 then
|
|
self:addTextRow(i18n:getText("spu_noRuns"))
|
|
return
|
|
end
|
|
self:addTextRow(i18n:getText("spu_flowList_hint"))
|
|
local function addFlowRow(run)
|
|
local row = self:addRow(self.flowListPrefab, {kind = "flowList"})
|
|
local entry = {runId = run.id, row = row, dot = row:getDescendantByName("dot"),
|
|
cells = {row:getDescendantByName("c1"), row:getDescendantByName("c2"), row:getDescendantByName("c3"),
|
|
row:getDescendantByName("c4"), row:getDescendantByName("c5")}}
|
|
local runId = run.id
|
|
local actionCell = entry.cells[5]
|
|
self:makeRowClickable(row, function(frame)
|
|
-- klik på [Start]/[Stop]-feltet = handling (kun dette flow); ellers åbn redigeringsvinduet
|
|
if frame.lastClickX ~= nil and actionCell.absPosition ~= nil and frame.lastClickX >= actionCell.absPosition[1] then
|
|
frame:toggleRun(frame.getAdEnv(), runId)
|
|
frame:requestRebuild()
|
|
else
|
|
frame.selectedRunId = runId
|
|
frame:openEditPanel("flow", runId)
|
|
end
|
|
end)
|
|
table.insert(self.flowListRows, entry)
|
|
end
|
|
for _, group in ipairs(ADFlowView.boardGroups(ADRunsController.store.runs)) do
|
|
self:addTextRow(i18n:getText(group.chain and "spu_board_chain" or group.kind == "outbound" and "spu_board_outbound" or "spu_board_supply"))
|
|
local runs, idle = group.runs, {}
|
|
-- kædeflows uden traktor (venter på en ledig traktor/vogn) foldes sammen (in-game 30/9)
|
|
if group.chain then runs, idle = ADFlowView.splitIdle(group.runs) end
|
|
for _, run in ipairs(runs) do addFlowRow(run) end
|
|
if #idle > 0 then
|
|
local key = self.showIdleChainFlows and "spu_board_chainIdleHide" or "spu_board_chainIdleShow"
|
|
self:addLinkRow(" " .. string.format(i18n:getText(key), #idle), function(frame)
|
|
frame.showIdleChainFlows = not frame.showIdleChainFlows
|
|
frame:requestRebuild()
|
|
end)
|
|
if self.showIdleChainFlows then
|
|
for _, run in ipairs(idle) do addFlowRow(run) end
|
|
end
|
|
end
|
|
end
|
|
self:refreshFlowListRows(adEnv)
|
|
end
|
|
|
|
-- Listens celler, prik og statusfarve (hvert sekund og efter opbygning).
|
|
function SmartPickupFrame:refreshFlowListRows(adEnv)
|
|
local unpackFn = table.unpack or unpack
|
|
for _, entry in ipairs(self.flowListRows or {}) do
|
|
local run = ADRuns.getRun(ADRunsController.store, entry.runId)
|
|
if run ~= nil then
|
|
local cells = self:flowCells(adEnv, run)
|
|
local color = ADFlowView.LEVEL_COLORS[self:flowLevel(adEnv, run)]
|
|
local canStop = ADRunsController.getRunStatus(adEnv, run).canStop
|
|
entry.cells[1]:setText(ADFlowView.listName(run))
|
|
entry.cells[2]:setText(tostring(cells[2]))
|
|
entry.cells[3]:setText(tostring(cells[5]))
|
|
entry.cells[4]:setText(tostring(cells[6]))
|
|
entry.cells[5]:setText(self.i18n:getText(canStop and "spu_flowList_stop" or "spu_flowList_start"))
|
|
if entry.dot ~= nil and entry.dot.setImageColor ~= nil then entry.dot:setImageColor(nil, unpackFn(color)) end
|
|
if entry.cells[4].setTextColor ~= nil then entry.cells[4]:setTextColor(unpackFn(color)) end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Start/Stop for ét flow (rækkens felt og vinduets knap). Husker om sidste start blev helt afvist (rød).
|
|
function SmartPickupFrame:toggleRun(adEnv, runId)
|
|
local run = ADRuns.getRun(ADRunsController.store, runId)
|
|
if adEnv == nil or run == nil then return end
|
|
self.lastStartFailed = self.lastStartFailed or {}
|
|
if ADRunsController.getRunStatus(adEnv, run).canStop then
|
|
ADRunsController.stopRun(adEnv, run.id)
|
|
self.lastStartFailed[run.id] = nil
|
|
self.statusOverride = nil
|
|
else
|
|
local started, skipped, reasons = self:summarizeStartResults(ADRunsController.startRun(adEnv, run.id))
|
|
self.lastStartFailed[run.id] = started == 0 and skipped > 0
|
|
local text = string.format(self.i18n:getText("spu_status_started"), started, skipped)
|
|
self:showOverride(text, reasons)
|
|
-- statuslinjen kan ligge uden for skærmen: sprunget over vises også som besked i højre side
|
|
if skipped > 0 and ADFieldJobs ~= nil and ADFieldJobs.notify ~= nil then
|
|
ADFieldJobs.notify(string.format("%s: %s — %s", tostring(run.name), text, table.concat(reasons, "; ")), started == 0)
|
|
end
|
|
end
|
|
ADRunsController.save()
|
|
end
|
|
|
|
function SmartPickupFrame:flowLevel(adEnv, run)
|
|
local row = ADRunsController.getFlowRow(adEnv, run)
|
|
local status = ADRunsController.getRunStatus(adEnv, run)
|
|
-- en gammel afvisning gælder ikke længere når flowet kører (fx startet fra Oversigt bagefter)
|
|
if row.running > 0 and self.lastStartFailed ~= nil then self.lastStartFailed[run.id] = nil end
|
|
return ADFlowView.flowStatus({running = row.running, total = row.total, stopped = run.stopped == true,
|
|
canStop = status.canStop == true, warning = row.warning, reason = row.reason,
|
|
lastStartFailed = (self.lastStartFailed or {})[run.id] == true})
|
|
end
|
|
|
|
function SmartPickupFrame:fillFlowSummary(adEnv, run)
|
|
local i18n = self.i18n
|
|
if not self.editPanelOpen then
|
|
self:addTextRow(string.format(i18n:getText("spu_guide_flow_section"), tostring(run.name)))
|
|
end
|
|
self:addTextRow(" " .. i18n:getText("spu_guide_sum_hint"))
|
|
local guide = ADFlowGuide.open(run, self:flowGuideContext(adEnv, run))
|
|
local getText = function(key) return i18n:getText(key) end
|
|
local runId = run.id
|
|
for _, line in ipairs(ADFlowGuide.summary(guide)) do
|
|
local step = line.step
|
|
self:addLinkRow(" " .. ADGuide.lineText(line, getText) .. i18n:getText("spu_guide_editSuffix"), function(frame)
|
|
if step == "name" then frame:onClickRename() else frame:openFlowStep(runId, step) end
|
|
end)
|
|
end
|
|
local cells = self:flowCells(adEnv, run)
|
|
self:addTextRow(" " .. string.format(i18n:getText("spu_field_statusFull"), tostring(cells[6])))
|
|
self:addLinkRow(" " .. i18n:getText("spu_guide_flow_open"), function(frame)
|
|
frame.selectedRunId = runId
|
|
frame:onClickFlowSetup()
|
|
end)
|
|
end
|
|
|
|
-- Redigeringsvinduet for et flow (gui/SmartPickupEditPanel.lua).
|
|
SmartPickupFrame.EDIT_PANEL_KINDS = SmartPickupFrame.EDIT_PANEL_KINDS or {}
|
|
SmartPickupFrame.EDIT_PANEL_KINDS.flow = {
|
|
canDelete = true,
|
|
exists = function(frame, id) return ADRuns.getRun(ADRunsController.store, id) ~= nil end,
|
|
title = function(frame, id)
|
|
local run = ADRuns.getRun(ADRunsController.store, id)
|
|
return string.format(frame.i18n:getText("spu_panel_flowTitle"), tostring(run ~= nil and run.name or "?"))
|
|
end,
|
|
fill = function(frame, adEnv, id)
|
|
local run = ADRuns.getRun(ADRunsController.store, id)
|
|
if run ~= nil then frame:fillFlowSummary(adEnv, run) end
|
|
end,
|
|
status = function(frame, adEnv, id)
|
|
local run = ADRuns.getRun(ADRunsController.store, id)
|
|
return {text = tostring(frame:flowCells(adEnv, run)[6]), level = frame:flowLevel(adEnv, run)}
|
|
end,
|
|
startStopText = function(frame, adEnv, id)
|
|
local run = ADRuns.getRun(ADRunsController.store, id)
|
|
return frame.i18n:getText(ADRunsController.getRunStatus(adEnv, run).canStop and "spu_button_stop" or "spu_button_start")
|
|
end,
|
|
startStop = function(frame, id) frame:toggleRun(frame.getAdEnv(), id) end,
|
|
delete = function(frame, id)
|
|
frame.selectedRunId = id
|
|
frame:onClickDelete()
|
|
end,
|
|
}
|
|
|
|
-- Hvert sekund: tavlens celler, statuslinje og knapper.
|
|
function SmartPickupFrame:refreshFlowTab(adEnv)
|
|
if not self.editPanelOpen and self:hasGuideOn(SmartPickupFrame.TAB_FLOWS) then
|
|
self:setStatusText(self.statusOverride or "")
|
|
return
|
|
end
|
|
self:refreshFlowListRows(adEnv)
|
|
local running, total = 0, 0
|
|
for _, run in ipairs(ADRunsController.store.runs) do
|
|
total = total + 1
|
|
if ADRunsController.getRunStatus(adEnv, run).running > 0 then running = running + 1 end
|
|
end
|
|
self:setStatusText(self.statusOverride or string.format(self.i18n:getText("spu_flowList_status"), running, total))
|
|
end
|
|
|
|
-- ---- hooks til den fælles guide-skærm ----
|
|
|
|
SmartPickupFrame.GUIDE_HOOKS = SmartPickupFrame.GUIDE_HOOKS or {}
|
|
SmartPickupFrame.GUIDE_HOOKS.flow = {
|
|
model = ADFlowGuide,
|
|
tab = SmartPickupFrame.TAB_FLOWS,
|
|
heading = function(frame, guide)
|
|
return string.format(frame.i18n:getText("spu_guide_flow_title"), tostring(guide.draft.name))
|
|
end,
|
|
context = function(frame, adEnv, guide)
|
|
-- flowet er slettet mens guiden var åben
|
|
if not guide.draft.isNew and ADRuns.getRun(ADRunsController.store, guide.draft.id) == nil then return nil end
|
|
return frame:flowGuideContext(adEnv, guide.draft)
|
|
end,
|
|
choose = function(frame, id)
|
|
if id ~= "rename" then return false end
|
|
TextInputDialog.show(SmartPickupFrame.onGuideNameResult, frame, frame.guide.draft.name, frame.i18n:getText("spu_renameTitle"), nil, 30, g_i18n:getText("button_ok"))
|
|
return true
|
|
end,
|
|
startKey = function() return "spu_guide_flow_start" end,
|
|
save = function(frame, guide, start) frame:saveFlowGuide(guide, start) end,
|
|
}
|
|
|
|
function SmartPickupFrame:onGuideNameResult(value, clickOk)
|
|
self:safe(function(frame)
|
|
if not clickOk or frame.guide == nil or frame.guideKind ~= "flow" then return end
|
|
frame.guide = ADFlowGuide.choose(frame.guide, "name", value)
|
|
frame:requestRebuild()
|
|
end)
|
|
end
|
|
|
|
-- Gem: nyt flow oprettes først nu; felterne via updateRun; traktorer tildeles/fjernes; markører findes.
|
|
-- start = true: flowet startes bagefter ([Start flow]).
|
|
function SmartPickupFrame:saveFlowGuide(guide, start)
|
|
local adEnv = self.getAdEnv()
|
|
local result = ADFlowGuide.result(guide)
|
|
local runId = result.runId
|
|
local oldIds = {}
|
|
if result.isNew then
|
|
runId = ADRunsController.createRun(result.name, result.kind).id
|
|
else
|
|
local existing = ADRuns.getRun(ADRunsController.store, runId)
|
|
if existing == nil then return end
|
|
oldIds = existing.vehicleIds
|
|
end
|
|
ADRunsController.updateRun(runId, result.changes)
|
|
local added, removed = ADFlowGuide.vehicleChanges(oldIds, result.vehicleIds)
|
|
for _, id in ipairs(removed) do
|
|
local vehicle = adEnv ~= nil and ADRunsController.findVehicleById(adEnv, id) or nil
|
|
if vehicle ~= nil then
|
|
ADRunsController.unassignVehicle(vehicle)
|
|
else
|
|
ADRunsController.store = ADRuns.unassignVehicle(ADRunsController.store, id)
|
|
end
|
|
end
|
|
for _, id in ipairs(added) do
|
|
local vehicle = adEnv ~= nil and ADRunsController.findVehicleById(adEnv, id) or nil
|
|
if vehicle ~= nil then ADRunsController.assignVehicle(runId, vehicle) end
|
|
end
|
|
-- solo-traktorernes vogne fra guiden: flowet husker dem straks og henter dem ved Connect ved start
|
|
local savedRun = ADRuns.getRun(ADRunsController.store, runId)
|
|
if savedRun ~= nil then
|
|
local wagons = ADRuns.copyWagons(savedRun.wagons)
|
|
for tractorId, wagonId in pairs(result.wagons or {}) do wagons[tractorId] = wagonId end
|
|
savedRun.wagons = wagons
|
|
end
|
|
ADRunsController.resolveMarkers(adEnv, ADRuns.getRun(ADRunsController.store, runId))
|
|
self.selectedRunId = runId
|
|
local saved = string.format(self.i18n:getText("spu_guide_flow_saved"), tostring(result.name))
|
|
if start and adEnv ~= nil and not ADRunsController.getRunStatus(adEnv, ADRuns.getRun(ADRunsController.store, runId)).isRunning then
|
|
local started, skipped, reasons = self:summarizeStartResults(ADRunsController.startRun(adEnv, runId))
|
|
self:showOverride(saved .. " — " .. string.format(self.i18n:getText("spu_status_started"), started, skipped), reasons)
|
|
else
|
|
self:showOverride(saved)
|
|
end
|
|
ADRunsController.save()
|
|
end
|
|
|
|
-- ---- knapper og [Ret] ----
|
|
|
|
function SmartPickupFrame:onClickFlowSetup()
|
|
self:safe(function(frame)
|
|
local adEnv, run = frame.getAdEnv(), frame:getRun()
|
|
if adEnv == nil or run == nil then return end
|
|
frame:openGuide("flow", ADFlowGuide.open(run, frame:flowGuideContext(adEnv, run)))
|
|
end)
|
|
end
|
|
|
|
-- [Nyt flow] (også fra fanen Oversigt): guiden på Flows-fanen; intet oprettes før [Gem].
|
|
function SmartPickupFrame:onClickFlowNew()
|
|
self:safe(function(frame)
|
|
local adEnv = frame.getAdEnv()
|
|
if adEnv == nil then return end
|
|
local name = string.format(frame.i18n:getText("spu_newRunName"), #ADRunsController.store.runs + 1)
|
|
local guide = ADFlowGuide.openNew(name, {})
|
|
guide = ADGuide.withContext(guide, frame:flowGuideContext(adEnv, guide.draft))
|
|
if frame.currentTab ~= SmartPickupFrame.TAB_FLOWS then frame:switchTab(SmartPickupFrame.TAB_FLOWS) end
|
|
frame:openGuide("flow", guide)
|
|
end)
|
|
end
|
|
|
|
function SmartPickupFrame:openFlowStep(runId, step)
|
|
local adEnv = self.getAdEnv()
|
|
local run = ADRuns.getRun(ADRunsController.store, runId)
|
|
if adEnv == nil or run == nil then return end
|
|
self:openGuide("flow", ADFlowGuide.open(run, self:flowGuideContext(adEnv, run), {step = step, single = true, returnTo = "close"}))
|
|
end
|