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

Материал из Space Station 14 Вики
мНет описания правки
Метки: ручная отмена отменено
мНет описания правки
Метка: ручная отмена
Строка 136: Строка 136:
     local moduleName = "Module:" .. baseUser .. pagePath .. "/data"
     local moduleName = "Module:" .. baseUser .. pagePath .. "/data"
     local ok, data = pcall(mw.loadData, moduleName)
     local ok, data = pcall(mw.loadData, moduleName)
     if not ok or not data then
     if not ok or not data then return "" end
 
    local entry = data[id] or data["default"] or {}
    if type(entry) ~= "table" then
         return ""
         return ""
     end
     end


     local entry = data[id] or data["default"] or {}
     local parts = {}
 
    local flat = {}
     local function walk(tbl, prefix)
     local function walk(tbl, prefix)
         if type(tbl) ~= "table" then
         local keys = {}
            flat[prefix] = format_value(tbl)
        for k in pairs(tbl) do table.insert(keys, k) end
            return
         table.sort(keys, function(a, b) return tostring(a) < tostring(b) end)
        end
         for _, k in ipairs(keys) do
         if prefix ~= "" then
             local v = tbl[k]
            flat[prefix] = format_value(tbl)
            local key = (prefix == "" and tostring(k) or prefix .. "." .. tostring(k))
        end
            if type(v) == "table" then
         if is_array(tbl) then
                walk(v, key)
            local max = 0
            else
            for k in pairs(tbl) do if type(k) == "number" and k > max then max = k end end
                table.insert(parts, key .. "=" .. tostring(v))
             for i = 1, max do
                local v = tbl[i]
                local key = (prefix == "" and tostring(i) or prefix .. "." .. tostring(i))
                if type(v) == "table" then
                    walk(v, key)
                else
                    flat[key] = format_value(v)
                end
            end
        else
            for k, v in pairs(tbl) do
                local key = (prefix == "" and tostring(k) or prefix .. "." .. tostring(k))
                if type(v) == "table" then
                    walk(v, key)
                else
                    flat[key] = format_value(v)
                end
             end
             end
         end
         end
Строка 176: Строка 160:


     walk(entry, "")
     walk(entry, "")
    local parts = {}
    for k, v in pairs(flat) do
        table.insert(parts, tostring(k) .. "=" .. tostring(v))
    end
     return table.concat(parts, "|")
     return table.concat(parts, "|")
end
end


return p
return p

Версия от 09:41, 23 января 2026

Документация

Модуль предназначен для получения данных из кэшированных JSON-страниц и их использования в шаблонах. С его помощью можно получить поле по пути, найти id по значению или сразу собрать вызов шаблона по найденным данным.

Поля берутся из json страниц

Для подпроектов

Основные функции

get

Возвращает запись целиком или отдельное поле по её id.

