全站通知:

模块:GiftsByItem

来自星露谷物语维基
跳到导航 跳到搜索

描述

当前模块用于物品的人物喜好列表的生成,能够根据导出的数据进行全自动的格式化、排序和输出。

人物按照一定的逻辑排序,此外还对排版显示上进行了一定的优化。

如果该模块存在任何问题,请在{{GiftsByItem}}对应的讨论页中反馈。

模块使用的数据见模块:GiftsByItem/data,相关数据是通过由中文社区维护的模组导出的,相关代码见 Github 仓库中的 GetNPCGiftTastes 部分

[ 查看 | 编辑 | 历史 | 刷新 ]上述文档的内容来自模块:GiftsByItem/doc
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]]&nbsp;[[%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