diff --git a/FS25_ADSmartPickup/adRuns.lua b/FS25_ADSmartPickup/adRuns.lua index 7d62cc7..d21c68b 100644 --- a/FS25_ADSmartPickup/adRuns.lua +++ b/FS25_ADSmartPickup/adRuns.lua @@ -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). ADRuns.DEFAULT_RETURN_BELOW_PERCENT = 50 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} -- Retning: Forsyning (ind til stald/fabrik) eller Udkørsel (fabrik/lager -> silo/salg). ADRuns.KINDS = {supply = true, outbound = true} @@ -45,6 +45,8 @@ local function copyRun(run) name = run.name, kind = run.kind, sourceWayPointIds = copyList(run.sourceWayPointIds), + sourceBuildingIds = copyList(run.sourceBuildingIds), + targetBuildingIds = copyList(run.targetBuildingIds), products = copyProducts(run.products), sellAtPercent = run.sellAtPercent, storeAbovePercent = run.storeAbovePercent, @@ -89,6 +91,8 @@ function ADRuns.createRun(store, name, kind) name = name, kind = ADRuns.KINDS[kind] and kind or "supply", sourceWayPointIds = {}, + sourceBuildingIds = {}, + targetBuildingIds = {}, products = {}, sellAtPercent = ADRuns.DEFAULT_SELL_AT_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 ADRuns.KINDS[changes.kind] then run.kind = changes.kind 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.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 @@ -159,6 +165,29 @@ function ADRuns.updateRun(store, runId, changes) return new 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 ---- -- Tilføj/fjern en kilde-markør (afkrydsning i fanen Udkørsel). @@ -319,6 +348,8 @@ function ADRuns.toRecords(store) vehicleIds = copyList(run.vehicleIds), kind = run.kind, sources = table.concat(run.sourceWayPointIds or {}, " "), + sourceBuildings = table.concat(run.sourceBuildingIds or {}, " "), + targetBuildings = table.concat(run.targetBuildingIds or {}, " "), products = ADRuns.serializeProducts(run.products), sellAt = run.sellAtPercent, storeAbove = run.storeAbovePercent, @@ -344,6 +375,11 @@ function ADRuns.fromRecords(records) if #targets == 0 and target ~= nil and target > 0 then targets = {target} 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 = {} for token in string.gmatch(tostring(record.sources or ""), "%S+") do local wayPointId = tonumber(token) @@ -354,6 +390,8 @@ function ADRuns.fromRecords(records) name = record.name, kind = ADRuns.KINDS[record.kind] and record.kind or "supply", sourceWayPointIds = sources, + sourceBuildingIds = parseIds(record.sourceBuildings), + targetBuildingIds = parseIds(record.targetBuildings), products = ADRuns.parseProducts(record.products), 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), diff --git a/FS25_ADSmartPickup/adRunsStorage.lua b/FS25_ADSmartPickup/adRunsStorage.lua index 8007ad5..4b72c64 100644 --- a/FS25_ADSmartPickup/adRunsStorage.lua +++ b/FS25_ADSmartPickup/adRunsStorage.lua @@ -39,6 +39,9 @@ function ADRunsStorage.writeRecords(xmlFile, records) -- v2: udkørsel xmlFile:setString(key .. "#kind", record.kind or "supply") 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:setInt(key .. "#sellAt", record.sellAt or ADRuns.DEFAULT_SELL_AT_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"), kind = xmlFile:getString(key .. "#kind"), sources = xmlFile:getString(key .. "#sources"), + sourceBuildings = xmlFile:getString(key .. "#sourceBuildings"), + targetBuildings = xmlFile:getString(key .. "#targetBuildings"), products = xmlFile:getString(key .. "#products"), sellAt = xmlFile:getInt(key .. "#sellAt"), storeAbove = xmlFile:getInt(key .. "#storeAbove"), diff --git a/tests/test_adRuns.lua b/tests/test_adRuns.lua index b55591b..a1f0756 100644 --- a/tests/test_adRuns.lua +++ b/tests/test_adRuns.lua @@ -157,7 +157,7 @@ end -- X1: records skrives som attributter + vehicle-underelementer local out = makeXmlMock() 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 target", out.values["ADSmartPickupRuns.run(0)#target"], 94) check("X1 run 0 varer", out.values["ADSmartPickupRuns.run(0)#ingredients"], "STRAW FORAGE") @@ -243,7 +243,7 @@ do end, } 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 sources", written["ADSmartPickupRuns.run(0)#sources"], "12694 12386") 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) 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")) os.exit(failures == 0 and 0 or 1)