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

Материал из Space Station 14 Вики
Нет описания правки
мНет описания правки
Строка 7: Строка 7:
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 gearData          = mw.loadData("Модуль:IanComradeBot/startingGear.json/data")
local jobData            = mw.loadData("Модуль:IanComradeBot/job.json/data")
local gearRoleLoadout    = mw.loadData("Модуль:IanComradeBot/roleLoadout.json/data")
local gearRoleLoadout    = mw.loadData("Модуль:IanComradeBot/roleLoadout.json/data")
local loadoutData        = mw.loadData("Модуль:IanComradeBot/loadout.json/data")
local loadoutData        = mw.loadData("Модуль:IanComradeBot/loadout.json/data")
Строка 109: Строка 110:
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 results = {}
     local foundJobs = {}
     -- Поиск в 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 and (not slotFilter or slot == slotFilter) then
                 if equipId == targetId then
                    table.insert(results, "Gear: " .. gearId .. " (слот: " .. slot .. ")")
                    -- Нашли подходящую экипировку – ищем в jobData, где startingGear равен gearId
                    for _, job in pairs(jobData) do
                        if job.startingGear == gearId then
                            table.insert(foundJobs, job.id)
                        end
                    end
                 end
                 end
             end
             end
Строка 126: Строка 131:
     end
     end


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


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


Строка 149: Строка 153:
---------------------------------------------------------------------
---------------------------------------------------------------------
function p.reverseCargo(frame)
function p.reverseCargo(frame)
    local mode = frame.args[2]
     local searchValue = frame.args[3]
     local searchValue = frame.args[3]
     if not mode or mode == "" or not searchValue or searchValue == "" then
     if not searchValue or searchValue == "" then
         return "Ошибка: необходимо указать режим (product, cost, category, icon) и значение для поиска."
         return "Ошибка: необходимо указать значение для поиска."
     end
     end


     local foundIds = {}
     local foundIds = {}
     for _, entry in ipairs(cargoData) do
     for _, entry in ipairs(cargoData) do
         if mode == "product" and entry.product == searchValue then
         if entry.product == searchValue then
            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)
             table.insert(foundIds, entry.id)
         end
         end
Строка 169: Строка 166:


     if #foundIds == 0 then
     if #foundIds == 0 then
         return "Запись для режима " .. mode .. " со значением '" .. searchValue .. "' не найдена."
         return "Запись для product со значением '" .. searchValue .. "' не найдена."
     end
     end



Версия от 18:31, 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 оборудования ищем, в каких наборах экипировки (gear или loadout)
-- оно используется, и возвращаем id набора с указанием слота.
---------------------------------------------------------------------
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)
    local targetId = frame.args[2]
    if not targetId or targetId == "" then
        return "Ошибка: не указан id оборудования для обратного поиска."
    end

    local foundJobs = {}
    -- Ищем в startingGear (gearData)
    for gearId, gear in pairs(gearData) do
        if gear.equipment then
            for slot, equipId in pairs(gear.equipment) do
                if equipId == targetId then
                    -- Нашли подходящую экипировку – ищем в jobData, где startingGear равен gearId
                    for _, job in pairs(jobData) do
                        if job.startingGear == gearId then
                            table.insert(foundJobs, job.id)
                        end
                    end
                end
            end
        end
    end

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

    -- Удаляем возможные дубликаты
    local uniqueJobs = {}
    local seen = {}
    for _, jobId in ipairs(foundJobs) do
        if not seen[jobId] then
            table.insert(uniqueJobs, jobId)
            seen[jobId] = true
        end
    end

    return "Найден job: " .. table.concat(uniqueJobs, ", ")
end

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