Module:RecipeLoader: Difference between revisions

From Evospace
Jump to navigation Jump to search
Created page with "local p = {} function p.get(frame) local dictName = frame.args[1] local recipeName = frame.args[2] if not dictName or not recipeName then return "❌ Missing parameters: {{Recipe|DictionaryName|RecipeName}}" end local success, recipes = pcall(mw.loadData, "Module:" .. dictName) if not success or type(recipes) ~= "table" then return "❌ Recipe dictionary not found: " .. tostring(dictName) end -- Находим все с..."
 
No edit summary
 
(29 intermediate revisions by the same user not shown)
Line 1: Line 1:
local p = {}
local p = {}


function p.get(frame)
local function normalizeArray(tbl)
     local dictName = frame.args[1]
     local result = {}
    local recipeName = frame.args[2]
    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("_", " ")
    -- "IronPlate" → "Iron Plate"
    str = str:gsub("(%l)(%u)", "%1 %2")
    -- "Uranium235" → "Uranium 235"
    str = str:gsub("(%a)(%d)", "%1 %2")
    -- "235Plate" → "235 Plate"
    str = str:gsub("(%d)(%a)", "%1 %2")
    return str
end


     if not dictName or not recipeName then
local function renderRecipeInput(recipe)
         return "❌ Missing parameters: {{Recipe|DictionaryName|RecipeName}}"
    local inputs = rnormalizeArray(ecipe.input)
    local tableNode = mw.html.create("table")
        :addClass("recipe-table")
    local str = ''
     if #inputs > 0 then
         for _, ing in ipairs(inputs) do
            str = "|-\n| " .. str .. 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
     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 tableNode = mw.html.create("table")
        :addClass("recipe-table")


     local success, recipes = pcall(mw.loadData, "Module:" .. dictName)
    -- Заголовок с иконкой результата
     if not success or type(recipes) ~= "table" then
     local title = recipe.name or "(no name)"
         return "❌ Recipe dictionary not found: " .. tostring(dictName)
     if outputs[1] and outputs[1][1] then
        tableNode:tag("caption")
            :wikitext(string.format("[[File:T_%s.png|20px]] %s",
                outputs[1][1],
                splitCamelCase(title)))
    else
         tableNode:tag("caption"):wikitext(splitCamelCase(title))
     end
     end


     -- Находим все совпадения (может быть несколько рецептов с одинаковым именем)
     -- Input
     local matches = {}
    tableNode:tag("tr"):tag("th"):attr("colspan", 2):wikitext("Input")
    for _, recipe in ipairs(recipes) do
     if #inputs > 0 then
        if recipe.name == recipeName then
        for _, ing in ipairs(inputs) do
             table.insert(matches, recipe)
            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
         end
    else
        tableNode:tag("tr"):tag("td"):attr("colspan", 2):wikitext("—")
     end
     end


     if #matches == 0 then
    -- Output
         return "⚠️ Recipe not found: " .. tostring(recipeName)
    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
     end


     local html = mw.html.create()
     -- 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


     for _, recipe in ipairs(matches) do
     local success, recipes = pcall(mw.loadData, "Module:" .. dictName)
        local tableNode = html:tag("table")
    if not success or type(recipes) ~= "table" then
            :addClass("wikitable recipe-table")
        return ""
            :css("text-align", "center")
    end
            :css("margin-bottom", "10px")


        tableNode:tag("tr")
    return renderRecipeInput(recipes[1])
            :tag("th"):wikitext("Ingredients"):done()
end
            :tag("th"):wikitext("Results"):done()
            :tag("th"):wikitext("Time"):done()
            :done()


        local maxRows = math.max(#(recipe.ingredients or {}), #(recipe.results or {}))
-- Вывод всех рецептов из словаря
        if maxRows < 1 then maxRows = 1 end
function p.getAll(frame)
    local dictName = frame.args[1]


         for i = 1, maxRows do
    if not dictName then
            local tr = tableNode:tag("tr")
         return "❌ Missing parameter: dictName"
    end


            -- Ingredient
    local success, recipes = pcall(mw.loadData, "Module:" .. dictName)
            if recipe.ingredients and recipe.ingredients[i] then
    if not success or type(recipes) ~= "table" then
                local ing = recipe.ingredients[i]
        return ""
                tr:tag("td"):wikitext(string.format("[[%s]] × %s", ing[1], ing[2])):done()
    end
            else
                tr:tag("td"):wikitext(""):done()
            end


            -- Result
    local html = mw.html.create()
            if recipe.results and recipe.results[i] then
                local res = recipe.results[i]
                tr:tag("td"):wikitext(string.format("[[%s]] × %s", res[1], res[2])):done()
            else
                tr:tag("td"):wikitext(""):done()
            end


            -- Time (одна ячейка на таблицу)
    for _, recipe in ipairs(recipes) do
            if i == 1 then
        html:node(renderRecipe(recipe))
                tr:tag("td"):attr("rowspan", maxRows):wikitext(tostring(recipe.time or "")):done()
            end
            tr:done()
        end
     end
     end



Latest revision as of 10:08, 2 August 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("_", " ")
    -- "IronPlate" → "Iron Plate"
    str = str:gsub("(%l)(%u)", "%1 %2")
    -- "Uranium235" → "Uranium 235"
    str = str:gsub("(%a)(%d)", "%1 %2")
    -- "235Plate" → "235 Plate"
    str = str:gsub("(%d)(%a)", "%1 %2")
    return str
end

local function renderRecipeInput(recipe)
    local inputs = rnormalizeArray(ecipe.input)
    local tableNode = mw.html.create("table")
        :addClass("recipe-table")
    local str = ''
    if #inputs > 0 then
        for _, ing in ipairs(inputs) do
            str = "|-\n| " .. str .. 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 tableNode = mw.html.create("table")
        :addClass("recipe-table")

    -- Заголовок с иконкой результата
    local title = recipe.name or "(no name)"
    if outputs[1] and outputs[1][1] then
        tableNode:tag("caption")
            :wikitext(string.format("[[File:T_%s.png|20px]] %s",
                outputs[1][1],
                splitCamelCase(title)))
    else
        tableNode:tag("caption"):wikitext(splitCamelCase(title))
    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