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

мНет описания правки
Метки: ручная отмена отменено
мНет описания правки
 
(не показано 7 промежуточных версий этого же участника)
Строка 4: Строка 4:
local getArgs = require('Module:Arguments').getArgs
local getArgs = require('Module:Arguments').getArgs


local function load_cached_data(pagePath)
function p.loadCachedData(pagePath)
local titleName = JsonPaths.get(pagePath)
local titleName = JsonPaths.get(pagePath)
if not titleName or titleName == "" then
if not titleName or titleName == "" then
Строка 152: Строка 152:
end
end


local function resolve_entry_from_data(data, id)
function p.ucfirst(s)
if not s or s == "" then return s end
return string.upper(s:sub(1, 1)) .. (s:sub(2) or "")
end
 
function p.normalizeComponentName(name)
if type(name) ~= "string" or name == "" then
return nil
end
name = mw.text.trim(name)
if name:sub(1, 5) == "type:" then
name = name:sub(6)
elseif name:sub(1, 6) == "!type:" then
name = name:sub(7)
end
if name == "" then
return nil
end
return name
end
 
local function split_data_page_path(pagePath)
local kind, name = string.match(pagePath or "", "^(component)/([^/]+)%.json$")
if not kind then
return nil, nil
end
return kind, p.ucfirst(name)
end
 
local function get_component_from_entity(entity, componentName)
if type(entity) ~= "table" or type(entity.components) ~= "table" then
return nil
end
 
return entity.components["type:" .. componentName]
or entity.components[componentName]
or entity.components["!type:" .. componentName]
end
 
local function load_specific_entry(pagePath, id, allowDefault)
local kind, name = split_data_page_path(pagePath)
if not kind or not id or id == "" then
return nil
end
 
if kind ~= "component" then
return nil
end
 
local base
local defaultData = p.loadCachedData(kind .. "/" .. name .. "/defaultFields.json")
if type(defaultData) == "table" then
base = deep_copy(defaultData)
end
 
local entityPage = "prototype/Entity/" .. id .. ".json"
local entity = p.loadCachedData(entityPage)
local specific = get_component_from_entity(entity, name)
 
if type(specific) ~= "table" then
if allowDefault == false then
return nil
end
return base
end
 
if base then
deep_merge(base, specific)
return base
end
 
return specific
end
 
local function resolve_entry_from_data(data, id, allowDefault)
if type(data) ~= "table" then
if type(data) ~= "table" then
return nil
return nil
Строка 176: Строка 250:
end
end
end
end
end
if allowDefault == false then
return nil
end
end


Строка 186: Строка 264:
end
end


local function load_entry(id, pagePath, data)
local function load_entry(id, pagePath, data, allowDefault)
data = data or load_cached_data(pagePath)
local specificPageEntry = load_specific_entry(pagePath, id, allowDefault)
return resolve_entry_from_data(data, id)
if specificPageEntry ~= nil then
return specificPageEntry
end
 
data = data or p.loadCachedData(pagePath)
if allowDefault == nil then
allowDefault = true
end
return resolve_entry_from_data(data, id, allowDefault)
end
end


Строка 424: Строка 510:
end
end


local function build_tpl(id, pagePath, tplPath, data, tplArgs, preEntry)
local function build_tpl(id, pagePath, tplPath, data, tplArgs, preEntry, strictExact)
if id == "" or pagePath == "" or tplPath == "" then
if id == "" or pagePath == "" or tplPath == "" then
return ""
return ""
end
end


local entry = preEntry or load_entry(id, pagePath, data)
local entry
if strictExact then
entry = load_entry(id, pagePath, data, false)
else
entry = preEntry or load_entry(id, pagePath, data)
end
 
if entry == nil then
if entry == nil then
return ""
return ""
Строка 456: Строка 548:
local searchId = args[1] or ""
local searchId = args[1] or ""
local kind = (args[2] or ""):lower()
local kind = (args[2] or ""):lower()
local fieldId = args[3] or ""
local fieldId = p.ucfirst(args[3] or "")


if searchId == "" or fieldId == "" then
if searchId == "" or fieldId == "" then
Строка 466: Строка 558:


local storeName = (kind == "prototype") and "prototype_store.json" or "component_store.json"
local storeName = (kind == "prototype") and "prototype_store.json" or "component_store.json"
local data = load_cached_data(storeName)
local data = p.loadCachedData(storeName)
if not data then
if not data then
return ""
return ""
Строка 650: Строка 742:


return out
return out
end
local function add_scalar_values(value, set)
if type(value) == "table" then
if is_array(value) then
for _, item in ipairs(value) do
add_scalar_values(item, set)
end
else
for _, item in pairs(value) do
add_scalar_values(item, set)
end
end
elseif value ~= nil then
set[tostring(value)] = true
end
end
local function table_has_all_values(value, targets)
if type(targets) ~= "table" or #targets == 0 then
return false
end
if type(value) ~= "table" then
return #targets == 1 and tostring(value) == targets[1]
end
local set = {}
add_scalar_values(value, set)
for i = 1, #targets do
if not set[targets[i]] then
return false
end
end
return true
end
end


