Модуль:Песочница/Pok: различия между версиями

мНет описания правки
Нет описания правки
Строка 2: Строка 2:


---------------------------------------------------------------------
---------------------------------------------------------------------
-- Загрузка данных  
-- Загрузка данных из разных модулей
---------------------------------------------------------------------
---------------------------------------------------------------------
-- Данные для модуля, работающего с содержимым/контейнерами
local itemData           = mw.loadData("Модуль:IanComradeBot/prototypes/fills/Item.json/data")
local itemData         = mw.loadData("Модуль:IanComradeBot/prototypes/fills/Item.json/data")
local tableData         = mw.loadData("Модуль:IanComradeBot/prototypes/table.json/data")
local tableData         = mw.loadData("Модуль:IanComradeBot/prototypes/table.json/data")
local gearData          = mw.loadData("Модуль:IanComradeBot/startingGear.json/data")
local itemSlotsData    = mw.loadData("Модуль:IanComradeBot/prototypes/ItemSlots.json/data")
local gearRoleLoadout    = mw.loadData("Модуль:IanComradeBot/roleLoadout.json/data")
local itemStackData    = mw.loadData("Модуль:IanComradeBot/prototypes/fills/stack.json/data")
local loadoutData        = mw.loadData("Модуль:IanComradeBot/loadout.json/data")
local chemData          = mw.loadData("Модуль:IanComradeBot/prototypes/fills/chem.json/data")
local loadoutGroupData  = mw.loadData("Модуль:IanComradeBot/loadoutGroup.json/data")
local chemTranslateData = mw.loadData("Модуль:IanComradeBot/chem prototypes.json/data")
local cargoData          = mw.loadData("Модуль:IanComradeBot/prototypes/сargo.json/base")
local latheData          = mw.loadData("Модуль:IanComradeBot/prototypes/lathe.json/data")
local recipeData        = mw.loadData("Модуль:IanComradeBot/prototypes/lathe/recipes.json/data")
local researchData      = mw.loadData("Модуль:IanComradeBot/prototypes/research.json/data")
local materialData      = mw.loadData("Модуль:IanComradeBot/prototypes/materials.json/data")
local chemDataLathe      = mw.loadData("Модуль:IanComradeBot/chem prototypes.json/data")


-- Данные для модуля экипировки/должностей
---------------------------------------------------------------------
local jobData          = mw.loadData("Модуль:IanComradeBot/job.json/data")
-- Функции для обратного поиска
local gearData          = mw.loadData("Модуль:IanComradeBot/startingGear.json/data")
---------------------------------------------------------------------
local gearRoleLoadout  = mw.loadData("Модуль:IanComradeBot/roleLoadout.json/data")
local gearloadout      = mw.loadData("Модуль:IanComradeBot/loadout.json/data")
local gearloadoutGroup  = mw.loadData("Модуль:IanComradeBot/loadoutGroup.json/data")


-- Данные для модуля грузов
-- Функция для рекурсивного поиска id предмета в произвольной структуре таблицы.
local cargoData         = mw.loadData("Модуль:IanComradeBot/prototypes/сargo.json/base")
local function searchItemInStructure(struct, targetId)
    if type(struct) ~= "table" then
         return false
    end
    if struct.id and struct.id == targetId then
        return true
    end
    for _, v in pairs(struct) do
        if type(v) == "table" then
            if searchItemInStructure(v, targetId) then
                return true
            end
        end
    end
    return false
end


-- Данные для модуля станков (lathe)
---------------------------------------------------------------------
local latheData        = mw.loadData("Модуль:IanComradeBot/prototypes/lathe.json/data")
-- Обратный поиск по содержимому (reverseContained)
local recipeData        = mw.loadData("Модуль:IanComradeBot/prototypes/lathe/recipes.json/data")
-- По заданному id предмета ищем таблицы, в которых он встречается,
local researchData      = mw.loadData("Модуль:IanComradeBot/prototypes/research.json/data")
-- а затем в itemData ищем хранилища, где используются найденные таблицы.
local materialData      = mw.loadData("Модуль:IanComradeBot/prototypes/materials.json/data")
---------------------------------------------------------------------
local latheChemData     = mw.loadData("Модуль:IanComradeBot/chem prototypes.json/data")
function p.reverseContained(frame)
    local targetId = frame.args[2]
    if not targetId or targetId == "" then
        return "Ошибка: не указан id предмета для обратного поиска."
     end


