Module:RecipeLoader: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| (7 intermediate revisions by the same user not shown) | |||
| Line 5: | Line 5: | ||
if not tbl then return result end | if not tbl then return result end | ||
for k, v in pairs(tbl) do | for k, v in pairs(tbl) do | ||
if type(v) == "table" then | if type(v) == "table" then | ||
local name = v[1] or v.name or v["1"] | local name = v[1] or v.name or v["1"] | ||
| Line 18: | Line 17: | ||
local function splitCamelCase(str) | local function splitCamelCase(str) | ||
str = str:gsub("_", " ") | str = str:gsub("_", " ") | ||
str = str:gsub("(%l)(%u)", "%1 %2") | str = str:gsub("(%l)(%u)", "%1 %2") | ||
str = str:gsub("(%a)(%d)", "%1 %2") | str = str:gsub("(%a)(%d)", "%1 %2") | ||
str = str:gsub("(%d)(%a)", "%1 %2") | str = str:gsub("(%d)(%a)", "%1 %2") | ||
return str | return str | ||
end | |||
local function firstExistingIcon(machine) | |||
local nsFile = mw.site.namespaces.File.id | |||
local candidates = { | |||
string.format("T_%s.png", machine), | |||
string.format("T_Stone%s.png", machine), | |||
string.format("T_Copper%s.png", machine), | |||
string.format("T_Steel%s.png", machine), | |||
string.format("T_Aluminium%s.png", machine), | |||
string.format("T_StainlessSteel%s.png", machine), | |||
string.format("T_Titanium%s.png", machine), | |||
string.format("T_Composite%s.png", machine), | |||
string.format("T_Neutronium%s.png", machine), | |||
} | |||
for _, filename in ipairs(candidates) do | |||
local title = mw.title.makeTitle(nsFile, filename) | |||
if title and title.exists then | |||
return filename | |||
end | |||
end | |||
return nil -- ничего не найдено | |||
end | end | ||
local function renderRecipeInput(recipe) | local function renderRecipeInput(recipe) | ||
local inputs = normalizeArray(recipe.input) | local inputs = normalizeArray(recipe.input) | ||
local str = '' | local str = '' | ||
if #inputs > 0 then | if #inputs > 0 then | ||
for _, ing in ipairs(inputs) do | for _, ing in ipairs(inputs) do | ||
str = str .. string.format("[[File:T_%s.png|22px]]", ing[1]) .. string.format("[[%s]] × %s", splitCamelCase(ing[1]), tostring(ing[2])) .. "\n" | str = str .. | ||
"|-\n| " .. | |||
string.format("[[File:T_%s.png|22px]]", ing[1]) .. | |||
string.format("[[%s]] × %s", splitCamelCase(ing[1]), tostring(ing[2])) .. | |||
"\n" | |||
end | end | ||
else | else | ||
str = str .. "—" | str = str .. "—" | ||
end | end | ||
return str | return str | ||
end | end | ||
| Line 46: | Line 70: | ||
local outputs = normalizeArray(recipe.output) | local outputs = normalizeArray(recipe.output) | ||
local ticks = recipe.ticks or recipe.time or "" | local ticks = recipe.ticks or recipe.time or "" | ||
local machine = recipe.machine or recipe.made_in or recipe.crafter or nil | |||
local tableNode = mw.html.create("table") | local tableNode = mw.html.create("table") | ||
:addClass("recipe-table") | :addClass("recipe-table") | ||
-- Заголовок | -- Заголовок: только машина, без fallback | ||
local | local caption = tableNode:tag("caption") | ||
if | |||
if machine then | |||
:wikitext(string.format("[[File: | local icon = firstExistingIcon(machine) | ||
splitCamelCase( | if icon then | ||
caption:wikitext(string.format( | |||
"[[File:%s|20px]] [[%s]]", | |||
icon, | |||
splitCamelCase(machine) | |||
)) | |||
else | |||
caption:wikitext(splitCamelCase(machine)) -- если иконки нет, показываем только текст | |||
end | |||
else | else | ||
caption:wikitext("") -- пустой | |||
end | end | ||
| Line 101: | Line 134: | ||
function p.getInput(frame) | function p.getInput(frame) | ||
local dictName = frame.args[1] | local dictName = frame.args[1] | ||
if not dictName then return "❌ Missing parameter: dictName" end | |||
if not dictName then | |||
local success, recipes = pcall(mw.loadData, "Module:" .. dictName) | local success, recipes = pcall(mw.loadData, "Module:" .. dictName) | ||
if not success or type(recipes) ~= "table" then | if not success or type(recipes) ~= "table" then return "" end | ||
return renderRecipeInput(recipes[1]) | return renderRecipeInput(recipes[1]) | ||
end | end | ||
function p.getAll(frame) | function p.getAll(frame) | ||
local dictName = frame.args[1] | local dictName = frame.args[1] | ||
if not dictName then return "❌ Missing parameter: dictName" end | |||
if not dictName then | |||
local success, recipes = pcall(mw.loadData, "Module:" .. dictName) | local success, recipes = pcall(mw.loadData, "Module:" .. dictName) | ||
if not success or type(recipes) ~= "table" then | if not success or type(recipes) ~= "table" then return "" end | ||
local html = mw.html.create() | local html = mw.html.create() | ||
Latest revision as of 11:01, 30 October 2025
Documentation for this module may be created at Module:RecipeLoader/doc
local p = {}
local function normalizeArray(tbl)
local result = {}
if not tbl then return result end
for k, v in pairs(tbl) do
if type(v) == "table" then
local name = v[1] or v.name or v["1"]
local count = v[2] or v.count or v["2"] or 1
table.insert(result, {name, count})
end
end
table.sort(result, function(a,b) return tostring(a[1]) < tostring(b[1]) end)
return result
end
local function splitCamelCase(str)
str = str:gsub("_", " ")
str = str:gsub("(%l)(%u)", "%1 %2")
str = str:gsub("(%a)(%d)", "%1 %2")
str = str:gsub("(%d)(%a)", "%1 %2")
return str
end
local function firstExistingIcon(machine)
local nsFile = mw.site.namespaces.File.id
local candidates = {
string.format("T_%s.png", machine),
string.format("T_Stone%s.png", machine),
string.format("T_Copper%s.png", machine),
string.format("T_Steel%s.png", machine),
string.format("T_Aluminium%s.png", machine),
string.format("T_StainlessSteel%s.png", machine),
string.format("T_Titanium%s.png", machine),
string.format("T_Composite%s.png", machine),
string.format("T_Neutronium%s.png", machine),
}
for _, filename in ipairs(candidates) do
local title = mw.title.makeTitle(nsFile, filename)
if title and title.exists then
return filename
end
end
return nil -- ничего не найдено
end
local function renderRecipeInput(recipe)
local inputs = normalizeArray(recipe.input)
local str = ''
if #inputs > 0 then
for _, ing in ipairs(inputs) do
str = str ..
"|-\n| " ..
string.format("[[File:T_%s.png|22px]]", ing[1]) ..
string.format("[[%s]] × %s", splitCamelCase(ing[1]), tostring(ing[2])) ..
"\n"
end
else
str = str .. "—"
end
return str
end
local function renderRecipe(recipe)
local inputs = normalizeArray(recipe.input)
local outputs = normalizeArray(recipe.output)
local ticks = recipe.ticks or recipe.time or ""
local machine = recipe.machine or recipe.made_in or recipe.crafter or nil
local tableNode = mw.html.create("table")
:addClass("recipe-table")
-- Заголовок: только машина, без fallback
local caption = tableNode:tag("caption")
if machine then
local icon = firstExistingIcon(machine)
if icon then
caption:wikitext(string.format(
"[[File:%s|20px]] [[%s]]",
icon,
splitCamelCase(machine)
))
else
caption:wikitext(splitCamelCase(machine)) -- если иконки нет, показываем только текст
end
else
caption:wikitext("") -- пустой
end
-- Input
tableNode:tag("tr"):tag("th"):attr("colspan", 2):wikitext("Input")
if #inputs > 0 then
for _, ing in ipairs(inputs) do
local tr = tableNode:tag("tr")
tr:tag("td"):wikitext(string.format("[[File:T_%s.png|22px]]", ing[1]))
tr:tag("td"):wikitext(string.format("[[%s]] × %s",
splitCamelCase(ing[1]),
tostring(ing[2])))
end
else
tableNode:tag("tr"):tag("td"):attr("colspan", 2):wikitext("—")
end
-- Output
tableNode:tag("tr"):tag("th"):attr("colspan", 2):wikitext("Output")
if #outputs > 0 then
for _, res in ipairs(outputs) do
local tr = tableNode:tag("tr")
tr:tag("td"):wikitext(string.format("[[File:T_%s.png|22px]]", res[1]))
tr:tag("td"):wikitext(string.format("[[%s]] × %s",
splitCamelCase(res[1]),
tostring(res[2])))
end
else
tableNode:tag("tr"):tag("td"):attr("colspan", 2):wikitext("—")
end
-- Time
tableNode:tag("tr"):tag("th"):attr("colspan", 2):wikitext("Time")
tableNode:tag("tr")
:tag("td"):attr("colspan", 2)
:css("text-align", "center")
:wikitext(tostring(ticks/20.0) .. " sec")
return tableNode
end
function p.getInput(frame)
local dictName = frame.args[1]
if not dictName then return "❌ Missing parameter: dictName" end
local success, recipes = pcall(mw.loadData, "Module:" .. dictName)
if not success or type(recipes) ~= "table" then return "" end
return renderRecipeInput(recipes[1])
end
function p.getAll(frame)
local dictName = frame.args[1]
if not dictName then return "❌ Missing parameter: dictName" end
local success, recipes = pcall(mw.loadData, "Module:" .. dictName)
if not success or type(recipes) ~= "table" then return "" end
local html = mw.html.create()
for _, recipe in ipairs(recipes) do
html:node(renderRecipe(recipe))
end
return tostring(html)
end
return p