Строка 703: Строка 758:
end
end


local data = load_cached_data(pagePath)
local data = p.loadCachedData(pagePath)
if not data then
if not data then
return "[]"
return "[]"
Строка 738: Строка 793:


return ""
return ""
end
local function collect_ids_from_entry(entry)
local out = {}
local seen = {}
local function add(v)
if v == nil then
return
end
local s = tostring(v)
if s ~= "" and not seen[s] then
seen[s] = true
out[#out + 1] = s
end
end
if type(entry) == "table" then
if is_array(entry) then
for _, v in ipairs(entry) do
add(v)
end
else
for _, v in pairs(entry) do
if type(v) == "table" and is_array(v) then
for _, item in ipairs(v) do
add(item)
end
elseif type(v) ~= "table" then
add(v)
end
end
end
else
add(entry)
end
return out
end
end


Строка 746: Строка 839:


if mode ~= "component" and mode ~= "tag" then
if mode ~= "component" and mode ~= "tag" then
return "[]"
return ""
end
end


local targets = split_csv_list(rawList)
local targets = split_csv_list(rawList)
if #targets == 0 then
if #targets == 0 then
return "[]"
return ""
end
end


local pagePath
local pagePath = (mode == "component") and "component.json" or "tag.json"
if mode == "component" then
local data = p.loadCachedData(pagePath)
pagePath = "component.json"
if not data then
else
return ""
pagePath = "component/tag.json"
end
end


local data = load_cached_data(pagePath)
local matches = {}
if not data or type(data) ~= "table" then
local seen = {}
return "[]"
end


local ids = collect_id_keys(data)
local function add_id(id)
if #ids == 0 then
local s = tostring(id)
return "[]"
if s ~= "" and not seen[s] then
end
seen[s] = true
 
matches[#matches + 1] = s
table.sort(ids, function(a, b)
return tostring(a) < tostring(b)
end)
 
local function entry_has_all_targets_component(entry, wanted)
if type(entry) ~= "table" then
return false
end
 
local set = {}
for _, v in ipairs(entry) do
set[tostring(v)] = true
end
 
for i = 1, #wanted do
if not set[wanted[i]] then
return false
end
end
end
return true
end
end


local function entry_has_all_targets_tag(entry, wanted)
for _, key in ipairs(targets) do
if type(entry) ~= "table" then
local entry = resolve_entry_from_data(data, key)
return false
if entry ~= nil then
end
local ids = collect_ids_from_entry(entry)
 
for _, id in ipairs(ids) do
local tags = entry.tags or entry.tag
add_id(id)
if type(tags) ~= "table" then
return false
end
 
local set = {}
if is_array(tags) then
for _, v in ipairs(tags) do
set[tostring(v)] = true
end
else
for _, v in pairs(tags) do
set[tostring(v)] = true
end
end
 
for i = 1, #wanted do
if not set[wanted[i]] then
return false
end
end
end
end
return true
end
end


local matches = {}
table.sort(matches, function(a, b)
 
return tostring(a) < tostring(b)
for _, idKey in ipairs(ids) do
end)
local entry = resolve_entry_from_data(data, idKey)
if mode == "component" then
if entry_has_all_targets_component(entry, targets) then
matches[#matches + 1] = idKey
end
else
if entry_has_all_targets_tag(entry, targets) then
matches[#matches + 1] = idKey
end
end
end


local ok, json = pcall(mw.text.jsonEncode, matches)
local ok, json = pcall(mw.text.jsonEncode, matches)
Строка 844: Строка 883:
end
end


return "[]"
return ""
end
end


Строка 877: Строка 916:
end
end


local data = load_cached_data(pagePath)
local data = p.loadCachedData(pagePath)
if not data then
if not data then
return ""
return ""
Строка 920: Строка 959:
local out = {}
local out = {}
for _, idKey in ipairs(matches) do
for _, idKey in ipairs(matches) do
local tpl = build_tpl(idKey, pagePath, tplPath, data, tplArgs, entryCache[idKey])
local tpl = build_tpl(idKey, pagePath, tplPath, data, tplArgs, entryCache[idKey], true)
if tpl ~= "" then
if tpl ~= "" then
out[#out + 1] = tpl
out[#out + 1] = tpl
Строка 947: Строка 986:


local data = frame.data
local data = frame.data
local tplStr = build_tpl(id, pagePath, tplPath, data, tplArgs)
local tplStr = build_tpl(id, pagePath, tplPath, data, tplArgs, nil, true)
return preprocess_or_return(frame, tplStr)
return preprocess_or_return(frame, tplStr)
end
end
Строка 955: Строка 994:
local searchId = args[1] or ""
local searchId = args[1] or ""
local kind = (args[2] or ""):lower()
local kind = (args[2] or ""):lower()
local generatorId = args[3] or ""
local generatorId = p.ucfirst(args[3] or "")
local tplPath = mw.text.unstripNoWiki(args[4] or "")
local tplPath = mw.text.unstripNoWiki(args[4] or "")
local tplArgs = args[5] or args.tplArgs or args.templateArgs or ""
local tplArgs = args[5] or args.tplArgs or args.templateArgs or ""
Строка 976: Строка 1015:
end
end


local data = load_cached_data(pagePath)
local data = p.loadCachedData(pagePath)
if not data then
if not data then
return ""
return ""
Строка 985: Строка 1024:
local entry = resolve_entry_from_data(data, id)
local entry = resolve_entry_from_data(data, id)
if entry ~= nil then
if entry ~= nil then
local tpl = build_tpl(id, pagePath, tplPath, data, tplArgs, entry)
local tpl = build_tpl(id, pagePath, tplPath, data, tplArgs, entry, true)
if tpl ~= "" then
if tpl ~= "" then
out[#out + 1] = tpl
out[#out + 1] = tpl
Строка 1004: Строка 1043:
local searchId = args[1] or ""
local searchId = args[1] or ""
local kind = (args[2] or ""):lower()
local kind = (args[2] or ""):lower()
local generatorId = args[3] or ""
local generatorId = p.ucfirst(args[3] or "")


if searchId == "" or generatorId == "" then
if searchId == "" or generatorId == "" then
Строка 1025: Строка 1064:


return ""
return ""
end
function p.loadEntityData(entityId)
if entityId == "" then
return nil
end
local pagePath = "prototype/Entity/" .. entityId .. ".json"
return p.loadCachedData(pagePath)
end
function p.entityHasComponent(entity, compName)
if type(entity) ~= "table" or type(entity.components) ~= "table" then
return false
end
return entity.components[compName] ~= nil
or entity.components["type:" .. compName] ~= nil
or entity.components["!type:" .. compName] ~= nil
end
function p.collectEntityComponents(entity)
if type(entity) ~= "table" or type(entity.components) ~= "table" then
return {}
end
local out = {}
local seen = {}
local comps = entity.components
if #comps > 0 then
for _, v in ipairs(comps) do
local name = p.normalizeComponentName(v)
if name and not seen[name] then
seen[name] = true
out[#out + 1] = name
end
end
else
for k in pairs(comps) do
local name = p.normalizeComponentName(k)
if name and not seen[name] then
seen[name] = true
out[#out + 1] = name
end
end
end
table.sort(out)
return out
end
end


Строка 1036: Строка 1125:
end
end


local data = load_cached_data("component.json")
local entity = p.loadEntityData(entityId)
if not data then
if not entity then
return "false"
return "false"
end
end


if type(data) ~= "table" then
return p.entityHasComponent(entity, compName) and "true" or "false"
return "false"
end
 
local entry = data[entityId]
if type(entry) ~= "table" then
return "false"
end
 
for _, v in ipairs(entry) do
if tostring(v) == compName then
return "true"
end
end
 
return "false"
end
end


Строка 1064: Строка 1138:


if entityId == "" then
if entityId == "" then
return "[]"
return ""
end
end


local data = load_cached_data("component.json")
local entity = p.loadEntityData(entityId)
if not data or type(data) ~= "table" then
if not entity then
return "[]"
return ""
end
 
local entry = data[entityId]
if type(entry) ~= "table" then
return "[]"
end
 
local out = {}
for _, v in ipairs(entry) do
if v ~= nil and v ~= "" then
out[#out + 1] = v
end
end
end


local out = p.collectEntityComponents(entity)
local ok, json = pcall(mw.text.jsonEncode, out)
local ok, json = pcall(mw.text.jsonEncode, out)
if ok and json then
if ok and json then
Строка 1089: Строка 1152:
end
end


return "[]"
return ""
end
end


Строка 1102: Строка 1165:
end
end


local data = load_cached_data(pagePath)
local data = p.loadCachedData(pagePath)
if not data then
if not data then
return ""
return ""
Строка 1152: Строка 1215:
end
end


local data = load_cached_data(pagePath)
local data = p.loadCachedData(pagePath)
if not data then
if not data then
return ""
return ""
Строка 1167: Строка 1230:
local entry = resolve_entry_from_data(data, idKey)
local entry = resolve_entry_from_data(data, idKey)
if entry ~= nil then
if entry ~= nil then
local tpl = build_tpl(idKey, pagePath, tplPath, data, tplArgs, entry)
local tpl = build_tpl(idKey, pagePath, tplPath, data, tplArgs, entry, true)
if tpl ~= "" then
if tpl ~= "" then
out[#out + 1] = tpl
out[#out + 1] = tpl