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

Материал из Space Station 14 Вики
мНет описания правки
мНет описания правки
Строка 96: Строка 96:
---------------------------------------------------------------------
---------------------------------------------------------------------
-- Обратный поиск для экипировки (reverseEquipment)
-- Обратный поиск для экипировки (reverseEquipment)
-- По заданному id оборудования ищем, в каких наборах экипировки (gear или loadout)
-- По заданному id оборудования ищем, в каких наборах экипировки
-- оно используется, и возвращаем id набора с указанием слота.
-- оно используется, и, если найдено в startingGear, ищем в jobData
-- по параметру startingGear, выводя id соответствующего job.
---------------------------------------------------------------------
---------------------------------------------------------------------
local function searchEquipmentInTable(equipmentTable, targetId)
    for slot, equipId in pairs(equipmentTable or {}) do
        if equipId == targetId then
            return slot
        end
    end
    return nil
end
function p.reverseEquipment(frame)
function p.reverseEquipment(frame)
     local targetId = frame.args[2]
     local targetId = frame.args[2]
    local slotFilter = frame.args[3]  -- если указан, фильтруем по конкретному слоту
     if not targetId or targetId == "" then
     if not targetId or targetId == "" then
         return "Ошибка: не указан id оборудования для обратного поиска."
         return "Ошибка: не указан id оборудования для обратного поиска."
     end
     end


     local foundJobs = {}
     local results = {}
     -- Ищем в startingGear (gearData)
     -- Поиск в 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 == targetId then
                 if equipId == targetId and (not slotFilter or slot == slotFilter) then
                     -- Нашли подходящую экипировку – ищем в jobData, где startingGear равен gearId
                     -- Ищем в jobData, где startingGear равен gearId
                     for _, job in pairs(jobData) do
                    local foundJob = nil
                     for jobId, job in pairs(jobData) do
                         if job.startingGear == gearId then
                         if job.startingGear == gearId then
                             table.insert(foundJobs, job.id)
                             foundJob = jobId
                            break
                         end
                         end
                    end
                    if foundJob then
                        table.insert(results, "Job: " .. foundJob .. " (слот: " .. slot .. ")")
                    else
                        table.insert(results, "Gear: " .. gearId .. " (слот: " .. slot .. ")")
                     end
                     end
                 end
                 end
Строка 131: Строка 131:
     end
     end


     if #foundJobs == 0 then
     -- Поиск в loadout (loadoutData)
        return "Оборудование с id " .. targetId .. " не найдено в стартовых наборах экипировки."
    for loadoutId, loadout in pairs(loadoutData) do
        if loadout.equipment then
            for slot, equipId in pairs(loadout.equipment) do
                if equipId == targetId and (not slotFilter or slot == slotFilter) then
                    table.insert(results, "Loadout: " .. loadoutId .. " (слот: " .. slot .. ")")
                end
            end
        end
     end
     end


     -- Удаляем возможные дубликаты
     if #results == 0 then
    local uniqueJobs = {}
         return "Оборудование с id " .. targetId .. " не найдено в наборах экипировки."
    local seen = {}
    for _, jobId in ipairs(foundJobs) do
         if not seen[jobId] then
            table.insert(uniqueJobs, jobId)
            seen[jobId] = true
        end
     end
     end


     return "Найден job: " .. table.concat(uniqueJobs, ", ")
     return "Найдено использование оборудования: " .. table.concat(results, "; ")
end
end


---------------------------------------------------------------------
---------------------------------------------------------------------
-- Обратный поиск для груза (cargo) (reverseCargo)
-- Обратный поиск для груза (cargo) (reverseCargo)
-- По заданному режиму (product, cost, category, icon) и значению ищем запись cargo и возвращаем её id.
-- Всегда осуществляется поиск по полю product.
---------------------------------------------------------------------
---------------------------------------------------------------------
function p.reverseCargo(frame)
function p.reverseCargo(frame)
     local searchValue = frame.args[3]
     local searchValue = frame.args[2]
     if not searchValue or searchValue == "" then
     if not searchValue or searchValue == "" then
         return "Ошибка: необходимо указать значение для поиска."
         return "Ошибка: не указано значение для поиска в режиме cargo."
     end
     end



Версия от 18:35, 20 февраля 2025

Для документации этого модуля может быть создана страница Модуль:Песочница/Pok/doc

local p = {}

---------------------------------------------------------------------
-- Загрузка данных из разных модулей
---------------------------------------------------------------------
local itemData           = mw.loadData("Модуль:IanComradeBot/prototypes/fills/Item.json/data")
local tableData          = mw.loadData("Модуль:IanComradeBot/prototypes/table.json/data")
local gearData           = mw.loadData("Модуль:IanComradeBot/startingGear.json/data")
local jobData            = mw.loadData("Модуль:IanComradeBot/job.json/data")
local gearRoleLoadout    = mw.loadData("Модуль:IanComradeBot/roleLoadout.json/data")
local loadoutData        = mw.loadData("Модуль:IanComradeBot/loadout.json/data")
local loadoutGroupData   = mw.loadData("Модуль:IanComradeBot/loadoutGroup.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")

