Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- simulationResults = {}
- round_robin = false
- function loadRecipes(filename)
- local recipes = {}
- for line in io.lines(filename) do
- local name, inputs, outputs = line:match("([^/]+)/(.+)/(.+)")
- if name and inputs and outputs then
- local recipe = {name = name, inputs = {}, outputs = {}}
- for input in inputs:gmatch("[^;]+") do
- local item, count = input:match("([^,]+),(%d+)")
- table.insert(recipe.inputs, {name = item, count = tonumber(count)})
- end
- for output in outputs:gmatch("[^;]+") do
- local item, count = output:match("([^,]+),(%d+)")
- table.insert(recipe.outputs, {name = item, count = tonumber(count)})
- end
- table.insert(recipes, recipe)
- end
- end
- return recipes
- end
- function calculateTotalItemCount(itemName, inventory)
- local totalCount = 0
- for slot, item in pairs(inventory) do
- if item.name == itemName then
- totalCount = totalCount + item.count
- end
- end
- return totalCount
- end
- function createVirtualInventory()
- virtualInventory = {}
- for i = 1, chest.size() do
- local item = chest.getItemDetail(i)
- if item ~= nil then
- virtualInventory[#virtualInventory + 1] = item
- end
- end
- end
- function takeVirtualItem(item_id, amount, remove)
- local found_amount = 0
- for i = 1, #virtualInventory do
- if virtualInventory[i]["name"] == item_id then
- found_amount = found_amount + virtualInventory[i]["count"]
- end
- end
- if found_amount >= amount then
- local required_amount = amount
- if remove then
- for i = 1, #virtualInventory do
- if virtualInventory[i]["name"] == item_id then
- if virtualInventory[i]["count"] >= amount then
- virtualInventory[i]["count"] = virtualInventory[i]["count"] - amount
- required_amount = 0
- elseif virtualInventory[i]["count"] > 0 then
- required_amount = required_amount - virtualInventory[i]["count"]
- virtualInventory[i]["count"] = 0
- end
- if virtualInventory[i]["count"] == 0 then
- virtualInventory[i] = nil
- end
- if required_amount == 0 then
- break
- end
- end
- end
- end
- return true
- else
- return false
- end
- end
- function initializeSimulationResults(recipes)
- for _, recipe in ipairs(recipes) do
- simulationResults[recipe.name] = {executed = 0, max = 0}
- end
- printResults()
- end
- function runSimulation(recipes)
- createVirtualInventory()
- local added_count = 1 -- Initial-wert, damit die schleife mindestens 1 mal durchläuft
- while added_count > 0 do
- added_count = 0 -- grundwert festlegen für round-robin-workaround
- for _, recipe in ipairs(recipes) do
- has_required_sources = true
- while has_required_sources do
- for _, input in ipairs(recipe.inputs) do
- if takeVirtualItem(input.name, input.count, false) == false then
- has_required_sources = false
- break
- end
- end
- if has_required_sources then
- for _, input in ipairs(recipe.inputs) do
- takeVirtualItem(input.name, input.count, true)
- end
- simulationResults[recipe.name].max = simulationResults[recipe.name].max + 1
- printResults()
- added_count = added_count + 1
- if round_robin then
- break
- end
- end
- end
- end
- end
- end
- function executeRecipe(recipe)
- -- Ressourcen von Chest zu Machine verschieben
- for _, input in ipairs(recipe.inputs) do
- local remaining = input.count
- for i = 1, chest.size() do
- local item = chest.getItemDetail(i)
- if item and item.name == input.name then
- local transferAmount = math.min(item.count, remaining)
- chest.pushItems("left", i, transferAmount)
- remaining = remaining - transferAmount
- if remaining <= 0 then
- break
- end
- end
- end
- end
- end
- -- Funktion zur Überprüfung und Speicherung des Ausgabeelements
- function waitForAndStoreOutput(recipe, executed)
- while true do
- local slot1results = machine.getItemDetail(1)
- if slot1results and slot1results.name == recipe.outputs[1].name and slot1results.count >= recipe.outputs[1].count then
- -- Ergebnis-Item in die Kiste ziehen
- chest.pullItems("left", 1, slot1results.count)
- executed = executed + 1
- -- Aktualisierte Anzeige des ausgeführten Rezeptes
- simulationResults[recipe.name].executed = executed
- printResults()
- return executed -- Aktualisierten Zähler zurückgeben
- end
- os.sleep(0.1) -- Kurze Pause, bevor erneut geprüft wird
- end
- end
- -- Funktion zur formatierten Anzeige der Simulationsergebnisse
- function printResults()
- term.setCursorPos(1, 1)
- for name, result in pairs(simulationResults) do
- print(name .. " " .. trail(4, result.executed) .. " / " .. trail(4, result.max))
- end
- end
- -- Hilfsfunktion zur Formatierung der Zahlen
- function trail(count, value)
- local str = tostring(value)
- return string.rep(" ", count - #str) .. str
- end
- -- Hauptprogramm zur Durchführung der Simulation und Ausführung der Rezepte
- function main()
- local recipes = loadRecipes("recipes.lst")
- -- Initialisierung der leeren Grundstruktur der Simulationsergebnisse
- initializeSimulationResults(recipes)
- -- Durchführung der Simulation mit Live-Updates
- runSimulation(recipes)
- -- Modus festlegen:
- round_robin = false
- -- Rezepte tatsächlich ausführen
- if round_robin ~= false then
- -- Stack-Modus: Jedes Rezept vollständig ausführen, bevor das nächste Rezept gestartet wird
- for _, recipe in ipairs(recipes) do
- local maxExecutions = simulationResults[recipe.name].max
- local executed = 0
- for _ = 1, maxExecutions do
- executeRecipe(recipe)
- executed = waitForAndStoreOutput(recipe, executed)
- end
- end
- elseif round_robin then
- -- Round-Robin-Modus: Rezepte nacheinander einmal ausführen, bis keine weiteren Ausführungen möglich sind
- local active = true
- local executionCounts = {}
- -- Initialisiere Zähler für alle Rezepte
- for _, recipe in ipairs(recipes) do
- executionCounts[recipe.name] = 0
- end
- while active do
- active = false
- for _, recipe in ipairs(recipes) do
- local maxExecutions = simulationResults[recipe.name].max
- if executionCounts[recipe.name] < maxExecutions then
- executeRecipe(recipe)
- executionCounts[recipe.name] = waitForAndStoreOutput(recipe, executionCounts[recipe.name])
- active = true
- end
- end
- end
- end
- end
- -- Initialisierung der Peripherie
- machine = peripheral.wrap("left")
- chest = peripheral.wrap("right")
- -- Skript ausführen
- main()
Advertisement
Add Comment
Please, Sign In to add comment