local function reverseFindStorageByItem(itemId, visited)
    local matchingTables = {}
    visited = visited or {}
     -- Перебираем все записи таблиц
     if visited[itemId] then return "" end
    for tableId, tblEntry in pairs(tableData) do
     visited[itemId] = true
        if type(tblEntry) == "table" then
            if searchItemInStructure(tblEntry, targetId) then
                table.insert(matchingTables, tableId)
            end
        end
     end


     local result = {}
     if #matchingTables == 0 then
        return "Таблица, содержащая предмет с id " .. targetId .. ", не найдена."
    end


     local function searchInEntry(entry)
     local matchingStorages = {}
         if type(entry) == "table" then
    -- Ищем в itemData хранилища, в которых используется найденная таблица
             if entry.id == itemId then
    for storageId, storage in pairs(itemData) do
                 return true
         if type(storage) == "table" and storage.EntityTableContainerFill and storage.EntityTableContainerFill.containers then
             local containers = storage.EntityTableContainerFill.containers
            if containers.entity_storage and containers.entity_storage.tableId then
                for _, tblId in ipairs(matchingTables) do
                    if containers.entity_storage.tableId == tblId then
                        table.insert(matchingStorages, storageId)
                    end
                 end
             end
             end
             for _, v in pairs(entry) do
             if containers.storagebase and containers.storagebase.tableId then
                if type(v) == "table" then
                for _, tblId in ipairs(matchingTables) do
                    if searchInEntry(v) then
                    if containers.storagebase.tableId == tblId then
                        return true
                        table.insert(matchingStorages, storageId)
                     end
                     end
                 end
                 end
             end
             end
         end
         end
        return false
     end
     end


     for tblId, tblEntry in pairs(tableData) do
     if #matchingStorages == 0 then
        if searchInEntry(tblEntry) then
        return "Хранилище, вызывающее найденные таблицы, не найдено."
            for storageId, storage in pairs(itemData) do
    end
                if storage.StorageFill and storage.StorageFill.tableId == tblId then
 
                    table.insert(result, storageId)
    return "Найденные хранилища: " .. table.concat(matchingStorages, ", ")
                elseif storage.EntityTableContainerFill and storage.EntityTableContainerFill.containers then
end
                    local cont = storage.EntityTableContainerFill.containers
 
                    if (cont.entity_storage and cont.entity_storage.tableId == tblId) or
---------------------------------------------------------------------
                      (cont.storagebase and cont.storagebase.tableId == tblId) then
-- Обратный поиск для экипировки (reverseEquipment)
                        table.insert(result, storageId)
-- По заданному id оборудования ищем, в каких наборах экипировки (gear или loadout)
                    end
-- оно используется, и возвращаем id набора с указанием слота.
                end
---------------------------------------------------------------------
             end
local function searchEquipmentInTable(equipmentTable, targetId)
    for slot, equipId in pairs(equipmentTable or {}) do
        if equipId == targetId then
             return slot
         end
         end
     end
     end
 
     return nil
     return #result > 0 and table.concat(result, ", ") or ""
end
end


local function reverseFindJobByItem(itemId)
function p.reverseEquipment(frame)
     local result = {}
     local targetId = frame.args[2]
    local slotFilter = frame.args[3]  -- если указан, фильтруем по конкретному слоту
    if not targetId or targetId == "" then
        return "Ошибка: не указан id оборудования для обратного поиска."
    end


    local results = {}
    -- Поиск в startingGear (gearData)
     for gearId, gear in pairs(gearData) do
     for gearId, gear in pairs(gearData) do
         if gear.equipment then
         if gear.equipment then
             for slot, equipId in pairs(gear.equipment) do
             for slot, equipId in pairs(gear.equipment) do
                 if equipId == itemId then
                 if equipId == targetId and (not slotFilter or slot == slotFilter) then
                     table.insert(result, gearId)
                     table.insert(results, "Gear: " .. gearId .. " (слот: " .. slot .. ")")
                 end
                 end
             end
             end
