feat: fabriksstyret forsyning — målets tændte produktioner styrer ingredienslisten (v1.6.0.0)
Er aflæsningsmålet et produktionspunkt, erstattes ingredienslisten af inputs fra ønskede produktioner (tændte, eller auto-slukkede af kortet med status MISSING_INPUTS — Dakotas ExtendedProductionPoint), begrænset til det vognen kan bære. Brugerens multi-valg er kun tændknappen og gendannes ved stop som hidtil. Prioritet: tid til tom = lager / (Σ amount × cyclesPerMinute); varer med kendt forbrug scorer i ]1,2] og går altid forud for relativ tomhed [0,1]. Loggen viser forbrug og minutter; fabrik uden ønskede produktioner logges én gang. API-navne verificeret mod EasyDevControls + Dakota16x ExtendedProductionPoint.
This commit is contained in:
@@ -250,21 +250,81 @@ function ADSmartPickup.findLeastFilledPickup(adEnv, driver)
|
||||
return findBestSource(collectMarkerStations(adEnv, groupMarkers, farmId, nil), fillTypes, farmId)
|
||||
end
|
||||
|
||||
local function getProductionPoint(station)
|
||||
local placeable = station.owningPlaceable
|
||||
if placeable ~= nil and placeable.spec_productionPoint ~= nil then
|
||||
return placeable.spec_productionPoint.productionPoint
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Lagrene bag aflæsningsstationen; produktionspunkter uden targetStorages læses direkte.
|
||||
local function getTargetStorages(station)
|
||||
if station.targetStorages ~= nil and next(station.targetStorages) ~= nil then
|
||||
return station.targetStorages
|
||||
end
|
||||
local placeable = station.owningPlaceable
|
||||
local productionPoint = placeable ~= nil and placeable.spec_productionPoint ~= nil and placeable.spec_productionPoint.productionPoint or nil
|
||||
local productionPoint = getProductionPoint(station)
|
||||
if productionPoint ~= nil and productionPoint.storage ~= nil then
|
||||
return {productionPoint.storage}
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
-- Niveau + kapacitet pr. ingrediens i aflæsningsmålets lager.
|
||||
local function getTargetNeeds(station, ingredients, farmId)
|
||||
local function isProductionEnabled(productionPoint, production)
|
||||
if productionPoint.getIsProductionEnabled ~= nil then
|
||||
return productionPoint:getIsProductionEnabled(production.id) == true
|
||||
end
|
||||
for _, active in ipairs(productionPoint.activeProductions or {}) do
|
||||
if active == production then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Fabriksstyret: {[fillType] = liter/min} som målets ønskede produktioner bruger,
|
||||
-- begrænset til det vognen kan bære. Tom tabel = intet produktionspunkt/intet ønsket.
|
||||
local function getProductionDemand(adEnv, station, driver)
|
||||
local productionPoint = getProductionPoint(station)
|
||||
if productionPoint == nil or productionPoint.productions == nil then
|
||||
return {}
|
||||
end
|
||||
local canCarry = {}
|
||||
for _, fillType in ipairs(adEnv.AutoDrive.getSupportedFillTypesOfAllUnitsAlphabetically(driver) or {}) do
|
||||
canCarry[fillType] = true
|
||||
end
|
||||
local missingInputs = ProductionPoint ~= nil and ProductionPoint.PROD_STATUS ~= nil and ProductionPoint.PROD_STATUS.MISSING_INPUTS or nil
|
||||
local function isWanted(production)
|
||||
return ADSupplyPlanner.isProductionWanted(isProductionEnabled(productionPoint, production), production.status, missingInputs)
|
||||
end
|
||||
return ADSupplyPlanner.collectProductionDemand(productionPoint.productions, isWanted, canCarry)
|
||||
end
|
||||
|
||||
-- Fabrikkens inputs som sorteret liste (stabil rækkefølge -> stabil log/rangering).
|
||||
local function getDemandFillTypes(demand)
|
||||
local fillTypes = {}
|
||||
for fillType in pairs(demand) do
|
||||
table.insert(fillTypes, fillType)
|
||||
end
|
||||
table.sort(fillTypes)
|
||||
return fillTypes
|
||||
end
|
||||
|
||||
-- Fabrik som mål uden ønskede produktioner: sig det én gang, så en stille
|
||||
-- tilbagefald til brugerens valg ikke ligner en fejl i moden.
|
||||
local factoryFallbackLogged = setmetatable({}, {__mode = "k"})
|
||||
local function logFactoryFallbackOnce(driver, station)
|
||||
local placeable = station.owningPlaceable
|
||||
local name = placeable ~= nil and placeable.getName ~= nil and placeable:getName() or "fabrik"
|
||||
local message = string.format("'%s': %s har ingen ønskede produktioner (tændte eller auto-slukkede pga. mangel) med varer vognen kan bære; bruger dit varevalg", tostring(driver:getName()), tostring(name))
|
||||
if factoryFallbackLogged[driver] ~= message then
|
||||
factoryFallbackLogged[driver] = message
|
||||
Logging.info(ADSmartPickup.LOG_PREFIX .. "%s", message)
|
||||
end
|
||||
end
|
||||
|
||||
-- Niveau + kapacitet pr. ingrediens i aflæsningsmålets lager; demand giver forbrug/min.
|
||||
local function getTargetNeeds(station, ingredients, farmId, demand)
|
||||
local needs = {}
|
||||
local storages = getTargetStorages(station)
|
||||
for _, fillType in ipairs(ingredients) do
|
||||
@@ -278,7 +338,7 @@ local function getTargetNeeds(station, ingredients, farmId)
|
||||
-- ukendt lagertype: brug stationens egen opgørelse af fri plads
|
||||
level, freeSpace = 0, station:getFreeCapacity(fillType, farmId) or 0
|
||||
end
|
||||
table.insert(needs, {fillType = fillType, level = level, capacity = level + freeSpace})
|
||||
table.insert(needs, {fillType = fillType, level = level, capacity = level + freeSpace, litersPerMinute = demand[fillType]})
|
||||
end
|
||||
end
|
||||
return needs
|
||||
@@ -297,9 +357,19 @@ function ADSmartPickup.findSupplyPickup(adEnv, driver, ingredients)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Er målet en fabrik med ønskede produktioner, følger listen fabrikken —
|
||||
-- brugerens multi-valg er kun tændknappen (og gendannes ved stop).
|
||||
local demand = getProductionDemand(adEnv, target, driver)
|
||||
if next(demand) ~= nil then
|
||||
ingredients = getDemandFillTypes(demand)
|
||||
factoryFallbackLogged[driver] = nil
|
||||
elseif getProductionPoint(target) ~= nil then
|
||||
logFactoryFallbackOnce(driver, target)
|
||||
end
|
||||
|
||||
local allMarkers = adEnv.ADGraphManager:getMapMarkers()
|
||||
local markerStations = collectMarkerStations(adEnv, allMarkers, farmId, target.owningPlaceable)
|
||||
for _, need in ipairs(ADSupplyPlanner.rankNeeds(getTargetNeeds(target, ingredients, farmId))) do
|
||||
for _, need in ipairs(ADSupplyPlanner.rankNeeds(getTargetNeeds(target, ingredients, farmId, demand))) do
|
||||
local choice = findBestSource(markerStations, {need.fillType}, farmId)
|
||||
if choice ~= nil then
|
||||
return {
|
||||
@@ -351,7 +421,11 @@ local function describeChoice(choice)
|
||||
return string.format("%.0f l, %s", choice.level, source)
|
||||
end
|
||||
local fillTypeName = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(choice.fillType) or tostring(choice.fillType)
|
||||
return string.format("%s: kilde %.0f l, %s, målet har %.0f/%.0f l", tostring(fillTypeName), choice.level, source, choice.need.level, choice.need.capacity)
|
||||
local urgency = ""
|
||||
if choice.need.minutesToEmpty ~= nil then
|
||||
urgency = string.format(", fabrikken bruger %.0f l/min = %.0f min til tom", choice.need.litersPerMinute, choice.need.minutesToEmpty)
|
||||
end
|
||||
return string.format("%s: kilde %.0f l, %s, målet har %.0f/%.0f l%s", tostring(fillTypeName), choice.level, source, choice.need.level, choice.need.capacity, urgency)
|
||||
end
|
||||
|
||||
local function logChoiceOnce(driver, choice)
|
||||
|
||||
@@ -48,29 +48,73 @@ function ADSupplyPlanner.copyList(list)
|
||||
return copy
|
||||
end
|
||||
|
||||
-- Ønsker en produktion input? Tændt, eller slukket af kortet fordi den MANGLEDE
|
||||
-- input (Dakotas ExtendedProductionPoint slår den fra automatisk, men lader
|
||||
-- status stå på MISSING_INPUTS). Manuelt slukket = status INACTIVE -> nej.
|
||||
function ADSupplyPlanner.isProductionWanted(isEnabled, status, missingInputsStatus)
|
||||
if isEnabled then
|
||||
return true
|
||||
end
|
||||
return status ~= nil and status == missingInputsStatus
|
||||
end
|
||||
|
||||
-- productions: produktionspunktets liste ({id, cyclesPerMinute, inputs = {{type, amount}}}).
|
||||
-- isWanted(production) afgør om den tæller; canCarry[fillType] = det vognen kan bære.
|
||||
-- Returnerer {[fillType] = liter pr. minut} summeret over ønskede produktioner.
|
||||
function ADSupplyPlanner.collectProductionDemand(productions, isWanted, canCarry)
|
||||
local demand = {}
|
||||
for _, production in ipairs(productions) do
|
||||
if isWanted(production) then
|
||||
local cyclesPerMinute = production.cyclesPerMinute or 0
|
||||
for _, input in ipairs(production.inputs or {}) do
|
||||
if canCarry[input.type] then
|
||||
demand[input.type] = (demand[input.type] or 0) + (input.amount or 0) * cyclesPerMinute
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return demand
|
||||
end
|
||||
|
||||
-- Minutter før målets lager af varen er tomt ved nuværende forbrug; nil uden forbrug.
|
||||
function ADSupplyPlanner.minutesToEmpty(level, litersPerMinute)
|
||||
if litersPerMinute == nil or litersPerMinute <= 0 then
|
||||
return nil
|
||||
end
|
||||
return level / litersPerMinute
|
||||
end
|
||||
|
||||
-- Hvor meget trænger målet til denne ingrediens? Højere = hentes først.
|
||||
-- Alle tal er liter i aflæsningsmålets lager. Standard: relativ tomhed (0..1),
|
||||
-- så en lille næsten-tom tank vinder over en stor halvfuld.
|
||||
function ADSupplyPlanner.scoreNeed(level, capacity, freeSpace)
|
||||
-- så en lille næsten-tom tank vinder over en stor halvfuld. Kendes forbruget
|
||||
-- (fabriksstyret), tæller i stedet tid til tom: score i ]1, 2], så varer med
|
||||
-- forbrug altid går forud for varer uden, og kortest tid vinder.
|
||||
function ADSupplyPlanner.scoreNeed(level, capacity, freeSpace, minutesToEmpty)
|
||||
if minutesToEmpty ~= nil then
|
||||
return 1 + 1 / (1 + minutesToEmpty)
|
||||
end
|
||||
if capacity <= 0 then
|
||||
return 0
|
||||
end
|
||||
return freeSpace / capacity
|
||||
end
|
||||
|
||||
-- needs: {{fillType, level, capacity}, ...}. Returnerer NY liste, mest trængende først;
|
||||
-- ingredienser uden plads i målet er sorteret fra.
|
||||
-- needs: {{fillType, level, capacity[, litersPerMinute]}, ...}. Returnerer NY liste,
|
||||
-- mest trængende først; ingredienser uden plads i målet er sorteret fra.
|
||||
function ADSupplyPlanner.rankNeeds(needs)
|
||||
local ranked = {}
|
||||
for _, need in ipairs(needs) do
|
||||
local freeSpace = need.capacity - need.level
|
||||
if freeSpace >= ADSupplyPlanner.MIN_FREE_LITERS then
|
||||
local minutesToEmpty = ADSupplyPlanner.minutesToEmpty(need.level, need.litersPerMinute)
|
||||
table.insert(ranked, {
|
||||
fillType = need.fillType,
|
||||
level = need.level,
|
||||
capacity = need.capacity,
|
||||
freeSpace = freeSpace,
|
||||
score = ADSupplyPlanner.scoreNeed(need.level, need.capacity, freeSpace),
|
||||
litersPerMinute = need.litersPerMinute,
|
||||
minutesToEmpty = minutesToEmpty,
|
||||
score = ADSupplyPlanner.scoreNeed(need.level, need.capacity, freeSpace, minutesToEmpty),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<modDesc descVersion="107">
|
||||
<author>masterdraco</author>
|
||||
<version>1.5.0.0</version>
|
||||
<version>1.6.0.0</version>
|
||||
<title>
|
||||
<en>AD Smart Pickup</en>
|
||||
</title>
|
||||
<description>
|
||||
<en><![CDATA[AutoDrive-tillæg: når pålæsningsmål roteres i en mappe, køres der direkte til den silo i mappen, der har den valgte vare (mindst fyldte først), i stedet for at prøve markørerne én efter én. Vælges FLERE varer i AutoDrive, ses de som ingredienser til aflæsningsmålet (fx en TMR-blander): én traktor henter pr. tur den vare målet mangler mest, fra en silo hvor som helst på kortet. Kræver FS25_AutoDrive med "Brug mapper" + "Rotér mål: pålæsning".]]></en>
|
||||
<en><![CDATA[AutoDrive-tillæg: når pålæsningsmål roteres i en mappe, køres der direkte til den silo i mappen, der har den valgte vare (mindst fyldte først), i stedet for at prøve markørerne én efter én. Vælges FLERE varer i AutoDrive, ses de som ingredienser til aflæsningsmålet (fx en TMR-blander): én traktor henter pr. tur den vare målet mangler mest, fra en silo hvor som helst på kortet. Er målet en fabrik, følger listen automatisk fabrikkens tændte produktioner (tid-til-tom først). Kræver FS25_AutoDrive med "Brug mapper" + "Rotér mål: pålæsning".]]></en>
|
||||
</description>
|
||||
<iconFilename>icon.dds</iconFilename>
|
||||
<multiplayer supported="true"/>
|
||||
|
||||
@@ -24,6 +24,20 @@ Slå fra ved at vælge en anden enkelt vare.
|
||||
|
||||
"Mest brug for" defineres i `ADSupplyPlanner.scoreNeed` (`adSupplyPlanner.lua`).
|
||||
|
||||
### Fabriksstyret (v1.6): målet er et produktionspunkt
|
||||
|
||||
Er aflæsningsmålet en fabrik (produktionspunkt), **erstattes** ingredienslisten af inputs fra
|
||||
fabrikkens ønskede produktioner — slår du fx TMR til i en AIO-fabrik, begynder traktoren at hente
|
||||
ensilage/hø/halm/roer/mineralfoder af sig selv; slår du den fra, holder den op. Dit multi-valg er kun
|
||||
tændknappen (og det gendannes ved stop). Listen genudledes hver tur, begrænset til det vognen kan bære.
|
||||
|
||||
- **Ønsket produktion** = tændt, ELLER slukket af kortet med status "mangler input" (Dakotas
|
||||
`ExtendedProductionPoint` slår produktioner fra automatisk, når de løber tør — dem skal vi netop
|
||||
fodre). Manuelt slukket = ikke ønsket.
|
||||
- **Prioritet = tid til tom:** `lager / (Σ amount × cyclesPerMinute)` over ønskede produktioner —
|
||||
den vare der løber tør først hentes først, uanset relativ fyldning. Loggen viser forbrug og minutter.
|
||||
- Fabrik uden ønskede produktioner, eller inputs vognen ikke kan bære → dit multi-valg som hidtil.
|
||||
|
||||
## Fælles
|
||||
|
||||
- Wrapper `ADMultipleTargetsManager.getNextPickup` (via den globale `FS25_AutoDrive`-tabel); rører ikke AutoDrive-zip'en.
|
||||
|
||||
@@ -290,6 +290,71 @@ bareStation.owningPlaceable = {spec_productionPoint = {productionPoint = {storag
|
||||
feeder = makeSupplyDriver(markerByIndex(1), markerByIndex(10), {HAY, GRASS, SILAGE})
|
||||
check("S10 lager læses fra produktionspunktet", manager:getNextPickup(feeder, false), 3)
|
||||
|
||||
-- ==== Fabriksstyret forsyning (aflæsningsmålet er et produktionspunkt) ====
|
||||
ProductionPoint = {PROD_STATUS = {INACTIVE = 0, RUNNING = 1, MISSING_INPUTS = 2, NO_OUTPUT_SPACE = 3}}
|
||||
local WATER = 40
|
||||
FILL_TYPE_NAMES[WATER] = "WATER"
|
||||
FS25_AutoDrive.AutoDrive.getSupportedFillTypesOfAllUnitsAlphabetically = function(vehicle) return vehicle.carriable end
|
||||
|
||||
-- Fabrik med TMR-opskrift: sluger ensilage, nipper til hø. Vand kan vognen ikke bære.
|
||||
local function buildFactoryWorld(tmrEnabled, tmrStatus)
|
||||
buildFeedWorld()
|
||||
local pp = {
|
||||
enabled = {tmr = tmrEnabled},
|
||||
productions = {
|
||||
{id = "tmr", cyclesPerMinute = 1, status = tmrStatus, inputs = {{type = SILAGE, amount = 250}, {type = HAY, amount = 10}, {type = WATER, amount = 1000}}},
|
||||
{id = "off", cyclesPerMinute = 1, status = ProductionPoint.PROD_STATUS.INACTIVE, inputs = {{type = GRASS, amount = 500}}},
|
||||
},
|
||||
getIsProductionEnabled = function(self, id) return self.enabled[id] == true end,
|
||||
}
|
||||
local factory = {spec_productionPoint = {productionPoint = pp}, getName = function() return "AIO" end}
|
||||
unloadStations = {makeUnloadStation(110, 5000, 10, blanderLevels, {[HAY] = 100000, [GRASS] = 100000, [SILAGE] = 100000, [WATER] = 100000}, factory)}
|
||||
local driver = makeSupplyDriver(markerByIndex(1), markerByIndex(10), {HAY, GRASS})
|
||||
driver.carriable = {HAY, GRASS, SILAGE}
|
||||
return driver, pp
|
||||
end
|
||||
|
||||
-- F1: tændt produktion styrer listen: ensilage (200 min til tom) vinder over hø (8000 min)
|
||||
-- og over græs, som er relativt tommest men ikke et input i fabrikken
|
||||
local factoryDriver = buildFactoryWorld(true, ProductionPoint.PROD_STATUS.RUNNING)
|
||||
check("F1 fabrikkens input med kortest tid til tom", manager:getNextPickup(factoryDriver, false), 4)
|
||||
check("F1 AD's vare skiftet til ensilage (ikke i brugerens valg)", factoryDriver.ad.stateModule.fillType, SILAGE)
|
||||
check("F1 log nævner minutter til tom", logLines[#logLines]:find("min til tom", 1, true) ~= nil, true)
|
||||
|
||||
-- F2: næste tur — listen genudledes fra fabrikken, ikke fra brugerens valg
|
||||
blanderLevels[SILAGE] = 99500
|
||||
check("F2 fuld ensilage -> hø (næste fabriks-input)", manager:getNextPickup(factoryDriver, false), 1)
|
||||
|
||||
-- F3: AD stopper -> brugerens OPRINDELIGE valg gendannes, ikke fabrikkens liste
|
||||
factoryDriver.ad.stateModule.active = false
|
||||
listener:update(16)
|
||||
check("F3 brugerens valg gendannet ved stop", #factoryDriver.ad.stateModule.selectedFillTypes, 2)
|
||||
|
||||
-- F4: manuelt slukket produktion -> fallback til brugerens valg (græs er tommest)
|
||||
factoryDriver = buildFactoryWorld(false, ProductionPoint.PROD_STATUS.INACTIVE)
|
||||
local function countLogsSince(startIndex, needle)
|
||||
local count = 0
|
||||
for i = startIndex + 1, #logLines do
|
||||
if logLines[i]:find(needle, 1, true) then count = count + 1 end
|
||||
end
|
||||
return count
|
||||
end
|
||||
local logMark = #logLines
|
||||
check("F4 slukket fabrik -> brugerens valg", manager:getNextPickup(factoryDriver, false), 3)
|
||||
check("F4 loggen forklarer fallback", countLogsSince(logMark, "ingen ønskede produktioner"), 1)
|
||||
manager:getNextPickup(factoryDriver, false)
|
||||
check("F4 forklaringen logges kun én gang", countLogsSince(logMark, "ingen ønskede produktioner"), 1)
|
||||
|
||||
-- F5: auto-slukket af kortet pga. manglende input -> stadig fabrikkens liste
|
||||
factoryDriver = buildFactoryWorld(false, ProductionPoint.PROD_STATUS.MISSING_INPUTS)
|
||||
check("F5 auto-slukket fabrik fodres stadig", manager:getNextPickup(factoryDriver, false), 4)
|
||||
|
||||
-- F6: produktionspunkt uden getIsProductionEnabled -> activeProductions-listen bruges
|
||||
local fallbackDriver, fallbackPp = buildFactoryWorld(false, ProductionPoint.PROD_STATUS.RUNNING)
|
||||
fallbackPp.getIsProductionEnabled = nil
|
||||
fallbackPp.activeProductions = {fallbackPp.productions[1]}
|
||||
check("F6 activeProductions som fallback", manager:getNextPickup(fallbackDriver, false), 4)
|
||||
|
||||
-- L1: moden valgte siloen -> AutoDrive skal stå og læsse (rotation skjules under opgaven)
|
||||
resetWorld()
|
||||
local loadLevels = {[SUGARBEET] = 5000}
|
||||
|
||||
@@ -62,5 +62,51 @@ check("mindst-først: højere niveau er ikke bedre", ADSupplyPlanner.isBetterSou
|
||||
check("fyldest-først: højere niveau er bedre", ADSupplyPlanner.isBetterSource(900, 500, true), true)
|
||||
check("første kandidat er altid bedre end ingen", ADSupplyPlanner.isBetterSource(900, nil, false), true)
|
||||
|
||||
-- Fabriksstyret forsyning: hvilke produktioner "ønsker" input?
|
||||
local MISSING_INPUTS, INACTIVE = 2, 0
|
||||
check("tændt produktion ønskes", ADSupplyPlanner.isProductionWanted(true, INACTIVE, MISSING_INPUTS), true)
|
||||
check("auto-slukket pga. mangel ønskes stadig", ADSupplyPlanner.isProductionWanted(false, MISSING_INPUTS, MISSING_INPUTS), true)
|
||||
check("manuelt slukket ønskes ikke", ADSupplyPlanner.isProductionWanted(false, INACTIVE, MISSING_INPUTS), false)
|
||||
check("ukendt status uden tænd -> ikke ønsket", ADSupplyPlanner.isProductionWanted(false, nil, MISSING_INPUTS), false)
|
||||
|
||||
-- collectProductionDemand: liter/min pr. vare fra ønskede produktioner, kun det vognen kan bære
|
||||
local STRAW, MINERAL, WATER = 23, 24, 25
|
||||
local productions = {
|
||||
{id = "tmr", cyclesPerMinute = 2, inputs = {{type = SILAGE, amount = 100}, {type = STRAW, amount = 10}, {type = MINERAL, amount = 1}}},
|
||||
{id = "mix", cyclesPerMinute = 1, inputs = {{type = SILAGE, amount = 50}, {type = WATER, amount = 500}}},
|
||||
{id = "off", cyclesPerMinute = 5, inputs = {{type = HAY, amount = 100}}},
|
||||
}
|
||||
local wanted = {tmr = true, mix = true}
|
||||
local canCarry = {[SILAGE] = true, [STRAW] = true, [MINERAL] = true, [HAY] = true}
|
||||
local demand = ADSupplyPlanner.collectProductionDemand(productions, function(p) return wanted[p.id] == true end, canCarry)
|
||||
check("forbrug summeres på tværs af produktioner", demand[SILAGE], 250)
|
||||
check("forbrug ganges med cyklusser/min", demand[STRAW], 20)
|
||||
check("uønsket produktion tæller ikke", demand[HAY], nil)
|
||||
check("vare vognen ikke kan bære udelades", demand[WATER], nil)
|
||||
check("tom produktionsliste -> tomt behov", next(ADSupplyPlanner.collectProductionDemand({}, function() return true end, canCarry)), nil)
|
||||
check("produktion uden inputs tåles", next(ADSupplyPlanner.collectProductionDemand({{id = "x", cyclesPerMinute = 1}}, function() return true end, canCarry)), nil)
|
||||
|
||||
-- minutesToEmpty
|
||||
check("minutter til tom", ADSupplyPlanner.minutesToEmpty(1000, 250), 4)
|
||||
check("intet forbrug -> nil", ADSupplyPlanner.minutesToEmpty(1000, 0), nil)
|
||||
check("ukendt forbrug -> nil", ADSupplyPlanner.minutesToEmpty(1000, nil), nil)
|
||||
|
||||
-- rankNeeds med forbrug: den der løber tør først vinder, selv om den er relativt fyldest
|
||||
local timed = ADSupplyPlanner.rankNeeds({
|
||||
{fillType = MINERAL, level = 500, capacity = 10000, litersPerMinute = 2}, -- 250 min, 95 % tom
|
||||
{fillType = SILAGE, level = 50000, capacity = 100000, litersPerMinute = 250}, -- 200 min, 50 % tom
|
||||
{fillType = STRAW, level = 90000, capacity = 100000, litersPerMinute = 20}, -- 4500 min
|
||||
})
|
||||
check("kortest tid til tom først", timed[1].fillType, SILAGE)
|
||||
check("dernæst næstkortest", timed[2].fillType, MINERAL)
|
||||
check("minutesToEmpty følger med", timed[1].minutesToEmpty, 200)
|
||||
check("vare med forbrug slår vare uden", ADSupplyPlanner.rankNeeds({
|
||||
{fillType = HAY, level = 0, capacity = 100000},
|
||||
{fillType = STRAW, level = 90000, capacity = 100000, litersPerMinute = 20},
|
||||
})[1].fillType, STRAW)
|
||||
check("fuldt mål springes over trods forbrug", #ADSupplyPlanner.rankNeeds({
|
||||
{fillType = STRAW, level = 99500, capacity = 100000, litersPerMinute = 20},
|
||||
}), 0)
|
||||
|
||||
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