---------------------------------------------------------------------
-- Функции для обратного поиска
---------------------------------------------------------------------

-- Функция для рекурсивного поиска id предмета в произвольной структуре таблицы.
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

---------------------------------------------------------------------
-- Обратный поиск по содержимому (reverseContained)
-- По заданному id предмета ищем таблицы, в которых он встречается,
-- а затем в itemData ищем хранилища, где используются найденные таблицы.
---------------------------------------------------------------------
function p.reverseContained(frame)
    local targetId = frame.args[2]
    if not targetId or targetId == "" then
        return "Ошибка: не указан id предмета для обратного поиска."
    end

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

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

    local matchingStorages = {}
    -- Ищем в itemData хранилища, в которых используется найденная таблица
    for storageId, storage in pairs(itemData) do
        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
            if containers.storagebase and containers.storagebase.tableId then
                for _, tblId in ipairs(matchingTables) do
                    if containers.storagebase.tableId == tblId then
                        table.insert(matchingStorages, storageId)
                    end
                end
            end
        end
    end

    if #matchingStorages == 0 then
        return "Хранилище, вызывающее найденные таблицы, не найдено."
    end

    return "Найденные хранилища: " .. table.concat(matchingStorages, ", ")
end

---------------------------------------------------------------------
-- Обратный поиск для экипировки (reverseEquipment)
-- По заданному id оборудования ищем, в каких наборах экипировки
-- оно используется, и, если найдено в startingGear, ищем в jobData
-- по параметру startingGear, выводя id соответствующего job.
---------------------------------------------------------------------
function p.reverseEquipment(frame)
    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
        if gear.equipment then
            for slot, equipId in pairs(gear.equipment) do
                if equipId == targetId and (not slotFilter or slot == slotFilter) then
                    -- Ищем в jobData, где startingGear равен gearId
                    local foundJob = nil
                    for jobId, job in pairs(jobData) do
                        if job.startingGear == gearId then
                            foundJob = jobId
                            break
                        end
                    end
                    if foundJob then
                        table.insert(results, "Job: " .. foundJob .. " (слот: " .. slot .. ")")
                    else
                        table.insert(results, "Gear: " .. gearId .. " (слот: " .. slot .. ")")
                    end
                end
            end
        end
    end

    -- Поиск в loadout (loadoutData)
    for loadoutId, loadout in pairs(loadoutData) do
        if loadout.equipment then
            for slot, equipId in pairs(loadout.equipment) do
                if equipId == targetId and (not slotFilter or slot == slotFilter) then
                    table.insert(results, "Loadout: " .. loadoutId .. " (слот: " .. slot .. ")")
                end
            end
        end
    end

    if #results == 0 then
        return "Оборудование с id " .. targetId .. " не найдено в наборах экипировки."
    end

    return "Найдено использование оборудования: " .. table.concat(results, "; ")
end

---------------------------------------------------------------------
-- Обратный поиск для груза (cargo) (reverseCargo)
-- Всегда осуществляется поиск по полю product.
---------------------------------------------------------------------
function p.reverseCargo(frame)
    local searchValue = frame.args[2]
    if not searchValue or searchValue == "" then
        return "Ошибка: не указано значение для поиска в режиме cargo."
    end

    local foundIds = {}
    for _, entry in ipairs(cargoData) do
        if entry.product == searchValue then
            table.insert(foundIds, entry.id)
        end
    end

    if #foundIds == 0 then
        return "Запись для product со значением '" .. 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
    return nil
end

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
        local found = false
        if lathe.Lathe then
            if checkRecipes(lathe.Lathe.staticRecipes) or checkRecipes(lathe.Lathe.dynamicRecipes) then
                found = true
            end
        end
        if not found and lathe.EmagLatheRecipes then
            if checkRecipes(lathe.EmagLatheRecipes.emagStaticRecipes) or checkRecipes(lathe.EmagLatheRecipes.emagDynamicRecipes) then
                found = true
            end
        end
        if found and lathe.id then
            table.insert(matchingLathes, lathe.id)
        end
    end

    if #matchingLathes == 0 then
        return "Станок, производящий '" .. targetResult .. "', не найден."
    end

    return "Найденные станки: " .. table.concat(matchingLathes, ", ")
end

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

    if mode == "reverseContained" then
        return p.reverseContained(frame)
    elseif mode == "reverseEquipment" then
        return p.reverseEquipment(frame)
    elseif mode == "reverseCargo" then
        return p.reverseCargo(frame)
    elseif mode == "reverseLathe" then
        return p.reverseLathe(frame)
    else
        return "Неизвестный режим: " .. mode .. ". Доступные режимы: reverseContained, reverseEquipment, reverseCargo, reverseLathe."
    end
end

return p