全站通知:
模块:FishPond
刷
历
编
跳到导航
跳到搜索
本模块用于计算和输出鱼塘的“任务”和“产物”表格。
本模块涉及到的相关模块:
本模块涉及到的相关模板:
代码复杂度过高,一般情况下不建议尝试修改(如果有能力,建议进行重构)。
[ 查看 | 编辑 | 历史 | 刷新 ]上述文档的内容来自模块:FishPond/doc。
local cache = require "mw.ext.LuaCache"
local KEY_PREFIX = "FishPond_Update"
local EXP_TIME = 172800
local utils = require("Module:Utils")
local object = require("Module:Object")
local items = require("Module:Items")
---@diagnostic disable-next-line: undefined-global
local mw = mw
local FishPondData = mw.loadData('Module:FishPond/data')
local FishPond = {}
local VALID_FISH_TAGS = {
fish_legendary = true,
fish_desert = true,
fish_semi_rare = true,
fish_carnivorous = true,
fish_freshwater = true,
fish_crab_pot = true,
fish_ocean = true,
fish_river = true,
fish_lake = true
}
-- ---------------------------------------------------------------------------
-- Utility helpers
-- ---------------------------------------------------------------------------
local function generateRowLocal(serializedRow)
local rowParts = {}
for part in string.gmatch(serializedRow, "([^,]+)") do
table.insert(rowParts, part)
end
local result = {}
local i = 1
table.insert(result, string.format('<td data-sort-value="%s">%s</td>',
rowParts[i + 1], rowParts[i]))
i = i + 2
while i <= #rowParts - 3 do
local colspan = tonumber(rowParts[i])
local content = rowParts[i + 1] or "/"
table.insert(result, string.format('<td colspan="%d">%s</td>', colspan,
content))
i = i + 2
end
table.insert(result, string.format('<td>%s</td>', rowParts[i]))
table.insert(result, string.format('<td>%s</td>', rowParts[i + 1]))
return "<tr>" .. table.concat(result) .. "</tr>"
end
local function toPercentage(value, omitSuffix, multiplier, formatter)
if value == "/" then return "/" end
if value == " " then return " " end
if value == "—" then return "—" end
multiplier = multiplier or 100
formatter = formatter or "%.1f"
local formatted = string.format(formatter, tonumber(value) * multiplier)
formatted = formatted:gsub("%.00$", ""):gsub("%.0$", ""):gsub("%.([1-9])0$",
".%1")
if omitSuffix then return formatted end
return formatted .. "%"
end
local function normalizeOwnedId(rawId)
if type(rawId) ~= "string" then return nil end
if rawId:sub(1, 3) ~= "(O)" then return nil end
return rawId:sub(4)
end
local function normaliseFishName(name)
if type(name) ~= "string" then return nil end
return name:lower():gsub(" ", "")
end
local function getFishTagsById(id)
if not id or id == "" then return nil end
local fields = object.getFieldsById(id)
if type(fields) ~= "table" then return nil end
local tags = fields.ContextTags
if type(tags) ~= "table" then return nil end
local matched = {}
for _, tag in ipairs(tags) do
if VALID_FISH_TAGS[tag] then table.insert(matched, tag) end
end
if #matched == 0 then return nil end
return matched
end
local function findFishData(fishKey)
if type(fishKey) == "table" then
for _, fish in ipairs(FishPondData) do
local requiredTags = fish["RequiredTags"] or {}
if requiredTags == {} then return nil end -- Intentional no-op parity
if utils.tablesEqual(fishKey, requiredTags) then
return fish
end
end
for _, fish in ipairs(FishPondData) do
local requiredTags = fish["RequiredTags"] or {}
if requiredTags == {} then return nil end -- Intentional no-op parity
if utils.tablesOverlap(fishKey, requiredTags) then
return fish
end
end
return nil
end
local lowerFishName = normaliseFishName(fishKey)
if not lowerFishName then return nil end
for _, fish in ipairs(FishPondData) do
local fishId = fish['Id']
if normaliseFishName(fishId) == lowerFishName then return fish end
end
return nil
end
local function resolveFishData(context)
local fishData = findFishData(context.name)
if fishData then return fishData, nil end
local tag = getFishTagsById(context.id)
if tag then
local tagData = findFishData(tag)
if tagData then return tagData, tag end
end
return nil, tag
end
local function buildFishContext(fishName)
if not fishName then return nil end
local rawId = items.getId(fishName)
local id = normalizeOwnedId(rawId)
if not id then return nil end
local fields = object.getFieldsById(id) or {}
local name = fields["Name"]
if not name then return nil end
local context = {
original = fishName,
rawId = rawId,
id = id,
fields = fields,
name = name
}
local fishData, tag = resolveFishData(context)
context.data = fishData
context.tag = tag
return context
end
local function ensureContext(frame)
local frameArgs = frame and frame.args or {}
local fishName = frameArgs[1]
local context = buildFishContext(fishName)
return context
end
local function computeSpawnTime(context)
if not context or not context.data then return nil end
local spawnTime = context.data['SpawnTime']
if tonumber(spawnTime or -1) ~= -1 then return spawnTime end
local price = tonumber(object.getPriceById(context.id)) or 0
if price <= 30 then
return 1
elseif price <= 80 then
return 2
elseif price <= 120 then
return 3
elseif price <= 250 then
return 4
else
return 5
end
end
local function getPopulationGateList(context)
if not context or not context.data then return nil end
local populationGates = context.data['PopulationGates']
if not populationGates then return nil end
local sortedGates = {}
for population, gates in pairs(populationGates) do
table.insert(sortedGates,
{population = tonumber(population), gates = gates})
end
table.sort(sortedGates,
function(a, b) return a.population < b.population end)
return sortedGates
end
local function gateItemsToString(gates)
local requiredItems = {}
for _, gateItem in ipairs(gates) do
local itemId, quantity = gateItem:match("^(%S+) (%S+)%s*(%S*)$")
if not itemId then
itemId = gateItem
quantity = 1
elseif quantity == "" then
quantity = itemId
itemId = gateItem
elseif quantity:find("~") then
quantity = quantity
end
local english = items.getEnglishNameById(itemId)
local safeName = english and english:gsub(":", "") or ""
table.insert(requiredItems, utils.expandTemplate("模板:Name", {
safeName,
quantity,
class = "inline"
}))
end
if #requiredItems == 1 then return requiredItems[1] end
if #requiredItems == 2 then
return requiredItems[1] .. "或" .. requiredItems[2]
end
return table.concat(requiredItems, "、", 1, #requiredItems - 1) .. "或" ..
requiredItems[#requiredItems]
end
local function collectOpacityRows(context)
local data = context and context.data
if not data then return nil end
if context.tag == "fish_legendary" then return nil end
local gates = getPopulationGateList(context)
if not gates or #gates == 0 then return nil end
local maximumPopulation = data['MaxPopulation'] or 11
if tonumber(maximumPopulation) == -1 then maximumPopulation = 11 end
local spawnTime = computeSpawnTime(context) or 0
local rows = {}
for gateIndex, gateInfo in ipairs(gates) do
local currentPopulation = gateInfo.population
local thresholdPopulation
if gateIndex < #gates then
thresholdPopulation = gates[gateIndex + 1].population - 1
else
thresholdPopulation = tonumber(maximumPopulation) - 1
end
local itemsSummary = gateItemsToString(gateInfo.gates)
local experienceReward = 20 + spawnTime * 5
table.insert(rows, {
population = currentPopulation,
nextPopulation = thresholdPopulation,
items = itemsSummary,
exp = experienceReward
})
end
return {rows = rows, spawnTime = spawnTime}
end
local function prepareProducedItemContext(context)
local data = context.data
if not data or not data['ProducedItems'] then return nil end
if context.tag == "fish_legendary" then return nil end
local maxPopulation = data['MaxPopulation'] or 11
if maxPopulation == "-1" or maxPopulation == -1 then maxPopulation = 11 end
local basePrice = 30 + (tonumber(object.getPriceById(context.id)) or 0) *
0.5
local roeColor = object.getColorById(context.id)
local iconName = (roeColor and roeColor .. " Roe") or "Roe"
if not utils.fileExists(iconName .. ".png") then iconName = "Roe" end
local producedItems = data['ProducedItems']
local productEntries = {}
local productOrder = {}
local sortedProducedItems = {}
for index, item in ipairs(producedItems) do
local clonedItem = utils.deepCopy(item)
clonedItem.priority = index
table.insert(sortedProducedItems, {
requiredPopulation = tonumber(item.RequiredPopulation),
chance = clonedItem.Chance,
item = clonedItem
})
end
table.sort(sortedProducedItems, function(a, b)
return a.requiredPopulation < b.requiredPopulation
end)
local emptySlotNeeded = false
for _, wrappedItem in ipairs(sortedProducedItems) do
local item = wrappedItem.item
local requiredPopulation = item.RequiredPopulation > 0 and
item.RequiredPopulation or 1
local rawItemId = item.ItemId
local cleanItemId = normalizeOwnedId(rawItemId) or rawItemId
local price = tonumber(object.getPriceById(cleanItemId)) or 0
if cleanItemId == "812" then price = basePrice end
local experienceReward = 10 + price * 0.04
local englishName = items.getEnglishNameById(rawItemId)
local minStack = item.MinStack ~= -1 and item.MinStack or 1
local maxStack = item.MaxStack ~= -1 and item.MaxStack or minStack
local quantityLabel = (minStack == maxStack) and tostring(minStack) or
(minStack .. "~" .. maxStack)
local entryKey = (englishName or "") .. "_" .. minStack .. "_" ..
maxStack
local safeName = englishName and englishName:gsub(":", "") or ""
if not productEntries[entryKey] then
productEntries[entryKey] = {
item = utils.expandTemplate("模板:Name", {
safeName,
quantityLabel,
class = "inline"
}),
requiredData = {},
quantity = quantityLabel,
priority = item.priority,
experience = experienceReward or 0
}
table.insert(productOrder, entryKey)
end
local requirementSegments = productEntries[entryKey].requiredData
if requiredPopulation == 10 then
table.insert(requirementSegments, {
rangeA = requiredPopulation,
rangeB = requiredPopulation,
priority = item.priority
})
else
table.insert(requirementSegments, {
rangeA = requiredPopulation,
priority = item.priority
})
end
if #productOrder == 1 and item.Chance ~= 1 then
if not productEntries['ZZZZ'] then
productEntries['ZZZZ'] = {
item = '无',
requiredData = {},
quantity = quantityLabel,
priority = -1,
experience = "—"
}
end
local emptySegments = productEntries['ZZZZ'].requiredData
local existingCount = #emptySegments
if existingCount ~= 0 then
local currentRangeEnd = emptySegments[existingCount].rangeB
if not currentRangeEnd then
emptySegments[existingCount].rangeB = requiredPopulation - 1
end
end
table.insert(emptySegments,
{rangeA = requiredPopulation, priority = -1})
emptySlotNeeded = true
end
local evaluationOrder = utils.deepCopy(productOrder)
if emptySlotNeeded then table.insert(evaluationOrder, 'ZZZZ') end
for _, evaluationKey in ipairs(evaluationOrder) do
local segments = productEntries[evaluationKey].requiredData
local segmentIndex = #segments
local segmentPriority = segments[segmentIndex].priority or -1
if segmentPriority >= item.priority or evaluationKey == 'ZZZZ' then
local previousPopulation = requiredPopulation - 1
local rangeStart = segments[segmentIndex].rangeA
local rangeEnd = segments[segmentIndex].rangeB
if rangeStart <= previousPopulation then
if not rangeEnd and rangeStart <= previousPopulation then
segments[segmentIndex].rangeB = previousPopulation
end
local nextRangeEnd = nil
if previousPopulation + 1 == 10 then
nextRangeEnd = 10
end
if rangeEnd ~= 10 then
table.insert(segments, {
chance = nil,
rangeA = previousPopulation + 1,
rangeB = nextRangeEnd,
priority = segmentPriority
})
end
end
end
end
local priorSegmentIndex = #requirementSegments - 1
if priorSegmentIndex ~= 0 and
not requirementSegments[priorSegmentIndex].rangeB then
requirementSegments[priorSegmentIndex].rangeB =
requiredPopulation - 1
end
end
if emptySlotNeeded then table.insert(productOrder, 'ZZZZ') end
for _, entryKey in ipairs(productOrder) do
local segments = productEntries[entryKey].requiredData
local lastSegment = segments[#segments]
if lastSegment and not lastSegment.rangeB then
lastSegment.rangeB = maxPopulation - 1
end
end
local producedItemsClone = utils.deepCopy(producedItems)
for index, clone in ipairs(producedItemsClone) do clone.priority = index end
local totalItems = #producedItemsClone
local processedPopulations = {}
local lastRequired = -1
local lastChance = -1
local probabilityLayers = {}
local populationThresholds = {}
for _, clone in ipairs(producedItemsClone) do
table.insert(populationThresholds, clone.RequiredPopulation)
end
local uniqueThresholds = utils.uniqueValues(populationThresholds)
table.sort(uniqueThresholds, function(a, b) return a > b end)
for startIndex = 1, totalItems do
local values = {}
local priorChances = {}
local totalProbability = 0
local currentRequiredPopulation =
producedItemsClone[startIndex].RequiredPopulation
if not utils.tableContains(processedPopulations,
currentRequiredPopulation) or lastRequired ==
-1 then
lastRequired = currentRequiredPopulation
table.insert(processedPopulations, currentRequiredPopulation)
for i = 1, totalItems do
local item = producedItemsClone[i]
if currentRequiredPopulation >= item.RequiredPopulation and
lastChance ~= 1 then
lastChance = item.Chance
local availableProbability = 1
for _, previousChance in ipairs(priorChances) do
availableProbability =
availableProbability * (1 - previousChance)
end
local itemId = item.ItemId
local englishName = items.getEnglishNameById(itemId)
local minStack = item.MinStack ~= -1 and item.MinStack or 1
local maxStack = item.MaxStack ~= -1 and item.MaxStack or
minStack
local entryKey = (englishName or "") .. "_" .. minStack ..
"_" .. maxStack
table.insert(priorChances, item.Chance)
local exactValue = availableProbability * item.Chance * 100
table.insert(values, {id = entryKey, prob = exactValue})
totalProbability = totalProbability + exactValue
end
if lastChance == 1 then lastChance = -1 end
end
if totalProbability <= 99 then
table.insert(values,
{id = "ZZZZ", prob = 100 - totalProbability})
else
table.insert(values, {id = "ZZZZ", prob = 0})
end
probabilityLayers[currentRequiredPopulation] = values
end
end
local orderedProbabilityLayers = {}
for _, threshold in ipairs(uniqueThresholds) do
table.insert(orderedProbabilityLayers, probabilityLayers[threshold])
end
local mergedValues = {}
for _, values in ipairs(orderedProbabilityLayers) do
local aggregation = {}
for _, value in ipairs(values) do
if aggregation[value.id] then
aggregation[value.id].prob =
aggregation[value.id].prob + value.prob
else
aggregation[value.id] = {id = value.id, prob = value.prob}
end
end
local mergedLayer = {}
for _, mergedValue in pairs(aggregation) do
table.insert(mergedLayer, mergedValue)
end
table.insert(mergedValues, mergedLayer)
end
local finalMerged = {}
for index = #mergedValues, 1, -1 do
local layer = mergedValues[index]
for _, item in ipairs(layer) do
local entryKey = item.id
if finalMerged[entryKey] then
table.insert(finalMerged[entryKey], 1, item.prob)
else
finalMerged[entryKey] = {item.prob}
end
end
end
for _, entryKey in ipairs(productOrder) do
local probabilityIndex = 1
local deduplicated = {}
local seen = {}
local mergedProbabilities = finalMerged[entryKey] or {}
for _, probability in ipairs(mergedProbabilities) do
if not seen[probability] then
seen[probability] = true
table.insert(deduplicated, probability)
end
end
for index = #deduplicated, 1, -1 do
productEntries[entryKey].requiredData[probabilityIndex].probability =
deduplicated[index]
productEntries[entryKey].requiredData[probabilityIndex].priority =
nil
probabilityIndex = probabilityIndex + 1
end
end
local englishName = context.name:gsub(":", "")
local itemDesc = utils.expandTemplate("模板:Name",
{englishName, nil, class = "inline"}) or
nil
if utils.stringContains(itemDesc, "Blank") then itemDesc = nil end
return {
entries = productEntries,
order = productOrder,
finalMerged = finalMerged,
maxPopulation = maxPopulation,
iconName = iconName,
itemDesc = itemDesc
}
end
local function buildProductRows(productContext)
local rows = {}
local productEntries = productContext.entries or productContext.itemTable
local finalMerged = productContext.finalMerged
local productOrder = productContext.order or productContext.producesOrder
local maxPopulation = productContext.maxPopulation
local iconName = productContext.iconName
for rowIndex, entryKey in ipairs(productOrder) do
local productEntry = productEntries[entryKey]
local segmentCursor = 1
local mergedProbabilities = utils.uniqueValues(
finalMerged[entryKey] or {})
local startCount = 1
local startProbability = 0
local endCount = 10
local endProbability = 0
local coveredPopulation = 0
local firstElement = productEntry.item
if utils.stringContains(firstElement, "File:Roe.png") and iconName ~=
"Roe" then
firstElement = firstElement:gsub("File:Roe.png",
"File:" .. iconName .. ".png")
end
local rowSegments = {firstElement, entryKey}
for _, probability in ipairs(mergedProbabilities) do
local segment = productEntry.requiredData[segmentCursor]
if #rowSegments == 2 then
startProbability = segment.probability or 0
end
if #rowSegments == 2 and segment.rangeA ~= 1 then
startCount = segment.rangeA
local skippedPopulation = segment.rangeA - 1
coveredPopulation = coveredPopulation + skippedPopulation
table.insert(rowSegments, skippedPopulation)
table.insert(rowSegments, toPercentage("—", false, 1))
end
local segmentLength = segment.rangeB - segment.rangeA + 1
local probabilityValue = segment.probability
table.insert(rowSegments, segmentLength)
table.insert(rowSegments, toPercentage(probabilityValue, false, 1))
endCount = segment.rangeB
if probabilityValue ~= 0 then
endProbability = probabilityValue
end
segmentCursor = segmentCursor + 1
if segmentLength == 0 then
coveredPopulation = coveredPopulation + 1
end
coveredPopulation = coveredPopulation + segmentLength
end
if coveredPopulation ~= maxPopulation - 1 then
local segmentLength = #rowSegments
if segmentLength >= 3 then
if rowSegments[segmentLength - 1] == 0 then
rowSegments[segmentLength - 1] = 2
else
rowSegments[segmentLength - 1] =
rowSegments[segmentLength - 1] + maxPopulation - 1 -
coveredPopulation
end
end
end
local startValue = toPercentage((startCount * 0.08 + 0.15) *
startProbability / 100, true)
local endValue = toPercentage(
(endCount * 0.08 + 0.15) * endProbability / 100,
true)
local actualProbability
if startValue == endValue then
actualProbability = endValue .. "%"
else
local a = tonumber(startValue)
local b = tonumber(endValue)
if b < a then a, b = b, a end
actualProbability = a .. " ~ " .. b .. "%"
end
if entryKey == "ZZZZ" then actualProbability = "—" end
table.insert(rowSegments, actualProbability)
if productEntry.experience == "—" then
table.insert(rowSegments, "—")
else
table.insert(rowSegments, math.floor(productEntry.experience))
end
table.insert(rows,
{index = rowIndex, key = entryKey, segments = rowSegments})
end
return rows
end
-- ---------------------------------------------------------------------------
-- Public API
-- ---------------------------------------------------------------------------
function FishPond.getMaxPopulation(frame)
local context = ensureContext(frame)
if not context or not context.data then return '' end
local result = context.data['MaxPopulation'] or -1
if tonumber(result) == -1 then result = 10 end
return result or ''
end
function FishPond.getSpawnTime(frame)
local context = ensureContext(frame)
if not context or not context.data then return '' end
local spawnTime = context.data['SpawnTime']
if tonumber(spawnTime or -1) == -1 then return computeSpawnTime(context) end
return spawnTime
end
function FishPond.getPopulationMissionCount(frame)
local context = ensureContext(frame)
local opacityData = collectOpacityRows(context)
if not opacityData then return 0 end
return #opacityData.rows
end
function FishPond.getFishCount(frame)
local context = ensureContext(frame)
if not context then return '' end
local maxPopulation = FishPond.getMaxPopulation(frame)
if tonumber(maxPopulation) == 1 then return 1 end
local gates = FishPond.getPopulationGates(frame)
if type(gates) ~= 'table' then return '' end
local availablePopulation = tonumber(maxPopulation) or 0
for _, gate in pairs(gates) do
local gatePopulation = tonumber(gate.Population)
if gatePopulation and availablePopulation > gatePopulation then
availablePopulation = gatePopulation
end
end
if availablePopulation < 2 then return 1 end
return availablePopulation - 1
end
function FishPond.getColor(frame)
local context = ensureContext(frame)
if not context or not context.data then return '' end
local waterColors = context.data['WaterColor']
if not waterColors then return '' end
local totalCount = 0
local trueColor
local countRequired
local gateRequired
for _, colorInfo in pairs(waterColors) do
trueColor = colorInfo['Color'] and colorInfo['Color']:gsub(" ", ", ")
countRequired = colorInfo['MinPopulation']
gateRequired = colorInfo['MinUnlockedPopulationGate']
totalCount = totalCount + 1
end
if totalCount ~= 1 then return '' end
local first = ''
if tonumber(gateRequired) == 2 then first = '完成首个任务,并且' end
local ref = "(RGB 色值:" .. tostring(trueColor or '') .. ")"
return string.format(
"%s鱼塘内有至少 %s 条鱼时,鱼塘的颜色会变为 <span style=\"background-color: rgb(%s); border: 1px solid #202122; margin: 2px;\"> </span>%s。",
tostring(first or ''), tostring(countRequired or ''),
tostring(trueColor or ''), tostring(ref or ''))
end
function FishPond.getProducedItems(frame)
local context = ensureContext(frame)
if not context or not context.data or not context.data['ProducedItems'] then
return ''
end
local result = {}
for _, item in ipairs(context.data['ProducedItems']) do
table.insert(result, {
RequiredPopulation = item['RequiredPopulation'],
Chance = item['Chance'],
Condition = item['Condition'],
Id = item['Id'],
MinStack = item['MinStack'],
MaxStack = item['MaxStack']
})
end
return result
end
function FishPond.getPopulationGates(frame)
local context = ensureContext(frame)
if not context or not context.data or not context.data['PopulationGates'] then
return ''
end
local result = {}
for population, gates in pairs(context.data['PopulationGates']) do
table.insert(result, {Population = population, Gates = gates})
end
return result
end
function FishPond.debug(frame)
local output = {}
output['MaxPopulation'] = FishPond.getMaxPopulation(frame)
output['SpawnTime'] = FishPond.getSpawnTime(frame)
output['ProducedItems'] = FishPond.getProducedItems(frame)
output['PopulationGates'] = FishPond.getPopulationGates(frame)
local result = {}
for key, value in pairs(output) do
if type(value) == 'table' then
for _, item in ipairs(value) do
table.insert(result, key .. ': ' .. mw.text.jsonEncode(item))
end
else
table.insert(result, key .. ': ' .. tostring(value))
end
end
return table.concat(result, '\n')
end
function FishPond.getOpacityTable(frame)
local context = ensureContext(frame)
if not context then return '' end
local opacityData = collectOpacityRows(context)
if not opacityData then return '' end
local result = {}
for _, row in ipairs(opacityData.rows) do
table.insert(result,
string.format(
"<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
row.population - 1, row.nextPopulation, row.items,
row.exp))
end
return table.concat(result, "\n")
end
function FishPond.getOpacityTableAlt(frame)
local context = ensureContext(frame)
if not context then return '' end
local fishName = frame.args and frame.args[1]
local displayFishName = frame.args and frame.args[2]
local cacheKey = KEY_PREFIX .. "|getOpacityTableAlt|" .. (fishName or '') ..
"|" .. (displayFishName or '')
local cached = cache.get(cacheKey)
if cached then return cached end
local opacityData = collectOpacityRows(context)
if not opacityData then return '' end
if not displayFishName or displayFishName == '' then
displayFishName = utils.expandTemplate("模板:Name", {
context.name,
nil,
class = "inline"
})
end
local rowCount = #opacityData.rows
local result = {}
for index, row in ipairs(opacityData.rows) do
local prefix = ""
if index == 1 then
prefix = string.format(
"<tr><td rowspan=\"%s\">%s</td><td>%s</td><td>%s</td><td>%s</td><td rowspan=\"%s\">%s</td></tr>",
rowCount, displayFishName, row.population - 1,
row.nextPopulation, row.items, rowCount, "每 " ..
tostring(opacityData.spawnTime or '') .. " 天")
else
prefix = string.format("<tr><td>%s</td><td>%s</td><td>%s</td></tr>",
row.population - 1, row.nextPopulation,
row.items)
end
table.insert(result, prefix)
end
local content = table.concat(result, "\n")
cache.set(cacheKey, content, EXP_TIME)
return content
end
function FishPond.getProductTable(frame)
local context = ensureContext(frame)
if not context then return '' end
local productContext = prepareProducedItemContext(context)
if not productContext then return '' end
local rows = buildProductRows(productContext)
local itemDesc = productContext.itemDesc
local maxPopulation = productContext.maxPopulation
local headers = {}
for i = 1, (maxPopulation - 1) do
table.insert(headers,
string.format('<th data-sort-type="number">%d</th>', i))
end
local headersString = table.concat(headers)
local result = {
string.format(
'<table class="wikitable roundedborder sortable" style="text-align: center;"><tr><th rowspan="2" class="no-wrap">%s鱼塘产物</th><th colspan="%s" class="no-wrap">鱼的数量及对应概率</th><th rowspan="2" data-sort-type="number" class="no-wrap">实际概率</th><th rowspan="2" data-sort-type="number" class="no-wrap">钓鱼<br>经验值</th></tr><tr>%s</tr>',
itemDesc and (itemDesc .. "<br>") or "", maxPopulation - 1,
headersString)
}
for _, row in ipairs(rows) do
local concatenated = table.concat(row.segments, ",")
table.insert(result, generateRowLocal(concatenated or "无,无,无,无"))
end
table.insert(result, "</table>")
return table.concat(result, "\n")
end
function FishPond.getProductTableAlt(frame)
local context = ensureContext(frame)
if not context then return '' end
local fishName = frame.args and frame.args[1]
local displayFishName = frame.args and frame.args[2]
local cacheKey = KEY_PREFIX .. "|getProductTableAlt|" .. (fishName or '') ..
"|" .. (displayFishName or '')
local cached = cache.get(cacheKey)
if cached then return cached end
local productContext = prepareProducedItemContext(context)
if not productContext then return '' end
local rows = buildProductRows(productContext)
if not displayFishName or displayFishName == '' then
displayFishName = utils.expandTemplate("模板:Name", {
context.name,
nil,
class = "inline"
})
end
local productOrder = productContext.order or productContext.producesOrder
local result = {}
for index, row in ipairs(rows) do
local insertContent = generateRowLocal(
table.concat(row.segments, ",") or
"无,无,无,无")
if index == 1 then
insertContent = insertContent:gsub('<tr><td data',
'<tr><td rowspan="' ..
#productOrder .. '">' ..
displayFishName ..
'</td><td data')
end
table.insert(result, insertContent)
end
local content = table.concat(result, "\n")
cache.set(cacheKey, content, EXP_TIME)
return content
end
return FishPond

沪公网安备 31011002002714 号