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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user