Last active
August 23, 2025 06:06
-
-
Save kaustubh-karkare/266c088f67fa0c216fe4464cf0def065 to your computer and use it in GitHub Desktop.
Factorio / Library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| local json = require("dkjson") | |
| local data = require("space-age-data") -- https://wiki.factorio.com/Data.raw | |
| local indent = " " | |
| function to_json(item) | |
| return json.encode(item, { indent = true }) | |
| end | |
| function onlyx(items) | |
| -- assert(#items == 1, string.format('Multiple items found in %s', to_json(items))) | |
| for _, value in pairs(items) do | |
| return value | |
| end | |
| end | |
| function create_config(input) | |
| productivity_module_bonus = input.productivity_module_bonus or 0 | |
| local category_to_productivity = { | |
| ["default"] = 4 * productivity_module_bonus, | |
| ["smelting"] = 2 * productivity_module_bonus, | |
| ["chemistry-or-cryogenics"] = (input.use_cryogenic_plant and 8 or 3) * productivity_module_bonus, | |
| ["chemistry"] = 3 * productivity_module_bonus, | |
| ["electronics"] = (input.use_em_plant and 5 or 4) * productivity_module_bonus, | |
| ["electronics-with-fluid"] = (input.use_em_plant and 5 or 4) * productivity_module_bonus, | |
| ["advanced-crafting"] = 4 * productivity_module_bonus, | |
| ["crafting-with-fluid"] = 4 * productivity_module_bonus, | |
| ["crafting"] = 4 * productivity_module_bonus, | |
| ["metallurgy"] = 4 * productivity_module_bonus, | |
| } | |
| local skipped_recipes = {} | |
| local default_skipped_recipes = {} -- {"casting-iron-stick"} | |
| for _, recipe_name in pairs(input.skipped_recipes or default_skipped_recipes) do | |
| assert(data['recipe'][recipe_name] ~= nil, string.format('Recipe %s not found', recipe_name)) | |
| skipped_recipes[recipe_name] = true | |
| end | |
| local preferred_recipes = {} | |
| if input.use_foundry then | |
| for recipe_name, item in pairs(data['recipe']) do | |
| if item.category ~= "metallurgy" then | |
| -- not relevant for foundry | |
| elseif string.find(recipe_name, "lava") then | |
| -- not relevant for nauvis | |
| elseif skipped_recipes[recipe_name] then | |
| -- less efficient than casting to plates and then assembling into sticks. | |
| -- in contrast, "casting-copper-cable" is less efficient at this stage. | |
| else | |
| preferred_recipes[onlyx(item.results).name] = recipe_name | |
| end | |
| end | |
| end | |
| return { | |
| name = input.name, | |
| category_to_productivity = category_to_productivity, | |
| preferred_recipes = preferred_recipes, | |
| use_foundry = input.use_foundry, | |
| use_em_plant = input.use_em_plant, | |
| productivity_bonus = input.productivity_bonus or {}, | |
| } | |
| end | |
| function create_result() | |
| return {raw_items = {}, intermediate_products = {}} | |
| end | |
| function get_productivity(item_name, recipe, config) | |
| local category = recipe.category or "default" | |
| if recipe.allow_productivity and config.category_to_productivity[category] == nil then -- debugging | |
| print(to_json(recipe)) | |
| end | |
| local productivity = 1 -- base | |
| if recipe.allow_productivity then -- modules | |
| productivity = productivity + config.category_to_productivity[category] or 0 | |
| end | |
| if config.use_foundry and recipe.category == "metallurgy" then -- buildings | |
| productivity = productivity + 0.5 | |
| elseif config.use_em_plant and (recipe.category == "electronics" or recipe.category == "electronics-with-fluid") then | |
| productivity = productivity + 0.5 | |
| end | |
| productivity = productivity + (config.productivity_bonus[item_name] or 0) -- research | |
| return productivity | |
| end | |
| function explore(item_name, item_amount, config, prefix, result) | |
| local recipe_name = config.preferred_recipes[item_name] or item_name | |
| local recipe = data['recipe'][recipe_name] | |
| local productivity = recipe and get_productivity(item_name, recipe, config) | |
| -- local preferred_suffix = (item_name ~= recipe_name and " using " .. recipe_name or "") | |
| -- local productivity_suffix = productivity and string.format(" (productivity=%.2f)", productivity) or "" | |
| -- print(string.format("%s%s (%.3f)%s%s", prefix, item_name, item_amount, preferred_suffix, productivity_suffix)) | |
| if recipe == nul then | |
| result.raw_items[item_name] = (result.raw_items[item_name] or 0.0) + item_amount | |
| return | |
| else | |
| result.intermediate_products[item_name] = (result.intermediate_products[item_name] or 0.0) + item_amount | |
| end | |
| local recipe_amount = onlyx(recipe.results).amount | |
| for _, ingredient in ipairs(recipe.ingredients) do | |
| ingredient_amount = ingredient.amount * item_amount / recipe_amount / productivity | |
| explore(ingredient.name, ingredient_amount, config, prefix .. indent, result) | |
| end | |
| end | |
| function print_table_divider(column_widths) | |
| io.write("+") | |
| for _, column_width in ipairs(column_widths) do | |
| io.write(string.rep("-", column_width+2) .. "+") | |
| end | |
| io.write("\n") | |
| end | |
| function print_table(table_cols, table_rows) | |
| local column_widths = {} | |
| for index, column_name in ipairs(table_cols) do | |
| column_widths[index] = #tostring(column_name) | |
| for _, table_row in ipairs(table_rows) do | |
| value = tostring(table_row[column_name]) | |
| column_widths[index] = math.max(column_widths[index], #value) | |
| end | |
| end | |
| print_table_divider(column_widths) | |
| io.write("|") | |
| for index, column_name in ipairs(table_cols) do | |
| prefix_length = column_widths[index] - #tostring(column_name) | |
| io.write(string.rep(" ", prefix_length + 1) .. column_name .. " |") | |
| end | |
| io.write("\n") | |
| print_table_divider(column_widths) | |
| for _, table_row in ipairs(table_rows) do | |
| io.write("|") | |
| for index, column_name in ipairs(table_cols) do | |
| value = tostring(table_row[column_name]) | |
| prefix_length = column_widths[index] - #value | |
| io.write(string.rep(" ", prefix_length + 1) .. value .. " |") | |
| end | |
| io.write("\n") | |
| end | |
| print_table_divider(column_widths) | |
| end | |
| return { | |
| to_json = to_json, | |
| onlyx = onlyx, | |
| create_config = create_config, | |
| create_result = create_result, | |
| explore = explore, | |
| print_table = print_table, | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment