模块:UnlockBook
来自星砂岛百科
更多操作
概述
UnlockBook 提供解锁类书本条目的数据读取与展示辅助,供 Template:Infobox unlockbook 调用。
当前数据来自 `数据:UnlockBook/unlockbook_index.json` 与 `数据:UnlockBook/unlockbook_target_index.json` 两页,后者用于去重解锁目标,控制单页大小。
用法
读取字段:
{{#invoke:UnlockBook|getField|西番柿炖牛脯食谱|type_display}}
渲染主解锁对象:
{{#invoke:UnlockBook|targetSummary|西番柿炖牛脯食谱}}
渲染完整解锁清单:
{{#invoke:UnlockBook|targetList|基础建造手册}}
渲染对应设备:
{{#invoke:UnlockBook|stationList|弓箭包}}
主要函数
getField:读取基础字段。targetSummary:渲染主解锁对象摘要。targetList:渲染完整解锁清单。stationList:渲染对应设备列表。
local common = require('Module:Common')
local css = require('Module:CSS')
local item_common = require('Module:ItemCommon')
local item = require('Module:Item')
local p = {}
local FIELD_MAP = {
type_display = 'td',
rarity = 'r',
base_value = 'bv',
sell_price = 'sp',
max_stack = 'ms',
origin = 'o',
locked_origin = 'lo',
use_description = 'u',
book_family_display = 'fd',
unlock_target_type_display = 'ud',
unlock_target_count = 'c',
unlock_station_hint = 'h',
unlock_source_description = 'sd',
target_keys = 'tk',
station_ids = 'si',
}
local data_cache
local target_cache
local mapping_cache
local function load_data()
if data_cache then
return
end
data_cache, mapping_cache = item_common.loadDomainData('数据:UnlockBook/unlockbook_index.json')
target_cache = common.loadJsonData('数据:UnlockBook/unlockbook_target_index.json') or {}
end
local function find_record(key)
load_data()
return item_common.findRecord(data_cache, mapping_cache, key)
end
local function get_record_from_frame(frame)
return find_record(common.getArg(frame, 1, ''))
end
local function get_record_value(record, key, field)
if type(record) ~= 'table' then
return nil
end
if record[field] ~= nil then
return record[field]
end
local mapped = FIELD_MAP[field]
if mapped then
return record[mapped]
end
if field == 'id' or field == 'name' or field == 'name_en' then
return item_common.getIdentityField(record, key, field)
end
return nil
end
local function split_target_key(target_key)
local resolved = common.trim(target_key)
if resolved == '' then
return '', ''
end
local kind, target_id = mw.ustring.match(resolved, '^(.-)::(.*)$')
if not kind then
return '', resolved
end
return common.trim(kind), common.trim(target_id)
end
local function render_item_card(frame, item_id, count, css_class)
local resolved_id = common.trim(item_id)
if resolved_id == '' then
return ''
end
local args = { resolved_id }
if count and tonumber(count) and tonumber(count) > 1 then
args[2] = tostring(count)
end
if common.trim(css_class) ~= '' then
args.class = css_class
end
local output = item.renderItemWithArgs(frame, args)
return common.trim(output) ~= '' and output or ''
end
local function resolve_target_entry(target_key)
load_data()
local kind, target_id = split_target_key(target_key)
local target = type(target_cache) == 'table' and target_cache[target_key] or nil
if type(target) ~= 'table' then
return {
kind = kind,
id = target_id,
name = target_id,
item_id = '',
result_count = 0,
}
end
return {
kind = kind,
id = target_id,
name = common.trim(target.n or target_id),
item_id = common.trim(target.i or ''),
result_count = tonumber(target.c or 0) or 0,
}
end
local function get_target_entries(record)
local keys = get_record_value(record, nil, 'target_keys')
if type(keys) ~= 'table' or #keys == 0 then
return {}
end
local entries = {}
for _, target_key in ipairs(keys) do
local entry = resolve_target_entry(target_key)
if type(entry) == 'table' then
entries[#entries + 1] = entry
end
end
return entries
end
local function get_station_ids(record)
local station_ids = get_record_value(record, nil, 'station_ids')
if type(station_ids) ~= 'table' then
return {}
end
return station_ids
end
local function render_plain_target(entry, show_id)
local display_name = common.trim(entry.name or entry.id or '')
if display_name == '' then
return ''
end
local text = mw.text.encode(display_name)
if show_id and common.trim(entry.item_id or '') == '' then
local target_id = common.trim(entry.id or '')
if target_id ~= '' then
text = text .. ' <span class="unlockbook-target-id"><code>' .. mw.text.encode(target_id) .. '</code></span>'
end
end
return text
end
local function render_target_entry(frame, entry, css_class, show_id)
if type(entry) ~= 'table' then
return ''
end
local count = tonumber(entry.result_count or 0) or 0
local card = render_item_card(frame, entry.item_id, count, css_class)
if card ~= '' then
return card
end
return render_plain_target(entry, show_id)
end
local function render_station_entry(frame, station_id)
local resolved_id = common.trim(station_id)
if resolved_id == '' then
return ''
end
local card = render_item_card(frame, resolved_id, nil, 'block')
if card ~= '' then
return card
end
return mw.text.encode(resolved_id)
end
local function any_item_entry(entries)
if type(entries) ~= 'table' then
return false
end
for _, entry in ipairs(entries) do
if type(entry) == 'table' and common.trim(entry.item_id or entry.id or '') ~= '' then
return true
end
end
return false
end
local function with_item_css(entries, text)
if common.trim(text) == '' then
return ''
end
if any_item_entry(entries) then
return (css.quickCall('Item') or '') .. text
end
return text
end
function p.findRecord(key)
return find_record(key)
end
function p.getField(frame)
local key = common.getArg(frame, 1, '')
local field = common.getArg(frame, 2, '')
if field == '' then
return ''
end
local record = find_record(key)
if not record then
return ''
end
if field == 'image' then
local item_id = common.trim(get_record_value(record, key, 'id') or '')
if item_id == '' then
return ''
end
local image_name = item_id .. '.png'
if common.filePageExists(image_name) then
return image_name
end
return ''
end
local value = get_record_value(record, key, field)
if type(value) == 'table' then
return common.toText(value)
end
return common.toText(value)
end
function p.targetSummary(frame)
local record = get_record_from_frame(frame)
if not record then
return ''
end
local targets = get_target_entries(record)
if #targets == 0 then
return common.trim(get_record_value(record, nil, 'unlock_station_hint') or '')
end
local primary = render_target_entry(frame, targets[1], 'block', false)
if primary == '' then
return ''
end
local total_count = tonumber(get_record_value(record, nil, 'unlock_target_count') or #targets) or #targets
local more_count = math.max(total_count - 1, 0)
if more_count <= 0 then
return with_item_css({ targets[1] }, primary)
end
local out = {}
out[#out + 1] = primary
out[#out + 1] = ('<div class="unlockbook-target-summary-note">另含 %d 项</div>'):format(more_count)
return with_item_css({ targets[1] }, table.concat(out))
end
function p.targetList(frame)
local record = get_record_from_frame(frame)
if not record then
return ''
end
local targets = get_target_entries(record)
if #targets == 0 then
return ''
end
local out = {}
out[#out + 1] = '<ul class="unlockbook-target-list">'
for _, entry in ipairs(targets) do
local rendered = render_target_entry(frame, entry, 'block', true)
if rendered ~= '' then
out[#out + 1] = '<li>' .. rendered .. '</li>'
end
end
out[#out + 1] = '</ul>'
return with_item_css(targets, table.concat(out))
end
function p.stationList(frame)
local record = get_record_from_frame(frame)
if not record then
return ''
end
local station_ids = get_station_ids(record)
if #station_ids == 0 then
return ''
end
local parts = {}
local entries = {}
for _, station_id in ipairs(station_ids) do
local rendered = render_station_entry(frame, station_id)
if rendered ~= '' then
parts[#parts + 1] = rendered
entries[#entries + 1] = {
id = station_id,
item_id = station_id,
}
end
end
if #parts == 0 then
return ''
end
return with_item_css(entries, table.concat(parts))
end
return p