Модуль:Meals Lookup: различия между версиями

Материал из Space Station 14 Вики
Нет описания правки
мНет описания правки
 
(не показано 10 промежуточных версий 2 участников)
Строка 1: Строка 1:
local prototypes = mw.loadData("Module:Meals Lookup/data")
local prototypes = mw.loadData("Module:Meals Lookup/data")
local chem = mw.loadData("Module:Chemistry Lookup/data")
local chem = mw.loadData("Module:Chemistry Lookup/data")
local tags = mw.loadData("Module:IanComradeBot/prototypes/entity tags.json/data")


local p = {}
local p = {}
Строка 8: Строка 9:
--#region universal
--#region universal


function table.containsv(table, value) -- FUCKING LUA
function table.containsv(t, value) -- FUCKING LUA
     -- containsv = contains value
     -- containsv = contains value
     for _, v in pairs(table) do
     for _, v in pairs(t) do
         if v == value then
         if v == value then
             return true
             return true
Строка 18: Строка 19:
end
end


function table.containsk(table, key) -- FUCKING LUA
function table.containsk(t, key) -- FUCKING LUA
     -- containsk = contains key
     -- containsk = contains key
     for k, _ in pairs(table) do
     for k, _ in pairs(t) do
         if k == key then
         if k == key then
             return true
             return true
Строка 28: Строка 29:
end
end


function table.length(table)
function table.length(t)
     local out = 0
     local out = 0
     for _ in pairs(table) do
     for _ in pairs(t) do
         out = out + 1
         out = out + 1
     end
     end
Строка 44: Строка 45:
     end
     end
     return false
     return false
end
-- Вспомогательная функция для обрезки пробелов
local function trim(s)
    return (s:gsub("^%s*(.-)%s*$", "%1"))
end
-- Функция проверки тегов рецепта по параметрам фильтрации
function p.recipePassesTags(frame, recipe)
    local productId = recipe["result"] or recipe["id"]
    local productTags = {}
    for _, entry in ipairs(tags) do
        if entry.id == productId then
            if entry.Tag and entry.Tag.tags then
                productTags = entry.Tag.tags
            end
            break
        end
    end
    -- Если заданы белый или чёрный списки, выполняем фильтрацию
    if frame.args.whiteListTags then
        local whitelist = {}
        for tag in string.gmatch(frame.args.whiteListTags, "([^,]+)") do
            table.insert(whitelist, trim(tag))
        end
        local found = false
        for _, wtag in ipairs(whitelist) do
            if table.containsv(productTags, wtag) then
                found = true
                break
            end
        end
        if not found then return false end
    elseif frame.args.blackListTags then
        local blacklist = {}
        for tag in string.gmatch(frame.args.blackListTags, "([^,]+)") do
            table.insert(blacklist, trim(tag))
        end
        for _, btag in ipairs(blacklist) do
            if table.containsv(productTags, btag) then
                return false
            end
        end
    end
    return true
end
-- Функция фильтрации набора рецептов
function p.filterRecipes(recipes, frame)
    local filtered = {}
    for id, recipe in pairs(recipes) do
        if p.recipePassesTags(frame, recipe) then
            filtered[id] = recipe
        end
    end
    return filtered
end
end


Строка 107: Строка 165:


-- returns recipes which id is matched by pattern
-- returns recipes which id is matched by pattern
function getrecipesbyname(frame, tabl, str, ignore) -- should not be inviked
function getrecipesbyname(frame, tabl, str) -- should not be inviked
     local out = {}
     local out = {}
    local ign = ""
    if ignore ~= nil then ign = ignore end
     for type, recipes in pairs(tabl) do
     for type, recipes in pairs(tabl) do
         out[type] = {}
         out[type] = {}
         for recipeId, recipe in pairs(recipes) do
         for recipeId, recipe in pairs(recipes) do
             if string.match(recipeId, str) and not string.match(recipeId, ign) then
             if string.match(recipeId, str) then
                 table.insert(out[type], recipe)
                 table.insert(out[type], recipe)
             end
             end
Строка 123: Строка 179:


-- same as above, but returns recipes that *does not* match given pattern
-- same as above, but returns recipes that *does not* match given pattern
function getotherrecipes(frame, tabl, str, ignore) -- should not be invoked
function getotherrecipes(frame, tabl, str) -- should not be invoked
     local out = {}
     local out = {}
    local ign = ""
    if ignore ~= nil then ign = ignore end
     for type, recipes in pairs(tabl) do
     for type, recipes in pairs(tabl) do
         if not table.containsk(out, type) then
         if not table.containsk(out, type) then
Строка 132: Строка 186:
         end
         end
         for recipeId, recipe in pairs(recipes) do
         for recipeId, recipe in pairs(recipes) do
             if not string.match(recipeId, str) and not string.match(recipeId, ign) then
             if not string.match(recipeId, str) then
                 if not table.containsv(out[type], recipe) then
                 if not table.containsv(out[type], recipe) then
                     table.insert(out[type], recipe)
                     table.insert(out[type], recipe)
Строка 229: Строка 283:
function p.buildmicrowaverecipes(frame)
function p.buildmicrowaverecipes(frame)
     local out = ""
     local out = ""
     for id in pairs(getrecipesfromtype(frame, "microwaveRecipes")) do
     local recipes = p.filterRecipes(getrecipesfromtype(frame, "microwaveRecipes"), frame)
    for id, _ in pairs(recipes) do
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildmicrowaverecipebox|" .. id .. "}}") .. "\n"
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildmicrowaverecipebox|" .. id .. "}}") .. "\n"
     end
     end
Строка 258: Строка 313:
function p.buildslicerecipes(frame)
function p.buildslicerecipes(frame)
     local out = ""
     local out = ""
     for id in pairs(getrecipesfromtype(frame, "sliceableRecipes")) do
     local recipes = p.filterRecipes(getrecipesfromtype(frame, "sliceableRecipes"), frame)
    for id, _ in pairs(recipes) do
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildslicerecipebox|" .. id .. "}}") .. "\n"
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildslicerecipebox|" .. id .. "}}") .. "\n"
     end
     end
Строка 286: Строка 342:
function p.buildgrindrecipes(frame)
function p.buildgrindrecipes(frame)
     local out = ""
     local out = ""
     for id in pairs(getrecipesfromtype(frame, "grindableRecipes")) do
     local recipes = p.filterRecipes(getrecipesfromtype(frame, "grindableRecipes"), frame)
    for id, _ in pairs(recipes) do
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildgrindrecipebox|" .. id .. "}}") .. "\n"
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildgrindrecipebox|" .. id .. "}}") .. "\n"
     end
     end
Строка 315: Строка 372:
function p.buildheatrecipes(frame)
function p.buildheatrecipes(frame)
     local out = ""
     local out = ""
     for id in pairs(getrecipesfromtype(frame, "heatableRecipes")) do
     local recipes = p.filterRecipes(getrecipesfromtype(frame, "heatableRecipes"), frame)
    for id, _ in pairs(recipes) do
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildheatrecipebox|" .. id .. "}}") .. "\n"
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildheatrecipebox|" .. id .. "}}") .. "\n"
     end
     end
Строка 345: Строка 403:
function p.buildtoolmaderecipes(frame)
function p.buildtoolmaderecipes(frame)
     local out = ""
     local out = ""
     for id in pairs(getrecipesfromtype(frame, "toolmadeRecipes")) do
     local recipes = p.filterRecipes(getrecipesfromtype(frame, "toolmadeRecipes"), frame)
    for id, _ in pairs(recipes) do
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildtoolmaderecipebox|" .. id .. "}}") .. "\n"
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildtoolmaderecipebox|" .. id .. "}}") .. "\n"
     end
     end
Строка 386: Строка 445:
function p.buildixablerecipes(frame)
function p.buildixablerecipes(frame)
     local out = ""
     local out = ""
     for id in pairs(getrecipesfromtype(frame, "mixableRecipes")) do
     local recipes = p.filterRecipes(getrecipesfromtype(frame, "mixableRecipes"), frame)
    for id, _ in pairs(recipes) do
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildmixablerecipebox|" .. id .. "}}") .. "\n"
         out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildmixablerecipebox|" .. id .. "}}") .. "\n"
     end
     end
Строка 404: Строка 464:
             do
             do
                 for n, recipe in pairs(recipes) do
                 for n, recipe in pairs(recipes) do
                     id = recipe["id"]
                     if p.recipePassesTags(frame, recipe) then
                    out = out ..
                        id = recipe["id"]
                    frame:preprocess("{{#invoke:Meals Lookup|buildmicrowaverecipebox|" .. id .. "}}") .. "\n"
                        out = out ..
                        frame:preprocess("{{#invoke:Meals Lookup|buildmicrowaverecipebox|" .. id .. "}}") .. "\n"
                    end
                 end
                 end
             end
             end
Строка 412: Строка 474:
             do
             do
                 for n, recipe in pairs(recipes) do
                 for n, recipe in pairs(recipes) do
                     id = recipe["id"]
                     if p.recipePassesTags(frame, recipe) then
                    out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildmixablerecipebox|" .. id .. "}}") .. "\n"
                        id = recipe["id"]
                        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildmixablerecipebox|" .. id .. "}}") .. "\n"
                    end
                 end
                 end
             end
             end
Строка 419: Строка 483:
             do
             do
                 for n, recipe in pairs(recipes) do
                 for n, recipe in pairs(recipes) do
                     id = recipe["id"]
                     if p.recipePassesTags(frame, recipe) then
                    out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildslicerecipebox|" .. id .. "}}") .. "\n"
                        id = recipe["id"]
                        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildslicerecipebox|" .. id .. "}}") .. "\n"
                    end
                 end
                 end
             end
             end