Использование:

  • {{#invoke:GetField|get|id|pagePath|keyPath}}

Простые значения возвращаются как текст, а таблицы в JSON-виде.

Например, json сущности MopItem из Участник:IanComradeBot/component/meleeWeapon.json выглядит так:

"MopItem": {
    "damage": {
        "types": {
            "Blunt": 10
        }
    },
...
},

то мы можем получить значение как как:

  • {{#invoke:GetField|get|MopItem|component/meleeWeapon.json|damage}} -> "types": {"Blunt": 10}}
  • {{#invoke:GetField|get|MopItem|component/meleeWeapon.json|damage.types}} -> {"Blunt": 10}
  • {{#invoke:GetField|get|MopItem|component/meleeWeapon.json|damage.types.Blunt}} -> 10
ПараметрОписаниеОбязателен?
|1 =Id записи.Да
|2 =Путь до JSON-страницы, например component/meleeWeapon.json.Да
|3 =Путь до поля внутри записи. Поддерживает вложенность через точку и индексы вида field.1Да

getTpl

Строит вызов шаблона для одного id передавая в него развёрнутые поля записи.

Использование:

  • {{#invoke:GetField|getTpl|id|pagePath|template}}

Шаблон вызывается в виде {{Имя шаблона|id=...|...поля записи...}}. Вложенные таблицы передаются как плоские параметры, а также в JSON-виде там, где это нужно для сохранения структуры.

Пример:

  • {{#invoke:GetField|getTpl|MopItem|сomponent/spillable.json|сomponent/spillable}}
ПараметрОписаниеОбязателен?
|1 =Id записи.Да
|2 =Путь до JSON-страницы.Да
|3 =Имя шаблона, который будет вызван как {{Имя шаблона|id=...|...}}.Да

searchId / searchIdTpl

Обе функции ищут id по значению в указанном поле. Разница в результате:

  • searchId возвращает найденные id в виде JSON-массива.
  • searchIdTpl по найденным id сразу вызывает шаблон.

Использование:

  • {{#invoke:GetField|searchId|searchValue|pagePath|keyPath}}
  • {{#invoke:GetField|searchIdTpl|searchValue|pagePath|keyPath|template}}
  • {{#invoke:GetField|searchIdTpl|pagePath|keyPath|template|searchType=path}}

Режимы поиска:

  • searchType=value — ищет id, у которых значение поля равно указанному значению. Это режим по умолчанию.
  • searchType=key — ищет id, у которых в поле-таблице существует ключ с указанным именем.
  • searchType=path — только для searchIdTpl; выводит все id, у которых поле по указанному пути существует и не пустое. В этом режиме первым параметром передаётся pagePath, а не значение для поиска.

searchIdTpl вызывает шаблон в виде {{Имя шаблона|id=...|...поля записи...}}. Если найдено несколько id, вызовы собираются подряд через пробел.

Примеры:

  • {{#invoke:GetField|searchId|Elements|prototype/reaction.json|group}} -> Ошибка скрипта: Функции «searchId» не существует.
ПараметрОписаниеОбязателен?
|1 =Значение для поиска.Да
|2 =Путь до JSON-страницы.Да
|3 =Путь до поля внутри записи. Поддерживает вложенность через точку и индексы вида field.1Да
|4 =Имя шаблона, который будет вызван для каждого найденного id.Только для searchIdTpl
|searchType =Режим поиска: value, key или path.Нет; value

hasComp

Проверяет, есть ли у сущности указанный компонент.

Использование:

  • {{#invoke:GetField|hasComp|entityId|componentName}}

Возвращает строку true или false.

Пример:

  • {{#invoke:GetField|hasComp|MopItem|Item}}
ПараметрОписаниеОбязателен?
|1 =Id сущности.Да
|2 =Имя компонента для проверки.Да

searchStore / searchStoreTpl

Эти функции находят прототипы или компоненты содержащие указанный id, используя Участник:IanComradeBot/prototype_store.json или Участник:IanComradeBot/component_store.json.

Использование:

  • {{#invoke:GetField|searchStore|searchId|prototype|Название}}
  • {{#invoke:GetField|searchStore|searchId|component|Название}}
  • {{#invoke:GetField|searchStoreTpl|searchId|prototype|Название|Шаблон}}

searchStore возвращает JSON-массив id, найденных в компонентах/прототипах. searchStoreTpl по тем же id сразу вызывает шаблон, используя страницу вида prototype/Название.json или component/Название.json.

Примеры:

  • {{#invoke:GetField|searchStore|MopItem|component|itemBorgModule}} -> Ошибка скрипта: Функции «searchStore» не существует.
  • {{#invoke:GetField|searchStore|MopItem|prototype|latheRecipe}} -> Ошибка скрипта: Функции «searchStore» не существует.
ПараметрОписаниеОбязателен?
|1 =Id, который ищется в хранилище.Да
|2 =Тип: prototype или component.Да
|3 =Имя хранилищя без .json.Да
|4 =Имя шаблона, который будет вызван для каждого найденного id.Только для searchStoreTpl

getAll / getAllTpl

Эти функции получают все id прототипов или компонентов.

Использование:

  • {{#invoke:GetField|getAll|pagePath}}
  • {{#invoke:GetField|getAllTpl|pagePath|template}}

getAll по умолчанию возвращает JSON-массив id. getAllTpl вызывает шаблон для каждого id в виде {{Имя шаблона|id=...|...поля записи...}}.

Примеры:

  • {{#invoke:GetField|getAll|component/staticPrice.json}} -> выводит все id сущностей с этим компонентом в формате JSON
  • {{#invoke:GetField|getAllTpl|component/staticPrice.json|component/staticPrice/wrapper}} -> выводит все id сущностей с этим компонентом обёрнутым в шаблон {{component/staticPrice/wrapper}}
ПараметрОписаниеОбязателен?
|1 =Путь до JSON-страницы.Да
|2 =Имя шаблона для getAllTpl.Только для getAllTpl
|replace =Строка замены для getAll. Если задана, результат выводится построчно вместо JSON-массива.Нет

jsonList

Преобразует JSON в список, перечисление или простой текст. Подходит для быстрого вывода данных без отдельного шаблона.

Использование:

  • {{#invoke:GetField|jsonList|["a","b","c"]}}
  • {{#invoke:GetField|jsonList|{"MopItem":"Швабра"}}}
  • {{#invoke:GetField|jsonList|{"MopItem":"Швабра"}|type=enum}}

Основные параметры:

  • type — формат вывода: list, enum или none.
  • prefix — префикс строки для режима списка. По умолчанию * .
  • sep — разделитель между ключом и значением. По умолчанию : .
  • replace — дополнительная обработка регулярным выражением уже собранной строки.
  • key_replace, value_replace — обработка ключей и значений регулярным выражением по отдельности.

Примеры:

  • {{#invoke:GetField|jsonList|["a","b","c"]}}
  • {{#invoke:GetField|jsonList|{"MopItem":"Швабра"}|type=list}}
  • {{#invoke:GetField|jsonList|{"MopItem":"Швабра"}|type=none|key_replace=<nowiki>[[\1]]</nowiki>}}
ПараметрОписаниеОбязателен?
|1 =JSON-строка. Можно также передать именованным параметром json.Да
|type =Формат вывода: list, enum или none.Нет; list
|prefix =Префикс строки для режима list.Нет; *
|sep =Разделитель между ключом и значением.Нет; :
|key_replace =Строка замены для ключей.Нет; \1
|value_replace =Строка замены для значений.Нет; \1
|replace =Строка замены для всего вывода.Нет; \1

json

Преобразует JSON-объект или JSON-массив объектов в набор вызовов шаблона и сразу обрабатывает их.

Использование:

  • {{#invoke:GetField|json|{"MopItem":{"name":"Швабра"}}|Предмет}}

Если значение по id является объектом, его поля разворачиваются в параметры шаблона. Если значение простое, оно передаётся как value=....

Пример вызова, который будет собран функцией:

  • {{Предмет|id=MopItem|name=Швабра}}
ПараметрОписаниеОбязателен?
|1 =JSON-строка.Да
|2 =Имя шаблона.Да

См. также

Примечания

  • Если запись, поле или JSON-страница не найдены, функции обычно возвращают пустую строку.
  • Функция get возвращает таблицы в JSON-виде.
  • В searchId и searchIdTpl значения сравниваются как строки.
  • Параметр keyPath поддерживает доступ к вложенным полям и индексам.
  • getTpl и searchIdTpl удобны, когда нужно не получить сырые данные, а сразу отрендерить карточку или другой шаблон.
  • Функции с searchStore работают только с генераторными страницами и хранилищами, где структура данных уже подготовлена под поиск по id.
  • json и jsonList ожидают корректный JSON; если строка не разбирается, результат будет пустым.
local p = {}

local function split(s, sep)
    if s == nil then return {} end
    local parts = {}
    sep = sep or "%."
    for part in string.gmatch(s, "([^" .. sep .. "]+)") do
        table.insert(parts, part)
    end
    return parts
end

local function parse_indexed_part(part)
    local key, idx = string.match(part, "^(.-)%[(%d+)%]$")
    if key then
        return key, tonumber(idx)
    end
    local num = tonumber(part)
    if num then
        return nil, num
    end
    return part, nil
end

local function get_by_path(tbl, path)
    if not tbl then return nil end
    local parts = split(path, "%.")
    local cur = tbl
    for _, part in ipairs(parts) do
        local key, idx = parse_indexed_part(part)
        if key and key ~= "" then
            local nextCur = nil
            if type(cur) == "table" then
                nextCur = cur[key]
                if nextCur == nil then
                    nextCur = cur["!type:" .. key]
                end
            end
            cur = nextCur
        end
        if idx then
            if type(cur) ~= "table" then
                return nil
            end
            cur = cur[idx]
        end
        if cur == nil then
            return nil
        end
    end
    return cur
end

local function is_array(t)
    if type(t) ~= "table" then return false end
    local i = 0
    for _ in pairs(t) do
        i = i + 1
    end
    local n = 0
    for k in pairs(t) do
        if type(k) ~= "number" then
            return false
        end
        if k > n then n = k end
    end
    return n > 0
end

local function format_value(v)
    if v == nil then return "" end
    local t = type(v)
    if t == "string" or t == "number" or t == "boolean" then
        return tostring(v)
    elseif t == "table" then
        if is_array(v) then
            local out = {}
            local max = 0
            for k in pairs(v) do if type(k) == "number" and k > max then max = k end end
            for i = 1, max do
                table.insert(out, format_value(v[i]))
            end
            return table.concat(out, ", ")
        else
            local out = {}
            for k, val in pairs(v) do
                table.insert(out, tostring(k) .. ": " .. format_value(val))
            end
            return table.concat(out, ", ")
        end
    else
        return tostring(v)
    end
end

function p.get(frame)
    local args = frame.args or {}
    local id = args[1] or ""
    local pagePath = args[2] or ""
    local keyPath = args[3] or ""

    local baseUser = "IanComradeBot/"
    local moduleName = "Module:" .. baseUser .. pagePath .. "/data"

    local ok, data = pcall(mw.loadData, moduleName)
    if not ok or not data then
        return ""
    end

    local entry = nil
    if id ~= "" then
        entry = data[id]
    end
    if entry == nil then
        entry = data["default"]
    end
    if entry == nil then
        return ""
    end

    if keyPath == "" then
        return format_value(entry)
    end

    local value = get_by_path(entry, keyPath)
    return format_value(value)
end

function p.flattenField(frame)
    local args = frame.args or {}
    local id = args[1] or ""
    local pagePath = args[2] or ""
    if id == "" or pagePath == "" then return "" end

    local baseUser = "IanComradeBot/"
    local moduleName = "Module:" .. baseUser .. pagePath .. "/data"
    local ok, data = pcall(mw.loadData, moduleName)
    if not ok or not data then return "" end

    local entry = data[id] or data["default"] or {}
    if type(entry) ~= "table" then
        return ""
    end

    local parts = {}
    local function walk(tbl, prefix)
        local keys = {}
        for k in pairs(tbl) do table.insert(keys, k) end
        table.sort(keys, function(a, b) return tostring(a) < tostring(b) end)
        for _, k in ipairs(keys) do
            local v = tbl[k]
            local key = (prefix == "" and tostring(k) or prefix .. "." .. tostring(k))
            if type(v) == "table" then
                walk(v, key)
            else
                table.insert(parts, key .. "=" .. tostring(v))
            end
        end
    end

    walk(entry, "")
    return table.concat(parts, "|")
end

return p