d2a4cf0d23
ADChainData leverer data.fieldGoods (vindue-varer, spillets konvertere, tørrede varianter og kendte markvarer der findes som fill type). En markvare uden producent/stald får kilden "fra marker" uden afgrødeplan og uden problem, så fermenteringssiloernes hø/lucerne/kløver/hakkelse ikke meldes som køb.
454 lines
22 KiB
Lua
454 lines
22 KiB
Lua
-- AD Chain Data (læse-adapter)
|
||
-- Omsætter spillets tilstand (gårdens fabrikker, stalde, afgrøder, lager og marker) til de rene data som
|
||
-- ADChainModel og ADCropPlan regner på. Varer og afgrøder er NAVNE; mængder er liter pr. måned (spillets
|
||
-- rå rater: én 24-timers dag pr. måned, som lagerfanen). Al spiladgang sker inde i funktionerne, så filen kan
|
||
-- dofile's uden spillet. Hver bygning/mark/afgrøde læses i pcall; en fejl logges én gang pr. nøgle.
|
||
|
||
ADChainData = {}
|
||
ADChainData.LOG_PREFIX = "ADSmartPickup: kæde: "
|
||
ADChainData.PERMANENT = {GRAPE = true, GRAPEB = true, OLIVE = true, POPLAR = true}
|
||
ADChainData.warned = {}
|
||
|
||
-- Varige afgrøder (vin, oliven, poppel) skiftes aldrig; mod-vine hedder også GRAPE…
|
||
function ADChainData.isPermanent(fruitName)
|
||
if type(fruitName) ~= "string" or fruitName == "" then return false end
|
||
return ADChainData.PERMANENT[fruitName] == true or fruitName:sub(1, 5) == "GRAPE"
|
||
end
|
||
|
||
function ADChainData.recipeKey(placeableUid, productionId)
|
||
return tostring(placeableUid) .. ":" .. tostring(productionId)
|
||
end
|
||
|
||
-- Samme omregning som lagerfanen (adSources addFactoryRates): cyklusser pr. 24-timers dag = pr. måned.
|
||
function ADChainData.cyclesPerMonth(production)
|
||
return (production.cyclesPerMinute or ((production.cyclesPerHour or 0) / 60)) * 1440
|
||
end
|
||
|
||
function ADChainData.warnOnce(key, fmt, ...)
|
||
if ADChainData.warned[key] then return end
|
||
ADChainData.warned[key] = true
|
||
if Logging ~= nil and Logging.warning ~= nil then Logging.warning(ADChainData.LOG_PREFIX .. fmt, ...) end
|
||
end
|
||
|
||
-- En læsefejl i dette kald: data.partial = true (også når advarslen allerede er logget), så kæden ikke
|
||
-- slukker eller stopper noget på et ufuldstændigt billede af gården.
|
||
-- data.readFailed skelner en ægte læsefejl fra en ufærdig markscanning (afhængighedstjekket bruger ikke markerne).
|
||
local function failed(data, key, fmt, ...)
|
||
data.partial, data.readFailed = true, true
|
||
ADChainData.warnOnce(key, fmt, ...)
|
||
end
|
||
|
||
-- ---- hjælpere ----
|
||
|
||
-- Navn for et fillType-indeks; husker indeks og titel til GUI og vognvalg.
|
||
local function nameResolver(data)
|
||
return function(index)
|
||
if index == nil or g_fillTypeManager == nil then return nil end
|
||
local name = g_fillTypeManager:getFillTypeNameByIndex(index)
|
||
if name == nil then return nil end
|
||
if data.fillIndex[name] == nil then
|
||
data.fillIndex[name] = index
|
||
local desc = g_fillTypeManager.getFillTypeByIndex ~= nil and g_fillTypeManager:getFillTypeByIndex(index) or nil
|
||
data.fillTitles[name] = tostring(desc ~= nil and desc.title or name)
|
||
end
|
||
return name
|
||
end
|
||
end
|
||
|
||
-- {{type, amount}} -> {[navn] = mængde pr. cyklus}
|
||
local function amountsByName(list, nameOf)
|
||
local result = {}
|
||
for _, entry in ipairs(list or {}) do
|
||
local name = nameOf(entry.type)
|
||
if name ~= nil and (entry.amount or 0) > 0 then result[name] = (result[name] or 0) + entry.amount end
|
||
end
|
||
return result
|
||
end
|
||
|
||
local function placeableId(placeable)
|
||
if placeable.uniqueId ~= nil then return tostring(placeable.uniqueId) end
|
||
return ADBuildings ~= nil and ADBuildings.getId ~= nil and ADBuildings.getId(placeable) or nil
|
||
end
|
||
|
||
-- Spillerens eget navn (ADNames) før spillets; samme rækkefølge som adSources/adBuildings.
|
||
local function placeableName(placeable, fallback)
|
||
local own = ADNames ~= nil and ADNames.forPlaceable ~= nil and ADNames.forPlaceable(placeable) or nil
|
||
if own ~= nil then return own end
|
||
if placeable.getName ~= nil then
|
||
local ok, name = pcall(placeable.getName, placeable)
|
||
if ok and name ~= nil then return tostring(name) end
|
||
end
|
||
return fallback
|
||
end
|
||
|
||
local function isEnabled(point, production)
|
||
if point.getIsProductionEnabled ~= nil then return point:getIsProductionEnabled(production.id) == true end
|
||
for _, active in ipairs(point.activeProductions or {}) do
|
||
if active == production then return true end
|
||
end
|
||
return false
|
||
end
|
||
|
||
-- ---- læsning pr. del ----
|
||
|
||
-- En fabriks produktioner -> opskrifter + punkter (samles først, så en fejl midtvejs ikke efterlader halve).
|
||
local function readFactory(placeable, point, byChain, nameOf)
|
||
local uid = placeableId(placeable)
|
||
if uid == nil then return {}, {} end
|
||
local buildingName = placeableName(placeable, uid)
|
||
local recipes, points = {}, {}
|
||
for _, production in ipairs(point.productions or {}) do
|
||
local key = ADChainData.recipeKey(uid, production.id)
|
||
table.insert(recipes, {key = key, name = tostring(production.name or production.id), building = uid,
|
||
buildingName = buildingName, enabled = isEnabled(point, production), byChain = (byChain or {})[key] == true,
|
||
cyclesPerMonth = ADChainData.cyclesPerMonth(production),
|
||
inputs = amountsByName(production.inputs, nameOf), outputs = amountsByName(production.outputs, nameOf)})
|
||
points[key] = {point = point, productionId = production.id, placeable = placeable}
|
||
end
|
||
return recipes, points
|
||
end
|
||
|
||
local function readHerd(placeable, nameOf)
|
||
local uid = placeableId(placeable)
|
||
local outputs = {}
|
||
for index, perMonth in pairs(ADSources.getHusbandryOutputs(placeable) or {}) do
|
||
local name = nameOf(index)
|
||
if name ~= nil then outputs[name] = (outputs[name] or 0) + perMonth end
|
||
end
|
||
if uid == nil or next(outputs) == nil then return nil end
|
||
return {building = uid, buildingName = placeableName(placeable, uid), outputs = outputs}
|
||
end
|
||
|
||
-- Stald-foder: {[vare] = {staldnavn...}} for det truget æder nu (forbrug > 0) — til afhængighedstjekket.
|
||
local function readBarnFood(data, placeable, nameOf)
|
||
if ADSources.getHusbandryConsumption == nil then return end
|
||
local barnName
|
||
for index, perDay in pairs(ADSources.getHusbandryConsumption(placeable) or {}) do
|
||
local name = nameOf(index)
|
||
if name ~= nil and (perDay or 0) > 0 then
|
||
barnName = barnName or placeableName(placeable, placeableId(placeable) or "?")
|
||
data.barnFood[name] = data.barnFood[name] or {}
|
||
table.insert(data.barnFood[name], barnName)
|
||
end
|
||
end
|
||
end
|
||
|
||
local function readPlaceables(data, farmId, byChain, nameOf)
|
||
local placeables = g_currentMission ~= nil and g_currentMission.placeableSystem ~= nil and g_currentMission.placeableSystem.placeables or {}
|
||
for index, placeable in pairs(placeables) do
|
||
local ok, err = pcall(function()
|
||
if not ADPrices.isOwnedBy(placeable, farmId) then return end
|
||
local uid = placeableId(placeable)
|
||
if uid ~= nil then data.placeables[uid] = placeable end
|
||
local point = placeable.spec_productionPoint ~= nil and placeable.spec_productionPoint.productionPoint or nil
|
||
if point ~= nil then
|
||
local recipes, points = readFactory(placeable, point, byChain, nameOf)
|
||
for _, recipe in ipairs(recipes) do table.insert(data.recipes, recipe) end
|
||
for key, entry in pairs(points) do data.points[key] = entry end
|
||
elseif placeable.spec_husbandry ~= nil or placeable.getHusbandryFillLevel ~= nil then
|
||
local herd = readHerd(placeable, nameOf)
|
||
if herd ~= nil then table.insert(data.husbandry, herd) end
|
||
readBarnFood(data, placeable, nameOf)
|
||
end
|
||
end)
|
||
if not ok then
|
||
local key = tostring(placeable ~= nil and placeable.uniqueId or index)
|
||
failed(data, "placeable:" .. key, "bygning %s kunne ikke læses: %s", key, tostring(err))
|
||
end
|
||
end
|
||
table.sort(data.recipes, function(a, b) return a.key < b.key end)
|
||
end
|
||
|
||
-- Markedspris for en afgrøde, først når kæden spørger (kun kandidatmarkernes afgrøder, kun ved mangel);
|
||
-- hver afgrøde slås højst op én gang pr. læsning. Fejl -> 0 (logget én gang).
|
||
local function priceResolver(data)
|
||
local cache = {}
|
||
return function(fruitName)
|
||
if cache[fruitName] ~= nil then return cache[fruitName] end
|
||
local index = data.fruitFillIndex[fruitName]
|
||
local price = 0
|
||
if index ~= nil then
|
||
local ok, quote = pcall(ADSources.getMarketQuote, index)
|
||
if ok then
|
||
price = quote ~= nil and quote.price or 0
|
||
else
|
||
ADChainData.warnOnce("price:" .. tostring(fruitName), "pris for %s kunne ikke læses: %s", tostring(fruitName), tostring(quote))
|
||
end
|
||
end
|
||
cache[fruitName] = price
|
||
return price
|
||
end
|
||
end
|
||
|
||
local function readCrops(data, nameOf)
|
||
local fruits = g_fruitTypeManager ~= nil and g_fruitTypeManager.fruitTypes or {}
|
||
for _, fruit in ipairs(fruits) do
|
||
if fruit.fillType ~= nil and fruit.allowsSeeding ~= false and fruit.name ~= nil then
|
||
local ok, err = pcall(function()
|
||
local fillName = fruit.fillType.name or nameOf(fruit.fillType.index)
|
||
if fillName == nil then return end
|
||
if fruit.fillType.index ~= nil then nameOf(fruit.fillType.index) end
|
||
data.crops[fillName] = fruit.name
|
||
data.yields[fruit.name] = (tonumber(fruit.literPerSqm) or 0) * 10000
|
||
data.fruitFillIndex[fruit.name] = fruit.fillType.index
|
||
end)
|
||
if not ok then failed(data, "fruit:" .. tostring(fruit.name), "afgrøde %s kunne ikke læses: %s", tostring(fruit.name), tostring(err)) end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- ---- markvarer (hø, hakkelse, halm …) ----
|
||
-- Varer der høstes/laves på marken uden at være en afgrødes hovedvare. Spillets konvertere hedder forskelligt
|
||
-- mellem versioner/kort (FORAGEHARVESTER/FORAGE_HARVESTER), så alle navne prøves; et ukendt navn giver nil.
|
||
ADChainData.FIELD_CONVERTERS = {"FORAGEHARVESTER", "FORAGE_HARVESTER", "MOWER", "COMBINE", "CUTTER"}
|
||
-- Kendte markvarer (basisspil, FermentingSiloPack, Dakota); kun dem der findes som fill type bruges.
|
||
ADChainData.KNOWN_FIELD_GOODS = {"STRAW", "CHAFF", "CROP_WINDROW", "GRASS_WINDROW", "ALFALFA_WINDROW", "CLOVER_WINDROW",
|
||
"DRYGRASS_WINDROW", "DRYALFALFA_WINDROW", "DRYCLOVER_WINDROW", "CCM", "CCMRAW", "WCS"}
|
||
|
||
-- fruit.windrowFillType kan være et indeks eller en fill type-beskrivelse
|
||
local function windrowIndex(fruit)
|
||
local windrow = fruit.windrowFillType
|
||
if type(windrow) == "number" then return windrow end
|
||
if type(windrow) == "table" then
|
||
if windrow.index ~= nil then return windrow.index end
|
||
if windrow.name ~= nil and g_fillTypeManager.getFillTypeIndexByName ~= nil then
|
||
return g_fillTypeManager:getFillTypeIndexByName(windrow.name)
|
||
end
|
||
end
|
||
return nil
|
||
end
|
||
|
||
-- Én konverters mål-indekser ({[fra] = {targetFillTypeIndex|fillTypeIndex}}, samme form som adFields.buildMowable)
|
||
local function converterTargets(converter, add)
|
||
for _, entry in pairs(converter or {}) do
|
||
if type(entry) == "table" then add(entry.targetFillTypeIndex or entry.fillTypeIndex) end
|
||
end
|
||
end
|
||
|
||
-- data.fieldGoods = {[navn] = true}. Kun eksisterende fill types; fejl logges én gang og gør ikke læsningen delvis
|
||
-- (en ændret spil-API må ikke blokere kæden for altid) — værst tænkeligt meldes en markvare som "køb".
|
||
local function readFieldGoods(data, nameOf)
|
||
local indices = {}
|
||
local function add(index) if type(index) == "number" then indices[index] = true end end
|
||
local function guarded(key, fn)
|
||
local ok, err = pcall(fn)
|
||
if not ok then ADChainData.warnOnce("fieldGoods:" .. key, "markvarer (%s) kunne ikke læses: %s", key, tostring(err)) end
|
||
end
|
||
if g_fillTypeManager == nil then return end
|
||
local fruitManager = g_fruitTypeManager
|
||
for _, fruit in ipairs(fruitManager ~= nil and fruitManager.fruitTypes or {}) do
|
||
guarded("windrow:" .. tostring(fruit.name), function() add(windrowIndex(fruit)) end)
|
||
end
|
||
if fruitManager ~= nil and fruitManager.getConverterDataByName ~= nil then
|
||
for _, name in ipairs(ADChainData.FIELD_CONVERTERS) do
|
||
guarded(name, function() converterTargets(fruitManager:getConverterDataByName(name), add) end)
|
||
end
|
||
end
|
||
if g_fillTypeManager.getFillTypeIndexByName ~= nil then
|
||
for _, name in ipairs(ADChainData.KNOWN_FIELD_GOODS) do
|
||
guarded(name, function() add(g_fillTypeManager:getFillTypeIndexByName(name)) end)
|
||
end
|
||
end
|
||
-- tørrede varianter (vender: græs-vindue -> hø)
|
||
if g_fillTypeManager.getConverterDataByName ~= nil then
|
||
guarded("TEDDER", function()
|
||
local tedder = g_fillTypeManager:getConverterDataByName("TEDDER") or {}
|
||
local windrows = {}
|
||
for index in pairs(indices) do table.insert(windrows, index) end
|
||
for _, index in ipairs(windrows) do
|
||
local entry = tedder[index]
|
||
if type(entry) == "table" then add(entry.targetFillTypeIndex or entry.fillTypeIndex) end
|
||
end
|
||
end)
|
||
end
|
||
for index in pairs(indices) do
|
||
local ok, name = pcall(nameOf, index)
|
||
if ok and name ~= nil and data.crops[name] == nil then data.fieldGoods[name] = true end
|
||
end
|
||
end
|
||
|
||
local function readStock(data, adEnv, farmId, nameOf)
|
||
local ok, err = pcall(function()
|
||
for index, liters in pairs(ADStorageStats.farmTotals(ADSources.getFarmInventory(adEnv, farmId))) do
|
||
local name = nameOf(index)
|
||
if name ~= nil then data.stockByFill[name] = (data.stockByFill[name] or 0) + liters end
|
||
local fruit = data.crops[name or ""]
|
||
if fruit ~= nil then data.stock[fruit] = (data.stock[fruit] or 0) + liters end
|
||
end
|
||
end)
|
||
if not ok then failed(data, "stock", "lager kunne ikke læses: %s", tostring(err)) end
|
||
end
|
||
|
||
-- Gårdens forbrug og produktion pr. døgn (fabrikker der kører + stalde) pr. varenavn og spillets tidsfaktor
|
||
-- (rå rater pr. måned × faktor = pr. døgn) — til lagerdage og dækning i afhængighedstjekket.
|
||
local function readRates(data, adEnv, farmId, nameOf)
|
||
local environment = g_currentMission ~= nil and g_currentMission.environment or nil
|
||
local adjustment = environment ~= nil and tonumber(environment.timeAdjustment) or nil
|
||
data.timeAdjustment = adjustment ~= nil and adjustment > 0 and adjustment or 1
|
||
local ok, err = pcall(function()
|
||
for index, rate in pairs(ADSources.getFarmRates(adEnv, farmId, false) or {}) do
|
||
local name = nameOf(index)
|
||
if name ~= nil then data.rates[name] = {consumption = rate.consumption or 0, production = rate.production or 0} end
|
||
end
|
||
end)
|
||
if not ok then failed(data, "allRates", "gårdens forbrug kunne ikke læses: %s", tostring(err)) end
|
||
end
|
||
|
||
-- Afgrøder gården selv bruger: input i en tændt produktion eller foder/halm i en stald (kun staldenes forbrug
|
||
-- læses: feedOnly springer fabrikkernes rater over — dem dækker opskrifterne allerede).
|
||
local function readUsedFruits(data, adEnv, farmId, nameOf)
|
||
for _, recipe in ipairs(data.recipes) do
|
||
if recipe.enabled then
|
||
for name in pairs(recipe.inputs) do
|
||
if data.crops[name] ~= nil then data.usedFruits[data.crops[name]] = true end
|
||
end
|
||
end
|
||
end
|
||
local ok, err = pcall(function()
|
||
for index, rate in pairs(ADSources.getFarmRates(adEnv, farmId, true) or {}) do
|
||
local fruit = data.crops[nameOf(index) or ""]
|
||
if fruit ~= nil and (rate.consumption or 0) > 0 then data.usedFruits[fruit] = true end
|
||
end
|
||
end)
|
||
if not ok then failed(data, "rates", "staldforbrug kunne ikke læses: %s", tostring(err)) end
|
||
end
|
||
|
||
-- Markscanningen har ikke nået alle marker endnu (efter indlæsning ~én mark pr. 2 s): marklisten er ufuldstændig,
|
||
-- så udbud undervurderes -> fieldsIncomplete (kæden rører ingen marker) og partial (intet slukkes/stoppes).
|
||
local function readFields(data)
|
||
if ADFields.isScanComplete ~= nil and not ADFields.isScanComplete() then
|
||
data.partial, data.fieldsIncomplete = true, true
|
||
end
|
||
for _, info in ipairs(ADFields.list() or {}) do
|
||
local ok, entry = pcall(function()
|
||
local field = ADFieldJobs.getField(info.id)
|
||
local plan = field.plan or {}
|
||
local fruit = info.growing and info.fruitName or field.lastFruit
|
||
return {id = info.id, areaHa = ADFields.polygonAreaHa(info.verts), fruit = fruit,
|
||
targetFruit = plan.targetFruit, targetSource = plan.targetSource, chainFree = plan.chainFree == true,
|
||
permanent = ADChainData.isPermanent(info.fruitName or field.lastFruit), excluded = info.kind == "mowable"}
|
||
end)
|
||
if ok then
|
||
table.insert(data.fields, entry)
|
||
else
|
||
failed(data, "field:" .. tostring(info.id), "mark %s kunne ikke læses: %s", tostring(info.id), tostring(entry))
|
||
end
|
||
end
|
||
end
|
||
|
||
-- ---- afhængighedstjek (spec afsnit 8) ----
|
||
|
||
local function unloadStationsOf(placeable)
|
||
local storage = g_currentMission ~= nil and g_currentMission.storageSystem or nil
|
||
local result = {}
|
||
if storage == nil or storage.getUnloadingStations == nil then return result end
|
||
for _, station in pairs(storage:getUnloadingStations() or {}) do
|
||
if station.owningPlaceable == placeable then table.insert(result, station) end
|
||
end
|
||
return result
|
||
end
|
||
|
||
-- Hvad auto-flowenes mål tager af varerne `goods` (navne): {[bygnings-id] = {[vare] = true}}.
|
||
-- Kun tændte forsyningsflows i auto-tilstand; hvert mål slås op én gang.
|
||
function ADChainData.acceptsMap(data, flows, goods)
|
||
local result = {}
|
||
for _, flow in ipairs(flows or {}) do
|
||
if flow.kind ~= "outbound" and not flow.stopped and flow.ingredientMode ~= "manual" then
|
||
for _, id in ipairs(flow.targetBuildingIds or {}) do
|
||
local placeable = data.placeables[id]
|
||
if result[id] == nil and placeable ~= nil then
|
||
result[id] = {}
|
||
local ok, err = pcall(function()
|
||
local stations = unloadStationsOf(placeable)
|
||
for _, name in ipairs(goods) do
|
||
local index = data.fillIndex[name]
|
||
for _, station in ipairs(stations) do
|
||
if index ~= nil and ADSources.stationAccepts(station, index) then result[id][name] = true; break end
|
||
end
|
||
end
|
||
end)
|
||
if not ok then ADChainData.warnOnce("accepts:" .. tostring(id), "mål %s kunne ikke læses: %s", tostring(id), tostring(err)) end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
return result
|
||
end
|
||
|
||
-- Kædens input-varer (alle varer i de aktive kæders træer) -> {[vare] = {kædenavn...}}
|
||
function ADChainData.chainInputs(chain, titles)
|
||
local result = {}
|
||
local function walk(nodes, rootTitle)
|
||
for _, node in ipairs(nodes or {}) do
|
||
result[node.fillType] = result[node.fillType] or {}
|
||
local list = result[node.fillType]
|
||
if list[#list] ~= rootTitle then table.insert(list, rootTitle) end
|
||
walk(node.children, rootTitle)
|
||
end
|
||
end
|
||
for _, root in ipairs(chain ~= nil and chain.roots or {}) do
|
||
walk(root.children, tostring((titles or {})[root.name] or root.name))
|
||
end
|
||
return result
|
||
end
|
||
|
||
-- Alt afhængighedstjekket regner på, i liter pr. døgn: {needed, stockDays, capacity, demand}.
|
||
-- flows = ADChain.runsView(...); chain = kædemodellen (kan være uden rødder).
|
||
function ADChainData.dependencyInputs(data, chain, flows)
|
||
local goods, seen = {}, {}
|
||
for _, recipe in ipairs(data.recipes or {}) do
|
||
if not recipe.enabled and not recipe.byChain then
|
||
for name in pairs(recipe.outputs or {}) do
|
||
if not seen[name] then seen[name] = true; table.insert(goods, name) end
|
||
end
|
||
end
|
||
end
|
||
table.sort(goods)
|
||
-- auto-flowets mål tager mange varer (fx biogas: korn, ensilage, gylle): kun varer gården faktisk forbruger
|
||
-- (stald eller fabrik) eller en kæde vil have, tæller
|
||
local consumed = {}
|
||
for _, name in ipairs(goods) do
|
||
local rate = (data.rates or {})[name]
|
||
if (rate ~= nil and (rate.consumption or 0) > 0) or ((chain ~= nil and chain.demand or {})[name] or 0) > 0 then
|
||
table.insert(consumed, name)
|
||
end
|
||
end
|
||
local needed = ADDependency.neededOutputs(flows, data.barnFood, ADChainData.chainInputs(chain, data.fillTitles),
|
||
#consumed > 0 and ADChainData.acceptsMap(data, flows, consumed) or {})
|
||
local adjustment = data.timeAdjustment or 1
|
||
local capacity, demand, stockDays = {}, {}, {}
|
||
for name, perMonth in pairs(ADDependency.capacity(data.recipes)) do capacity[name] = perMonth * adjustment end
|
||
for _, name in ipairs(goods) do
|
||
local rate = (data.rates or {})[name] or {}
|
||
local consumption, production = rate.consumption or 0, rate.production or 0
|
||
local chainDemand = ((chain ~= nil and chain.demand or {})[name] or 0) * adjustment
|
||
demand[name] = math.max(consumption, chainDemand)
|
||
if consumption > production then
|
||
stockDays[name] = ((data.stockByFill or {})[name] or 0) / (consumption - production)
|
||
elseif consumption > 0 then
|
||
stockDays[name] = math.huge
|
||
end
|
||
end
|
||
return {needed = needed, stockDays = stockDays, capacity = capacity, demand = demand}
|
||
end
|
||
|
||
-- ---- samlet ----
|
||
|
||
-- byChain = {[recipeKey] = true} for produktioner kæden selv har tændt (ikke rødder).
|
||
-- data.partial = true når noget ikke kunne læses i dette kald (data.readFailed) eller markscanningen kører; data.fieldsIncomplete = true mens markscanningen
|
||
-- ikke har nået alle marker.
|
||
function ADChainData.collect(adEnv, farmId, byChain)
|
||
local data = {recipes = {}, husbandry = {}, crops = {}, stock = {}, fields = {}, yields = {}, fruitFillIndex = {},
|
||
usedFruits = {}, points = {}, fillTitles = {}, fillIndex = {}, placeables = {}, barnFood = {}, stockByFill = {}, rates = {}, fieldGoods = {}}
|
||
local nameOf = nameResolver(data)
|
||
data.priceOf = priceResolver(data)
|
||
readPlaceables(data, farmId, byChain, nameOf)
|
||
readCrops(data, nameOf)
|
||
readFieldGoods(data, nameOf)
|
||
readStock(data, adEnv, farmId, nameOf)
|
||
readRates(data, adEnv, farmId, nameOf)
|
||
readUsedFruits(data, adEnv, farmId, nameOf)
|
||
readFields(data)
|
||
return data
|
||
end
|