Строка 426: Строка 492:
             do
             do
                 for n, recipe in pairs(recipes) do
                 for n, recipe in pairs(recipes) do
                     id = recipe["id"]
                     if p.recipePassesTags(frame, recipe) then
                    out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildgrindrecipebox|" .. id .. "}}") .. "\n"
                        id = recipe["id"]
                        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildgrindrecipebox|" .. id .. "}}") .. "\n"
                    end
                 end
                 end
             end
             end
Строка 433: Строка 501:
             do
             do
                 for n, recipe in pairs(recipes) do
                 for n, recipe in pairs(recipes) do
                     id = recipe["id"]
                     if p.recipePassesTags(frame, recipe) then
                    out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildheatrecipebox|" .. id .. "}}") .. "\n"
                        id = recipe["id"]
                        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildheatrecipebox|" .. id .. "}}") .. "\n"
                    end
                 end
                 end
             end
             end
Строка 440: Строка 510:
             do
             do
                 for n, recipe in pairs(recipes) do
                 for n, recipe in pairs(recipes) do
                     id = recipe["id"]
                     if p.recipePassesTags(frame, recipe) then
                    out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildtoolmaderecipebox|" .. id .. "}}") .. "\n"
                        id = recipe["id"]
                        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildtoolmaderecipebox|" .. id .. "}}") .. "\n"
                    end
                 end
                 end
             end
             end
Строка 453: Строка 525:
     local out = ""
     local out = ""
     local tablo = p.meals
     local tablo = p.meals
    local ignore = frame.args["ignore"]
     for _, patt in pairs(frame.args) do
     for _, patt in pairs(frame.args) do
         local ids = getrecipesbyname(frame, tablo, patt, ignore)
         local ids = getrecipesbyname(frame, tablo, patt)
         out = out .. p.buildrecipeboxuniversal(frame, ids)
         out = out .. p.buildrecipeboxuniversal(frame, ids)
     end
     end
Строка 465: Строка 536:
     local out = ""
     local out = ""
     local tablo = p.meals
     local tablo = p.meals
    local ignore = frame.args["ignore"]
     for _, patt in pairs(frame.args) do
     for _, patt in pairs(frame.args) do
         local ids = getotherrecipes(frame, tablo, patt, ignore)
         local ids = getotherrecipes(frame, tablo, patt)
         out = out .. p.buildrecipeboxuniversal(frame, ids)
         out = out .. p.buildrecipeboxuniversal(frame, ids)
     end
     end
Строка 473: Строка 543:
end
end


--#endregion
-- builds recipes list but does not constructs it, for debug purposes
 
function p.getrecipeslist(frame)
 
-- tests.
function p.tests1(frame)
     local out = ""
     local out = ""
     local tablo = p.meals
     local tablo = p.meals
     for _, patt in pairs(frame.args) do
     for _, patt in pairs(frame.args) do
         for type, recipes in pairs(getotherrecipes(frame, tablo, patt)) do
         for type, recipes in pairs(getrecipesbyname(frame, tablo, patt)) do
             out = out .. type .. "("
             out = out .. type .. "("
             for k, r in pairs(recipes) do
             for k, r in pairs(recipes) do
Строка 492: Строка 559:
end
end


function p.tests2(frame)
-- same as getrecipeslist, but instead returns recipes that does not match the pattern
function p.getotherrecipeslist(frame)
     local out = ""
     local out = ""
     local tablo = p.meals
     local tablo = p.meals
    local ignore = frame.args["ignore"]
     for _, patt in pairs(frame.args) do
     for _, patt in pairs(frame.args) do
         for type, recipes in pairs(getrecipesbyname(frame, tablo, patt, ignore)) do
         for type, recipes in pairs(getotherrecipes(frame, tablo, patt)) do
             out = out .. type .. "("
             out = out .. type .. "("
             for k, r in pairs(recipes) do
             for k, r in pairs(recipes) do
Строка 508: Строка 575:
end
end


--#endregion


-- function p.tests2(frame)
--#region newdishestest
--    local out = ""
 
--    for type, recipes in pairs(getrecipesbyname(frame, "[Dd]ough")) do
-- returns recipes which id is matched by pattern
--         out = out .. type .. "("
function getrecipesbynamenew(frame, tabl, str) -- should not be invoked
--        for k, r in pairs(recipes) do
     local out = {}
--            out = out .. " " .. k .. ":" .. r["id"]
    for rtype, recipes in pairs(tabl) do
--         end
        for recipeId, recipe in pairs(recipes) do
--         out = out .. ")"
            out[rtype] = out[rtype] or {}
--     end
            if type(str) == "table" then
--     return out
                for _, patt in pairs(str) do
-- end
                    if string.match(recipeId, patt) and not table.containsv(recipe) then
                        table.insert(out[rtype], recipe)
                    end
                end
            else
                if string.match(recipeId, str) then
                    table.insert(out[rtype], recipe)
                end
            end
        end
    end
    return out
