feat(oversigt): 'Stop alt og parkér' — flows, markarbejde og marksilo-lån stoppes, køretøjer til AD-parkering (manuelle høstere nævnes), pause der gemmes; 'Start alle' ophæver pausen og starter traktorerne én ad gangen hvert 10. sekund (v1.42.0.0)
This commit is contained in:
@@ -208,6 +208,7 @@ function ADFieldJobs.load()
|
||||
ADFieldJobs.state.fleetMode = loaded.fleetMode or "all"
|
||||
ADFieldJobs.state.courseRecords = loaded.courseRecords or {}
|
||||
ADFieldJobs.state.manual = loaded.manual or {}
|
||||
ADFieldJobs.state.paused = loaded.paused == true
|
||||
else
|
||||
Logging.warning(ADFieldJobs.LOG_PREFIX .. "marker kunne ikke indlæses: %s", tostring(loaded))
|
||||
end
|
||||
@@ -252,6 +253,13 @@ function ADFieldJobs.setFleetMode(mode)
|
||||
ADFieldJobs.save()
|
||||
end
|
||||
|
||||
-- Pause (Stop alt og parkér): intet nyt sendes ud, ingen genstart efter indlæsning. Gemmes.
|
||||
function ADFieldJobs.setPaused(value)
|
||||
ADFieldJobs.state.paused = value == true
|
||||
ADFieldJobs.save()
|
||||
Logging.info(ADFieldJobs.LOG_PREFIX .. "markarbejde %s", value and "på pause" or "genoptaget")
|
||||
end
|
||||
|
||||
function ADFieldJobs.toggleManual(vehicleId)
|
||||
ADFieldJobs.state.manual = ADFieldFleet.toggle(ADFieldJobs.state.manual or {}, vehicleId)
|
||||
ADFieldJobs.save()
|
||||
@@ -407,6 +415,8 @@ function ADFieldJobs.tick(adEnv, dt)
|
||||
-- lidt efter start, og indtil da ligner de maskiner ledige (in-game 26/9: kultivatoren blev taget midt
|
||||
-- i spillerens eget CP-job 45 s efter indlæsning)
|
||||
if ADFieldJobs.now < ADFieldJobs.STARTUP_GRACE_MS then return end
|
||||
-- Stop alt og parkér: intet sendes ud og intet genstartes, før spilleren trykker Start alle
|
||||
if ADFieldJobs.state.paused then return end
|
||||
if not ADFieldJobs.resumedAfterLoad then
|
||||
-- én gang, før noget nyt sendes ud: CP-maskiner der var midt i et job, fortsætter (og tæller som aktive)
|
||||
ADFieldJobs.resumedAfterLoad = true
|
||||
|
||||
@@ -337,7 +337,8 @@ function ADFieldSilos.planNow(adEnv)
|
||||
local plan = ADFieldSiloPlanner.plan({silos = silos, stores = stores, loans = loanList(), vehicles = vehicles,
|
||||
paused = currentPaused(), maxVehicles = cfg.maxVehicles, minLiters = cfg.minLiters})
|
||||
ADFieldSilos.lastPlan = plan
|
||||
if not cfg.enabled then return plan end
|
||||
local paused = ADFieldJobs ~= nil and ADFieldJobs.state ~= nil and ADFieldJobs.state.paused
|
||||
if not cfg.enabled or paused then return plan end
|
||||
local silosById, storesById = {}, {}
|
||||
for _, silo in ipairs(silos) do silosById[silo.id] = silo end
|
||||
for _, store in ipairs(stores) do storesById[store.id] = store end
|
||||
|
||||
@@ -68,6 +68,7 @@ function ADFieldStorage.save(state)
|
||||
index = index + 1
|
||||
end
|
||||
xmlFile:setString(ADFieldStorage.ROOT .. "#fleetMode", state.fleetMode or "all")
|
||||
xmlFile:setInt(ADFieldStorage.ROOT .. "#paused", state.paused == true and 1 or 0)
|
||||
local vehicleIndex = 0
|
||||
for vehicleId in pairs(state.fleet) do
|
||||
xmlFile:setString(string.format("%s.fleet.vehicle(%d)#id", ADFieldStorage.ROOT, vehicleIndex), vehicleId)
|
||||
@@ -89,12 +90,13 @@ function ADFieldStorage.save(state)
|
||||
end
|
||||
|
||||
function ADFieldStorage.load()
|
||||
local result = {fields = {}, fleet = {}, fleetMode = "all", courseRecords = {}, manual = {}}
|
||||
local result = {fields = {}, fleet = {}, fleetMode = "all", courseRecords = {}, manual = {}, paused = false}
|
||||
local path = ADFieldStorage.getPath()
|
||||
if path == nil or not fileExists(path) then return result end
|
||||
local xmlFile = XMLFile.load("ADSmartPickupFields", path)
|
||||
if xmlFile == nil then return result end
|
||||
result.fleetMode = xmlFile:getString(ADFieldStorage.ROOT .. "#fleetMode") == "ticked" and "ticked" or "all"
|
||||
result.paused = xmlFile:getInt(ADFieldStorage.ROOT .. "#paused") == 1
|
||||
xmlFile:iterate(ADFieldStorage.ROOT .. ".field", function(_, key)
|
||||
local field = ADFieldModel.fromRecord(ADFieldStorage.readRecord(xmlFile, key))
|
||||
if field.id ~= nil then result.fields[field.id] = field end
|
||||
|
||||
@@ -1083,6 +1083,21 @@ function ADFieldWork.windDownHelpers(adEnv, fieldId, stage)
|
||||
end
|
||||
end
|
||||
|
||||
-- Stop alle markarbejdets opgaver (Stop alt og parkér). Returnerer {{vehicle, manual}}; markernes trin bevares,
|
||||
-- så arbejdet fortsætter efter pausen.
|
||||
function ADFieldWork.stopAllAssignments(adEnv)
|
||||
local stopped = {}
|
||||
local list = {}
|
||||
for _, assignment in pairs(ADFieldJobs.state.assignments) do table.insert(list, assignment) end
|
||||
for _, assignment in ipairs(list) do
|
||||
pcall(stopAd, assignment.vehicle)
|
||||
pcall(ADCpBridge.stop, assignment.vehicle)
|
||||
table.insert(stopped, {vehicle = assignment.vehicle, manual = assignment.manual == true})
|
||||
ADFieldWork.release(assignment)
|
||||
end
|
||||
return stopped
|
||||
end
|
||||
|
||||
function ADFieldWork.stopAll(adEnv, fieldId)
|
||||
for _, assignment in ipairs(ADFieldJobs.assignmentsFor(fieldId)) do
|
||||
pcall(stopAd, assignment.vehicle)
|
||||
|
||||
@@ -1153,6 +1153,56 @@ function ADRunsController.queueStartAll(adEnv)
|
||||
return summary
|
||||
end
|
||||
|
||||
-- Stop alt og parkér (Oversigt): flows, markarbejde og marksilo-lån stoppes, køretøjerne sendes til deres
|
||||
-- AD-parkeringspunkt, og moden sættes på pause (gemmes), så intet starter igen før "Start alle".
|
||||
-- Høstere med manuel transport parkeres ikke (må ikke køre på vejen med skærebord). Returnerer
|
||||
-- {stopped, parked, noPark = {navne}, manual = {navne}}.
|
||||
function ADRunsController.stopAllAndPark(adEnv)
|
||||
local summary = {stopped = 0, parked = 0, noPark = {}, manual = {}}
|
||||
ADRunsController.clearStartQueue()
|
||||
local toPark, seen = {}, {}
|
||||
local vehiclesById = getFarmVehiclesById(adEnv)
|
||||
for _, run in ipairs(ADRunsController.store.runs) do
|
||||
for _, vehicleId in ipairs(run.vehicleIds) do
|
||||
local vehicle = vehiclesById[vehicleId]
|
||||
if vehicle ~= nil and not seen[vehicle] then
|
||||
seen[vehicle] = true
|
||||
if isVehicleActive(vehicle) then
|
||||
stopVehicle(vehicle)
|
||||
summary.stopped = summary.stopped + 1
|
||||
end
|
||||
table.insert(toPark, vehicle)
|
||||
end
|
||||
end
|
||||
ADRunsController.runningRuns[run.id] = nil
|
||||
end
|
||||
if ADFieldWork ~= nil and ADFieldWork.stopAllAssignments ~= nil then
|
||||
for _, stopped in ipairs(ADFieldWork.stopAllAssignments(adEnv) or {}) do
|
||||
summary.stopped = summary.stopped + 1
|
||||
if stopped.manual then
|
||||
table.insert(summary.manual, tostring(ADRuns.vehicleLabel(stopped.vehicle)))
|
||||
elseif not seen[stopped.vehicle] then
|
||||
seen[stopped.vehicle] = true
|
||||
table.insert(toPark, stopped.vehicle)
|
||||
end
|
||||
end
|
||||
end
|
||||
if ADFieldSilos ~= nil and ADFieldSilos.stopAll ~= nil then pcall(ADFieldSilos.stopAll, adEnv) end
|
||||
if ADFieldJobs ~= nil and ADFieldJobs.setPaused ~= nil then ADFieldJobs.setPaused(true) end
|
||||
for _, vehicle in ipairs(toPark) do
|
||||
local park = ADFieldWork ~= nil and ADFieldWork.parkMarkerId ~= nil and ADFieldWork.parkMarkerId(adEnv, vehicle) or nil
|
||||
if park ~= nil then
|
||||
local ok = pcall(ADFieldWork.startAd, adEnv, vehicle, adEnv.AutoDrive.MODE_DRIVETO, park, nil)
|
||||
if ok then summary.parked = summary.parked + 1 end
|
||||
else
|
||||
table.insert(summary.noPark, tostring(ADRuns.vehicleLabel(vehicle)))
|
||||
end
|
||||
end
|
||||
Logging.info(ADRunsController.LOG_PREFIX .. "Stop alt og parkér: %d stoppet, %d til parkering, %d uden parkeringspunkt, %d høstere hentes manuelt — pause",
|
||||
summary.stopped, summary.parked, #summary.noPark, #summary.manual)
|
||||
return summary
|
||||
end
|
||||
|
||||
-- Starter næste traktor i køen, når der er gået STAGGER_MS siden forrige.
|
||||
function ADRunsController.processStartQueue(adEnv, dt)
|
||||
if #ADRunsController.startQueue == 0 then return end
|
||||
|
||||
@@ -1254,6 +1254,9 @@ function ADSmartPickup:update(dt)
|
||||
if ADOutbound ~= nil and ADOutbound.releaseInactive ~= nil then
|
||||
pcall(ADOutbound.releaseInactive)
|
||||
end
|
||||
if ADRunsController ~= nil and ADRunsController.processStartQueue ~= nil then
|
||||
pcall(ADRunsController.processStartQueue, getAutoDriveEnv(), dt)
|
||||
end
|
||||
if ADRunsController ~= nil and ADRunsController.applyVehicleNamesThrottled ~= nil then
|
||||
pcall(ADRunsController.applyVehicleNamesThrottled, getAutoDriveEnv(), dt)
|
||||
end
|
||||
|
||||
@@ -58,7 +58,9 @@ function SmartPickupFrame.new(i18n, getAdEnv)
|
||||
self.renameBuildingButtonInfo = {inputAction = InputAction.MENU_EXTRA_2, text = i18n:getText("spu_button_renameBuilding"), callback = function() self:onClickRenameBuilding() end}
|
||||
self.storageButtons = {self.backButtonInfo, self.renameBuildingButtonInfo}
|
||||
self.flowButtons = {self.backButtonInfo, self.startButtonInfo, self.newButtonInfo, self.renameButtonInfo, self.deleteButtonInfo}
|
||||
self.overviewButtons = {self.backButtonInfo, self.startAllButtonInfo, self.stopAllButtonInfo, self.newButtonInfo}
|
||||
-- Stop alt og parkér: flows + markarbejde + marksilo stoppes, køretøjer til parkering, pause til Start alle
|
||||
self.stopParkButtonInfo = {inputAction = InputAction.MENU_CANCEL, text = i18n:getText("spu_button_stopPark"), callback = function() self:onClickStopAndPark() end}
|
||||
self.overviewButtons = {self.backButtonInfo, self.startAllButtonInfo, self.stopAllButtonInfo, self.stopParkButtonInfo, self.newButtonInfo}
|
||||
-- Marker: Start nu / Stop for den valgte mark
|
||||
-- Marker: [Start nu/Stop], [Opsæt mark], [Markflåde] (gui/SmartPickupFieldGuide.lua); guidens knapper
|
||||
self:initFieldButtons(i18n)
|
||||
@@ -628,7 +630,15 @@ function SmartPickupFrame:refreshLive()
|
||||
running, total = running + status.running, total + status.total
|
||||
if status.running > 0 then activeRuns = activeRuns + 1 end
|
||||
end
|
||||
self:setStatusText(self.statusOverride or string.format(self.i18n:getText("spu_status_overview"), running, total, activeRuns, #ADRunsController.store.runs))
|
||||
local statusText = string.format(self.i18n:getText("spu_status_overview"), running, total, activeRuns, #ADRunsController.store.runs)
|
||||
local queued = #(ADRunsController.startQueue or {})
|
||||
if queued > 0 then
|
||||
local totalQueued = ADRunsController.startQueueTotal or queued
|
||||
statusText = string.format(self.i18n:getText("spu_status_starting"), totalQueued - queued, totalQueued)
|
||||
elseif ADFieldJobs ~= nil and ADFieldJobs.state ~= nil and ADFieldJobs.state.paused then
|
||||
statusText = self.i18n:getText("spu_status_paused")
|
||||
end
|
||||
self:setStatusText(self.statusOverride or statusText)
|
||||
self.stopAllButtonInfo.disabled = running == 0
|
||||
elseif run ~= nil then
|
||||
self:syncOptionsFromModel(adEnv, run)
|
||||
@@ -786,11 +796,28 @@ function SmartPickupFrame:onClickStartAll()
|
||||
self:safe(function(frame)
|
||||
local adEnv = frame.getAdEnv()
|
||||
if adEnv == nil then return end
|
||||
local summary = ADRunsController.startAllRuns(adEnv)
|
||||
local _, skipped, reasons = frame:summarizeStartResults(summary.results)
|
||||
Logging.info(SmartPickupFrame.LOG_PREFIX .. "Start alle: %d flows startet (%d traktorer), %d kørte allerede, %d sprunget over",
|
||||
summary.runsStarted, summary.vehiclesStarted, summary.alreadyRunning, skipped)
|
||||
frame:showOverride(string.format(frame.i18n:getText("spu_status_startedAll"), summary.runsStarted, summary.vehiclesStarted, summary.alreadyRunning, skipped), reasons)
|
||||
-- pausen (Stop alt og parkér) ophæves; traktorerne startes én ad gangen med mellemrum
|
||||
if ADFieldJobs ~= nil and ADFieldJobs.state ~= nil and ADFieldJobs.state.paused then ADFieldJobs.setPaused(false) end
|
||||
local summary = ADRunsController.queueStartAll(adEnv)
|
||||
local _, skipped, reasons = frame:summarizeStartResults(summary.skipped)
|
||||
Logging.info(SmartPickupFrame.LOG_PREFIX .. "Start alle: %d traktorer i kø (én hvert %d. sekund), %d flows kørte allerede, %d sprunget over",
|
||||
summary.queued, math.floor(ADRunsController.STAGGER_MS / 1000), summary.alreadyRunning, skipped)
|
||||
frame:showOverride(string.format(frame.i18n:getText("spu_status_queuedAll"), summary.queued, math.floor(ADRunsController.STAGGER_MS / 1000), summary.alreadyRunning, skipped), reasons)
|
||||
ADRunsController.save()
|
||||
frame:requestRebuild()
|
||||
end)
|
||||
end
|
||||
|
||||
function SmartPickupFrame:onClickStopAndPark()
|
||||
self:safe(function(frame)
|
||||
local adEnv = frame.getAdEnv()
|
||||
if adEnv == nil then return end
|
||||
local summary = ADRunsController.stopAllAndPark(adEnv)
|
||||
local text = string.format(frame.i18n:getText("spu_status_stopParked"), summary.stopped, summary.parked)
|
||||
local notes = {}
|
||||
if #summary.noPark > 0 then table.insert(notes, string.format(frame.i18n:getText("spu_status_noPark"), table.concat(summary.noPark, ", "))) end
|
||||
if #summary.manual > 0 then table.insert(notes, string.format(frame.i18n:getText("spu_status_fetchManual"), table.concat(summary.manual, ", "))) end
|
||||
frame:showOverride(text, notes)
|
||||
ADRunsController.save()
|
||||
frame:requestRebuild()
|
||||
end)
|
||||
|
||||
@@ -218,6 +218,13 @@
|
||||
<text name="spu_button_new" text="Nyt flow"/>
|
||||
<text name="spu_button_renameBuilding" text="Omdøb bygning"/>
|
||||
<text name="spu_renameBuildingTitle" text="Nyt navn på bygningen (tomt = butiksnavnet)"/>
|
||||
<text name="spu_button_stopPark" text="Stop alt og parkér"/>
|
||||
<text name="spu_status_queuedAll" text="Start alle: %d traktorer startes én ad gangen (hvert %d. sekund), %d flows kørte allerede, %d sprunget over"/>
|
||||
<text name="spu_status_stopParked" text="Stop alt: %d stoppet, %d på vej til parkering — pause til Start alle"/>
|
||||
<text name="spu_status_noPark" text="uden parkeringspunkt: %s"/>
|
||||
<text name="spu_status_fetchManual" text="hent selv (for brede): %s"/>
|
||||
<text name="spu_status_starting" text="Starter traktorer: %d af %d …"/>
|
||||
<text name="spu_status_paused" text="Pause — tryk Start alle for at fortsætte"/>
|
||||
<text name="spu_button_rename" text="Omdøb"/>
|
||||
<text name="spu_button_delete" text="Slet flow"/>
|
||||
<text name="spu_newRunName" text="Flow %d"/>
|
||||
|
||||
@@ -218,6 +218,13 @@
|
||||
<text name="spu_button_new" text="New flow"/>
|
||||
<text name="spu_button_renameBuilding" text="Rename building"/>
|
||||
<text name="spu_renameBuildingTitle" text="New name for the building (empty = shop name)"/>
|
||||
<text name="spu_button_stopPark" text="Stop all and park"/>
|
||||
<text name="spu_status_queuedAll" text="Start all: %d tractors start one at a time (every %d seconds), %d flows already running, %d skipped"/>
|
||||
<text name="spu_status_stopParked" text="Stop all: %d stopped, %d driving to parking — paused until Start all"/>
|
||||
<text name="spu_status_noPark" text="no park destination: %s"/>
|
||||
<text name="spu_status_fetchManual" text="fetch yourself (too wide): %s"/>
|
||||
<text name="spu_status_starting" text="Starting tractors: %d of %d …"/>
|
||||
<text name="spu_status_paused" text="Paused — press Start all to continue"/>
|
||||
<text name="spu_button_rename" text="Rename"/>
|
||||
<text name="spu_button_delete" text="Delete flow"/>
|
||||
<text name="spu_newRunName" text="Flow %d"/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<modDesc descVersion="107">
|
||||
<author>masterdraco</author>
|
||||
<version>1.41.1.0</version>
|
||||
<version>1.42.0.0</version>
|
||||
<title>
|
||||
<en>AD Smart Pickup</en>
|
||||
</title>
|
||||
|
||||
@@ -98,5 +98,13 @@ ADFieldStorage.save({fields = {}, fleet = {}, fleetMode = "all", manual = {vehic
|
||||
check("ST8 manuel transport indlæst", ADFieldStorage.load().manual.vehicleCombine, true)
|
||||
check("ST8 gammel fil: ingen manuelle", next(old.manual or {}), nil)
|
||||
|
||||
-- ST9: pause ("Stop alt og parkér") gemmes, så intet starter af sig selv efter indlæsning
|
||||
disk = {}
|
||||
ADFieldStorage.save({fields = {}, fleet = {}, fleetMode = "all", paused = true})
|
||||
check("ST9 pause indlæst", ADFieldStorage.load().paused, true)
|
||||
disk = {}
|
||||
ADFieldStorage.save({fields = {}, fleet = {}, fleetMode = "all"})
|
||||
check("ST9 ingen pause", ADFieldStorage.load().paused, false)
|
||||
|
||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||
os.exit(failures == 0 and 0 or 1)
|
||||
|
||||
@@ -863,5 +863,38 @@ do
|
||||
check("C20 run markeret kørende", ADRunsController.runningRuns[qrun.id], true)
|
||||
end
|
||||
|
||||
|
||||
-- C21: Stop alt og parkér — stopper flow-traktorerne, sender dem til AD-parkering, sætter pause
|
||||
do
|
||||
buildWorld()
|
||||
local p1 = makeVehicle("vehicleP1", "P1", {STRAW, TMR}, 1000000, 100, 0)
|
||||
local p2 = makeVehicle("vehicleP2", "P2", {STRAW, TMR}, 1000000, 110, 0)
|
||||
local prun = ADRunsController.createRun("Park")
|
||||
ADRunsController.updateRun(prun.id, {targetWayPointIds = {94}})
|
||||
ADRunsController.assignVehicle(prun.id, p1)
|
||||
ADRunsController.assignVehicle(prun.id, p2)
|
||||
ADRunsController.startRun(adEnv, prun.id)
|
||||
local parked, paused = {}, nil
|
||||
local oldWork, oldJobs, oldSilos = ADFieldWork, ADFieldJobs, ADFieldSilos
|
||||
ADFieldWork = {
|
||||
parkMarkerId = function(_, v) return v == p1 and 700 or nil end,
|
||||
startAd = function(_, v, mode, first) parked[v] = first end,
|
||||
stopAllAssignments = function() return {} end,
|
||||
}
|
||||
ADFieldJobs = {setPaused = function(value) paused = value end}
|
||||
ADFieldSilos = {stopAll = function() end}
|
||||
ADRunsController.queueStartAll(adEnv)
|
||||
local summary = ADRunsController.stopAllAndPark(adEnv)
|
||||
check("C21 begge stoppet", (p1.stopped or 0) >= 1 and (p2.stopped or 0) >= 1, true)
|
||||
check("C21 P1 kører til parkering", parked[p1], 700)
|
||||
check("C21 P2 uden parkering bliver stående", parked[p2], nil)
|
||||
check("C21 tæller parkerede", summary.parked, 1)
|
||||
check("C21 nævner dem uden parkering", summary.noPark[1], "P2")
|
||||
check("C21 pause sat", paused, true)
|
||||
check("C21 startkø tømt", #ADRunsController.startQueue, 0)
|
||||
check("C21 run ikke længere kørende", ADRunsController.runningRuns[prun.id], nil)
|
||||
ADFieldWork, ADFieldJobs, ADFieldSilos = oldWork, oldJobs, oldSilos
|
||||
end
|
||||
|
||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||
os.exit(failures == 0 and 0 or 1)
|
||||
|
||||
Reference in New Issue
Block a user