(Title Case all the things and do lower-case comparisons to avoid casing issues) |
(Add vein and gas giant support, and use local variables) |
||
Line 11: | Line 11: | ||
Fractionate='Fractionator', | Fractionate='Fractionator', | ||
Research='Matrix Lab', | Research='Matrix Lab', | ||
Mine='Mining Machine', | |||
Gas='Orbital Collector', | |||
} | } | ||
function funcs.recipesMaking(frame) | function funcs.recipesMaking(frame) | ||
return recipesMakingName(frame:getParent().args[1], frame) | |||
end | end | ||
function funcs.recipesMakingDirect(frame) | function funcs.recipesMakingDirect(frame) | ||
return recipesMakingName(frame.args[1], frame) | |||
item = itemByName(name) | end | ||
recipes = recipesMakingByID(item.ID) | |||
return tableRecipes(recipes, frame) | function recipesMakingName(name, frame) | ||
local item = itemByName(name) | |||
local recipes = recipesMakingByID(item.ID) | |||
local vein = veinMakingByID(item.ID) | |||
local gas = deduplicateGiants(gasGiantsMakingByID(item.ID)) | |||
return tableRecipes(item, recipes, vein, gas, frame) | |||
end | end | ||
function funcs.recipesUsing(frame) | function funcs.recipesUsing(frame) | ||
return recipesUsingName(frame:getParent().args[1], frame) | |||
end | end | ||
function funcs.recipesUsingDirect(frame) | function funcs.recipesUsingDirect(frame) | ||
return recipesUsingName(frame.args[1], frame) | |||
end | |||
item = itemByName(name) | |||
components, buildings = recipesUsingByID(item.ID) | function recipesUsingName(name, frame) | ||
local output = {} | |||
local item = itemByName(name) | |||
local components, buildings = recipesUsingByID(item.ID) | |||
if next(components) then | if next(components) then | ||
table.insert(output, '=== Components ===') | table.insert(output, '=== Components ===') | ||
table.insert(output, tableRecipes(components, frame)) | table.insert(output, tableRecipes(item, components, nil, nil, frame)) | ||
end | end | ||
if next(buildings) then | if next(buildings) then | ||
table.insert(output, '=== Buildings ===') | table.insert(output, '=== Buildings ===') | ||
table.insert(output, tableRecipes(buildings, frame)) | table.insert(output, tableRecipes(item, buildings, nil, nil, frame)) | ||
end | end | ||
return table.concat(output, '\n') | return table.concat(output, '\n') | ||
end | end | ||
function tableRecipes(recipes, frame) | function tableRecipes(item, recipes, vein, gas, frame) | ||
result = {} | local result = {} | ||
for _, recipe in pairs(recipes) do | for _, recipe in pairs(recipes) do | ||
itemdata = {} | local itemdata = {} | ||
itemdata.CraftTime = string.format('%s s', tostring(recipe.TimeSpend/60)) | itemdata.CraftTime = string.format('%s s', tostring(recipe.TimeSpend/60)) | ||
for i, itemid in ipairs(recipe.Results) do | for i, itemid in ipairs(recipe.Results) do | ||
Line 72: | Line 67: | ||
itemdata[string.format('In%dQty', i)] = tostring(recipe.ItemCounts[i]) | itemdata[string.format('In%dQty', i)] = tostring(recipe.ItemCounts[i]) | ||
end | end | ||
data = { | local data = { | ||
Building = machines[recipe.Type], | Building = titleCase(machines[recipe.Type]), | ||
Recipe = frame:expandTemplate{title='ItemRecipe', args=itemdata}, | Recipe = frame:expandTemplate{title='ItemRecipe', args=itemdata}, | ||
} | } | ||
Line 81: | Line 76: | ||
data.Replicator = 'No' | data.Replicator = 'No' | ||
end | end | ||
tech = technologyForRecipeID(recipe.ID) | local tech = technologyForRecipeID(recipe.ID) | ||
if tech ~= nil then | if tech ~= nil then | ||
data.Technology = titleCase(tech.Name) | data.Technology = titleCase(tech.Name) | ||
Line 89: | Line 84: | ||
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=data}) | table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=data}) | ||
end | end | ||
prefix = frame:expandTemplate{title='ProductionChainTable/head', args={}} | if vein then | ||
local miner = itemByName(machines.Mine) | |||
local minerTech = technologyForRecipeID(recipesMakingByID(miner.ID)[1].ID) | |||
local vname = string.gsub(vein.Name, '%sVeins$', ' Vein') | |||
local idata = { | |||
In1 = titleCase(vname), | |||
In1Qty = '1', | |||
Out1 = titleCase(item.Name), | |||
Out1Qty = '1', | |||
CraftTime = '2 s', | |||
} | |||
local vrecipe = frame:expandTemplate{title='ItemRecipe', args=idata} | |||
local veindata = { | |||
Building = titleCase(miner.Name), | |||
Replicator = 'Mine', | |||
Technology = titleCase(minerTech.Name), | |||
Recipe = vrecipe, | |||
} | |||
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=veindata}) | |||
end | |||
if gas then | |||
local collector = itemByName(machines.Gas) | |||
local collectorTech = technologyForRecipeID(recipesMakingByID(collector.ID)[1].ID) | |||
for _, giant in pairs(gas) do | |||
itemrecipe = { | |||
CraftTime = '?', | |||
In1 = titleCase(giant.DisplayName), | |||
In1Qty = '', | |||
} | |||
for i, productID in ipairs(giant.GasItems) do | |||
product = itemByID(productID) | |||
itemrecipe[string.format('Out%d', i)] = titleCase(product.Name) | |||
itemrecipe[string.format('Out%dQty', i)] = '1' | |||
end | |||
gasdata = { | |||
Building = titleCase(collector.Name), | |||
Replicator = 'Mine', | |||
Technology = titleCase(collectorTech.Name), | |||
Recipe = frame:expandTemplate{title='ItemRecipe', args=itemrecipe} | |||
} | |||
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=gasdata}) | |||
end | |||
end | |||
local prefix = frame:expandTemplate{title='ProductionChainTable/head', args={}} | |||
return string.format('%s\n%s\n|}', prefix, table.concat(result, '\n|-\n')) | return string.format('%s\n%s\n|}', prefix, table.concat(result, '\n|-\n')) | ||
end | end | ||
function itemByName(name) | function itemByName(name) | ||
lame = string.lower(name) | local lame = string.lower(name) | ||
for _, item in pairs(protosets.ItemProtoSet.dataArray) do | for _, item in pairs(protosets.ItemProtoSet.dataArray) do | ||
if string.lower(item.Name) == lame then | if string.lower(item.Name) == lame then | ||
Line 112: | Line 150: | ||
function recipesMakingByID(id) | function recipesMakingByID(id) | ||
result = {} | local result = {} | ||
for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do | for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do | ||
for _, itemid in pairs(recipe.Results) do | for _, itemid in pairs(recipe.Results) do | ||
Line 124: | Line 162: | ||
end | end | ||
function recipesUsingByID(id) | function recipesUsingByID(id) | ||
components = {} | local components = {} | ||
buildings = {} | local buildings = {} | ||
for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do | for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do | ||
for _, itemid in pairs(recipe.Items) do | for _, itemid in pairs(recipe.Items) do | ||
Line 150: | Line 188: | ||
end | end | ||
return nil | return nil | ||
end | |||
function veinMakingByID(id) | |||
for _, vein in pairs(protosets.VeinProtoSet.dataArray) do | |||
if vein.MiningItem == id then | |||
return vein | |||
end | |||
end | |||
return nil | |||
end | |||
function gasGiantsMakingByID(id) | |||
local giants = {} | |||
for _, planet in pairs(protosets.ThemeProtoSet.dataArray) do | |||
for _, item in pairs(planet.GasItems) do | |||
if item == id then | |||
table.insert(giants, planet) | |||
break | |||
end | |||
end | |||
end | |||
return giants | |||
end | |||
function deduplicateGiants(giants) | |||
local dedup = {} | |||
for _, planet in pairs(giants) do | |||
new = true | |||
for _, exist in pairs(dedup) do | |||
if string.lower(planet.DisplayName) == string.lower(exist.DisplayName) then | |||
new = false | |||
break | |||
end | |||
end | |||
if new then table.insert(dedup, planet) end | |||
end | |||
return dedup | |||
end | end | ||
function titleCase(str) | function titleCase(str) | ||
start | local start = string.gsub(str, '^%l', string.upper) | ||
title | local title = string.gsub(start, '[-%s]%l', string.upper) | ||
return title | return title | ||
end | end | ||
return funcs | return funcs |
Revision as of 17:43, 27 April 2024
Source data for this module is stored at Module:GameData/protosets.json
Exported Functions
Each function in this module is exported twice: one as-is for use in templates, and once with a Direct suffix for use directly on pages using {{#invoke|GameData|functionDirect|...}}.
recipesMaking
Arguments: Item Name
Print recipes making an item, given by name. This produces a full table with headers.
Example invocation:
{{#invoke:GameData|recipesMakingDirect|Sulfuric Acid}}
Recipe | Building | Replicator? | Technology |
---|---|---|---|
✖ |
recipesUsing
Arguments: Item Name
Print recipes using an item as an ingredient. Output is separated into two full tables: recipes which create components, and recipes which create buildings. This is selected by the CanBuild property of the produced items.
Example invocation:
{{#invoke:GameData|recipesUsingDirect|Copper Ingot}}
Components
Recipe | Building | Replicator? | Technology |
---|---|---|---|
✔ | |||
✔ | N/A | ||
✔ | |||
✔ | |||
✔ | N/A | ||
✖ | |||
✔ | |||
✔ | |||
✔ | |||
✔ |
Buildings
Recipe | Building | Replicator? | Technology |
---|---|---|---|
✔ | |||
✔ | |||
✔ |
itemRecipes
Arguments: Item Name
Print recipes making an item. This does not produce a full table, and is intended for use in ItemInfo boxes such as at Graphene/ItemInfo.
itemField
Arguments: Item Name, Field Name
Print a field from an item, with the field to print as an argument. You can look at Module:GameData/protosets.json and scroll down or search (Ctrl+F) to the ItemProtoSet to browse fields.
Example invocation:
{{#invoke:GameData|itemFieldDirect|Magnetic Coil|Description}}
Script error: The function "itemFieldDirect" does not exist.
{{#invoke:GameData|itemFieldDirect|Hydrogen|StackSize}}
Script error: The function "itemFieldDirect" does not exist.
local funcs = {}
local protosets = mw.loadJsonData('Module:GameData/protosets.json')
local machines = {
Smelt='Smelter',
Assemble='Assembling Machine',
Refine='Oil Refinery',
Chemical='Chemical Plant',
Exchange='Energy Exchanger',
Particle='Miniature Particle Collider',
PhotonStore='Ray Receiver',
Fractionate='Fractionator',
Research='Matrix Lab',
Mine='Mining Machine',
Gas='Orbital Collector',
}
function funcs.recipesMaking(frame)
return recipesMakingName(frame:getParent().args[1], frame)
end
function funcs.recipesMakingDirect(frame)
return recipesMakingName(frame.args[1], frame)
end
function recipesMakingName(name, frame)
local item = itemByName(name)
local recipes = recipesMakingByID(item.ID)
local vein = veinMakingByID(item.ID)
local gas = deduplicateGiants(gasGiantsMakingByID(item.ID))
return tableRecipes(item, recipes, vein, gas, frame)
end
function funcs.recipesUsing(frame)
return recipesUsingName(frame:getParent().args[1], frame)
end
function funcs.recipesUsingDirect(frame)
return recipesUsingName(frame.args[1], frame)
end
function recipesUsingName(name, frame)
local output = {}
local item = itemByName(name)
local components, buildings = recipesUsingByID(item.ID)
if next(components) then
table.insert(output, '=== Components ===')
table.insert(output, tableRecipes(item, components, nil, nil, frame))
end
if next(buildings) then
table.insert(output, '=== Buildings ===')
table.insert(output, tableRecipes(item, buildings, nil, nil, frame))
end
return table.concat(output, '\n')
end
function tableRecipes(item, recipes, vein, gas, frame)
local result = {}
for _, recipe in pairs(recipes) do
local itemdata = {}
itemdata.CraftTime = string.format('%s s', tostring(recipe.TimeSpend/60))
for i, itemid in ipairs(recipe.Results) do
itemdata[string.format('Out%d', i)] = titleCase(itemByID(itemid).Name)
itemdata[string.format('Out%dQty', i)] = tostring(recipe.ResultCounts[i])
end
for i, itemid in ipairs(recipe.Items) do
itemdata[string.format('In%d', i)] = titleCase(itemByID(itemid).Name)
itemdata[string.format('In%dQty', i)] = tostring(recipe.ItemCounts[i])
end
local data = {
Building = titleCase(machines[recipe.Type]),
Recipe = frame:expandTemplate{title='ItemRecipe', args=itemdata},
}
if recipe.Handcraft then
data.Replicator = 'Yes'
else
data.Replicator = 'No'
end
local tech = technologyForRecipeID(recipe.ID)
if tech ~= nil then
data.Technology = titleCase(tech.Name)
else
data.Technology = ''
end
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=data})
end
if vein then
local miner = itemByName(machines.Mine)
local minerTech = technologyForRecipeID(recipesMakingByID(miner.ID)[1].ID)
local vname = string.gsub(vein.Name, '%sVeins$', ' Vein')
local idata = {
In1 = titleCase(vname),
In1Qty = '1',
Out1 = titleCase(item.Name),
Out1Qty = '1',
CraftTime = '2 s',
}
local vrecipe = frame:expandTemplate{title='ItemRecipe', args=idata}
local veindata = {
Building = titleCase(miner.Name),
Replicator = 'Mine',
Technology = titleCase(minerTech.Name),
Recipe = vrecipe,
}
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=veindata})
end
if gas then
local collector = itemByName(machines.Gas)
local collectorTech = technologyForRecipeID(recipesMakingByID(collector.ID)[1].ID)
for _, giant in pairs(gas) do
itemrecipe = {
CraftTime = '?',
In1 = titleCase(giant.DisplayName),
In1Qty = '',
}
for i, productID in ipairs(giant.GasItems) do
product = itemByID(productID)
itemrecipe[string.format('Out%d', i)] = titleCase(product.Name)
itemrecipe[string.format('Out%dQty', i)] = '1'
end
gasdata = {
Building = titleCase(collector.Name),
Replicator = 'Mine',
Technology = titleCase(collectorTech.Name),
Recipe = frame:expandTemplate{title='ItemRecipe', args=itemrecipe}
}
table.insert(result, '| ' .. frame:expandTemplate{title='ProductionChain', args=gasdata})
end
end
local prefix = frame:expandTemplate{title='ProductionChainTable/head', args={}}
return string.format('%s\n%s\n|}', prefix, table.concat(result, '\n|-\n'))
end
function itemByName(name)
local lame = string.lower(name)
for _, item in pairs(protosets.ItemProtoSet.dataArray) do
if string.lower(item.Name) == lame then
return item
end
end
error('No item named ' .. name)
end
function itemByID(id)
for _, item in pairs(protosets.ItemProtoSet.dataArray) do
if item.ID == id then
return item
end
end
error('No item with ID ' .. id)
end
function recipesMakingByID(id)
local result = {}
for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do
for _, itemid in pairs(recipe.Results) do
if itemid == id then
table.insert(result, recipe)
break
end
end
end
return result
end
function recipesUsingByID(id)
local components = {}
local buildings = {}
for _, recipe in pairs(protosets.RecipeProtoSet.dataArray) do
for _, itemid in pairs(recipe.Items) do
if itemid == id then
if itemByID(recipe.Results[1]).CanBuild then
table.insert(buildings, recipe)
else
table.insert(components, recipe)
end
break
end
end
end
return components, buildings
end
function technologyForRecipeID(id)
for _, tech in pairs(protosets.TechProtoSet.dataArray) do
for _, recipeid in pairs(tech.UnlockRecipes) do
if recipeid == id then
return tech
end
end
end
return nil
end
function veinMakingByID(id)
for _, vein in pairs(protosets.VeinProtoSet.dataArray) do
if vein.MiningItem == id then
return vein
end
end
return nil
end
function gasGiantsMakingByID(id)
local giants = {}
for _, planet in pairs(protosets.ThemeProtoSet.dataArray) do
for _, item in pairs(planet.GasItems) do
if item == id then
table.insert(giants, planet)
break
end
end
end
return giants
end
function deduplicateGiants(giants)
local dedup = {}
for _, planet in pairs(giants) do
new = true
for _, exist in pairs(dedup) do
if string.lower(planet.DisplayName) == string.lower(exist.DisplayName) then
new = false
break
end
end
if new then table.insert(dedup, planet) end
end
return dedup
end
function titleCase(str)
local start = string.gsub(str, '^%l', string.upper)
local title = string.gsub(start, '[-%s]%l', string.upper)
return title
end
return funcs