end
 
-- same as above, but returns recipes that *does not* match given pattern
function getotherrecipesnew(frame, tabl, str) -- should not be invoked
    local out = {}
     for type, recipes in pairs(tabl) do
        out[type] = out[type] or {}
        for recipeId, recipe in pairs(recipes) do
            if not string.match(recipeId, str) then
                if not table.containsv(out[type], recipe) then
                    table.insert(out[type], recipe)
                end
            end
        end
    end
    return out
end
 
-- you should not use this for building recipes inside lua
function p.buildnamedrecipesnew(frame) -- {{#invoke:Meals Lookup|buildnamedrecipes|[Pattern1 | Pattern2 | Pattern3 | ...]}}
    local out = ""
    local tablo = p.meals
    for _, patt in pairs(frame.args) do
        local ids = getrecipesbynamenew(frame, tablo, patt)
        out = out .. p.buildrecipeboxuniversal(frame, ids)
    end
    return out
end
 
-- same as buildnamedrecipes, but instead builds recipes that does not match the pattern
function p.buildotherrecipesnew(frame) -- {{#invoke:Meals Lookup|buildotherrecipes|[Pattern1 | Pattern2 | Pattern3 | ...]}}
    local out = ""
    local tablo = p.meals
    for _, patt in pairs(frame.args) do
         local ids = getotherrecipesnew(frame, tablo, patt)
         out = out .. p.buildrecipeboxuniversal(frame, ids)
     end
     return out
end
 
--#endregion


return p
return p

Текущая версия от 15:49, 2 апреля 2025

Теги

Параметры для сортировки выводимых рецептов после вызова функции способа приготовления. Теги перечисляются через , в параметрах.

Список тегов entity находится здесь: Участник:IanComradeBot/prototypes/entity tags.json

ПараметрОписаниеОбязателен?
|blackListTags =Исключает продукты с введенными тегами.
Пример: {{#invoke:Meals Lookup|buildmicrowaverecipes|blackListTags=Pizza, Cake}}.
Нет
|whiteListTags =Выводит только продукты с введенными тегами.
Пример: {{#invoke:Meals Lookup|buildmicrowaverecipes|whiteListTags=Pizza}}.
Нет

local prototypes = mw.loadData("Module:Meals Lookup/data")
local chem = mw.loadData("Module:Chemistry Lookup/data")
local tags = mw.loadData("Module:IanComradeBot/prototypes/entity tags.json/data")

local p = {}
p.meals = prototypes.meals
p.chemicals = chem.react

--#region universal

function table.containsv(t, value) -- FUCKING LUA
    -- containsv = contains value
    for _, v in pairs(t) do
        if v == value then
            return true
        end
    end
    return false
end

function table.containsk(t, key) -- FUCKING LUA
    -- containsk = contains key
    for k, _ in pairs(t) do
        if k == key then
            return true
        end
    end
    return false
end

function table.length(t)
    local out = 0
    for _ in pairs(t) do
        out = out + 1
    end
    return out
end

function table.isempty(t)
    local count = table.length(t)
    if count == 0 then
        do
            return true
        end
    end
    return false
end

-- Вспомогательная функция для обрезки пробелов
local function trim(s)
    return (s:gsub("^%s*(.-)%s*$", "%1"))
end

-- Функция проверки тегов рецепта по параметрам фильтрации
function p.recipePassesTags(frame, recipe)
    local productId = recipe["result"] or recipe["id"]
    local productTags = {}
    for _, entry in ipairs(tags) do
        if entry.id == productId then
            if entry.Tag and entry.Tag.tags then
                productTags = entry.Tag.tags
            end
            break
        end
    end

    -- Если заданы белый или чёрный списки, выполняем фильтрацию
    if frame.args.whiteListTags then
        local whitelist = {}
        for tag in string.gmatch(frame.args.whiteListTags, "([^,]+)") do
            table.insert(whitelist, trim(tag))
        end
        local found = false
        for _, wtag in ipairs(whitelist) do
            if table.containsv(productTags, wtag) then
                found = true
                break
            end
        end
        if not found then return false end
    elseif frame.args.blackListTags then
        local blacklist = {}
        for tag in string.gmatch(frame.args.blackListTags, "([^,]+)") do
            table.insert(blacklist, trim(tag))
        end
        for _, btag in ipairs(blacklist) do
            if table.containsv(productTags, btag) then
                return false
            end
        end
    end
    return true
end

-- Функция фильтрации набора рецептов
function p.filterRecipes(recipes, frame)
    local filtered = {}
    for id, recipe in pairs(recipes) do
        if p.recipePassesTags(frame, recipe) then
            filtered[id] = recipe
        end
    end
    return filtered
end

function getrecipesfromtype(frame, type) -- should not be invoked
    return p.meals[type]
end

function getrecipe(frame, type, id) -- should not be invoked
    return getrecipesfromtype(frame, type)[id:gsub(' ', '')]
end

function getrecipetypes(frame, id) -- should not be invoked
    local out = {}
    for type, recipes in pairs(p.meals) do
        for recipeId, recipe in pairs(recipes) do
            if (recipeId:gsub(' ', '') == id:gsub(' ', '')) or (recipe["id"]:gsub(' ', '') == id:gsub(' ', '')) then
                table.insert(out, type)
                break
            end
        end
    end
    return out
end

function getimage(frame, fileid) -- should not be invoked
    local out = ""
    --[[
        WARNING!! THE NEXT THING IS "EXPENSIVE" AND DOES NOT WORKS AFTER 30 OR SMTHNG RUNS
        read https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Expensive_properties for more info
        local gifFileTitle = mw.title.new(fileid .. ".gif", "File")
        local pngFileTitle = mw.title.new(fileid .. ".png", "File")
        if gifFileTitle.file.exists then
            out = "File:" .. fileid .. ".gif"
        elseif pngFileTitle.file.exists then
            out = "File:" .. fileid .. ".png"
        else
            out = ""
        end
    --]]

    -- less expensive variant, but returns only png (AND BIG RED TEXT IF PNG DOES NOT EXISTS)
    out = "File:" .. fileid .. ".png"
    return out
end

function buildsolids(frame, array) -- should not be invoked
    local out = ""
    for solid, amount in pairs(array) do
        out = out ..
            frame:preprocess("{{Recipe Component|item={{#invoke:Entity Lookup|getname|" ..
                solid .. "}}|image=" .. getimage(frame, solid) .. "|amount=" .. amount .. "}}")
    end
    return out
end

function buildreagents(frame, array) -- should not be invoked
    local out = ""
    for item, amount in pairs(array) do
        out = out .. frame:preprocess("{{Chem Recipe Component|reagent=" .. item .. "|amount=" .. amount .. "}}")
    end
    return out
end

-- returns recipes which id is matched by pattern
function getrecipesbyname(frame, tabl, str) -- should not be inviked
    local out = {}
    for type, recipes in pairs(tabl) do
        out[type] = {}
        for recipeId, recipe in pairs(recipes) do
            if string.match(recipeId, str) then
                table.insert(out[type], recipe)
            end
        end
    end
    return out
end

-- same as above, but returns recipes that *does not* match given pattern
function getotherrecipes(frame, tabl, str) -- should not be invoked
    local out = {}
    for type, recipes in pairs(tabl) do
        if not table.containsk(out, type) then
            out[type] = {}
        end
        for recipeId, recipe in pairs(recipes) do
            if not string.match(recipeId, str) then
                if not table.containsv(out[type], recipe) then
                    table.insert(out[type], recipe)
                end
            end
        end
    end
    return out
end

function p.imageslist(frame)
    local out = "'''REQUIRED IMAGES:'''<br>"
    for cat, recipes in pairs(p.meals) do
        for id, recipe in pairs(recipes) do
            if cat == "microwaveRecipes" then
                do
                    out = out .. recipe["result"] .. ": [[:File:" .. recipe["result"] .. ".png]]<br>"
                    if #recipe["solids"] > 0 then
                        do
                            for solid in pairs(getmicrowaverecipesolids(recipe)) do
                                out = out .. solid .. ": [[:File:" .. solid .. ".png]]<br>"
                            end
                        end
                    end
                end
            end
            if cat == "sliceableRecipes" or cat == "heatableRecipes" or cat == "toolmadeRecipes" then
                do
                    out = out .. recipe["result"] .. ": [[:File:" .. recipe["result"] .. ".png]]<br>"
                    out = out .. recipe["input"] .. ": [[:File:" .. recipe["input"] .. ".png]]<br>"
                end
            end
            if cat == "grindableRecipes" then
                do
                    out = out .. recipe["input"] .. ": [[:File:" .. recipe["input"] .. ".png]]<br>"
                end
            end
        end
    end
    out = out .. "<br><hr>"
    return out
end

function p.buildeverything(frame) -- old code compatibility
    return p.buildeverythingnew(frame)
end

function p.buildeverythingold(frame)
    local out = ""
    out = out .. p.buildmicrowaverecipes(frame)
    out = out .. p.buildslicerecipes(frame)
    out = out .. p.buildgrindrecipes(frame)
    out = out .. p.buildheatrecipes(frame)
    out = out .. p.buildtoolmaderecipes(frame)
    out = out .. p.buildixablerecipes(frame)
    return out
end

--#endregion

--#region microwaveRecipes

function getmicrowaverecipesolids(frame, recipe) -- should not be invoked
    local out = {}
    for ingredient, amount in pairs(recipe["solids"]) do
        out[ingredient] = amount
    end
    return out
end

function getmicrowaverecipereagents(frame, recipe) -- should not be invoked
    local out = {}
    for ingredient, amount in pairs(recipe["reagents"]) do
        out[ingredient] = amount
    end
    return out
end

function p.buildmicrowaverecipebox(frame) -- {{#invoke:Meals Lookup|buildmicrowaverecipebox|MicrowaveRecipeID}}
    local out = ""
    local id = frame.args[1]:gsub(' ', '')
    local recipe = getrecipe(frame, "microwaveRecipes", id)
    local solids = buildsolids(frame, getmicrowaverecipesolids(frame, recipe))
    local reagents = buildreagents(frame, getmicrowaverecipereagents(frame, recipe))
    out = frame:preprocess("{{Recipe Box" ..
        "|name={{#invoke:Entity Lookup|getname|" .. recipe["result"] .. "}}" ..
        "|component-1=" .. solids .. "\n" .. reagents ..
        "|transformer={{Recipe Transformers|microwaveRecipes|" .. recipe["time"] .. "}}" ..
        "|result=" ..
        frame:preprocess("{{Result Component|item={{#invoke:Entity Lookup|getname|" ..
            recipe["result"] .. "}}|image=" .. getimage(frame, recipe["result"]) .. "}}") ..
        "}}")
    return out
end

function p.buildmicrowaverecipes(frame)
    local out = ""
    local recipes = p.filterRecipes(getrecipesfromtype(frame, "microwaveRecipes"), frame)
    for id, _ in pairs(recipes) do
        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildmicrowaverecipebox|" .. id .. "}}") .. "\n"
    end
    return out
end

--#endregion microwaveRecipes

--#region sliceableRecipes

function p.buildslicerecipebox(frame) -- {{#invoke:Meals Lookup|buildslicerecipebox|SliceableRecipeID}}
    local out = ""
    local id = frame.args[1]:gsub(' ', '')
    local recipe = getrecipe(frame, "sliceableRecipes", id)
    out = frame:preprocess("{{Recipe Box" ..
        "|name={{#invoke:Entity Lookup|getname|" .. recipe["result"] .. "}}" ..
        "|component-1=" ..
        frame:preprocess("{{Recipe Component|item={{#invoke:Entity Lookup|getname|" ..
            recipe["input"] .. "}}|image=" .. getimage(frame, recipe["input"]) .. "}}") ..
        "|transformer={{Recipe Transformers|sliceableRecipes}}" ..
        "|result=" ..
        frame:preprocess("{{Result Component|item={{#invoke:Entity Lookup|getname|" ..
            recipe["result"] .. "}}|image=" .. getimage(frame, recipe["result"]) .. "|amount=" .. recipe["count"] .. "}}") ..
        "}}")
    return out
end

function p.buildslicerecipes(frame)
    local out = ""
    local recipes = p.filterRecipes(getrecipesfromtype(frame, "sliceableRecipes"), frame)
    for id, _ in pairs(recipes) do
        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildslicerecipebox|" .. id .. "}}") .. "\n"
    end
    return out
end

--#endregion sliceableRecipes

--#region grindableRecipes

function p.buildgrindrecipebox(frame) -- {{#invoke:Meals Lookup|buildgrindrecipebox|GrindableRecipeID}}
    local out = ""
    local id = frame.args[1]:gsub(' ', '')
    local recipe = getrecipe(frame, "grindableRecipes", id)
    local reagents = buildreagents(frame, recipe["result"])
    out = frame:preprocess("{{Recipe Box" ..
        "|name={{#invoke:Entity Lookup|getname|" .. recipe["id"] .. "}}" ..
        "|component-1=" ..
        frame:preprocess("{{Result Component|item={{#invoke:Entity Lookup|getname|" ..
            recipe["input"] .. "}}|image=" .. getimage(frame, recipe["input"]) .. "}}") ..
        "|transformer={{Recipe Transformers|grindableRecipes}}" ..
        "|result=" .. reagents ..
        "}}")
    return out
end

function p.buildgrindrecipes(frame)
    local out = ""
    local recipes = p.filterRecipes(getrecipesfromtype(frame, "grindableRecipes"), frame)
    for id, _ in pairs(recipes) do
        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildgrindrecipebox|" .. id .. "}}") .. "\n"
    end
    return out
end

--#endregion grindableRecipes

--#region heatableRecipes

function p.buildheatrecipebox(frame) -- {{#invoke:Meals Lookup|buildheatrecipebox|HeatableRecipeID}}
    local out = ""
    local id = frame.args[1]:gsub(' ', '')
    local recipe = getrecipe(frame, "heatableRecipes", id)
    out = frame:preprocess("{{Recipe Box" ..
        "|name={{#invoke:Entity Lookup|getname|" .. recipe["result"] .. "}}" ..
        "|component-1=" ..
        frame:preprocess("{{Recipe Component|item={{#invoke:Entity Lookup|getname|" ..
            recipe["input"] .. "}}|image=" .. getimage(frame, recipe["input"]) .. "}}") ..
        "|transformer={{Recipe Transformers|heatableRecipes|" .. recipe["minTemp"] .. "}}" ..
        "|result=" ..
        frame:preprocess("{{Result Component|item={{#invoke:Entity Lookup|getname|" ..
            recipe["result"] .. "}}|image=" .. getimage(frame, recipe["result"]) .. "}}") ..
        "}}")
    return out
end

function p.buildheatrecipes(frame)
    local out = ""
    local recipes = p.filterRecipes(getrecipesfromtype(frame, "heatableRecipes"), frame)
    for id, _ in pairs(recipes) do
        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildheatrecipebox|" .. id .. "}}") .. "\n"
    end
    return out
end

--#endregion heatableRecipes

--#region toolmadeRecipes

function p.buildtoolmaderecipebox(frame) -- {{#invoke:Meals Lookup|buildtoolmaderecipebox|ToolmadeRecipeID}}
    local out = ""
    local id = frame.args[1]:gsub(' ', '')
    local recipe = getrecipe(frame, "toolmadeRecipes", id)
    local transformer = "toolmadeRecipes" .. recipe["tool"]
    out = frame:preprocess("{{Recipe Box" ..
        "|name={{#invoke:Entity Lookup|getname|" .. recipe["result"] .. "}}" ..
        "|component-1=" ..
        frame:preprocess("{{Recipe Component|item={{#invoke:Entity Lookup|getname|" ..
            recipe["input"] .. "}}|image=" .. getimage(frame, recipe["input"]) .. "}}") ..
        "|transformer={{Recipe Transformers|" .. transformer .. "}}" ..
        "|result=" ..
        frame:preprocess("{{Result Component|item={{#invoke:Entity Lookup|getname|" ..
            recipe["result"] .. "}}|image=" .. getimage(frame, recipe["result"]) .. "}}") ..
        "}}")
    return out
end

function p.buildtoolmaderecipes(frame)
    local out = ""
    local recipes = p.filterRecipes(getrecipesfromtype(frame, "toolmadeRecipes"), frame)
    for id, _ in pairs(recipes) do
        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildtoolmaderecipebox|" .. id .. "}}") .. "\n"
    end
    return out
end

--#endregion toolmadeRecipes

--#region mixableRecipes

function getchemicalreagents(recipe) -- should not be invoked
    local out = {}
    for ingredient, data in pairs(recipe["reactants"]) do
        out[ingredient] = data["amount"]
    end
    return out
end

function p.buildmixablerecipebox(frame) -- {{#invoke:Meals Lookup|buildmixablerecipebox|MixableRecipeID}}
    local out = ""
    local id = frame.args[1]:gsub(' ', '')
    local recipe = p.chemicals[id]
    local input = buildreagents(frame, getchemicalreagents(recipe))

    local results = {}
    for _, v in pairs(recipe["effects"]) do
        table.insert(results, v.description)
    end

    local result = table.concat(results, "\n")

    out = frame:preprocess("{{Recipe Box" ..
        "|component-1=" .. input ..
        "|name= " ..
        "|transformer={{Recipe Transformers|mixableRecipes}}" ..
        "|result=" .. result .. "}}")
    return out
end

function p.buildixablerecipes(frame)
    local out = ""
    local recipes = p.filterRecipes(getrecipesfromtype(frame, "mixableRecipes"), frame)
    for id, _ in pairs(recipes) do
        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildmixablerecipebox|" .. id .. "}}") .. "\n"
    end
    return out
end

--#endregion mixableRecipes

--#region dishes

function p.buildrecipeboxuniversal(frame, idtable)
    local out = ""
    for type, recipes in pairs(idtable) do
        -- INTRUDER ALERT: SHITCODE IS IN THE BASE
        local id = ""
        if type == "microwaveRecipes" and not table.isempty(recipes) then
            do
                for n, recipe in pairs(recipes) do
                    if p.recipePassesTags(frame, recipe) then
                        id = recipe["id"]
                        out = out ..
                        frame:preprocess("{{#invoke:Meals Lookup|buildmicrowaverecipebox|" .. id .. "}}") .. "\n"
                    end
                end
            end
        elseif type == "mixableRecipes" and not table.isempty(recipes) then
            do
                for n, recipe in pairs(recipes) do
                    if p.recipePassesTags(frame, recipe) then
                        id = recipe["id"]
                        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildmixablerecipebox|" .. id .. "}}") .. "\n"
                    end
                end
            end
        elseif type == "sliceableRecipes" and not table.isempty(recipes) then
            do
                for n, recipe in pairs(recipes) do
                    if p.recipePassesTags(frame, recipe) then
                        id = recipe["id"]
                        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildslicerecipebox|" .. id .. "}}") .. "\n"
                    end
                end
            end
        elseif type == "grindableRecipes" and not table.isempty(recipes) then
            do
                for n, recipe in pairs(recipes) do
                    if p.recipePassesTags(frame, recipe) then
                        id = recipe["id"]
                        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildgrindrecipebox|" .. id .. "}}") .. "\n"
                    end
                end
            end
        elseif type == "heatableRecipes" and not table.isempty(recipes) then
            do
                for n, recipe in pairs(recipes) do
                    if p.recipePassesTags(frame, recipe) then
                        id = recipe["id"]
                        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildheatrecipebox|" .. id .. "}}") .. "\n"
                    end
                end
            end
        elseif type == "toolmadeRecipes" and not table.isempty(recipes) then
            do
                for n, recipe in pairs(recipes) do
                    if p.recipePassesTags(frame, recipe) then
                        id = recipe["id"]
                        out = out .. frame:preprocess("{{#invoke:Meals Lookup|buildtoolmaderecipebox|" .. id .. "}}") .. "\n"
                    end
                end
            end
        end
    end
    return out
