Modul:RenderRecipesTable
Zur Navigation springen
Zur Suche springen
Die Dokumentation für dieses Modul kann unter Modul:RenderRecipesTable/Doku erstellt werden
require("Module:DocsUtils")
local p = {}
-- hover tooltips
loc.tooltips = {
ingredientsPerCycle = "How much of this resource is consumed every crafting cycle",
ingredientsPerMinute = "How much of this resource has to be supplied to the machine every minute for 100% efficiency",
productsPerCycle = "How much of this resource is produced every crafting cycle",
productsPerMinute = "How much of this resource has to be withdrawn from the machine every minute for 100% efficiency",
minMaxPower = "The power consumption of this machine when producing this recipe increases throughout the crafting cycle",
}
-- table column headers
loc.columns = {
recipe = "Recipe",
ingredients = "Ingredients",
duration = "Duration",
producedIn = "Produced in",
products = "Products",
unlockedBy = "Unlocked by"
}
-- errors shown when no recipes are found in place of the recipe table
-- make sure to respect spaces
loc.errors = {
listAnd = "and",
listOr = "or",
noRecipes = "No recipes found.",
producing = " cannot be crafted.",
using = "No recipe uses ",
producedIn = "No recipes can be produced in ",
}
-- page links, may be wiki links
loc.links = {
inCraftBench = "[[Craft Bench]]",
inWorkshop = "[[Equipment Workshop]]",
inBuildGun = "[[Build Gun]]",
inCustomizer = "[[Customizer]]",
alternate = "[[Hard Drive|Alternate]]",
asByproduct = " As byproduct",
}
-- manual crafting hammer
loc.manualCrafting = "File:Manual crafting.png"
-- TEMP - Remove recipes using Customizer materials
-- - recipes - array of recipes
local function filterCustomizerRecipes(recipes)
local filteredRecipes = {}
for _,recipe in pairs(recipes) do
-- ily2, regex
if not (recipe.inCustomizer or string.match(recipe.className, [=[^Recipe_Wall]=]) or string.match(recipe.className, [=[^Recipe_WallSet]=]) or string.match(recipe.className, [=[^Recipe_SteelWall]=]) or string.match(recipe.className, [=[^Recipe_Foundation_[^%s_]+_]=]) or string.match(recipe.className, [=[^Recipe_Ramp]=]) or string.match(recipe.className, [=[^Recipe_InvertedRamp]=]) or string.match(recipe.className, [=[^Recipe_Roof]=]) or string.match(recipe.className, [=[^Recipe_Pillar]=]) or string.match(recipe.className, [=[QuarterPipe]=]) or string.match(recipe.className, [=[Asphalt]=])) then
table.insert(filteredRecipes, recipe)
end
end
return filteredRecipes
end
-- Sort by inBuildGun descending, alternate descending, name ascending, experimental descending
-- - a - recipe
-- - b - recipe
local function recipeComparator(a, b)
if a.inBuildGun ~= b.inBuildGun then
return not a.inBuildGun and b.inBuildGun
elseif a.alternate ~= b.alternate then
return not a.alternate and b.alternate
elseif a.name ~= b.name then
return a.name < b.name
else
return not a.experimental and b.experimental
end
end
-- Populates a table cell with a recipe's ingredients or products.
-- - recipe - table
-- - mode - string, either "ingredients" or "products"
local function renderItemsCell(recipe, mode)
local html = [=[<div class="recipe-items" data-items-count="]=] .. #recipe[mode] .. [=[">]=]
local showPerMinValues = #recipe.producedIn > 0
for _,item in pairs(recipe[mode]) do
local itemLink, itemName = getLinkAndName(item.item, recipe.stable, recipe.experimental)
html = html .. [=[<div class="recipe-item"><span class="item-amount" title="]=] .. loc.tooltips[mode .. "PerCycle"] .. [=[">]=] .. formatNumber(item.amount) .. " × </span>[[" .. loc.filePage .. itemLink .. ".png|40px|link=" .. itemLink .. [=[]]<span class="item-name">]=] .. itemName .. [=[</span>]=] .. (showPerMinValues and ([=[<span class="item-minute" title="]=] .. loc.tooltips[mode .. "PerMinute"] .. [=[">]=] .. formatNumber((60.0/recipe.duration)*item.amount) .. loc.units.pmin .. "</span>") or "") .. "</div>"
end
html = html .. "</div>"
return html
end
-- Populates a table cell with a recipe's produced in buildings, plus the cycle duration or craft steps.
-- - recipe - table
-- - singleBuilding - boolean - if the recipe is produced in a single building, do not render the building name
local function renderProducedInCell(recipe, singleBuilding)
local html = ""
if singleBuilding then
html = recipe.duration .. loc.units.sec
if recipe.minPower and recipe.maxPower then
html = html .. [=[<br><span title="]=] .. loc.tooltips.minMaxPower .. [=[">]=] .. formatNumber(recipe.minPower) .. " - " .. formatNumber(recipe.maxPower) .. loc.units.mw .. "</span>"
end
else
for _,building in pairs(recipe.producedIn) do
local buildingLink, buildingName = getLinkAndName(building, recipe.stable, recipe.experimental)
html = html .. [=[<div class="recipe-building">[[]=] .. buildingLink .. "|" .. buildingName .. [=[]]<br>]=] .. recipe.duration .. loc.units.sec
if building == "Desc_HadronCollider_C" and recipe.minPower and recipe.maxPower then
html = html .. [=[<br><span class="recipe-energy" title="]=] .. loc.tooltips.minMaxPower .. [=[">]=] .. formatNumber(recipe.minPower) .. " - " .. formatNumber(recipe.maxPower) .. loc.units.mw .. "</span>"
end
html = html .. "</div>"
end
if recipe.inCraftBench then
html = html .. [=[<div class="recipe-building">]=] .. loc.links.inCraftBench .. [=[<br>[[]=] .. loc.manualCrafting .. [=[|16px|link=|class=invert-on-dark]] × ]=] .. formatNumber(math.ceil((recipe.manualCraftingMultiplier*recipe.duration)/2)) .. "</div>"
end
if recipe.inWorkshop then
html = html .. [=[<div class="recipe-building">]=] .. loc.links.inWorkshop .. [=[<br>[[]=] .. loc.manualCrafting .. [=[|16px|link=|class=invert-on-dark]] × ]=] .. formatNumber(math.ceil((recipe.manualCraftingMultiplier*recipe.duration)/2)) .. "</div>"
end
if recipe.inBuildGun then
html = html .. [=[<div class="recipe-building">]=] .. loc.links.inBuildGun .. [=[</div>]=]
end
if recipe.inCustomizer then
html = html .. [=[<div class="recipe-building">]=] .. loc.links.inCustomizer .. [=[</div>]=]
end
end
return html
end
-- Renders a recipe table from supplied recipes.
-- - recipes - array of recipes
-- - singleBuilding - boolean, building mode, changes the "Produced in" column
-- - targetProducts - array of product classNames, used for "recipes producing items", used for marking byproducts
-- - noRecipeMessage - string to return in place of the table if the recipes array is empty
local function renderRecipeTable(recipes, singleBuilding, targetProducts, noRecipeMessage)
if #recipes == 0 then
return noRecipeMessage or loc.errors.noRecipes
end
table.sort(recipes, recipeComparator)
recipes = filterCustomizerRecipes(recipes)
-- start table
local html = [=[{| class="wikitable sortable recipetable"]=] .. "\n|-\n" .. [=[!]=] .. loc.columns.recipe .. [=[!!class="unsortable"|]=] .. loc.columns.ingredients .. [=[!!]=] .. (singleBuilding and loc.columns.duration or loc.columns.producedIn) .. [=[!!class="unsortable"|]=] .. loc.columns.products .. [=[!!class="unsortable"|]=] .. loc.columns.unlockedBy
for _,recipe in pairs(recipes) do
-- season check
local season = ""
for _,recipeSeason in ipairs(recipe.seasons) do
if recipeSeason == "ficsmas" then -- more seasons to be added later
season = season .. [=[<br><span class="recipe-badge recipe-season-]=] .. string.lower(recipeSeason) .. [=[">]=] .. string.upper(recipeSeason) .. [=[</span>]=]
end
end
-- byproduct check
local asByproduct = ""
if targetProducts ~= nil then
for i=2, #recipe.products do
for _,targetProduct in pairs(targetProducts) do
if targetProduct == recipe.products[i].item then
asByproduct = asByproduct .. "[[" .. loc.filePage .. getLinkAndName(targetProduct, recipe.stable, recipe.experimental) .. ".png|16px|link=]]"
end
end
end
end
-- add table row
html = html .. "\n|-\n|" .. recipe.name .. ((recipe.stable and not recipe.experimental) and [=[<br><span class="recipe-badge recipe-stable">]=] .. loc.branches.stable ..[=[</span>]=] or ((recipe.experimental and not recipe.stable) and [=[<br><span class="recipe-badge recipe-experimental">]=] .. loc.branches.experimental ..[=[</span>]=]) or "") .. season .. (recipe.alternate and ([=[<br><span class="recipe-badge recipe-alternate">]=] .. loc.links.alternate .. [=[</span>]=]) or "") .. ((asByproduct ~= "") and ([=[<br><span class="recipe-badge recipe-byproduct">]=] .. asByproduct .. loc.links.asByproduct .. [=[</span>]=]) or "") .. "||" .. renderItemsCell(recipe, "ingredients") .. "||" .. renderProducedInCell(recipe, singleBuilding) .. "||" .. renderItemsCell(recipe, "products") .. "||" .. recipe.unlockedBy
end
html = html .. "\n|-\n|}"
return html
end
-- Render a table with recipes that yield specified products.
function p.renderRecipesProducing(frame)
local recipes = {}
local items = {}
local seasonsEnabled = false
for name,item in pairs(frame:getParent().args) do
if name == "seasons" and item ~= "" and item ~= "0" then
seasonsEnabled = true
else
table.insert(items, item)
end
end
-- go through all recipes, branch entries, products, check if at least one is in the items array
for _,branchRecipes in pairs(recipesJSON) do
for _,recipe in pairs(branchRecipes) do
if seasonsEnabled or #recipe.seasons == 0 then
for _,product in pairs(recipe.products) do
for _,item in pairs(items) do
if item == product.item then
table.insert(recipes, recipe)
break
end
end
end
end
end
end
return renderRecipeTable(recipes, false, items, "'''" .. table.concat(items, "'''" .. loc.errors.listAnd .. "'''") .. "'''" .. loc.errors.producing)
end
-- Render a table with recipes that use specified ingredients.
function p.renderRecipesUsing(frame)
local recipes = {}
local items = {}
local seasonsEnabled = false
for name,item in pairs(frame:getParent().args) do
if name == "seasons" and item ~= "" and item ~= "0" then
seasonsEnabled = true
else
table.insert(items, item)
end
end
-- go through all recipes, branch entries, ingredients, check if at least one is in the items array
for _,branchRecipes in pairs(recipesJSON) do
for _,recipe in pairs(branchRecipes) do
if seasonsEnabled or #recipe.seasons == 0 then
for _,ingredient in pairs(recipe.ingredients) do
for _,item in pairs(items) do
if item == ingredient.item then
table.insert(recipes, recipe)
break
end
end
end
end
end
end
return renderRecipeTable(recipes, false, nil, loc.errors.using .. "'''" .. table.concat(items, "'''" .. loc.errors.listOr .. "'''") .. "'''")
end
-- Render a table with recipes produced in specified buildings.
function p.renderRecipesProducedIn(frame)
local recipes = {}
local buildings = {}
local seasonsEnabled = false
for name,building in pairs(frame:getParent().args) do
if name == "seasons" and building ~= "" and building ~= "0" then
seasonsEnabled = true
else
table.insert(buildings, building)
end
end
-- go through all recipes, branch entries, producedIn buildings, check if at least one is in the buildings array
for _,branchRecipes in pairs(recipesJSON) do
for _,recipe in pairs(branchRecipes) do
if seasonsEnabled or #recipe.seasons == 0 then
for _,producedInBuilding in pairs(recipe.producedIn) do
for _,building in pairs(buildings) do
if producedInBuilding == building then
table.insert(recipes, recipe)
break
end
end
end
end
end
end
return renderRecipeTable(recipes, #buildings == 1, nil, loc.errors.producedIn .. "'''" .. table.concat(buildings, "'''" .. loc.errors.listOr .. "'''") .. "'''")
end
-- Render alternate recipes
function p.renderAlternateRecipes(frame)
local recipes = {}
for _,branchRecipes in pairs(recipesJSON) do
for _,recipe in pairs(branchRecipes) do
if recipe.alternate then
table.insert(recipes, recipe)
end
end
end
table.sort(recipes, function(a, b) return a.name < b.name end)
return renderRecipeTable(recipes, nil, nil)
end
function p.renderRecipesProducedInSpecial(frame)
local recipes = {}
for _,branchRecipes in pairs(recipesJSON) do
for _,recipe in pairs(branchRecipes) do
local target = frame.args[1]
if (target == "Build Gun" and recipe.inBuildGun) or (target == "Customizer" and recipe.inCustomizer) or (target == "Craft Bench" and recipe.inCraftBench) or (target == "Equipment Workshop" and recipe.inWorkshop) then
-- empty the building list
recipe.producedIn = {}
table.insert(recipes, recipe)
end
end
end
table.sort(recipes, function(a, b) return a.name < b.name end)
return renderRecipeTable(recipes, false)
end
return p