Строка 84: Строка 126:
     end
     end


     for roleId, role in pairs(gearRoleLoadout) do
     -- Поиск в loadout (loadoutData)
        if role.groups then
    for loadoutId, loadout in pairs(loadoutData) do
            for _, groupId in ipairs(role.groups) do
        if loadout.equipment then
                local groupData = gearloadoutGroup[groupId]
            for slot, equipId in pairs(loadout.equipment) do
                if groupData and groupData.loadouts then
                if equipId == targetId and (not slotFilter or slot == slotFilter) then
                    for _, loadoutId in ipairs(groupData.loadouts) do
                    table.insert(results, "Loadout: " .. loadoutId .. " (слот: " .. slot .. ")")
                        local loadout = gearloadout[loadoutId]
                        if loadout and loadout.equipment then
                            for slot, equipId in pairs(loadout.equipment) do
                                if equipId == itemId then
                                    table.insert(result, roleId)
                                end
                            end
                        end
                    end
                 end
                 end
             end
             end
Строка 104: Строка 137:
     end
     end


     return #result > 0 and table.concat(result, ", ") or ""
     if #results == 0 then
        return "Оборудование с id " .. targetId .. " не найдено в наборах экипировки."
    end
 
    return "Найдено использование оборудования: " .. table.concat(results, "; ")
end
end


local function reverseCargoLookup(field, value)
---------------------------------------------------------------------
-- Обратный поиск для груза (cargo) (reverseCargo)
-- По заданному режиму (product, cost, category, icon) и значению ищем запись cargo и возвращаем её id.
---------------------------------------------------------------------
function p.reverseCargo(frame)
    local mode = frame.args[2]
    local searchValue = frame.args[3]
    if not mode or mode == "" or not searchValue or searchValue == "" then
        return "Ошибка: необходимо указать режим (product, cost, category, icon) и значение для поиска."
    end
 
    local foundIds = {}
     for _, entry in ipairs(cargoData) do
     for _, entry in ipairs(cargoData) do
         if entry[field] and tostring(entry[field]) == tostring(value) then
         if mode == "product" and entry.product == searchValue then
             return entry.id
            table.insert(foundIds, entry.id)
        elseif mode == "cost" and tostring(entry.cost) == searchValue then
            table.insert(foundIds, entry.id)
        elseif mode == "category" and entry.category == searchValue then
            table.insert(foundIds, entry.id)
        elseif mode == "icon" and entry.icon and entry.icon.sprite == searchValue then
             table.insert(foundIds, entry.id)
        end
    end
 
    if #foundIds == 0 then
        return "Запись для режима " .. mode .. " со значением '" .. searchValue .. "' не найдена."
    end
 
    return "Найденные записи cargo: " .. table.concat(foundIds, ", ")
end
 
---------------------------------------------------------------------
-- Обратный поиск для станков (lathe) (reverseLathe)
-- По заданному результату рецепта ищем рецепты станков и возвращаем id станка, который его производит.
---------------------------------------------------------------------
local function getRecipeById(recipeId)
    for _, recipe in ipairs(recipeData) do
        if recipe.id == recipeId then
            return recipe
         end
         end
     end
     end
Строка 116: Строка 188:
end
end


