feat: flere mål pr. run (afkrydsning; den stald der mangler mest får turen, AD's mål skiftes ved turstart) + under-faner Overblik/Runs (v1.11.0.0)
This commit is contained in:
@@ -9,6 +9,8 @@ SmartPickupFrame._mt = Class(SmartPickupFrame, TabbedMenuFrameElement)
|
||||
SmartPickupFrame.REFRESH_INTERVAL_MS = 1000
|
||||
SmartPickupFrame.LOG_PREFIX = "ADSmartPickup: "
|
||||
SmartPickupFrame.STATE_OFF, SmartPickupFrame.STATE_ON = 1, 2
|
||||
SmartPickupFrame.TAB_OVERVIEW, SmartPickupFrame.TAB_RUNS = 1, 2
|
||||
SmartPickupFrame.TAB_NAMES = {"spu_tab_overview", "spu_tab_runs"}
|
||||
|
||||
function SmartPickupFrame.new(i18n, getAdEnv)
|
||||
local self = SmartPickupFrame:superClass().new(nil, SmartPickupFrame._mt)
|
||||
@@ -22,10 +24,12 @@ function SmartPickupFrame.new(i18n, getAdEnv)
|
||||
self.refreshTimer = 0
|
||||
self.statusOverride = nil
|
||||
self.statusRow = nil -- Text-elementet i den klonede statusrække
|
||||
self.needsRow = nil
|
||||
self.needsRows = {}
|
||||
self.pendingRebuild = false
|
||||
self.frameOpen = false
|
||||
self.focusLost = false
|
||||
self.currentTab = SmartPickupFrame.TAB_OVERVIEW
|
||||
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}
|
||||
self.newButtonInfo = {inputAction = InputAction.MENU_EXTRA_1, text = i18n:getText("spu_button_new"), callback = function() self:onClickNew() end}
|
||||
@@ -55,6 +59,25 @@ function SmartPickupFrame:initialize()
|
||||
FocusManager:removeElement(prefab)
|
||||
end
|
||||
end
|
||||
if self.selectorPrefab ~= nil and self.subCategoryBox ~= nil and self.subCategoryPaging ~= nil then
|
||||
self.selectorPrefab:unlinkElement()
|
||||
FocusManager:removeElement(self.selectorPrefab)
|
||||
for index, key in ipairs(SmartPickupFrame.TAB_NAMES) do
|
||||
self.subCategoryPaging:addText(tostring(index))
|
||||
local tab = self.selectorPrefab:clone(self.subCategoryBox)
|
||||
FocusManager:loadElementFromCustomValues(tab)
|
||||
tab:setText(self.i18n:getText(key))
|
||||
local background = tab:getDescendantByName("background")
|
||||
if background ~= nil then
|
||||
background:setSize(tab.size[1], tab.size[2])
|
||||
end
|
||||
local tabIndex = index
|
||||
tab.onClickCallback = function() self:switchTab(tabIndex) end
|
||||
self.subCategoryTabs[index] = tab
|
||||
end
|
||||
self.subCategoryBox:invalidateLayout()
|
||||
self.subCategoryPaging:setSize(self.subCategoryBox.maxFlowSize + 140 * g_pixelSizeScaledX)
|
||||
end
|
||||
self.ingredientModeOption:setTexts({self.i18n:getText("spu_mode_auto"), self.i18n:getText("spu_mode_manual")})
|
||||
local loopTexts = {self.i18n:getText("spu_loops_infinite")}
|
||||
for loops = 1, ADRuns.MAX_LOOPS do
|
||||
@@ -173,6 +196,33 @@ function SmartPickupFrame:requestRebuild()
|
||||
self:safe(self.rebuild)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:switchTab(tabIndex)
|
||||
self.currentTab = tabIndex
|
||||
for index, tab in ipairs(self.subCategoryTabs) do
|
||||
tab:setSelected(index == tabIndex)
|
||||
end
|
||||
if self.subCategoryPaging ~= nil then
|
||||
self.subCategoryPaging:setState(tabIndex, false)
|
||||
end
|
||||
self:requestRebuild()
|
||||
self:safe(function(frame)
|
||||
FocusManager:setFocus(frame.boxLayout)
|
||||
end)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickTab(state)
|
||||
self:switchTab(state)
|
||||
end
|
||||
|
||||
-- De faste rækker (Run, Varer, Wait-pulje, Ture, tærskel) hører til Runs-fanen.
|
||||
function SmartPickupFrame:setStaticRowsVisible(isVisible)
|
||||
for _, option in ipairs({self.runOption, self.ingredientModeOption, self.waitPoolOption, self.loopsOption, self.returnBelowOption}) do
|
||||
if option ~= nil and option.parent ~= nil then
|
||||
option.parent:setVisible(isVisible)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SmartPickupFrame:getRun()
|
||||
return self.selectedRunId ~= nil and ADRuns.getRun(ADRunsController.store, self.selectedRunId) or nil
|
||||
end
|
||||
@@ -192,7 +242,7 @@ function SmartPickupFrame:clearRows()
|
||||
end
|
||||
self.clonedRows, self.rowData = {}, {}
|
||||
self.statusRow = nil
|
||||
self.needsRow = nil
|
||||
self.needsRows = {}
|
||||
self.overviewRows = {}
|
||||
end
|
||||
|
||||
@@ -239,30 +289,39 @@ function SmartPickupFrame:rebuild()
|
||||
self.selectedRunId = store.runs[1] ~= nil and store.runs[1].id or nil
|
||||
end
|
||||
self:clearRows()
|
||||
if adEnv ~= nil then
|
||||
self:fillOverviewRows(adEnv)
|
||||
local isOverview = self.currentTab == SmartPickupFrame.TAB_OVERVIEW
|
||||
self:setStaticRowsVisible(not isOverview)
|
||||
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.targetOption, self.ingredientModeOption, self.waitPoolOption, self.loopsOption, self.returnBelowOption}) do
|
||||
for _, element in ipairs({self.ingredientModeOption, self.waitPoolOption, self.loopsOption, self.returnBelowOption}) do
|
||||
element:setDisabled(not hasRun)
|
||||
end
|
||||
if hasRun then
|
||||
self:fillTargetOption(adEnv, run)
|
||||
self.ingredientModeOption:setState(run.ingredientMode == "manual" and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false)
|
||||
self:fillIngredientRows(adEnv, run)
|
||||
self.needsRow = self:addTextRow(self:describeNeeds(adEnv, run))
|
||||
self:fillWaitPoolOption(adEnv, run)
|
||||
self.loopsOption:setState(run.loops + 1, false)
|
||||
self.returnBelowOption:setState(self:getReturnBelowIndex(run), false)
|
||||
self:addTextRow(self.i18n:getText("spu_targets"))
|
||||
self:fillTargetRows(adEnv, run)
|
||||
self:fillIngredientRows(adEnv, run)
|
||||
self:fillNeedsRows(adEnv, run)
|
||||
self:addTextRow(self.i18n:getText("spu_vehicles"))
|
||||
self:fillVehicleRows(adEnv, run)
|
||||
end
|
||||
if adEnv ~= nil then
|
||||
self:addTextRow(self.i18n:getText("spu_waitPools"))
|
||||
self:fillPoolRows(adEnv)
|
||||
end
|
||||
self.statusRow = self:addTextRow("")
|
||||
self:colorRows()
|
||||
self.boxLayout:invalidateLayout()
|
||||
@@ -289,18 +348,49 @@ function SmartPickupFrame:fillRunOption(adEnv)
|
||||
self.runOption:setDisabled(#self.runIds == 0)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fillTargetOption(adEnv, run)
|
||||
local texts, index = {self.i18n:getText("spu_noTarget")}, 1
|
||||
self.targetIds = {false}
|
||||
-- Mål = afkrydsning (flere stalde/fabrikker pr. run). Ved hver tur vælges den der mangler mest.
|
||||
function SmartPickupFrame:fillTargetRows(adEnv, run)
|
||||
local chosen = {}
|
||||
for _, id in ipairs(ADRunsController.getRunTargets(run)) do
|
||||
chosen[id] = true
|
||||
end
|
||||
for _, marker in ipairs(ADRunsController.getTargetMarkers(adEnv, g_currentMission:getFarmId())) do
|
||||
table.insert(texts, tostring(marker.name))
|
||||
table.insert(self.targetIds, marker.id)
|
||||
if marker.id == run.targetWayPointId then
|
||||
index = #texts
|
||||
local row = self:addRow(self.ingredientPrefab, {kind = "target", wayPointId = marker.id})
|
||||
row:getDescendantByName("title"):setText(" " .. tostring(marker.name))
|
||||
row:getDescendantByName("option"):setState(chosen[marker.id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false)
|
||||
end
|
||||
end
|
||||
|
||||
-- Behovsrække pr. mål ("Cow 1 Food: Forage 0/33.750 l · …"), opdateres hvert sekund.
|
||||
function SmartPickupFrame:fillNeedsRows(adEnv, run)
|
||||
self.needsRows = {}
|
||||
local targets = ADRunsController.getTargetsLevels(adEnv, run)
|
||||
if #targets == 0 then
|
||||
self:addTextRow(self.i18n:getText("spu_needs_noTarget"))
|
||||
return
|
||||
end
|
||||
for _, target in ipairs(targets) do
|
||||
table.insert(self.needsRows, {wayPointId = target.wayPointId, title = self:addTextRow(self:describeTargetNeeds(target))})
|
||||
end
|
||||
end
|
||||
|
||||
function SmartPickupFrame:describeTargetNeeds(target)
|
||||
if #target.levels == 0 then
|
||||
return string.format("%s: %s", target.name, self.i18n:getText("spu_needs_none"))
|
||||
end
|
||||
return string.format(self.i18n:getText("spu_needs"), target.name .. ": " .. self:formatLevels(target.levels))
|
||||
end
|
||||
|
||||
function SmartPickupFrame:refreshNeedsRows(adEnv, run)
|
||||
local byId = {}
|
||||
for _, target in ipairs(ADRunsController.getTargetsLevels(adEnv, run)) do
|
||||
byId[target.wayPointId] = target
|
||||
end
|
||||
for _, row in ipairs(self.needsRows or {}) do
|
||||
if byId[row.wayPointId] ~= nil then
|
||||
row.title:setText(self:describeTargetNeeds(byId[row.wayPointId]))
|
||||
end
|
||||
end
|
||||
self.targetOption:setTexts(texts)
|
||||
self.targetOption:setState(index, false)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:fillIngredientRows(adEnv, run)
|
||||
@@ -404,11 +494,6 @@ function SmartPickupFrame:syncOptionsFromModel(adEnv, run)
|
||||
option:setState(wantedIndex, false)
|
||||
end
|
||||
end
|
||||
local targetIndex = 1
|
||||
for index, id in ipairs(self.targetIds) do
|
||||
if id == run.targetWayPointId then targetIndex = index end
|
||||
end
|
||||
sync(self.targetOption, targetIndex)
|
||||
sync(self.ingredientModeOption, run.ingredientMode == "manual" and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF)
|
||||
local poolIndex = 1
|
||||
for index, group in ipairs(self.poolGroups) do
|
||||
@@ -429,17 +514,6 @@ function SmartPickupFrame:formatLevels(levels)
|
||||
return table.concat(parts, " · ")
|
||||
end
|
||||
|
||||
function SmartPickupFrame:describeNeeds(adEnv, run)
|
||||
if run.targetWayPointId == nil then
|
||||
return self.i18n:getText("spu_needs_noTarget")
|
||||
end
|
||||
local levels = ADRunsController.getTargetLevels(adEnv, run)
|
||||
if #levels == 0 then
|
||||
return self.i18n:getText("spu_needs_none")
|
||||
end
|
||||
return string.format(self.i18n:getText("spu_needs"), self:formatLevels(levels))
|
||||
end
|
||||
|
||||
-- ---- overblik (øverst): ét afsnit pr. run — status, traktorernes aktivitet, målets niveauer ----
|
||||
|
||||
function SmartPickupFrame:describeActivity(adEnv, vehicle)
|
||||
@@ -469,24 +543,22 @@ function SmartPickupFrame:fillOverviewRows(adEnv)
|
||||
return title
|
||||
end
|
||||
add(self.i18n:getText("spu_overview"))
|
||||
local targetMarkerName = function(run)
|
||||
local marker = run.targetWayPointId ~= nil and adEnv.ADGraphManager:getMapMarkerByWayPointId(run.targetWayPointId) or nil
|
||||
return marker ~= nil and tostring(marker.name) or self.i18n:getText("spu_noTarget")
|
||||
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 = {}, target = nil}
|
||||
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
|
||||
entry.target = add(string.format(" %s: %s", targetMarkerName(run), self:formatLevels(ADRunsController.getTargetLevels(adEnv, run))))
|
||||
for _, target in ipairs(ADRunsController.getTargetsLevels(adEnv, run)) do
|
||||
table.insert(entry.targets, {wayPointId = target.wayPointId, title = add(" " .. self:describeTargetNeeds(target))})
|
||||
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
|
||||
@@ -512,9 +584,14 @@ function SmartPickupFrame:refreshOverview(adEnv)
|
||||
for _, item in ipairs(entry.vehicles) do
|
||||
item.title:setText(" " .. self:describeActivity(adEnv, item.vehicle))
|
||||
end
|
||||
if entry.target ~= nil then
|
||||
local marker = entry.run.targetWayPointId ~= nil and adEnv.ADGraphManager:getMapMarkerByWayPointId(entry.run.targetWayPointId) or nil
|
||||
entry.target:setText(string.format(" %s: %s", marker ~= nil and tostring(marker.name) or self.i18n:getText("spu_noTarget"), self:formatLevels(ADRunsController.getTargetLevels(adEnv, entry.run))))
|
||||
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:describeTargetNeeds(byId[item.wayPointId]))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -564,9 +641,7 @@ function SmartPickupFrame:refreshLive()
|
||||
local isRunning = false
|
||||
if run ~= nil then
|
||||
self:syncOptionsFromModel(adEnv, run)
|
||||
if self.needsRow ~= nil then
|
||||
self.needsRow:setText(self:describeNeeds(adEnv, run))
|
||||
end
|
||||
self:refreshNeedsRows(adEnv, run)
|
||||
local status = ADRunsController.getRunStatus(adEnv, run)
|
||||
isRunning = status.running > 0
|
||||
local text = isRunning and string.format(self.i18n:getText("spu_status_running"), status.running, status.total)
|
||||
@@ -600,12 +675,12 @@ function SmartPickupFrame:onClickRun(state)
|
||||
self:requestRebuild()
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickTarget(state)
|
||||
function SmartPickupFrame:onClickTarget(state, element)
|
||||
self:safe(function(frame)
|
||||
local run = frame:getRun()
|
||||
if run == nil then return end
|
||||
-- targetIds[1] er false = "(vælg mål)"; modellen tolker false som "ryd målet"
|
||||
ADRunsController.updateRun(run.id, {targetWayPointId = frame.targetIds[state] or false})
|
||||
local run, data = frame:getRun(), frame.rowData[element]
|
||||
if run == nil or data == nil then return end
|
||||
ADRunsController.store = ADRuns.toggleTarget(ADRunsController.store, run.id, data.wayPointId)
|
||||
Logging.info(SmartPickupFrame.LOG_PREFIX .. "run '%s': targets=%s", tostring(run.name), table.concat(ADRunsController.getRunTargets(ADRuns.getRun(ADRunsController.store, run.id)), " "))
|
||||
frame:requestRebuild()
|
||||
end)
|
||||
end
|
||||
@@ -620,9 +695,14 @@ function SmartPickupFrame:onClickIngredientMode(state)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickIngredient(state, element)
|
||||
-- mål-rækkerne deler prefab (og dermed onClick) med vare-rækkerne
|
||||
local data = self.rowData[element]
|
||||
if data ~= nil and data.kind == "target" then
|
||||
return self:onClickTarget(state, element)
|
||||
end
|
||||
self:safe(function(frame)
|
||||
local run, data = frame:getRun(), frame.rowData[element]
|
||||
if run == nil or data == nil then return end
|
||||
if run == nil or data == nil or data.kind ~= "ingredient" then return end
|
||||
local names = {}
|
||||
for _, name in ipairs(run.ingredients) do
|
||||
if name ~= data.name then table.insert(names, name) end
|
||||
|
||||
Reference in New Issue
Block a user