模块:GiftsByItem
描述
当前模块用于物品的人物喜好列表的生成,能够根据导出的数据进行全自动的格式化、排序和输出。
人物按照一定的逻辑排序,此外还对排版显示上进行了一定的优化。
如果该模块存在任何问题,请在{{GiftsByItem}}对应的讨论页中反馈。
模块使用的数据见模块:GiftsByItem/data,相关数据是通过由中文社区维护的模组导出的,相关代码见 Github 仓库中的 GetNPCGiftTastes 部分。
local items = require("Module:Items")
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
	local result = items.getId(itemName):gsub('%(O%)', ''):gsub('%(TR%)', '')
    return result
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
                
                    沪公网安备 31011002002714 号