local function reverseFindLatheByProduct(product)
function p.reverseLathe(frame)
    local targetResult = frame.args[2]
    if not targetResult or targetResult == "" then
        return "Ошибка: не указан результат рецепта для обратного поиска."
    end
 
    local matchingLathes = {}
    -- Вспомогательная функция для проверки набора рецептов
    local function checkRecipes(recipeIds)
        for _, recipeId in ipairs(recipeIds or {}) do
            local recipe = getRecipeById(recipeId)
            if recipe and recipe.result == targetResult then
                return true
            end
        end
        return false
    end
 
     for _, lathe in ipairs(latheData) do
     for _, lathe in ipairs(latheData) do
         local found = false
         local found = false
         if lathe.Lathe then
         if lathe.Lathe then
             if lathe.Lathe.staticRecipes then
             if checkRecipes(lathe.Lathe.staticRecipes) or checkRecipes(lathe.Lathe.dynamicRecipes) then
                for _, recipeId in ipairs(lathe.Lathe.staticRecipes) do
                 found = true
                    for _, recipe in ipairs(recipeData) do
                        if recipe.id == recipeId and recipe.result == product then
                            return lathe.id
                        end
                    end
                 end
             end
             end
            if lathe.Lathe.dynamicRecipes then
        end
                for _, recipeId in ipairs(lathe.Lathe.dynamicRecipes) do
        if not found and lathe.EmagLatheRecipes then
                    for _, recipe in ipairs(recipeData) do
            if checkRecipes(lathe.EmagLatheRecipes.emagStaticRecipes) or checkRecipes(lathe.EmagLatheRecipes.emagDynamicRecipes) then
                        if recipe.id == recipeId and recipe.result == product then
                 found = true
                            return lathe.id
                        end
                    end
                 end
             end
             end
         end
         end
         if lathe.EmagLatheRecipes then
         if found and lathe.id then
             if lathe.EmagLatheRecipes.emagStaticRecipes then
             table.insert(matchingLathes, lathe.id)
                for _, recipeId in ipairs(lathe.EmagLatheRecipes.emagStaticRecipes) do
                    for _, recipe in ipairs(recipeData) do
                        if recipe.id == recipeId and recipe.result == product then
                            return lathe.id
                        end
                    end
                end
            end
            if lathe.EmagLatheRecipes.emagDynamicRecipes then
                for _, recipeId in ipairs(lathe.EmagLatheRecipes.emagDynamicRecipes) do
                    for _, recipe in ipairs(recipeData) do
                        if recipe.id == recipeId and recipe.result == product then
                            return lathe.id
                        end
                    end
                end
            end
         end
         end
     end
     end
     return nil
 
     if #matchingLathes == 0 then
        return "Станок, производящий '" .. targetResult .. "', не найден."
    end
 
    return "Найденные станки: " .. table.concat(matchingLathes, ", ")
end
end


---------------------------------------------------------------------
-- Основная функция модуля
-- Принимает первым аргументом режим обратного поиска:
-- reverseContained, reverseEquipment, reverseCargo, reverseLathe.
-- Второй (и последующие) аргументы передаются соответствующим функциям.
---------------------------------------------------------------------
function p.main(frame)
function p.main(frame)
     local mode = mw.text.trim(frame.args[1] or "")
     local mode = frame.args[1]
    local param = mw.text.trim(frame.args[2] or "")
     if not mode or mode == "" then
   
         return "Ошибка: не указан режим обратного поиска. Доступные режимы: reverseContained, reverseEquipment, reverseCargo, reverseLathe."
     if mode == "" or param == "" then
         return "Ошибка: не указаны необходимые параметры для обратного поиска."
     end
     end


     if mode == "reverseStorage" then
     if mode == "reverseContained" then
         local storageResult = reverseFindStorageByItem(param)
         return p.reverseContained(frame)
        if storageResult ~= "" then
     elseif mode == "reverseEquipment" then
            return "Найденные хранилища (itemData), ссылающиеся на таблицу, содержащую предмет " .. param .. ": " .. storageResult
         return p.reverseEquipment(frame)
        else
            return "Хранилище не найдено для предмета " .. param
        end
     elseif mode == "reverseJob" then
         local jobResult = reverseFindJobByItem(param)
        if jobResult ~= "" then
            return "Найденные роли/экипировки, использующие предмет " .. param .. ": " .. jobResult
        else
            return "Нет данных для предмета " .. param
        end
     elseif mode == "reverseCargo" then
     elseif mode == "reverseCargo" then
         -- Здесь предполагается, что param – значение поля product.
         return p.reverseCargo(frame)
        local cargoId = reverseCargoLookup("product", param)
        if cargoId then
            return "Найден груз с ID: " .. cargoId
        else
            return "Груз не найден по значению " .. param
        end
     elseif mode == "reverseLathe" then
     elseif mode == "reverseLathe" then
         local latheId = reverseFindLatheByProduct(param)
         return p.reverseLathe(frame)
        if latheId then
            return "Найден станок (lathe) с ID: " .. latheId
        else
            return "Станок не найден для продукта " .. param
        end
     else
     else
         return "Ошибка: неизвестный режим обратного поиска: " .. mode
         return "Неизвестный режим: " .. mode .. ". Доступные режимы: reverseContained, reverseEquipment, reverseCargo, reverseLathe."
     end
     end
end
end


return p
return p