end

-- you should not use this for building recipes inside lua
function p.buildnamedrecipes(frame) -- {{#invoke:Meals Lookup|buildnamedrecipes|[Pattern1 | Pattern2 | Pattern3 | ...]}}
    local out = ""
    local tablo = p.meals
    for _, patt in pairs(frame.args) do
        local ids = getrecipesbyname(frame, tablo, patt)
        out = out .. p.buildrecipeboxuniversal(frame, ids)
    end
    return out
end

-- same as buildnamedrecipes, but instead builds recipes that does not match the pattern
function p.buildotherrecipes(frame) -- {{#invoke:Meals Lookup|buildotherrecipes|[Pattern1 | Pattern2 | Pattern3 | ...]}}
    local out = ""
    local tablo = p.meals
    for _, patt in pairs(frame.args) do
        local ids = getotherrecipes(frame, tablo, patt)
        out = out .. p.buildrecipeboxuniversal(frame, ids)
    end
    return out
end

-- builds recipes list but does not constructs it, for debug purposes 
function p.getrecipeslist(frame)
    local out = ""
    local tablo = p.meals
    for _, patt in pairs(frame.args) do
        for type, recipes in pairs(getrecipesbyname(frame, tablo, patt)) do
            out = out .. type .. "("
            for k, r in pairs(recipes) do
                out = out .. " " .. k .. ":" .. r["id"]
            end
            out = out .. ")"
        end
    end
    return out
end

-- same as getrecipeslist, but instead returns recipes that does not match the pattern
function p.getotherrecipeslist(frame)
    local out = ""
    local tablo = p.meals
    for _, patt in pairs(frame.args) do
        for type, recipes in pairs(getotherrecipes(frame, tablo, patt)) do
            out = out .. type .. "("
            for k, r in pairs(recipes) do
                out = out .. " " .. k .. ":" .. r["id"]
            end
            out = out .. ")"
        end
    end
    return out
end

--#endregion

--#region newdishestest

-- returns recipes which id is matched by pattern
function getrecipesbynamenew(frame, tabl, str) -- should not be invoked
    local out = {}
    for rtype, recipes in pairs(tabl) do
        for recipeId, recipe in pairs(recipes) do
            out[rtype] = out[rtype] or {}
            if type(str) == "table" then
                for _, patt in pairs(str) do
                    if string.match(recipeId, patt) and not table.containsv(recipe) then
                        table.insert(out[rtype], recipe)
                    end
                end
            else
                if string.match(recipeId, str) then
                    table.insert(out[rtype], recipe)
                end
            end
        end
    end
    return out
end

-- same as above, but returns recipes that *does not* match given pattern
function getotherrecipesnew(frame, tabl, str) -- should not be invoked
    local out = {}
    for type, recipes in pairs(tabl) do
        out[type] = out[type] or {}
        for recipeId, recipe in pairs(recipes) do
            if not string.match(recipeId, str) then
                if not table.containsv(out[type], recipe) then
                    table.insert(out[type], recipe)
                end
            end
        end
    end
    return out
end

-- you should not use this for building recipes inside lua
function p.buildnamedrecipesnew(frame) -- {{#invoke:Meals Lookup|buildnamedrecipes|[Pattern1 | Pattern2 | Pattern3 | ...]}}
    local out = ""
    local tablo = p.meals
    for _, patt in pairs(frame.args) do
        local ids = getrecipesbynamenew(frame, tablo, patt)
        out = out .. p.buildrecipeboxuniversal(frame, ids)
    end
    return out
end

-- same as buildnamedrecipes, but instead builds recipes that does not match the pattern
function p.buildotherrecipesnew(frame) -- {{#invoke:Meals Lookup|buildotherrecipes|[Pattern1 | Pattern2 | Pattern3 | ...]}}
    local out = ""
    local tablo = p.meals
    for _, patt in pairs(frame.args) do
        local ids = getotherrecipesnew(frame, tablo, patt)
        out = out .. p.buildrecipeboxuniversal(frame, ids)
    end
    return out
end

--#endregion

return p