feat: run-model v3 — bygninger som kilder/mål (sourceBuildingIds/targetBuildingIds), XML v3
This commit is contained in:
@@ -9,7 +9,7 @@ ADRuns.MAX_LOOPS = 99
|
|||||||
-- "Kør hjem fra Wait når målet er under X %": 10..90, standard 50 (= den gamle 50 %-regel).
|
-- "Kør hjem fra Wait når målet er under X %": 10..90, standard 50 (= den gamle 50 %-regel).
|
||||||
ADRuns.DEFAULT_RETURN_BELOW_PERCENT = 50
|
ADRuns.DEFAULT_RETURN_BELOW_PERCENT = 50
|
||||||
ADRuns.MIN_RETURN_BELOW_PERCENT, ADRuns.MAX_RETURN_BELOW_PERCENT = 10, 90
|
ADRuns.MIN_RETURN_BELOW_PERCENT, ADRuns.MAX_RETURN_BELOW_PERCENT = 10, 90
|
||||||
ADRuns.XML_VERSION = 2
|
ADRuns.XML_VERSION = 3
|
||||||
ADRuns.INGREDIENT_MODES = {auto = true, manual = true}
|
ADRuns.INGREDIENT_MODES = {auto = true, manual = true}
|
||||||
-- Retning: Forsyning (ind til stald/fabrik) eller Udkørsel (fabrik/lager -> silo/salg).
|
-- Retning: Forsyning (ind til stald/fabrik) eller Udkørsel (fabrik/lager -> silo/salg).
|
||||||
ADRuns.KINDS = {supply = true, outbound = true}
|
ADRuns.KINDS = {supply = true, outbound = true}
|
||||||
@@ -45,6 +45,8 @@ local function copyRun(run)
|
|||||||
name = run.name,
|
name = run.name,
|
||||||
kind = run.kind,
|
kind = run.kind,
|
||||||
sourceWayPointIds = copyList(run.sourceWayPointIds),
|
sourceWayPointIds = copyList(run.sourceWayPointIds),
|
||||||
|
sourceBuildingIds = copyList(run.sourceBuildingIds),
|
||||||
|
targetBuildingIds = copyList(run.targetBuildingIds),
|
||||||
products = copyProducts(run.products),
|
products = copyProducts(run.products),
|
||||||
sellAtPercent = run.sellAtPercent,
|
sellAtPercent = run.sellAtPercent,
|
||||||
storeAbovePercent = run.storeAbovePercent,
|
storeAbovePercent = run.storeAbovePercent,
|
||||||
@@ -89,6 +91,8 @@ function ADRuns.createRun(store, name, kind)
|
|||||||
name = name,
|
name = name,
|
||||||
kind = ADRuns.KINDS[kind] and kind or "supply",
|
kind = ADRuns.KINDS[kind] and kind or "supply",
|
||||||
sourceWayPointIds = {},
|
sourceWayPointIds = {},
|
||||||
|
sourceBuildingIds = {},
|
||||||
|
targetBuildingIds = {},
|
||||||
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,
|
||||||
@@ -152,6 +156,8 @@ function ADRuns.updateRun(store, runId, changes)
|
|||||||
if changes.returnBelowPercent ~= nil then run.returnBelowPercent = clampPercent(changes.returnBelowPercent) end
|
if changes.returnBelowPercent ~= nil then run.returnBelowPercent = clampPercent(changes.returnBelowPercent) end
|
||||||
if ADRuns.KINDS[changes.kind] then run.kind = changes.kind end
|
if ADRuns.KINDS[changes.kind] then run.kind = changes.kind end
|
||||||
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.targetBuildingIds ~= nil then run.targetBuildingIds = copyList(changes.targetBuildingIds) 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
|
||||||
@@ -159,6 +165,29 @@ function ADRuns.updateRun(store, runId, changes)
|
|||||||
return new
|
return new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ---- bygninger som kilder/mål (flow-tavlen) ----
|
||||||
|
|
||||||
|
local function toggleInList(list, value)
|
||||||
|
local result, found = {}, false
|
||||||
|
for _, item in ipairs(list or {}) do
|
||||||
|
if item == value then found = true else table.insert(result, item) end
|
||||||
|
end
|
||||||
|
if not found then table.insert(result, value) end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function ADRuns.toggleSourceBuilding(store, runId, buildingId)
|
||||||
|
local run = ADRuns.getRun(store, runId)
|
||||||
|
if run == nil then return copyStore(store) end
|
||||||
|
return ADRuns.updateRun(store, runId, {sourceBuildingIds = toggleInList(run.sourceBuildingIds, buildingId)})
|
||||||
|
end
|
||||||
|
|
||||||
|
function ADRuns.toggleTargetBuilding(store, runId, buildingId)
|
||||||
|
local run = ADRuns.getRun(store, runId)
|
||||||
|
if run == nil then return copyStore(store) end
|
||||||
|
return ADRuns.updateRun(store, runId, {targetBuildingIds = toggleInList(run.targetBuildingIds, buildingId)})
|
||||||
|
end
|
||||||
|
|
||||||
-- ---- udkørsel: kilder og varer ----
|
-- ---- udkørsel: kilder og varer ----
|
||||||
|
|
||||||
-- Tilføj/fjern en kilde-markør (afkrydsning i fanen Udkørsel).
|
-- Tilføj/fjern en kilde-markør (afkrydsning i fanen Udkørsel).
|
||||||
@@ -319,6 +348,8 @@ function ADRuns.toRecords(store)
|
|||||||
vehicleIds = copyList(run.vehicleIds),
|
vehicleIds = copyList(run.vehicleIds),
|
||||||
kind = run.kind,
|
kind = run.kind,
|
||||||
sources = table.concat(run.sourceWayPointIds or {}, " "),
|
sources = table.concat(run.sourceWayPointIds or {}, " "),
|
||||||
|
sourceBuildings = table.concat(run.sourceBuildingIds or {}, " "),
|
||||||
|
targetBuildings = table.concat(run.targetBuildingIds or {}, " "),
|
||||||
products = ADRuns.serializeProducts(run.products),
|
products = ADRuns.serializeProducts(run.products),
|
||||||
sellAt = run.sellAtPercent,
|
sellAt = run.sellAtPercent,
|
||||||
storeAbove = run.storeAbovePercent,
|
storeAbove = run.storeAbovePercent,
|
||||||
@@ -344,6 +375,11 @@ function ADRuns.fromRecords(records)
|
|||||||
if #targets == 0 and target ~= nil and target > 0 then
|
if #targets == 0 and target ~= nil and target > 0 then
|
||||||
targets = {target}
|
targets = {target}
|
||||||
end
|
end
|
||||||
|
local function parseIds(text)
|
||||||
|
local ids = {}
|
||||||
|
for token in string.gmatch(tostring(text or ""), "%S+") do table.insert(ids, token) end
|
||||||
|
return ids
|
||||||
|
end
|
||||||
local sources = {}
|
local sources = {}
|
||||||
for token in string.gmatch(tostring(record.sources or ""), "%S+") do
|
for token in string.gmatch(tostring(record.sources or ""), "%S+") do
|
||||||
local wayPointId = tonumber(token)
|
local wayPointId = tonumber(token)
|
||||||
@@ -354,6 +390,8 @@ function ADRuns.fromRecords(records)
|
|||||||
name = record.name,
|
name = record.name,
|
||||||
kind = ADRuns.KINDS[record.kind] and record.kind or "supply",
|
kind = ADRuns.KINDS[record.kind] and record.kind or "supply",
|
||||||
sourceWayPointIds = sources,
|
sourceWayPointIds = sources,
|
||||||
|
sourceBuildingIds = parseIds(record.sourceBuildings),
|
||||||
|
targetBuildingIds = parseIds(record.targetBuildings),
|
||||||
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),
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ function ADRunsStorage.writeRecords(xmlFile, records)
|
|||||||
-- v2: udkørsel
|
-- v2: udkørsel
|
||||||
xmlFile:setString(key .. "#kind", record.kind or "supply")
|
xmlFile:setString(key .. "#kind", record.kind or "supply")
|
||||||
xmlFile:setString(key .. "#sources", record.sources or "")
|
xmlFile:setString(key .. "#sources", record.sources or "")
|
||||||
|
-- v3: bygninger (flow-tavlen)
|
||||||
|
xmlFile:setString(key .. "#sourceBuildings", record.sourceBuildings or "")
|
||||||
|
xmlFile:setString(key .. "#targetBuildings", record.targetBuildings 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)
|
||||||
@@ -64,6 +67,8 @@ function ADRunsStorage.readRecords(xmlFile)
|
|||||||
returnBelow = xmlFile:getInt(key .. "#returnBelow"),
|
returnBelow = xmlFile:getInt(key .. "#returnBelow"),
|
||||||
kind = xmlFile:getString(key .. "#kind"),
|
kind = xmlFile:getString(key .. "#kind"),
|
||||||
sources = xmlFile:getString(key .. "#sources"),
|
sources = xmlFile:getString(key .. "#sources"),
|
||||||
|
sourceBuildings = xmlFile:getString(key .. "#sourceBuildings"),
|
||||||
|
targetBuildings = xmlFile:getString(key .. "#targetBuildings"),
|
||||||
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"),
|
||||||
|
|||||||
+41
-2
@@ -157,7 +157,7 @@ end
|
|||||||
-- X1: records skrives som attributter + vehicle-underelementer
|
-- X1: records skrives som attributter + vehicle-underelementer
|
||||||
local out = makeXmlMock()
|
local out = makeXmlMock()
|
||||||
ADRunsStorage.writeRecords(out, ADRuns.toRecords(s5))
|
ADRunsStorage.writeRecords(out, ADRuns.toRecords(s5))
|
||||||
check("X1 version", out.values["ADSmartPickupRuns#version"], 2)
|
check("X1 version", out.values["ADSmartPickupRuns#version"], 3)
|
||||||
check("X1 run 0 navn", out.values["ADSmartPickupRuns.run(0)#name"], "Cow 1")
|
check("X1 run 0 navn", out.values["ADSmartPickupRuns.run(0)#name"], "Cow 1")
|
||||||
check("X1 run 0 target", out.values["ADSmartPickupRuns.run(0)#target"], 94)
|
check("X1 run 0 target", out.values["ADSmartPickupRuns.run(0)#target"], 94)
|
||||||
check("X1 run 0 varer", out.values["ADSmartPickupRuns.run(0)#ingredients"], "STRAW FORAGE")
|
check("X1 run 0 varer", out.values["ADSmartPickupRuns.run(0)#ingredients"], "STRAW FORAGE")
|
||||||
@@ -243,7 +243,7 @@ do
|
|||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
ADRunsStorage.writeRecords(xml, ADRuns.toRecords(o4))
|
ADRunsStorage.writeRecords(xml, ADRuns.toRecords(o4))
|
||||||
check("Rv2 xml version 2", written["ADSmartPickupRuns#version"], 2)
|
check("Rv2 xml version 2", written["ADSmartPickupRuns#version"], 3)
|
||||||
check("Rv2 xml kind", written["ADSmartPickupRuns.run(0)#kind"], "outbound")
|
check("Rv2 xml kind", written["ADSmartPickupRuns.run(0)#kind"], "outbound")
|
||||||
check("Rv2 xml sources", written["ADSmartPickupRuns.run(0)#sources"], "12694 12386")
|
check("Rv2 xml sources", written["ADSmartPickupRuns.run(0)#sources"], "12694 12386")
|
||||||
check("Rv2 xml products", written["ADSmartPickupRuns.run(0)#products"], "SUGAR:sell FORAGE:store")
|
check("Rv2 xml products", written["ADSmartPickupRuns.run(0)#products"], "SUGAR:sell FORAGE:store")
|
||||||
@@ -253,5 +253,44 @@ do
|
|||||||
check("Rv2 xml læs runde", ADRuns.getRun(back, out.id).collectRound, true)
|
check("Rv2 xml læs runde", ADRuns.getRun(back, out.id).collectRound, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- R-v3: bygninger som kilder/mål (id-lister); XML v3; v2-fil uden bygninger giver tomme lister
|
||||||
|
local b1, flow = ADRuns.createRun(ADRuns.newStore(), "Milk", "outbound")
|
||||||
|
check("Rv3 tomme kilde-bygninger", #flow.sourceBuildingIds, 0)
|
||||||
|
check("Rv3 tomme mål-bygninger", #flow.targetBuildingIds, 0)
|
||||||
|
local b2 = ADRuns.toggleSourceBuilding(b1, flow.id, "barn1")
|
||||||
|
b2 = ADRuns.toggleSourceBuilding(b2, flow.id, "barn2")
|
||||||
|
check("Rv3 to kilde-bygninger", table.concat(ADRuns.getRun(b2, flow.id).sourceBuildingIds, ","), "barn1,barn2")
|
||||||
|
check("Rv3 toggle fjerner", #ADRuns.getRun(ADRuns.toggleSourceBuilding(b2, flow.id, "barn1"), flow.id).sourceBuildingIds, 1)
|
||||||
|
local b3 = ADRuns.toggleTargetBuilding(b2, flow.id, "mill")
|
||||||
|
check("Rv3 mål-bygning", ADRuns.getRun(b3, flow.id).targetBuildingIds[1], "mill")
|
||||||
|
check("Rv3 gammel store urørt", #ADRuns.getRun(b2, flow.id).targetBuildingIds, 0)
|
||||||
|
local b4 = ADRuns.updateRun(b3, flow.id, {sourceBuildingIds = {"shed"}, targetBuildingIds = {}})
|
||||||
|
check("Rv3 updateRun sætter lister", ADRuns.getRun(b4, flow.id).sourceBuildingIds[1], "shed")
|
||||||
|
check("Rv3 updateRun tømmer", #ADRuns.getRun(b4, flow.id).targetBuildingIds, 0)
|
||||||
|
local rt3 = ADRuns.fromRecords(ADRuns.toRecords(b3))
|
||||||
|
check("Rv3 roundtrip kilder", table.concat(ADRuns.getRun(rt3, flow.id).sourceBuildingIds, ","), "barn1,barn2")
|
||||||
|
check("Rv3 roundtrip mål", ADRuns.getRun(rt3, flow.id).targetBuildingIds[1], "mill")
|
||||||
|
check("Rv3 XML_VERSION", ADRuns.XML_VERSION, 3)
|
||||||
|
local v2 = ADRuns.fromRecords({{id = 3, name = "V2", kind = "outbound", sources = "12694", products = "SUGAR:sell", vehicleIds = {}}})
|
||||||
|
check("Rv3 v2 rå markør bevares", ADRuns.getRun(v2, 3).sourceWayPointIds[1], 12694)
|
||||||
|
check("Rv3 v2 ingen bygninger", #ADRuns.getRun(v2, 3).sourceBuildingIds, 0)
|
||||||
|
do
|
||||||
|
local written = {}
|
||||||
|
local xml = {
|
||||||
|
setInt = function(_, k, v) written[k] = v end, setString = function(_, k, v) written[k] = v end,
|
||||||
|
getInt = function(_, k) return written[k] end, getString = function(_, k) return written[k] end,
|
||||||
|
iterate = function(_, prefix, fn)
|
||||||
|
local i = 0
|
||||||
|
while written[string.format("%s(%d)#id", prefix, i)] ~= nil do fn(i, string.format("%s(%d)", prefix, i)); i = i + 1 end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
ADRunsStorage.writeRecords(xml, ADRuns.toRecords(b3))
|
||||||
|
check("Rv3 xml version 3", written["ADSmartPickupRuns#version"], 3)
|
||||||
|
check("Rv3 xml sourceBuildings", written["ADSmartPickupRuns.run(0)#sourceBuildings"], "barn1 barn2")
|
||||||
|
check("Rv3 xml targetBuildings", written["ADSmartPickupRuns.run(0)#targetBuildings"], "mill")
|
||||||
|
local back = ADRuns.fromRecords(ADRunsStorage.readRecords(xml))
|
||||||
|
check("Rv3 xml læs kilder", table.concat(ADRuns.getRun(back, flow.id).sourceBuildingIds, ","), "barn1,barn2")
|
||||||
|
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user