feat(udkørsel): 'Lager til' — tvunget aflæsningssted pr. flow (siloer/egne fabrikker; første med plads og vej), XML #storeBuildings (v1.18.0.0)
This commit is contained in:
@@ -139,6 +139,30 @@ function ADLoadSwap.findDumpMarker(adEnv, vehicle, fillType, rest, homeWayPointI
|
|||||||
return nil, string.format("%d silo(er) tager varen, men AutoDrive finder ingen rute fra traktoren til dem", withSpace)
|
return nil, string.format("%d silo(er) tager varen, men AutoDrive finder ingen rute fra traktoren til dem", withSpace)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Tvunget lagermål (flowets "Lager til"): kun de valgte aflæsningsmarkører, i rækkefølge. Første der
|
||||||
|
-- tager varen, har plads til læsset og kan nås, vinder. Returnerer marker — eller nil + forklaring.
|
||||||
|
function ADLoadSwap.findForcedDumpMarker(adEnv, vehicle, fillType, liters, markerIds, isReachable)
|
||||||
|
local farmId = ADSmartPickup.getFarmId(vehicle)
|
||||||
|
local reasons = {}
|
||||||
|
for _, wayPointId in ipairs(markerIds or {}) do
|
||||||
|
local marker = adEnv.ADGraphManager:getMapMarkerByWayPointId(wayPointId)
|
||||||
|
local station = marker ~= nil and ADSmartPickup.getUnloadStationAtWayPointId(adEnv, wayPointId, farmId) or nil
|
||||||
|
local name = marker ~= nil and tostring(marker.name) or tostring(wayPointId)
|
||||||
|
if station == nil then
|
||||||
|
table.insert(reasons, name .. ": ingen aflæsning ved markøren")
|
||||||
|
elseif station.getIsFillTypeSupported ~= nil and not station:getIsFillTypeSupported(fillType) then
|
||||||
|
table.insert(reasons, name .. ": tager ikke varen")
|
||||||
|
elseif not acceptsRest(station, fillType, liters, farmId) then
|
||||||
|
table.insert(reasons, name .. ": fuld")
|
||||||
|
elseif not isReachable(wayPointId) then
|
||||||
|
table.insert(reasons, name .. ": ingen vej")
|
||||||
|
else
|
||||||
|
return marker
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil, "valgt lager: " .. (#reasons > 0 and table.concat(reasons, "; ") or "ingen markør")
|
||||||
|
end
|
||||||
|
|
||||||
-- Kaldes fra Wait-logikken hvert tick; redirect(task, id) og release(vehicle) er dens egne.
|
-- Kaldes fra Wait-logikken hvert tick; redirect(task, id) og release(vehicle) er dens egne.
|
||||||
-- true = traktoren er sendt til en silo (Wait-punktet er frigivet).
|
-- true = traktoren er sendt til en silo (Wait-punktet er frigivet).
|
||||||
function ADLoadSwap.tryFromWait(adEnv, task, wait, dt, redirect, release, isReachable)
|
function ADLoadSwap.tryFromWait(adEnv, task, wait, dt, redirect, release, isReachable)
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ local function findSellQuote(adEnv, vehicle, product, sellMarkers, sellAtPercent
|
|||||||
return quotes[1], nil
|
return quotes[1], nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local function findStoreMarker(adEnv, vehicle, product, capacity, sources, litersOverride)
|
local function findStoreMarker(adEnv, vehicle, product, capacity, sources, litersOverride, run)
|
||||||
local isReachable = function(markerId)
|
local isReachable = function(markerId)
|
||||||
return ADWaitPool.hasRouteTo(adEnv, vehicle, markerId)
|
return ADWaitPool.hasRouteTo(adEnv, vehicle, markerId)
|
||||||
end
|
end
|
||||||
@@ -200,6 +200,16 @@ local function findStoreMarker(adEnv, vehicle, product, capacity, sources, liter
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local liters = math.max(1, math.min(available, capacity or available))
|
local liters = math.max(1, math.min(available, capacity or available))
|
||||||
|
-- "Lager til" valgt i flowet: KUN de bygninger (fx gylle -> BGA, aldrig AIO-fabrikken)
|
||||||
|
local forced = run ~= nil and ADRunsController ~= nil and ADRunsController.getStoreMarkers ~= nil and ADRunsController.getStoreMarkers(adEnv, run) or {}
|
||||||
|
if #forced > 0 and ADLoadSwap.findForcedDumpMarker ~= nil then
|
||||||
|
local chosen, why = ADLoadSwap.findForcedDumpMarker(adEnv, vehicle, product.fillType, liters, forced, isReachable)
|
||||||
|
if chosen == nil then
|
||||||
|
warnOnce(adEnv, vehicle, "forced:" .. tostring(product.name) .. ":" .. tostring(why), string.format("'%s': %s kan ikke læsses af — %s", tostring(ADRuns.vehicleLabel(vehicle)), tostring(product.name), tostring(why)))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return {wayPointId = chosen.id, name = tostring(chosen.name), free = liters}
|
||||||
|
end
|
||||||
local avoid = ADRunsController ~= nil and ADRunsController.getPickupMarkers ~= nil and ADRunsController.getPickupMarkers() or nil
|
local avoid = ADRunsController ~= nil and ADRunsController.getPickupMarkers ~= nil and ADRunsController.getPickupMarkers() or nil
|
||||||
local marker = ADLoadSwap.findDumpMarker(adEnv, vehicle, product.fillType, liters, nil, isReachable, ADSources.getSourcePlaceables(sources), avoid, true)
|
local marker = ADLoadSwap.findDumpMarker(adEnv, vehicle, product.fillType, liters, nil, isReachable, ADSources.getSourcePlaceables(sources), avoid, true)
|
||||||
if marker == nil then
|
if marker == nil then
|
||||||
@@ -293,7 +303,7 @@ function ADOutbound.buildPlanInput(adEnv, run, vehicle)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if wantsStore(product.policy) then
|
if wantsStore(product.policy) then
|
||||||
product.store = findStoreMarker(adEnv, vehicle, product, capacity, sources)
|
product.store = findStoreMarker(adEnv, vehicle, product, capacity, sources, nil, run)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local input = {
|
local input = {
|
||||||
@@ -331,7 +341,7 @@ function ADOutbound.planCargoTarget(adEnv, run, vehicle, fillType, liters)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if wantsStore(policy) then
|
if wantsStore(policy) then
|
||||||
local store = findStoreMarker(adEnv, vehicle, product, capacity, sources, liters or capacity)
|
local store = findStoreMarker(adEnv, vehicle, product, capacity, sources, liters or capacity, run)
|
||||||
if store ~= nil then
|
if store ~= nil then
|
||||||
return store.wayPointId
|
return store.wayPointId
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ local function copyRun(run)
|
|||||||
sourceWayPointIds = copyList(run.sourceWayPointIds),
|
sourceWayPointIds = copyList(run.sourceWayPointIds),
|
||||||
sourceBuildingIds = copyList(run.sourceBuildingIds),
|
sourceBuildingIds = copyList(run.sourceBuildingIds),
|
||||||
targetBuildingIds = copyList(run.targetBuildingIds),
|
targetBuildingIds = copyList(run.targetBuildingIds),
|
||||||
|
storeBuildingIds = copyList(run.storeBuildingIds),
|
||||||
products = copyProducts(run.products),
|
products = copyProducts(run.products),
|
||||||
sellAtPercent = run.sellAtPercent,
|
sellAtPercent = run.sellAtPercent,
|
||||||
storeAbovePercent = run.storeAbovePercent,
|
storeAbovePercent = run.storeAbovePercent,
|
||||||
@@ -93,6 +94,7 @@ function ADRuns.createRun(store, name, kind)
|
|||||||
sourceWayPointIds = {},
|
sourceWayPointIds = {},
|
||||||
sourceBuildingIds = {},
|
sourceBuildingIds = {},
|
||||||
targetBuildingIds = {},
|
targetBuildingIds = {},
|
||||||
|
storeBuildingIds = {},
|
||||||
products = {},
|
products = {},
|
||||||
sellAtPercent = ADRuns.DEFAULT_SELL_AT_PERCENT,
|
sellAtPercent = ADRuns.DEFAULT_SELL_AT_PERCENT,
|
||||||
storeAbovePercent = ADRuns.DEFAULT_STORE_ABOVE_PERCENT,
|
storeAbovePercent = ADRuns.DEFAULT_STORE_ABOVE_PERCENT,
|
||||||
@@ -158,6 +160,7 @@ function ADRuns.updateRun(store, runId, changes)
|
|||||||
if changes.sourceWayPointIds ~= nil then run.sourceWayPointIds = copyList(changes.sourceWayPointIds) end
|
if changes.sourceWayPointIds ~= nil then run.sourceWayPointIds = copyList(changes.sourceWayPointIds) end
|
||||||
if changes.sourceBuildingIds ~= nil then run.sourceBuildingIds = copyList(changes.sourceBuildingIds) end
|
if changes.sourceBuildingIds ~= nil then run.sourceBuildingIds = copyList(changes.sourceBuildingIds) end
|
||||||
if changes.targetBuildingIds ~= nil then run.targetBuildingIds = copyList(changes.targetBuildingIds) end
|
if changes.targetBuildingIds ~= nil then run.targetBuildingIds = copyList(changes.targetBuildingIds) end
|
||||||
|
if changes.storeBuildingIds ~= nil then run.storeBuildingIds = copyList(changes.storeBuildingIds) end
|
||||||
if changes.products ~= nil then run.products = copyProducts(changes.products) end
|
if changes.products ~= nil then run.products = copyProducts(changes.products) end
|
||||||
if changes.sellAtPercent ~= nil then run.sellAtPercent = clampRange(changes.sellAtPercent, ADRuns.DEFAULT_SELL_AT_PERCENT, ADRuns.MIN_SELL_AT_PERCENT, ADRuns.MAX_SELL_AT_PERCENT) end
|
if changes.sellAtPercent ~= nil then run.sellAtPercent = clampRange(changes.sellAtPercent, ADRuns.DEFAULT_SELL_AT_PERCENT, ADRuns.MIN_SELL_AT_PERCENT, ADRuns.MAX_SELL_AT_PERCENT) end
|
||||||
if changes.storeAbovePercent ~= nil then run.storeAbovePercent = clampRange(changes.storeAbovePercent, ADRuns.DEFAULT_STORE_ABOVE_PERCENT, ADRuns.MIN_STORE_ABOVE_PERCENT, ADRuns.MAX_STORE_ABOVE_PERCENT) end
|
if changes.storeAbovePercent ~= nil then run.storeAbovePercent = clampRange(changes.storeAbovePercent, ADRuns.DEFAULT_STORE_ABOVE_PERCENT, ADRuns.MIN_STORE_ABOVE_PERCENT, ADRuns.MAX_STORE_ABOVE_PERCENT) end
|
||||||
@@ -182,6 +185,13 @@ function ADRuns.toggleSourceBuilding(store, runId, buildingId)
|
|||||||
return ADRuns.updateRun(store, runId, {sourceBuildingIds = toggleInList(run.sourceBuildingIds, buildingId)})
|
return ADRuns.updateRun(store, runId, {sourceBuildingIds = toggleInList(run.sourceBuildingIds, buildingId)})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Tvunget lagermål for udkørsel: lagerture kører KUN til disse bygninger (tom = moden vælger selv).
|
||||||
|
function ADRuns.toggleStoreBuilding(store, runId, buildingId)
|
||||||
|
local run = ADRuns.getRun(store, runId)
|
||||||
|
if run == nil then return copyStore(store) end
|
||||||
|
return ADRuns.updateRun(store, runId, {storeBuildingIds = toggleInList(run.storeBuildingIds, buildingId)})
|
||||||
|
end
|
||||||
|
|
||||||
function ADRuns.toggleTargetBuilding(store, runId, buildingId)
|
function ADRuns.toggleTargetBuilding(store, runId, buildingId)
|
||||||
local run = ADRuns.getRun(store, runId)
|
local run = ADRuns.getRun(store, runId)
|
||||||
if run == nil then return copyStore(store) end
|
if run == nil then return copyStore(store) end
|
||||||
@@ -350,6 +360,7 @@ function ADRuns.toRecords(store)
|
|||||||
sources = table.concat(run.sourceWayPointIds or {}, " "),
|
sources = table.concat(run.sourceWayPointIds or {}, " "),
|
||||||
sourceBuildings = table.concat(run.sourceBuildingIds or {}, " "),
|
sourceBuildings = table.concat(run.sourceBuildingIds or {}, " "),
|
||||||
targetBuildings = table.concat(run.targetBuildingIds or {}, " "),
|
targetBuildings = table.concat(run.targetBuildingIds or {}, " "),
|
||||||
|
storeBuildings = table.concat(run.storeBuildingIds or {}, " "),
|
||||||
products = ADRuns.serializeProducts(run.products),
|
products = ADRuns.serializeProducts(run.products),
|
||||||
sellAt = run.sellAtPercent,
|
sellAt = run.sellAtPercent,
|
||||||
storeAbove = run.storeAbovePercent,
|
storeAbove = run.storeAbovePercent,
|
||||||
@@ -392,6 +403,7 @@ function ADRuns.fromRecords(records)
|
|||||||
sourceWayPointIds = sources,
|
sourceWayPointIds = sources,
|
||||||
sourceBuildingIds = parseIds(record.sourceBuildings),
|
sourceBuildingIds = parseIds(record.sourceBuildings),
|
||||||
targetBuildingIds = parseIds(record.targetBuildings),
|
targetBuildingIds = parseIds(record.targetBuildings),
|
||||||
|
storeBuildingIds = parseIds(record.storeBuildings),
|
||||||
products = ADRuns.parseProducts(record.products),
|
products = ADRuns.parseProducts(record.products),
|
||||||
sellAtPercent = clampRange(record.sellAt, ADRuns.DEFAULT_SELL_AT_PERCENT, ADRuns.MIN_SELL_AT_PERCENT, ADRuns.MAX_SELL_AT_PERCENT),
|
sellAtPercent = clampRange(record.sellAt, ADRuns.DEFAULT_SELL_AT_PERCENT, ADRuns.MIN_SELL_AT_PERCENT, ADRuns.MAX_SELL_AT_PERCENT),
|
||||||
storeAbovePercent = clampRange(record.storeAbove, ADRuns.DEFAULT_STORE_ABOVE_PERCENT, ADRuns.MIN_STORE_ABOVE_PERCENT, ADRuns.MAX_STORE_ABOVE_PERCENT),
|
storeAbovePercent = clampRange(record.storeAbove, ADRuns.DEFAULT_STORE_ABOVE_PERCENT, ADRuns.MIN_STORE_ABOVE_PERCENT, ADRuns.MAX_STORE_ABOVE_PERCENT),
|
||||||
|
|||||||
@@ -147,6 +147,20 @@ function ADRunsController.getPickupMarkers()
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- "Lager til": aflæsningsmarkører for flowets valgte lagerbygninger, i valgt rækkefølge (tom = ingen tvang).
|
||||||
|
function ADRunsController.getStoreMarkers(adEnv, run)
|
||||||
|
local result = {}
|
||||||
|
if ADBuildings == nil or run == nil then return result end
|
||||||
|
local farmId = g_currentMission ~= nil and g_currentMission.getFarmId ~= nil and g_currentMission:getFarmId() or 1
|
||||||
|
for _, buildingId in ipairs(run.storeBuildingIds or {}) do
|
||||||
|
local building = ADBuildings.find(adEnv, farmId, buildingId)
|
||||||
|
if building ~= nil and building.unloadMarker ~= nil then
|
||||||
|
table.insert(result, building.unloadMarker.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
-- ---- køretøjsnavne ----
|
-- ---- køretøjsnavne ----
|
||||||
|
|
||||||
ADRunsController.NAME_INTERVAL_MS = 2000
|
ADRunsController.NAME_INTERVAL_MS = 2000
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ function ADRunsStorage.writeRecords(xmlFile, records)
|
|||||||
-- v3: bygninger (flow-tavlen)
|
-- v3: bygninger (flow-tavlen)
|
||||||
xmlFile:setString(key .. "#sourceBuildings", record.sourceBuildings or "")
|
xmlFile:setString(key .. "#sourceBuildings", record.sourceBuildings or "")
|
||||||
xmlFile:setString(key .. "#targetBuildings", record.targetBuildings or "")
|
xmlFile:setString(key .. "#targetBuildings", record.targetBuildings or "")
|
||||||
|
xmlFile:setString(key .. "#storeBuildings", record.storeBuildings or "")
|
||||||
xmlFile:setString(key .. "#products", record.products or "")
|
xmlFile:setString(key .. "#products", record.products or "")
|
||||||
xmlFile:setInt(key .. "#sellAt", record.sellAt or ADRuns.DEFAULT_SELL_AT_PERCENT)
|
xmlFile:setInt(key .. "#sellAt", record.sellAt or ADRuns.DEFAULT_SELL_AT_PERCENT)
|
||||||
xmlFile:setInt(key .. "#storeAbove", record.storeAbove or ADRuns.DEFAULT_STORE_ABOVE_PERCENT)
|
xmlFile:setInt(key .. "#storeAbove", record.storeAbove or ADRuns.DEFAULT_STORE_ABOVE_PERCENT)
|
||||||
@@ -69,6 +70,7 @@ function ADRunsStorage.readRecords(xmlFile)
|
|||||||
sources = xmlFile:getString(key .. "#sources"),
|
sources = xmlFile:getString(key .. "#sources"),
|
||||||
sourceBuildings = xmlFile:getString(key .. "#sourceBuildings"),
|
sourceBuildings = xmlFile:getString(key .. "#sourceBuildings"),
|
||||||
targetBuildings = xmlFile:getString(key .. "#targetBuildings"),
|
targetBuildings = xmlFile:getString(key .. "#targetBuildings"),
|
||||||
|
storeBuildings = xmlFile:getString(key .. "#storeBuildings"),
|
||||||
products = xmlFile:getString(key .. "#products"),
|
products = xmlFile:getString(key .. "#products"),
|
||||||
sellAt = xmlFile:getInt(key .. "#sellAt"),
|
sellAt = xmlFile:getInt(key .. "#sellAt"),
|
||||||
storeAbove = xmlFile:getInt(key .. "#storeAbove"),
|
storeAbove = xmlFile:getInt(key .. "#storeAbove"),
|
||||||
|
|||||||
@@ -122,22 +122,25 @@ function SmartPickupFrame:fillBuildingRows(adEnv, run, role)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
local chosen = {}
|
local chosen = {}
|
||||||
local ids = role == "load" and run.sourceBuildingIds or run.targetBuildingIds
|
local ids = role == "load" and run.sourceBuildingIds or role == "store" and run.storeBuildingIds or run.targetBuildingIds
|
||||||
|
local rowKind = role == "load" and "sourceBuilding" or role == "store" and "storeBuilding" or "targetBuilding"
|
||||||
for _, id in ipairs(ids or {}) do chosen[id] = true end
|
for _, id in ipairs(ids or {}) do chosen[id] = true end
|
||||||
local count = 0
|
local count = 0
|
||||||
for _, building in ipairs(ADBuildings.list(adEnv, g_currentMission:getFarmId())) do
|
for _, building in ipairs(ADBuildings.list(adEnv, g_currentMission:getFarmId())) do
|
||||||
|
-- "Lager til": siloer og gårdens fabrikker (fx BGA) — markøren er bygningens aflæsningsmarkør
|
||||||
local fits = (role == "load" and building.canBeSource) or (role == "unload" and building.canBeTarget)
|
local fits = (role == "load" and building.canBeSource) or (role == "unload" and building.canBeTarget)
|
||||||
|
or (role == "store" and (building.kind == "silo" or building.kind == "factory"))
|
||||||
if fits then
|
if fits then
|
||||||
count = count + 1
|
count = count + 1
|
||||||
local row = self:addRow(self.ingredientPrefab, {kind = role == "load" and "sourceBuilding" or "targetBuilding", buildingId = building.id})
|
local row = self:addRow(self.ingredientPrefab, {kind = rowKind, buildingId = building.id})
|
||||||
row:getDescendantByName("title"):setText(self:describeBuilding(building, role))
|
row:getDescendantByName("title"):setText(self:describeBuilding(building, role == "store" and "unload" or role))
|
||||||
row:getDescendantByName("option"):setState(chosen[building.id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false)
|
row:getDescendantByName("option"):setState(chosen[building.id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- valgte bygninger der ikke længere findes (solgt)
|
-- valgte bygninger der ikke længere findes (solgt)
|
||||||
for _, id in ipairs(ids or {}) do
|
for _, id in ipairs(ids or {}) do
|
||||||
if ADBuildings.find(adEnv, g_currentMission:getFarmId(), id) == nil then
|
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})
|
local row = self:addRow(self.ingredientPrefab, {kind = rowKind, buildingId = id})
|
||||||
row:getDescendantByName("title"):setText(string.format(" %s — %s", tostring(id), self.i18n:getText("spu_buildingGone")))
|
row:getDescendantByName("title"):setText(string.format(" %s — %s", tostring(id), self.i18n:getText("spu_buildingGone")))
|
||||||
row:getDescendantByName("option"):setState(SmartPickupFrame.STATE_ON, false)
|
row:getDescendantByName("option"):setState(SmartPickupFrame.STATE_ON, false)
|
||||||
end
|
end
|
||||||
@@ -162,6 +165,8 @@ function SmartPickupFrame:rebuildFlowDetail(adEnv, run)
|
|||||||
self.sellAtOption:setState(SmartPickupFrame.getStepIndex(self.sellAtSteps, run.sellAtPercent, ADRuns.DEFAULT_SELL_AT_PERCENT), false)
|
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.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.collectRoundRowOption = self:addToggleRow("collectRound", self.i18n:getText("spu_collectRound"), {self.i18n:getText("ui_no"), self.i18n:getText("ui_yes")}, run.collectRound == true)
|
||||||
|
self:addTextRow(self.i18n:getText("spu_section_store"))
|
||||||
|
self:fillBuildingRows(adEnv, run, "store")
|
||||||
self:fillOutboundStatusRows(adEnv, run)
|
self:fillOutboundStatusRows(adEnv, run)
|
||||||
else
|
else
|
||||||
self:addTextRow(self.i18n:getText("spu_section_to"))
|
self:addTextRow(self.i18n:getText("spu_section_to"))
|
||||||
@@ -193,6 +198,12 @@ function SmartPickupFrame:onClickBuilding(state, element)
|
|||||||
if run == nil or data == nil then return end
|
if run == nil or data == nil then return end
|
||||||
if data.kind == "sourceBuilding" then
|
if data.kind == "sourceBuilding" then
|
||||||
ADRunsController.store = ADRuns.toggleSourceBuilding(ADRunsController.store, run.id, data.buildingId)
|
ADRunsController.store = ADRuns.toggleSourceBuilding(ADRunsController.store, run.id, data.buildingId)
|
||||||
|
elseif data.kind == "storeBuilding" then
|
||||||
|
ADRunsController.store = ADRuns.toggleStoreBuilding(ADRunsController.store, run.id, data.buildingId)
|
||||||
|
local updatedStore = ADRuns.getRun(ADRunsController.store, run.id)
|
||||||
|
Logging.info(SmartPickupFrame.LOG_PREFIX .. "run '%s': storeBuildings=%s", tostring(run.name), table.concat(updatedStore.storeBuildingIds or {}, " "))
|
||||||
|
frame:requestRebuild()
|
||||||
|
return
|
||||||
else
|
else
|
||||||
ADRunsController.store = ADRuns.toggleTargetBuilding(ADRunsController.store, run.id, data.buildingId)
|
ADRunsController.store = ADRuns.toggleTargetBuilding(ADRunsController.store, run.id, data.buildingId)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -678,7 +678,7 @@ function SmartPickupFrame:onClickIngredient(state, element)
|
|||||||
return self:onClickCollectRound(state)
|
return self:onClickCollectRound(state)
|
||||||
elseif data ~= nil and data.kind == "direction" then
|
elseif data ~= nil and data.kind == "direction" then
|
||||||
return self:onClickDirection(state)
|
return self:onClickDirection(state)
|
||||||
elseif data ~= nil and (data.kind == "sourceBuilding" or data.kind == "targetBuilding") then
|
elseif data ~= nil and (data.kind == "sourceBuilding" or data.kind == "targetBuilding" or data.kind == "storeBuilding") then
|
||||||
return self:onClickBuilding(state, element)
|
return self:onClickBuilding(state, element)
|
||||||
end
|
end
|
||||||
self:safe(function(frame)
|
self:safe(function(frame)
|
||||||
|
|||||||
@@ -134,6 +134,7 @@
|
|||||||
<text name="spu_stat_use" text="forbrug %s/døgn"/>
|
<text name="spu_stat_use" text="forbrug %s/døgn"/>
|
||||||
<text name="spu_stat_prod" text="prod. %s/døgn"/>
|
<text name="spu_stat_prod" text="prod. %s/døgn"/>
|
||||||
<text name="spu_stat_total" text="Bygningen i alt"/>
|
<text name="spu_stat_total" text="Bygningen i alt"/>
|
||||||
|
<text name="spu_section_store" text="— Lager til (valgfrit; intet valgt = moden vælger selv) —"/>
|
||||||
<text name="spu_stat_rising" text="stiger"/>
|
<text name="spu_stat_rising" text="stiger"/>
|
||||||
<text name="spu_tab_factories" text="Fabrikker"/>
|
<text name="spu_tab_factories" text="Fabrikker"/>
|
||||||
<text name="spu_tab_silos" text="Siloer"/>
|
<text name="spu_tab_silos" text="Siloer"/>
|
||||||
|
|||||||
@@ -134,6 +134,7 @@
|
|||||||
<text name="spu_stat_use" text="use %s/day"/>
|
<text name="spu_stat_use" text="use %s/day"/>
|
||||||
<text name="spu_stat_prod" text="prod. %s/day"/>
|
<text name="spu_stat_prod" text="prod. %s/day"/>
|
||||||
<text name="spu_stat_total" text="Building total"/>
|
<text name="spu_stat_total" text="Building total"/>
|
||||||
|
<text name="spu_section_store" text="— Store to (optional; none chosen = the mod picks) —"/>
|
||||||
<text name="spu_stat_rising" text="rising"/>
|
<text name="spu_stat_rising" text="rising"/>
|
||||||
<text name="spu_tab_factories" text="Factories"/>
|
<text name="spu_tab_factories" text="Factories"/>
|
||||||
<text name="spu_tab_silos" text="Silos"/>
|
<text name="spu_tab_silos" text="Silos"/>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
<modDesc descVersion="107">
|
<modDesc descVersion="107">
|
||||||
<author>masterdraco</author>
|
<author>masterdraco</author>
|
||||||
<version>1.17.7.0</version>
|
<version>1.18.0.0</version>
|
||||||
<title>
|
<title>
|
||||||
<en>AD Smart Pickup</en>
|
<en>AD Smart Pickup</en>
|
||||||
</title>
|
</title>
|
||||||
|
|||||||
+10
-1
@@ -1,6 +1,6 @@
|
|||||||
# AD Smart Pickup — brugermanual
|
# AD Smart Pickup — brugermanual
|
||||||
|
|
||||||
Version 1.17.7 · Farming Simulator 25 · tillæg til AutoDrive
|
Version 1.18.0 · Farming Simulator 25 · tillæg til AutoDrive
|
||||||
|
|
||||||
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
|
*English version: [USER_MANUAL.md](USER_MANUAL.md)*
|
||||||
|
|
||||||
@@ -298,6 +298,15 @@ Bulkvarer kræver en tipvogn eller tank. Pallevarer kræver en vogn med Universa
|
|||||||
| **Kør til lager over** | Lager-varer køres væk, når kilden er fyldt over denne andel | 50–95 %, standard 80 % |
|
| **Kør til lager over** | Lager-varer køres væk, når kilden er fyldt over denne andel | 50–95 %, standard 80 % |
|
||||||
| **Saml op på én tur** | Opsamlingsrunde, se nedenfor | Ja/Nej |
|
| **Saml op på én tur** | Opsamlingsrunde, se nedenfor | Ja/Nej |
|
||||||
|
|
||||||
|
### Lager til: tvunget aflæsningssted
|
||||||
|
|
||||||
|
Under reglerne står afsnittet **Lager til** med gårdens siloer og egne fabrikker. Vælger du én eller
|
||||||
|
flere, kører lagerture kun dertil. Den første i listen, der tager varen, har plads og kan nås, får
|
||||||
|
læsset. Et eksempel er gylle, der kun må til biogasanlægget og aldrig til AIO-fabrikken. Kan ingen af
|
||||||
|
de valgte tage læsset, venter traktoren ved Wait, og loggen skriver hvorfor, fx *valgt lager: BGA500kw:
|
||||||
|
fuld*. Vælger du ingen, finder moden selv den nærmeste silo eller egne fabrik, der bruger varen.
|
||||||
|
Paller følger stadig reglen om nærmeste palleskur.
|
||||||
|
|
||||||
### Sådan vælges hver tur
|
### Sådan vælges hver tur
|
||||||
|
|
||||||
Før hver pålæsning, og hvert femte sekund mens traktoren holder, vurderer moden:
|
Før hver pålæsning, og hvert femte sekund mens traktoren holder, vurderer moden:
|
||||||
|
|||||||
+10
-1
@@ -1,6 +1,6 @@
|
|||||||
# AD Smart Pickup — user manual
|
# AD Smart Pickup — user manual
|
||||||
|
|
||||||
Version 1.17.7 · Farming Simulator 25 · add-on for AutoDrive
|
Version 1.18.0 · Farming Simulator 25 · add-on for AutoDrive
|
||||||
|
|
||||||
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
|
*Dansk version: [BRUGERMANUAL.md](BRUGERMANUAL.md)*
|
||||||
|
|
||||||
@@ -302,6 +302,15 @@ Bulk goods need a tipper or tank. Pallet goods need a trailer with Universal Aut
|
|||||||
| **Drive to storage above** | Store goods are moved when the source is filled above this share | 50–95 %, default 80 % |
|
| **Drive to storage above** | Store goods are moved when the source is filled above this share | 50–95 %, default 80 % |
|
||||||
| **Collect in one trip** | Collection round, see below | Yes/No |
|
| **Collect in one trip** | Collection round, see below | Yes/No |
|
||||||
|
|
||||||
|
### Store to: forced drop-off
|
||||||
|
|
||||||
|
Below the rules there is a **Store to** section listing the farm's silos and own factories. If you
|
||||||
|
pick one or more, storage trips only go there. The first one in the list that accepts the good, has
|
||||||
|
room and can be reached gets the load. An example is slurry that must only go to the biogas plant and
|
||||||
|
never to the AIO factory. If none of the chosen buildings can take the load, the tractor waits at
|
||||||
|
Wait, and the log says why, such as *valgt lager: BGA500kw: fuld*. If you pick none, the mod finds the
|
||||||
|
nearest silo or own factory that uses the good by itself. Pallets still follow the nearest pallet shed rule.
|
||||||
|
|
||||||
### How each trip is chosen
|
### How each trip is chosen
|
||||||
|
|
||||||
Before each loading, and every five seconds while the tractor waits, the mod checks:
|
Before each loading, and every five seconds while the tractor waits, the mod checks:
|
||||||
|
|||||||
@@ -44,5 +44,30 @@ check("LS2 fremmed anlæg aldrig", L.isStoreTarget({owningPlaceable = foreignBio
|
|||||||
check("LS2 hjemmet selv aldrig", L.isStoreTarget({owningPlaceable = biogas}, SLURRY, {owningPlaceable = biogas}, true), false)
|
check("LS2 hjemmet selv aldrig", L.isStoreTarget({owningPlaceable = biogas}, SLURRY, {owningPlaceable = biogas}, true), false)
|
||||||
g_currentMission = nil
|
g_currentMission = nil
|
||||||
|
|
||||||
|
-- LS3: tvunget lagermål — kun de valgte markører, i rækkefølge; første der tager varen, har plads og kan nås
|
||||||
|
do
|
||||||
|
local stations = {
|
||||||
|
[101] = {accepts = {[SLURRY] = true}, free = 0}, -- BGA fuld
|
||||||
|
[102] = {accepts = {[SLURRY] = true}, free = 900000}, -- gylletank
|
||||||
|
[103] = {accepts = {[MILK] = true}, free = 900000}, -- tager ikke gylle
|
||||||
|
}
|
||||||
|
for _, st in pairs(stations) do
|
||||||
|
st.getIsFillTypeSupported = function(self, ft) return self.accepts[ft] == true end
|
||||||
|
st.getFreeCapacity = function(self) return self.free end
|
||||||
|
end
|
||||||
|
ADSmartPickup = {getFarmId = function() return 1 end, getUnloadStationAtWayPointId = function(_, id) return stations[id] end}
|
||||||
|
local adEnv = {ADGraphManager = {getMapMarkerByWayPointId = function(_, id) return {id = id, name = "m" .. id} end}}
|
||||||
|
local vehicle = {}
|
||||||
|
local all = function() return true end
|
||||||
|
check("LS3 fuld BGA springes over -> tank", L.findForcedDumpMarker(adEnv, vehicle, SLURRY, 20000, {101, 102}, all).id, 102)
|
||||||
|
stations[101].free = 500000
|
||||||
|
check("LS3 BGA med plads vælges først", L.findForcedDumpMarker(adEnv, vehicle, SLURRY, 20000, {101, 102}, all).id, 101)
|
||||||
|
local none, why = L.findForcedDumpMarker(adEnv, vehicle, SLURRY, 20000, {103}, all)
|
||||||
|
check("LS3 intet valgt mål tager varen -> nil", none, nil)
|
||||||
|
check("LS3 forklaring", why ~= nil and why:find("valgt", 1, true) ~= nil, true)
|
||||||
|
check("LS3 ikke nåelig -> næste", L.findForcedDumpMarker(adEnv, vehicle, SLURRY, 20000, {101, 102}, function(id) return id ~= 101 end).id, 102)
|
||||||
|
ADSmartPickup = nil
|
||||||
|
end
|
||||||
|
|
||||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||||
os.exit(failures == 0 and 0 or 1)
|
os.exit(failures == 0 and 0 or 1)
|
||||||
|
|||||||
@@ -582,5 +582,22 @@ do
|
|||||||
sources[31], sources[32], products[31], products[32] = nil, nil, nil, nil
|
sources[31], sources[32], products[31], products[32] = nil, nil, nil, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- O-forced: "Lager til" valgt -> lagerturen går til det valgte mål, ikke moden egen silo-valg
|
||||||
|
do
|
||||||
|
sources[41] = {kind = "silo", wayPointId = 41, station = {name = "gylleSilo"}, name = "Gyllesilo"}
|
||||||
|
products[41] = {{fillType = SUGAR, name = "SUGAR", title = "Sukker", available = 11000000, level = 11000000, capacity = 12000000, isPallet = false}}
|
||||||
|
local vF = newVehicle("Gyllevogn", 0, 0, 20000)
|
||||||
|
runs[vF] = outboundRun(79, {41}, {{fillType = "SUGAR", policy = "store"}})
|
||||||
|
runs[vF].forcedMarkers = {31}
|
||||||
|
ADRunsController.getStoreMarkers = function(_, run) return run.forcedMarkers or {} end
|
||||||
|
local forcedCalls = 0
|
||||||
|
ADLoadSwap.findForcedDumpMarker = function(_, _, _, _, ids) forcedCalls = forcedCalls + 1 return {id = ids[1], name = "BGA", markerIndex = 99} end
|
||||||
|
dumpMarker = mStore
|
||||||
|
ADOutbound.choosePickup(adEnv, vF)
|
||||||
|
check("O-forced valgt mål brugt", forcedCalls > 0, true)
|
||||||
|
check("O-forced tur-mål = BGA", ADOutbound.getTripFor(vF) and ADOutbound.getTripFor(vF).targetWayPointId, 31)
|
||||||
|
ADRunsController.getStoreMarkers, ADLoadSwap.findForcedDumpMarker = nil, nil
|
||||||
|
end
|
||||||
|
|
||||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||||
os.exit(failures == 0 and 0 or 1)
|
os.exit(failures == 0 and 0 or 1)
|
||||||
|
|||||||
@@ -307,5 +307,20 @@ do
|
|||||||
check("RN ukendt køretøj", names.v9, nil)
|
check("RN ukendt køretøj", names.v9, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- RS: tvunget lagermål — storeBuildingIds (toggle, kopi, records roundtrip)
|
||||||
|
do
|
||||||
|
local store, run = ADRuns.createRun(ADRuns.newStore(), "Slurry", "outbound")
|
||||||
|
check("RS tom som standard", #run.storeBuildingIds, 0)
|
||||||
|
store = ADRuns.toggleStoreBuilding(store, run.id, "BGA500kw")
|
||||||
|
store = ADRuns.toggleStoreBuilding(store, run.id, "tank2")
|
||||||
|
check("RS to valgt", table.concat(ADRuns.getRun(store, run.id).storeBuildingIds, ","), "BGA500kw,tank2")
|
||||||
|
store = ADRuns.toggleStoreBuilding(store, run.id, "tank2")
|
||||||
|
check("RS fravalgt igen", table.concat(ADRuns.getRun(store, run.id).storeBuildingIds, ","), "BGA500kw")
|
||||||
|
local records = ADRuns.toRecords(store)
|
||||||
|
check("RS record", records[1].storeBuildings, "BGA500kw")
|
||||||
|
local back = ADRuns.fromRecords(records)
|
||||||
|
check("RS roundtrip", table.concat(ADRuns.getRun(back, run.id).storeBuildingIds, ","), "BGA500kw")
|
||||||
|
end
|
||||||
|
|
||||||
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
|
||||||
os.exit(failures == 0 and 0 or 1)
|
os.exit(failures == 0 and 0 or 1)
|
||||||
|
|||||||
@@ -700,6 +700,14 @@ local rowIn = ADRunsController.getFlowRow(adEnv, ADRuns.getRun(ADRunsController.
|
|||||||
check("CF5 forsyning fra = alle siloer", rowIn.fromAllSilos, true)
|
check("CF5 forsyning fra = alle siloer", rowIn.fromAllSilos, true)
|
||||||
check("CF5 forsyning til", table.concat(rowIn.toNames, ","), "Kostald 1,Sukkerfabrik")
|
check("CF5 forsyning til", table.concat(rowIn.toNames, ","), "Kostald 1,Sukkerfabrik")
|
||||||
check("CF5 forsyning auto-varer", rowIn.productAuto, true)
|
check("CF5 forsyning auto-varer", rowIn.productAuto, true)
|
||||||
|
-- SB: "Lager til" — valgte bygninger -> deres aflæsningsmarkører (i valgt rækkefølge; ukendte udelades)
|
||||||
|
do
|
||||||
|
local sbRun = ADRunsController.createRun("Gylle", "outbound")
|
||||||
|
ADRunsController.updateRun(sbRun.id, {storeBuildingIds = {"mill", "findes-ikke", "barn1"}})
|
||||||
|
check("SB markører", table.concat(ADRunsController.getStoreMarkers(adEnv, ADRuns.getRun(ADRunsController.store, sbRun.id)), ","), "77,94")
|
||||||
|
ADRunsController.updateRun(sbRun.id, {storeBuildingIds = {}})
|
||||||
|
check("SB tom = ingen tvang", #ADRunsController.getStoreMarkers(adEnv, ADRuns.getRun(ADRunsController.store, sbRun.id)), 0)
|
||||||
|
end
|
||||||
ADBuildings = nil; ADSources = nil; ADOutbound = nil
|
ADBuildings = nil; ADSources = nil; ADOutbound = nil
|
||||||
|
|
||||||
-- RC-navne: køretøjer får AD-førernavn efter forløbet; ude af forløb -> modelnavnet igen
|
-- RC-navne: køretøjer får AD-førernavn efter forløbet; ude af forløb -> modelnavnet igen
|
||||||
|
|||||||
Reference in New Issue
Block a user