模块:GiftsByItem
描述
当前模块用于物品的人物喜好列表的生成,能够根据导出的数据进行全自动的格式化、排序和输出。
人物按照一定的逻辑排序,此外还对排版显示上进行了一定的优化。
如果该模块存在任何问题,请在{{GiftsByItem}}
对应的讨论页中反馈。
模块使用的数据见模块:GiftsByItem/data,相关数据是通过由中文社区维护的模组导出的,相关代码见 Github 仓库中的 GetNPCGiftTastes 部分。
local ID = require("Module:ID")
local GiftsByItemData = mw.loadData('Module:GiftsByItem/data')
local p = {}
-- 是否优先使用传入的参数
p.PREFER_MANUAL_DATA = false
p.predefinedOrder = {
"哈维", "山姆", "谢恩", "亚历克斯", "艾利欧特",
"塞巴斯蒂安", "海莉", "莉亚", "玛鲁", "潘妮", "艾米丽",
"阿比盖尔", "皮埃尔", "卡洛琳", "刘易斯", "玛妮", "罗宾",
"德米特里厄斯", "艾芙琳", "乔治", "贾斯", "文森特",
"乔迪", "肯特", "威利", "格斯", "潘姆", "莱纳斯", "克林特",
"法师", "矮人", "科罗布斯", "桑迪", "雷欧"
}
p.translation = {
["Alex"] = "亚历克斯",
["Elliott"] = "艾利欧特",
["Harvey"] = "哈维",
["Sam"] = "山姆",
["Sebastian"] = "塞巴斯蒂安",
["Shane"] = "谢恩",
["Abigail"] = "阿比盖尔",
["Emily"] = "艾米丽",
["Haley"] = "海莉",
["Leah"] = "莉亚",
["Maru"] = "玛鲁",
["Penny"] = "潘妮",
["Caroline"] = "卡洛琳",
["Clint"] = "克林特",
["Demetrius"] = "德米特里厄斯",
["Dwarf"] = "矮人",
["Evelyn"] = "艾芙琳",
["George"] = "乔治",
["Gus"] = "格斯",
["Jas"] = "贾斯",
["Jodi"] = "乔迪",
["Kent"] = "肯特",
["Krobus"] = "科罗布斯",
["Leo"] = "雷欧",
["Lewis"] = "刘易斯",
["Linus"] = "莱纳斯",
["Marnie"] = "玛妮",
["Pam"] = "潘姆",
["Pierre"] = "皮埃尔",
["Robin"] = "罗宾",
["Sandy"] = "桑迪",
["Vincent"] = "文森特",
["Willy"] = "威利",
["Wizard"] = "法师"
}
p.original = {}
for en, zh in pairs(p.translation) do p.original[zh] = en end
p.orderIndex = {}
for i, name in ipairs(p.predefinedOrder) do p.orderIndex[name] = i end
function p.removeDuplicates(list)
local seen = {}
local result = {}
for _, item in ipairs(list) do
if not seen[item] then
table.insert(result, item)
seen[item] = true
end
end
return result
end
function p.translateVillagers(villagers, translationMap)
for i, villager in ipairs(villagers) do
villagers[i] = translationMap[villager] or villager
end
end
function p.customSort(villagers, orderIndexMap)
table.sort(villagers, function(a, b)
local indexA = orderIndexMap[a] or math.huge
local indexB = orderIndexMap[b] or math.huge
return indexA < indexB
end)
end
function p.generateHTML(villagers, originalMap, linkPrefix)
linkPrefix = linkPrefix or ""
local result = {}
for i, villager in ipairs(villagers) do
local iconName = originalMap[villager] or villager
local link = linkPrefix ~= "" and (linkPrefix .. ":" .. villager) or
villager
local html = string.format(
'<span class="no-wrap">[[File:%s Icon.png|24px|link=%s]] [[%s|%s]]</span>',
iconName, link, link, villager)
table.insert(result, html)
end
return table.concat(result, " • ")
end
function p.processVillagers(villagerlist, translationMap, orderIndexMap,
originalMap, linkPrefix)
if not villagerlist then return "" end
local villagers = {}
for villager in villagerlist:gmatch("[^,]+") do
villager = mw.text.trim(villager)
if villager ~= "" then table.insert(villagers, villager) end
end
villagers = p.removeDuplicates(villagers)
table.sort(villagers)
p.translateVillagers(villagers, translationMap)
p.customSort(villagers, orderIndexMap)
return p.generateHTML(villagers, originalMap, linkPrefix)
end
function p.ts(frame)
local villagerlist = frame.args[1]
return p.processVillagers(villagerlist, p.translation, p.orderIndex,
p.original)
end
function p.getItemID(itemName)
local itemNameToIDMapping = {
["诡异玩偶(绿)"] = "126",
["诡异玩偶(黄)"] = "127",
["Joja可乐"] = "167",
["垃圾(物品)"] = "168",
["破损的CD"] = "171",
["鱼饵(物品)"] = "685",
["针对性鱼饵"] = "SpecificBait",
["熏鱼"] = "Smoked",
["果干"] = "DriedFruit",
["蘑菇干"] = "DriedMushrooms",
["青蛙蛋"] = "FrogEgg"
}
if itemNameToIDMapping[itemName] then
return itemNameToIDMapping[itemName]
end
return ID.id(itemName):gsub('%(O%)', ''):gsub('%(TR%)', '')
end
function p.hasManualData(args)
return args.love or args.like or args.neutral or args.dislike or args.hate
end
function p.checkAutoTableAvailable(itemName, dataSource)
local itemID = p.getItemID(itemName)
local item = dataSource[itemID] or dataSource[itemName]
if not item then return false end
for _, category in ipairs({ "Love", "Like", "Neutral", "Dislike", "Hate" }) do
if item[category] then
for i, _ in pairs(item[category]) do
if type(i) == "number" and i > 0 then
return true
end
end
end
end
return false
end
function p.generateManualRow(category, npcList, itemName)
if not npcList or npcList == "" then
return ""
end
local categoryConfig = {
love = {
label = "最爱",
points = (itemName == "星之果茶") and "+250" or "+80"
},
like = { label = "喜欢", points = "+45" },
neutral = { label = "普通", points = "+20" },
dislike = { label = "不喜欢", points = "-20" },
hate = { label = "讨厌", points = "-40" }
}
local config = categoryConfig[category]
if not config then return "" end
local mockFrame = { args = { [1] = npcList } }
local processedList = p.ts(mockFrame)
return string.format([[
<tr>
<th><span class="no-wrap">%s</span><br><span style="font-size:smaller;">%s</span></th>
<td>%s</td>
</tr>]], config.label, config.points, processedList)
end
function p.generateManualTable(itemName, displayName, args)
local result = {}
table.insert(result, '<table class="wikitable roundedborder">')
table.insert(result, '<tr>')
table.insert(result, '<th colspan="2">收到' .. displayName .. '后</th>')
table.insert(result, '</tr>')
table.insert(result, p.generateManualRow("love", args.love, itemName))
table.insert(result, p.generateManualRow("like", args.like, itemName))
table.insert(result, p.generateManualRow("neutral", args.neutral, itemName))
table.insert(result, p.generateManualRow("dislike", args.dislike, itemName))
table.insert(result, p.generateManualRow("hate", args.hate, itemName))
table.insert(result, '</table>')
return table.concat(result, '\n')
end
function p.generateAutoTable(itemName, displayName, dataSource)
local itemID = p.getItemID(itemName)
local item = dataSource[itemID] or dataSource[itemName]
if not item then return "" end
local result = {}
local flag = false
table.insert(result, '<table class="wikitable roundedborder">')
table.insert(result, '<tr>')
table.insert(result, '<th colspan="2">收到' .. displayName .. '后</th>')
table.insert(result, '</tr>')
local categories = {
{ key = "Love", label = "最爱", points = (itemName == "星之果茶" or itemName == "StardropTea") and "+250" or "+80" },
{ key = "Like", label = "喜欢", points = "+45" },
{ key = "Neutral", label = "普通", points = "+20" },
{ key = "Dislike", label = "不喜欢", points = "-20" },
{ key = "Hate", label = "讨厌", points = "-40" }
}
for _, cat in ipairs(categories) do
if item[cat.key] then
local npcList = {}
for i, npc in pairs(item[cat.key]) do
if type(i) == "number" and i > 0 then
table.insert(npcList, npc)
end
end
if #npcList > 0 then
flag = true
local npcString = table.concat(npcList, ",")
local mockFrame = { args = { [1] = npcString } }
local processedList = p.ts(mockFrame)
table.insert(result, '<tr>')
table.insert(result, string.format(
'<th><span class="no-wrap">%s</span><br><span style="font-size:smaller;">%s</span></th>',
cat.label, cat.points))
table.insert(result, '<td>' .. processedList .. '</td>')
table.insert(result, '</tr>')
end
end
end
table.insert(result, '</table>')
if not flag then
table.insert(result, '[[分类:礼物喜好解析存在问题的物品]]')
end
return table.concat(result, '\n')
end
function p.generateGiftTable(frame)
local args = frame.args
if frame == mw.getCurrentFrame() then
args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:GiftsByItem'
})
end
local itemName = args.item or args[1] or mw.title.getCurrentTitle().text
local displayName = args.alt or itemName
if not itemName or itemName == "" then
return ""
end
local hasManual = p.hasManualData(args)
local hasAuto = p.checkAutoTableAvailable(itemName, GiftsByItemData)
-- 特殊页面强制使用手动表格
if itemName == "星之果茶" or itemName == "错误物品" then
if hasManual then
return p.generateManualTable(itemName, displayName, args)
else
return p.generateAutoTable(itemName, displayName, GiftsByItemData)
end
end
-- 根据配置决定优先级
if p.PREFER_MANUAL_DATA then
if hasManual then
return p.generateManualTable(itemName, displayName, args)
elseif hasAuto then
return p.generateAutoTable(itemName, displayName, GiftsByItemData)
else
return ""
end
else
if hasAuto then
return p.generateAutoTable(itemName, displayName, GiftsByItemData)
elseif hasManual then
return p.generateManualTable(itemName, displayName, args)
else
return ""
end
end
end
return p