打开/关闭菜单
331
1.7K
131
11.8K
星露谷物语扩展百科
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

模块:FishPond:修订间差异

来自星露谷物语扩展百科
Sizau留言 | 贡献
无编辑摘要
Sizau留言 | 贡献
无编辑摘要
 
(未显示同一用户的3个中间版本)
第1行: 第1行:
local cache = require "mw.ext.LuaCache"
local cache = require "mw.ext.LuaCache"
local KEY_PREFIX = "Module:Expanded/FishPond"
local KEY_PREFIX = "Module:FishPond"
local EXP_TIME = 172800
local EXP_TIME = 172800
local utils = require("Module:Utils")
local utils = require("Module:Utils")
local ID = require("Module:Expanded/ID")
local ID = require("Module:ID")
local Object = require("Module:Expanded/Object")
local Object = require("Module:Expanded/Object")
local ObjectCommon = require("Module:Object")
local ObjectCommon = require("Module:Object")
local Name = require("Module:Expanded/Name")
local Name = require("Module:Name")
local langlinks = require("Module:LangLinks")
local langlinks = require("Module:LangLinks")
local Items = require("Module:Items")
local Items = require("Module:Items")
local FishPondData = mw.loadData('Module:Expanded/FishPond/data')
local FishPondData = mw.loadData('Module:FishPond/data')


local p = {}
local p = {}
第397行: 第397行:
             local sname = english:gsub(":", "")
             local sname = english:gsub(":", "")
             mw.logObject(sname)
             mw.logObject(sname)
             table.insert(items, utils.expandTemplate("模板:Expanded/Name",{sname, quantity, class = "inline"}))
             table.insert(items, utils.expandTemplate("模板:Name",{sname, quantity, class = "inline"}))
         end
         end
         local itemsString
         local itemsString
第424行: 第424行:
     local displayFishName = frame.args[2]
     local displayFishName = frame.args[2]
      
      
    local cacheKey = KEY_PREFIX .. "|getOpacityTableAlt|" .. (fishName or "") .. "|" .. (displayFishName or "")
--  local cacheKey = KEY_PREFIX .. "|getOpacityTableAlt|" .. (fishName or "") .. "|" .. (displayFishName or "")
if (cache.get(cacheKey)) then
-- if (cache.get(cacheKey)) then
    local result = cache.get(cacheKey)
--  local result = cache.get(cacheKey)
    return result
--  return result
end
-- end
      
      
     local id = getIDSVE(fishName)
     local id = getIDSVE(fishName)
第492行: 第492行:


             local sname = english:gsub(":", "")
             local sname = english:gsub(":", "")
             table.insert(items, utils.expandTemplate("模板:Expanded/Name",{sname, quantity, class = "inline"}))
             table.insert(items, utils.expandTemplate("模板:Name",{sname, quantity, class = "inline"}))
         end
         end
         local itemsString
         local itemsString
第505行: 第505行:
         local exp = 20 + spawnTime * 5
         local exp = 20 + spawnTime * 5
         if displayFishName == "" or displayFishName == nil then
         if displayFishName == "" or displayFishName == nil then
         displayFishName = utils.expandTemplate("模板:Expanded/Name",{name, nil, class = "inline"})
         displayFishName = utils.expandTemplate("模板:Name",{name, nil, class = "inline"})
         end
         end
          
          
第529行: 第529行:
     end
     end
     content = table.concat(result, "\n")
     content = table.concat(result, "\n")
     cache.set(cacheKey, content, EXP_TIME)
     -- cache.set(cacheKey, content, EXP_TIME)
     return content
     return content
end
end
第660行: 第660行:
         if not itemTable[uniqueId] then
         if not itemTable[uniqueId] then
             itemTable[uniqueId] = {
             itemTable[uniqueId] = {
                 item = utils.expandTemplate("模板:Expanded/Name", { sname, quantityString, class = "inline" }),
                 item = utils.expandTemplate("模板:Name", { sname, quantityString, class = "inline" }),
                 requiredData = {},
                 requiredData = {},
                 quantity = quantityString,
                 quantity = quantityString,
第878行: 第878行:
     -- mw.logObject(itemTable)
     -- mw.logObject(itemTable)
     EN = EN:gsub(":", "")
     EN = EN:gsub(":", "")
     local itemDesc = utils.expandTemplate("模板:Expanded/Name",{EN, nil, class = "inline"}) or nil
     local itemDesc = utils.expandTemplate("模板:Name",{EN, nil, class = "inline"}) or nil
     if contains(itemDesc, "Blank") then itemDesc = nil end
     if contains(itemDesc, "Blank") then itemDesc = nil end
     local headers = {}
     local headers = {}
第1,004行: 第1,004行:
      
      
     local cacheKey = KEY_PREFIX .. "|getProductTableAlt|" .. (fishName or "") .. "|" .. (displayFishName or "")
     local cacheKey = KEY_PREFIX .. "|getProductTableAlt|" .. (fishName or "") .. "|" .. (displayFishName or "")
if (cache.get(cacheKey)) then
-- if (cache.get(cacheKey)) then
    local result = cache.get(cacheKey)
--  local result = cache.get(cacheKey)
    cache.delete(cacheKey)
--  cache.delete(cacheKey)
    -- return result
--  -- return result
end
-- end
     local id = getIDSVE(fishName)
     local id = getIDSVE(fishName)
第1,084行: 第1,084行:
         if not itemTable[uniqueId] then
         if not itemTable[uniqueId] then
             itemTable[uniqueId] = {
             itemTable[uniqueId] = {
                 item = utils.expandTemplate("模板:Expanded/Name", { sname, quantityString, class = "inline" }),
                 item = utils.expandTemplate("模板:Name", { sname, quantityString, class = "inline" }),
                 requiredData = {},
                 requiredData = {},
                 quantity = quantityString,
                 quantity = quantityString,
第1,306行: 第1,306行:
     -- mw.logObject(itemTable)
     -- mw.logObject(itemTable)
     EN = EN:gsub(":", "")
     EN = EN:gsub(":", "")
     local itemDesc = utils.expandTemplate("模板:Expanded/Name",{EN, nil, class = "inline"}) or nil
     local itemDesc = utils.expandTemplate("模板:Name",{EN, nil, class = "inline"}) or nil
     if contains(itemDesc, "Blank") then itemDesc = nil end
     if contains(itemDesc, "Blank") then itemDesc = nil end
      
      
第1,411行: 第1,411行:
         if sim == 1 then
         if sim == 1 then
         if displayFishName == "" or displayFishName == nil then
         if displayFishName == "" or displayFishName == nil then
         displayFishName = utils.expandTemplate("模板:Expanded/Name",{name, nil, class = "inline"})
         displayFishName = utils.expandTemplate("模板:Name",{name, nil, class = "inline"})
         end
         end
insertContent = insertContent:gsub('<tr><td data', '<tr><td rowspan="'.. #producesOrder ..'">' .. displayFishName .. '</td><td data')
insertContent = insertContent:gsub('<tr><td data', '<tr><td rowspan="'.. #producesOrder ..'">' .. displayFishName .. '</td><td data')
第1,419行: 第1,419行:
     end
     end
     content = table.concat(result, "\n")
     content = table.concat(result, "\n")
     cache.set(cacheKey, content, EXP_TIME)
     -- cache.set(cacheKey, content, EXP_TIME)
     return content
     return content
end
end


return p
return p

2026年1月19日 (一) 16:09的最新版本

本模块用于计算和输出鱼塘的“任务”和“产物”表格。

本模块针对 SVE 物品进行了特殊的兼容处理。

具体说明请见原模块模块:FishPond

[ 查看 | 编辑 | 历史 | 刷新 ]上述文档的内容来自模块:FishPond/doc
local cache = require "mw.ext.LuaCache"
local KEY_PREFIX = "Module:FishPond"
local EXP_TIME = 172800
local utils = require("Module:Utils")
local ID = require("Module:ID")
local Object = require("Module:Expanded/Object")
local ObjectCommon = require("Module:Object")
local Name = require("Module:Name")
local langlinks = require("Module:LangLinks")
local Items = require("Module:Items")
local FishPondData = mw.loadData('Module:FishPond/data')

local p = {}

local function generateRowLocal(inputString)
    local args = {}
    for part in string.gmatch(inputString, "([^,]+)") do
        table.insert(args, part)
    end
    
    local result = {}
    local i = 1
    table.insert(result, string.format('<td data-sort-value="%s">%s</td>', args[i + 1], args[i]))
    i = i + 2
    while i <= #args - 3 do
        local colspan = tonumber(args[i])
        local content = args[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>', args[i]))
    table.insert(result, string.format('<td>%s</td>', args[i + 1]))
    return "<tr>" .. table.concat(result) .. "</tr>"
end

function tablesEqual(t1, t2)
    if t1 == t2 then
        return true
    end
    if type(t1) ~= "table" or type(t2) ~= "table" then
        return false
    end
    for key, value in pairs(t1) do
    	if not tableContains(t2, value) then return false end
    end

    for key, value in pairs(t2) do
        if not tableContains(t1, value) then return false end
    end
    return true
end

function tablesEqual2(t1, t2)
    if t1 == t2 then
        return true
    end
    if type(t1) ~= "table" or type(t2) ~= "table" then
        return false
    end
    for key, value in pairs(t1) do
    	if tableContains(t2, value) then return true end
    end

    for key, value in pairs(t2) do
        if tableContains(t1, value) then return true end
    end
    return false
end

local function findFishData(fishName)
	if type(fishName) == "table" then
	    for _, fish in ipairs(FishPondData) do
	    	local requiredTags = fish['RequiredTags'] or {}
	    	if requiredTags == {} then return nil end
	    	if (tablesEqual(fishName, requiredTags)) then return fish end
	    end
	    for _, fish in ipairs(FishPondData) do
	    	local requiredTags = fish['RequiredTags'] or {}
	    	if requiredTags == {} then return nil end
	    	if (tablesEqual2(fishName, requiredTags)) then return fish end
	    end
	    return nil
	end
	
	
	
    local lowerFishName = string.lower(fishName):gsub(" ", "")
    for _, fish in ipairs(FishPondData) do
        if string.lower(fish['ID']):gsub(" ", "") == lowerFishName then
            return fish
        end
    end
    return nil
end

function getIDSVE(fishName)
	local id = ID.getId(fishName)
	if id then
		if id:sub(1, 3) == "(O)" then
	        id = id:sub(4)
	    end
		return id
	end
	return nil
end

-- =p.test{ args = { "小狗鱼"} }
function p.test(frame)
	local fishName = frame.args[1]
	mw.logObject(FishPondData)
	return getIDSVE(fishName)
end

-- =p.getMaxPopulation{ args = { "小狗鱼"} }
function p.getMaxPopulation(frame)
    local fishName = frame.args[1]
    local id = getIDSVE(fishName)
    if not id then
    	return ''
	end
    local name = id
    local fishData = findFishData(name)
    local tag
    if not fishData then
    	tag = Object.getAllFishTagById{args = {id}}
    	if tag then
    		fishData = findFishData(tag)
    	end
    	if not fishData then
        	return ''
        end
    end
    local result = -1
    -- mw.logObject(fishData)
    if fishData then
    	result = fishData['MaxPopulation']
	end
    if tonumber(result) == -1 then
    	result = 10
	end
    return result or 10
end

-- =p.getSpawnTime{ args = { "小狗鱼"} }
function p.getSpawnTime(frame)
    local fishName = frame.args[1]
    local id = getIDSVE(fishName)
    if not id then
    	return ''
	end
    local name = id
    local fishData = findFishData(name)
    local tag
    if not fishData then
    	tag = Object.getAllFishTagById{args = {id}}
    	if tag then
    		fishData = findFishData(tag)
    	end
    	if not fishData then
        	return ''
        end
    end
    local result = fishData and fishData['SpawnTime'] or '-1'
    if tonumber(result) == -1 then
	    local id = getIDSVE(fishName)
	    if not id then
	    	return -1
		end
    	local price = Object.getPriceById {args = { id }}
    	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
    return result
end

-- =p.getPopulationMissionCount{ args = { "小狗鱼"} }
function p.getPopulationMissionCount(frame)
    local Gates = p.getPopulationGates(frame)
    if Gates ~= nil then
    	if #Gates <=0 then
    		return 0
		end
    	return #Gates
    end
	return ''
end

-- =p.getFishCount{ args = { "小狗鱼"} }
function p.getFishCount(frame)
	local result = tonumber(p.getMaxPopulation(frame))
	if result == 1 then return 1 end
    local Gates = p.getPopulationGates(frame)
    for _, k in pairs(Gates) do
    	-- mw.log(k["Population"])
    	if result > tonumber(k["Population"]) then result = tonumber(k["Population"]) end
    end
	if result < 2 then return 1 end
	return result-1
end

-- =p.getColor{ args = { "岩浆鳗鱼"} }
function p.getColor(frame)
	local totalCount = 0
    local fishName = frame.args[1]
    local id = getIDSVE(fishName)
    if not id then
    	return ''
	end
    local name = id
    local fishData = findFishData(name)
    if not fishData or not fishData['WaterColor'] then
        return ''
    end
    local trueColor = ''
    local countRequired = 0
    local gateRequired = 0
    for _, k in pairs(fishData['WaterColor']) do
    	-- mw.logObject(k)
    	trueColor = k['Color']:gsub(" ", ", ")
    	countRequired = k['MinPopulation']
    	gateRequired = k['MinUnlockedPopulationGate']
    	totalCount = totalCount + 1
    end
    if totalCount ~= 1 then return '' end
    local first = ''
    if tonumber(gateRequired) == 2 then first = '完成首个任务,并且' end
    local ref = "(RGB 色值:".. trueColor ..")"
    return string.format(
        "%s鱼塘内有至少 %s 条鱼时,鱼塘的颜色会变为 <span style=\"background-color: rgb(%s); border: 1px solid #202122; margin: 2px;\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>%s。",
        tostring(first or ""),
        tostring(countRequired or ""),
        tostring(trueColor or ""),
        tostring(ref or "")
    )
end

-- mw.logObject(p.getProducedItems{ args = { "小狗鱼"} })
function p.getProducedItems(frame)
    local fishName = frame.args[1]
    local id = getIDSVE(fishName)
    if not id then
    	return ''
	end
    local name = id
    local fishData = findFishData(name)
    local tag
    if not fishData or not fishData['ProducedItems'] then
    	tag = Object.getAllFishTagById{args = {id}}
    	if tag then
    		fishData = findFishData(tag)
    	end
    	if not fishData then
        	return ''
        end
    end

    
    local result = {}
    for _, item in ipairs(fishData['ProducedItems']) do
        table.insert(result, {
            RequiredPopulation = item['RequiredPopulation'],
            Chance = item['Chance'],
            Condition = item['Condition'],
            Id = item['ItemID'],
            MinStack = item['MinQuantity'],
            MaxStack = item['MaxQuantity']
        })
    end
    return result
end

-- mw.logObject(p.getPopulationGates{ args = { "小狗鱼"} })
function p.getPopulationGates(frame)
    local fishName = frame.args[1]
    local id = getIDSVE(fishName)
    if not id then
    	return ''
	end
    local name = id
    local fishData = findFishData(name)
    local tag
    if not fishData or not fishData['PopulationGates'] then
    	tag = Object.getAllFishTagById{args = {id}}
    	if tag then
    		fishData = findFishData(tag)
    	end
    	if not fishData then
        	return ''
        end
    end
    
    local result = {}
    for population, gates in pairs(fishData['PopulationGates']) do
        table.insert(result, {
            Population = population,
            Gates = gates
        })
    end
    return result
end

-- =p.debug{ args = { "小狗鱼"} }
function p.debug(frame)
    local fishName = frame.args[1]
    local output = {}
    output['MaxPopulation'] = p.getMaxPopulation(frame)
    output['SpawnTime'] = p.getSpawnTime(frame)
    output['ProducedItems'] = p.getProducedItems(frame)
    output['PopulationGates'] = p.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

-- =p.getOpacityTable{ args = { "小狗鱼"} }
function p.getOpacityTable(frame)
    local fishName = frame.args[1]
    local id = getIDSVE(fishName)
    if not id then
    	return ''
	end
    local name = id
    local fishData = findFishData(name)
    local tag
    if not fishData or not fishData['PopulationGates'] then
    	tag = Object.getAllFishTagById{args = {id}}
    	if tag then
    		fishData = findFishData(tag)
    	end
    	if not fishData then
        	return ''
        end
    end
	local result = {}
    local maxPopulation = fishData['MaxPopulation'] or 11
    if tonumber(maxPopulation) == -1 then
    	maxPopulation = 11
    end
    local populationGates = fishData['PopulationGates']
	local sortedGates = {}
	if tag == "fish_legendary" then
		-- mw.logObject(fishData)
		-- mw.logObject(populationGates)
		return ''
	end
	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)
    for i, gate in ipairs(sortedGates) do
        local population = gate.Population
        local nextPopulation = (i < #sortedGates) and sortedGates[i + 1].Population - 1 or tonumber(maxPopulation) - 1
        local items = {}
        for _, gateItem in ipairs(gate.Gates) do
            local item, quantity = gateItem:match("^(%S+) (%S+)%s*(%S*)$")

			if not item then
			    item = gateItem
			    quantity = 1
			elseif quantity == "" then
			    quantity = item
			    item = gateItem
			elseif quantity ~= "" and quantity:find("~") then
			    quantity = quantity
			end

            -- english = English.english{args = { "(O)" .. item }}
            -- if not english then
            -- 	english = langlinks.getLangLink(item)
        	-- end

			local english = Items.getEnglishNameById("(O)" .. item)
			if not english or english == '' then
				english = langlinks.getLangLink(item)
			end
			if not english or english == '' then
				english = Object.getFieldsById { args = { item } }["Name"]
			end
			
            local sname = english:gsub(":", "")
            mw.logObject(sname)
            table.insert(items, utils.expandTemplate("模板:Name",{sname, quantity, class = "inline"}))
        end
        local itemsString
        if #items == 1 then
            itemsString = items[1]
        elseif #items == 2 then
            itemsString = items[1] .. "或" .. items[2]
        else
            itemsString = table.concat(items, "、", 1, #items - 1) .. "或" .. items[#items]
        end
        local exp = 20 + p.getSpawnTime(frame) * 5
        table.insert(result, string.format(
		    "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
		    population - 1,
		    nextPopulation,
		    itemsString,
		    exp
		))
    end
    return table.concat(result, "\n")
end

-- =p.getOpacityTableAlt{ args = { "小狗鱼", "测试"} }
function p.getOpacityTableAlt(frame)
    local fishName = frame.args[1]
    local displayFishName = frame.args[2]
    
 --   local cacheKey = KEY_PREFIX .. "|getOpacityTableAlt|" .. (fishName or "") .. "|" .. (displayFishName or "")
	-- if (cache.get(cacheKey)) then
 --   	local result = cache.get(cacheKey)
 --   	return result
	-- end
    
    local id = getIDSVE(fishName)
    if not id then
    	return ''
	end
    local name = id
    local fishData = findFishData(name)
    local tag
    if not fishData or not fishData['PopulationGates'] then
    	tag = Object.getAllFishTagById{args = {id}}
    	if tag then
    		fishData = findFishData(tag)
    	end
    	if not fishData then
        	return ''
        end
    end
	local result = {}
    local maxPopulation = fishData['MaxPopulation'] or 11
    if tonumber(maxPopulation) == -1 then
    	maxPopulation = 11
    end
    local populationGates = fishData['PopulationGates']
	local sortedGates = {}
	if tag == "fish_legendary" then
		return ''
	end
	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)
	local rowCount = #sortedGates
    for i, gate in ipairs(sortedGates) do
        local population = gate.Population
        local nextPopulation = (i < #sortedGates) and sortedGates[i + 1].Population - 1 or tonumber(maxPopulation) - 1
        local items = {}
        for _, gateItem in ipairs(gate.Gates) do
            local item, quantity = gateItem:match("^(%S+) (%S+)%s*(%S*)$")

			if not item then
			    item = gateItem
			    quantity = 1
			elseif quantity == "" then
			    quantity = item
			    item = gateItem
			elseif quantity ~= "" and quantity:find("~") then
			    quantity = quantity
			end

            -- english = English.english{args = { "(O)" .. item }}
            -- if not english then
            -- 	english = langlinks.getLangLink(item)
        	-- end

			local english = Items.getEnglishNameById("(O)" .. item)
			if not english or english == '' then
				english = langlinks.getLangLink(item)
			end
			if not english or english == '' then
				english = Object.getFieldsById { args = { item } }["Name"]
			end

            local sname = english:gsub(":", "")
            table.insert(items, utils.expandTemplate("模板:Name",{sname, quantity, class = "inline"}))
        end
        local itemsString
        if #items == 1 then
            itemsString = items[1]
        elseif #items == 2 then
            itemsString = items[1] .. "或" .. items[2]
        else
            itemsString = table.concat(items, "、", 1, #items - 1) .. "或" .. items[#items]
        end
        local spawnTime = p.getSpawnTime(frame)
        local exp = 20 + spawnTime * 5
        if displayFishName == "" or displayFishName == nil then
        	displayFishName = utils.expandTemplate("模板:Name",{name, nil, class = "inline"})
        end
        
        if i == 1 then
			table.insert(result, string.format(
			    "|-\n|rowspan=\"%s\"|%s\n|%s\n|%s\n|%s\n|rowspan=\"%s\"|%s",
			    tostring(rowCount or ""),
			    tostring(displayFishName or ""),
			    tostring((population - 1) or ""),
			    tostring(nextPopulation or ""),
			    tostring(itemsString or ""),
			    tostring(rowCount or ""),
			    tostring("每 ".. (spawnTime or "") .. " 天")
			))
        else
			table.insert(result, string.format(
			    "|-\n|%s\n|%s\n|%s",
			    tostring((population - 1) or ""),
			    tostring(nextPopulation or ""),
			    tostring(itemsString or "")
			))
    	end
    end
    content = table.concat(result, "\n")
    -- cache.set(cacheKey, content, EXP_TIME)
    return content
end

function toPercentage(number, disabled, multiplier, formatter)
	if number == "/" then return "/" end
	if number == "&nbsp;" then return "&nbsp;" end
	if number == "—" then return "—" end
	if multiplier == nil then multiplier = 100 end
	if formatter == nil then formatter = "%.1f" end -- %.2f
    local formatted = string.format(formatter, tonumber(number) * multiplier)
    formatted = formatted:gsub("%.00$", ""):gsub("%.0$", ""):gsub("%.([1-9])0$", ".%1")
    if disabled == true then
    	return formatted
	end
    return formatted .. "%"
end

local function deepcopy(original)
    local copy = {}
    for key, value in pairs(original) do
        if type(value) == "table" then
            copy[key] = deepcopy(value)  -- recursively copy nested tables
        else
            copy[key] = value
        end
    end
    return copy
end

function tableContains(table, element)
    for index, value in ipairs(table) do
        if value == element then
            return true
        end
    end
    return false
end

local function fileExists(filename)
    local title = mw.title.new("File:" .. filename)
    return title and title.exists
end

local function contains(text, substring)
    return string.find(text, substring, 1, true) ~= nil
end

-- =p.getProductTable{ args = { "鲳鱼"} }
-- =p.getProductTable{ args = { "小狗鱼"} }
function p.getProductTable(frame)
    local fishName = frame.args[1]
    local id = getIDSVE(fishName)

    if not id then
    	return ''
	end
    local name = Object.getFieldsById { args = { id } }["Name"]
    local EN = name
    local base_price = 30 + Object.getPriceById {args = { id }} * 0.5
    local promised_name = Object.getColorById{args = {id}} .. " Roe" or "Roe"
    if not fileExists(promised_name..".png") then
    	promised_name = "Roe"
	end

    local fishData = findFishData(id)
    -- mw.logObject(name)
    -- mw.logObject(fishData)
    local tag
    if not fishData or not fishData['ProducedItems'] then
        tag = Object.getAllFishTagById { args = { id } }
        if tag then
            fishData = findFishData(tag)
        end
        if not fishData then
            return ''
        end
    end
	if tag == "fish_legendary" then
        return ''
	end
	
    local maxPopulation = fishData['MaxPopulation'] or 11
    if maxPopulation == "-1" or maxPopulation == -1 then
        maxPopulation = 11
    end
    local producedItems = fishData['ProducedItems']
    local itemTable = {}
    local producesOrder = {}
    local sortedItems = {}
	for i, item in pairs(producedItems) do
		local item2 = deepcopy(item)
		item2["priority"] = i
        table.insert(sortedItems, { RequiredPopulation = tonumber(item.RequiredPopulation), Chance = item2.Chance, item = item2 })
    end
    table.sort(sortedItems, function(a, b) return a.RequiredPopulation < b.RequiredPopulation end)
	local lastUniqueId = ""
	local isZZZZ = false
    for i, item2 in pairs(sortedItems) do
    	local item = item2.item
        local population = item.RequiredPopulation > 0 and item.RequiredPopulation or 1
        local itemId = item.ItemID
        local cleanId = itemId
		-- if itemId:sub(1, 3) == "(O)" then
	 --       cleanId = itemId:sub(4)
		-- end
		local price
		price = Object.getPriceById {args = { cleanId }}
		if not price then
			price = ObjectCommon.getPriceById {args = { tostring(cleanId) }}
		end
		
		if cleanId == "812" then price = base_price end
		local experience = 10 + price * 0.04
		
        local english = Items.getEnglishNameById("(O)" .. itemId)
        if not english or english == '' then
        	english = langlinks.getLangLink(itemId)
        end
        if not english or english == '' then
        	english = Object.getFieldsById { args = { itemId } }["Name"]
    	end
		
        local minStack = item.MinQuantity ~= -1 and item.MinQuantity or 1
        local maxStack = item.MaxQuantity ~= -1 and item.MaxQuantity or minStack
        local uniqueId = english .. "_" .. minStack .. "_" .. maxStack
        local quantityString = minStack == maxStack and tostring(minStack) or minStack .. "~" .. maxStack
		local priorityN = item.priority
		local sname = english:gsub(":", "")
        if not itemTable[uniqueId] then
            itemTable[uniqueId] = {
                item = utils.expandTemplate("模板:Name", { sname, quantityString, class = "inline" }),
                requiredData = {},
                quantity = quantityString,
                priority = priorityN,
                experience = experience or 0
            }
            table.insert(producesOrder, uniqueId)
        end

        if population == 10 then
	        table.insert(itemTable[uniqueId].requiredData, {
	            rangeA = population,
	            rangeB = population,
                priority = priorityN
	        })
        else
        	table.insert(itemTable[uniqueId].requiredData, {
	            rangeA = population,
                priority = priorityN
	        })
        end
        local producesCount = #producesOrder
        
        if producesCount == 1 and item.Chance ~= 1 then
        	if itemTable['ZZZZ'] == nil then
	            itemTable['ZZZZ'] = {
	                item = '无',
	                requiredData = {},
	                quantity = quantityString,
	                priority = -1,
	                experience = "—"
	            }
        	end
        	local count = #itemTable['ZZZZ'].requiredData
        	if count~=0 then
        		local rangeB = itemTable['ZZZZ'].requiredData[count].rangeB
        		if rangeB == nil then itemTable['ZZZZ'].requiredData[count].rangeB = population - 1 end
        	end
        	table.insert(itemTable['ZZZZ'].requiredData, {
	            rangeA = population,
                priority = -1
	        })
	        isZZZZ = true
        end
        local tempProducesOrder = deepcopy(producesOrder)
        if isZZZZ == true then table.insert(tempProducesOrder, 'ZZZZ') end
	    for i, k in ipairs(tempProducesOrder) do
	    	local count = #itemTable[k].requiredData
	    	local priorityM = itemTable[k].requiredData[count].priority or nil
	    	if priorityM == nil then priorityM = -1 end
	    	if priorityM >= item.priority or k == "ZZZZ" then -- priorityM >= item.priority - 1
		    	local pop = population - 1
		    	local rangeA = itemTable[k].requiredData[count].rangeA
		    	local rangeB = itemTable[k].requiredData[count].rangeB
		    	if rangeA <= pop then
			    	local newChance = nil
					if rangeB == nil and rangeA <= pop then
						itemTable[k].requiredData[count].rangeB = pop
					end
					local newRangeB = nil
					if pop + 1 == 10 then newRangeB = 10 end
					if rangeB ~= 10 then
						table.insert(itemTable[k].requiredData, {
				            chance = newChance,
				            rangeA = pop + 1,
				            rangeB = newRangeB,
				            priority = priorityM
				        })
					end
		    	end
	    	end
	    end
        local count2 = #itemTable[uniqueId].requiredData - 1
        if count2 ~= 0 and itemTable[uniqueId].requiredData[count2].rangeB == nil then
        	itemTable[uniqueId].requiredData[count2].rangeB = population - 1
        end
    end
    if isZZZZ == true then table.insert(producesOrder, 'ZZZZ') end
    local producesCount = #producesOrder
    for _, k in ipairs(producesOrder) do
    	local v = itemTable[k]
    	local count3 = #itemTable[k].requiredData
    	if itemTable[k].requiredData[count3].rangeB == nil then
        	itemTable[k].requiredData[count3].rangeB = maxPopulation - 1
        end
    end
	local allValues = {}
	local producedItemsLength = 0
	local producedItems2 = deepcopy(producedItems)
	for i in pairs(producedItems2) do
	    producedItems2[i]["priority"] = i
	end
	for _ in pairs(producedItems2) do
	    producedItemsLength = producedItemsLength + 1
	end
	local lastRequired2 = -1
	local lastChance = -1
	local valuesDone = {}
	local common = {}
	local seen = {}
	for i = 1, producedItemsLength do
        local item = producedItems2[i]
        table.insert(common, item.RequiredPopulation)
	end
	local z = 1
	while z <= #common do
	    local value = common[z]
	    if seen[value] then
	        table.remove(common, z)
	    else
	        seen[value] = true
	        z = z + 1
	    end
	end
	table.sort(common, function(a, b) return a > b end)
	for startIndex = 1, producedItemsLength do
	    local values = {}
	    local probs = {}
	    local sum = 0
	    local currentRequiredPopulation = producedItems2[startIndex].RequiredPopulation
	    local currentPriority = producedItems2[startIndex].priority
	    if not tableContains(valuesDone, currentRequiredPopulation) or lastRequired2 == -1 then
	        lastRequired2 = currentRequiredPopulation
	        table.insert(valuesDone, currentRequiredPopulation)
	        local everTrue = false
	        for i = 1, producedItemsLength do
	            local item = producedItems2[i]
	            if currentRequiredPopulation >= item.RequiredPopulation and lastChance ~= 1 then
					lastChance = item.Chance
		            local prob = 1
		            for _, j in pairs(probs) do
		                prob = prob * (1 - j)
		            end
		            local itemId2 = item.ItemID
		            local english2 = Items.getEnglishNameById("(O)" .. itemId2)
		            if not english2 or english == '' then
			        	english2 = langlinks.getLangLink(itemId2)
		            end
			    	if not english2 or english2 == '' then
			        	english2 = Object.getFieldsById { args = { itemId2 } }["Name"]
			    	end
		            local minStack2 = item.MinQuantity ~= -1 and item.MinQuantity or 1
		            local maxStack2 = item.MaxQuantity ~= -1 and item.MaxQuantity or minStack2
		            local uniqueId2 = english2 .. "_" .. minStack2 .. "_" .. maxStack2
		            table.insert(probs, item.Chance)
		            local exactValue = prob * item.Chance * 100
		            if exactValue == 0 then
		                uniqueId2 = "ZZZZ"
		            end
		            table.insert(values,  {id = uniqueId2, prob = exactValue})
		            sum = sum + exactValue
	            end
	            if lastChance == 1 then
	            	lastChance = -1
	        	end
	        end
	        if sum <= 99 then
	            table.insert(values, {id = "ZZZZ", prob = 100 - sum})
	        end
			allValues[currentRequiredPopulation] = values
	    end
	end
	local allValuesTrue = {}
	for _, j in pairs(common) do
		table.insert(allValuesTrue, allValues[j])
	end
	allValues = allValuesTrue
	local mergedValues = {}
	for _, values in ipairs(allValues) do
	    local tempDict = {}
	    for _, value in ipairs(values) do
	        if tempDict[value.id] then
	            tempDict[value.id].prob = tempDict[value.id].prob + value.prob
	        else
	            tempDict[value.id] = {id = value.id, prob = value.prob}
	        end
	    end
	
	    local mergedLayer = {}
	    for _, mergedValue in pairs(tempDict) do
	        table.insert(mergedLayer, mergedValue)
	    end
	    table.insert(mergedValues, mergedLayer)
	end
	
	local finalMerged = {}
	for i = #mergedValues, 1, -1 do
	    local layer = mergedValues[i]
	    for _, item in ipairs(layer) do
	        local id = item.id
	        local prob = item.prob
	        if finalMerged[id] then
	            table.insert(finalMerged[id], 1, prob)
	        else
	            finalMerged[id] = {prob}
	        end
	    end
	end
    for i, k in ipairs(producesOrder) do
		local v = itemTable[k]
		local count3 = #itemTable[k].requiredData
		local counting2 = 1
		local test = {}
		local test2 = {}
		for _, x in pairs(finalMerged[k]) do
			if not tableContains(test2, x) then
				table.insert(test2, x)
				table.insert(test, x)
			end
		end
		for j = #test, 1, -1 do
			itemTable[k].requiredData[counting2]["probability"] = test[j]
			itemTable[k].requiredData[counting2]["priority"] = nil
			counting2 = counting2 + 1
		end
    end
    -- mw.logObject(itemTable)
    EN = EN:gsub(":", "")
    local itemDesc = utils.expandTemplate("模板:Name",{EN, nil, class = "inline"}) or nil
    if contains(itemDesc, "Blank") then itemDesc = nil end
    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 _, k in ipairs(producesOrder) do
    	local v = itemTable[k]
    	local count3 = #itemTable[k].requiredData
    	local counting2 = 1
    	local test = {}
		local test2 = {}
		local final = ""
		for _, x in pairs(finalMerged[k]) do
			if not tableContains(test2, x) then
				table.insert(test2, x)
				table.insert(test, x)
			end
		end
		local start = 1
		local startProb = 0
		local endCount = 10
		local endProb = 0
		local totalLength = 0
		local last1 = ''
		local last2 = ''
		local firstElement = v.item
		if contains(firstElement, "File:Roe.png") and promised_name ~= "Roe" then
			firstElement = firstElement:gsub("File:Roe.png", "File:" .. promised_name .. ".png")
		end
		local smallTable = {firstElement, k}
		for j = 1, #test do
			local x = itemTable[k].requiredData[counting2]
			if j == 1 then
				startProb = x.probability
			end
			if j == 1 and x.rangeA ~= 1 then
				start = x.rangeA
				local length2 = x.rangeA - 1
				totalLength = totalLength + length2
				local prob2 = "—" -- / 
				table.insert(smallTable, length2)
				table.insert(smallTable, toPercentage(prob2, false, 1))
				-- if final == "" then final = length2 else final = final .. "," .. length2 end
				-- final = final .. "," .. prob2
			end
			
			local length = x.rangeB - x.rangeA +1
			local prob = x.probability
			table.insert(smallTable, length)
			table.insert(smallTable, toPercentage(prob, false, 1))
			-- if final == "" then final = length else final = final .. "," .. length end
			-- final = final .. "," .. prob
			endCount = x.rangeB
			if x.probability ~= 0 then
				endProb = x.probability
			end
			counting2 = counting2 + 1
			if length == 0 then totalLength = totalLength + 1 end
			totalLength = totalLength + length
			
		end
		if totalLength ~= maxPopulation - 1 then
			local smallTableL = #smallTable
			if smallTableL >= 3 then
				-- mw.log(smallTable[smallTableL])
				if smallTable[smallTableL-1] == 0 then
					smallTable[smallTableL-1] = 2
				else
					if true then -- smallTable[smallTableL] == "0%"
						-- smallTable[smallTableL-1] = smallTable[smallTableL-1] + 1
						smallTable[smallTableL-1] = smallTable[smallTableL-1] + maxPopulation - 1 - totalLength
					else
						-- mw.log("maxPopulation - 1", maxPopulation - 1, "totalLength", totalLength)
						table.insert(smallTable, maxPopulation - 1 - totalLength)
						table.insert(smallTable, toPercentage(0))
					end
				end
				-- mw.log(smallTable[smallTableL-1],smallTable[smallTableL])
				-- if smallTable[smallTableL -1 ]
			end
		end
		-- mw.log(start, endCount)

		
		local cal1 = toPercentage((start * 0.08 + 0.15) * startProb / 100, true)
		local cal2 = toPercentage((endCount * 0.08 + 0.15) * endProb / 100, true)
		local calString = ""
		if cal1 == cal2 then
			calString = cal2 .. "%"
		else
			if cal2 < cal1 then
				cal1, cal2 = cal2, cal1
			end
			calString = cal1 .. " ~ " .. cal2 .. "%"
		end
		if k == "ZZZZ" then calString = "—" end
		table.insert(smallTable, calString)
		if v.experience == "—" then
			table.insert(smallTable, "—")
		else
			table.insert(smallTable, math.floor(v.experience))
		end
		final = table.concat(smallTable, ",")
		-- mw.log(final)
		table.insert(result, generateRowLocal(final or "无,无,无,无"))
	
    end
    table.insert(result, "</table>")
    return table.concat(result, "\n")
end

-- =p.getProductTableAlt{ args = { "小狗鱼"} }
function p.getProductTableAlt(frame)
    local fishName = frame.args[1]
    local displayFishName = frame.args[2]
    
    local cacheKey = KEY_PREFIX .. "|getProductTableAlt|" .. (fishName or "") .. "|" .. (displayFishName or "")
	-- if (cache.get(cacheKey)) then
 --   	local result = cache.get(cacheKey)
 --   	cache.delete(cacheKey)
 --   	-- return result
	-- end
	
    local id = getIDSVE(fishName)
    if not id then
    	return ''
	end
    local name = Object.getFieldsById { args = { id } }["Name"]
    local EN = name
    local base_price = 30 + Object.getPriceById {args = { id }} * 0.5
    local promised_name = Object.getColorById{args = {id}} .. " Roe" or "Roe"
    if not fileExists(promised_name..".png") then
    	promised_name = "Roe"
	end

    local fishData = findFishData(id)
    local tag
    if not fishData or not fishData['ProducedItems'] then
        tag = Object.getAllFishTagById { args = { id } }
        if tag then
            fishData = findFishData(tag)
        end
        if not fishData then
            return ''
        end
    end
	if tag == "fish_legendary" then
        return ''
	end
	
    local maxPopulation = fishData['MaxPopulation'] or 11
    if maxPopulation == "-1" or maxPopulation == -1 then
        maxPopulation = 11
    end
    local producedItems = fishData['ProducedItems']
    local itemTable = {}
    local producesOrder = {}
    local sortedItems = {}
	for i, item in pairs(producedItems) do
		local item2 = deepcopy(item)
		item2["priority"] = i
        table.insert(sortedItems, { RequiredPopulation = tonumber(item.RequiredPopulation), Chance = item2.Chance, item = item2 })
    end
    table.sort(sortedItems, function(a, b) return a.RequiredPopulation < b.RequiredPopulation end)
	local lastUniqueId = ""
	local isZZZZ = false
    for i, item2 in pairs(sortedItems) do
    	local item = item2.item
        local population = item.RequiredPopulation > 0 and item.RequiredPopulation or 1
        local itemId = item.ItemID
        local cleanId = itemId
		-- if itemId:sub(1, 3) == "(O)" then
	 --       cleanId = itemId:sub(4)
		-- end
		local price
		price = Object.getPriceById {args = { cleanId }}
		if not price then
			price = ObjectCommon.getPriceById {args = { tostring(cleanId) }}
		end
		if tostring(cleanId) == "812" then price = base_price end
		

		
		local experience = 10 + price * 0.04
		
        local english = Items.getEnglishNameById("(O)" .. itemId)
        if not english then
        	english = langlinks.getLangLink(itemId)
    	end
        local minStack = item.MinQuantity ~= -1 and item.MinQuantity or 1
        local maxStack = item.MaxQuantity ~= -1 and item.MaxQuantity or minStack
        local uniqueId = english .. "_" .. minStack .. "_" .. maxStack
        local quantityString = minStack == maxStack and tostring(minStack) or minStack .. "~" .. maxStack
		local priorityN = item.priority
		local sname = english:gsub(":", "")
        if not itemTable[uniqueId] then
            itemTable[uniqueId] = {
                item = utils.expandTemplate("模板:Name", { sname, quantityString, class = "inline" }),
                requiredData = {},
                quantity = quantityString,
                priority = priorityN,
                experience = experience or 0
            }
            table.insert(producesOrder, uniqueId)
        end

        if population == 10 then
	        table.insert(itemTable[uniqueId].requiredData, {
	            rangeA = population,
	            rangeB = population,
                priority = priorityN
	        })
        else
        	table.insert(itemTable[uniqueId].requiredData, {
	            rangeA = population,
                priority = priorityN
	        })
        end
        local producesCount = #producesOrder
        
        if producesCount == 1 and item.Chance ~= 1 then
        	if itemTable['ZZZZ'] == nil then
	            itemTable['ZZZZ'] = {
	                item = '无',
	                requiredData = {},
	                quantity = quantityString,
	                priority = -1,
	                experience = "—"
	            }
        	end
        	local count = #itemTable['ZZZZ'].requiredData
        	if count~=0 then
        		local rangeB = itemTable['ZZZZ'].requiredData[count].rangeB
        		if rangeB == nil then itemTable['ZZZZ'].requiredData[count].rangeB = population - 1 end
        	end
        	table.insert(itemTable['ZZZZ'].requiredData, {
	            rangeA = population,
                priority = -1
	        })
	        isZZZZ = true
        end
        local tempProducesOrder = deepcopy(producesOrder)
        if isZZZZ == true then table.insert(tempProducesOrder, 'ZZZZ') end
	    for i, k in ipairs(tempProducesOrder) do
	    	local count = #itemTable[k].requiredData
	    	local priorityM = itemTable[k].requiredData[count].priority or nil
	    	if priorityM == nil then priorityM = -1 end
	    	if priorityM >= item.priority or k == "ZZZZ" then -- priorityM >= item.priority - 1
		    	local pop = population - 1
		    	local rangeA = itemTable[k].requiredData[count].rangeA
		    	local rangeB = itemTable[k].requiredData[count].rangeB
		    	if rangeA <= pop then
			    	local newChance = nil
					if rangeB == nil and rangeA <= pop then
						itemTable[k].requiredData[count].rangeB = pop
					end
					local newRangeB = nil
					if pop + 1 == 10 then newRangeB = 10 end
					if rangeB ~= 10 then
						table.insert(itemTable[k].requiredData, {
				            chance = newChance,
				            rangeA = pop + 1,
				            rangeB = newRangeB,
				            priority = priorityM
				        })
					end
		    	end
	    	end
	    end
        local count2 = #itemTable[uniqueId].requiredData - 1
        if count2 ~= 0 and itemTable[uniqueId].requiredData[count2].rangeB == nil then
        	itemTable[uniqueId].requiredData[count2].rangeB = population - 1
        end
    end
    if isZZZZ == true then table.insert(producesOrder, 'ZZZZ') end
    local producesCount = #producesOrder
    for _, k in ipairs(producesOrder) do
    	local v = itemTable[k]
    	local count3 = #itemTable[k].requiredData
    	if itemTable[k].requiredData[count3].rangeB == nil then
        	itemTable[k].requiredData[count3].rangeB = maxPopulation - 1
        end
    end
	local allValues = {}
	local producedItemsLength = 0
	local producedItems2 = deepcopy(producedItems)
	for i in pairs(producedItems2) do
	    producedItems2[i]["priority"] = i
	end
	for _ in pairs(producedItems2) do
	    producedItemsLength = producedItemsLength + 1
	end
	local lastRequired2 = -1
	local lastChance = -1
	local valuesDone = {}
	local common = {}
	local seen = {}
	local result = {}
	for i = 1, producedItemsLength do
        local item = producedItems2[i]
        table.insert(common, item.RequiredPopulation)
	end
	local z = 1
	while z <= #common do
	    local value = common[z]
	    if seen[value] then
	        table.remove(common, z)
	    else
	        seen[value] = true
	        z = z + 1
	    end
	end
	table.sort(common, function(a, b) return a > b end)
	for startIndex = 1, producedItemsLength do
	    local values = {}
	    local probs = {}
	    local sum = 0
	    local currentRequiredPopulation = producedItems2[startIndex].RequiredPopulation
	    local currentPriority = producedItems2[startIndex].priority
	    if not tableContains(valuesDone, currentRequiredPopulation) or lastRequired2 == -1 then
	        lastRequired2 = currentRequiredPopulation
	        table.insert(valuesDone, currentRequiredPopulation)
	        local everTrue = false
	        for i = 1, producedItemsLength do
	            local item = producedItems2[i]
	            if currentRequiredPopulation >= item.RequiredPopulation and lastChance ~= 1 then
					lastChance = item.Chance
		            local prob = 1
		            for _, j in pairs(probs) do
		                prob = prob * (1 - j)
		            end
		            local itemId2 = item.ItemID
		            local english2 = Items.getEnglishNameById("(O)" .. itemId2)
		            mw.logObject(itemId2)
		            if not english2 then
			        	english2 = langlinks.getLangLink(itemId2)
			    	end
		            local minStack2 = item.MinQuantity ~= -1 and item.MinQuantity or 1
		            local maxStack2 = item.MaxQuantity ~= -1 and item.MaxQuantity or minStack2
		            local uniqueId2 = english2 .. "_" .. minStack2 .. "_" .. maxStack2
		            table.insert(probs, item.Chance)
		            local exactValue = prob * item.Chance * 100
		            if exactValue == 0 then
		                uniqueId2 = "ZZZZ"
		            end
		            table.insert(values,  {id = uniqueId2, prob = exactValue})
		            sum = sum + exactValue
	            end
	            if lastChance == 1 then
	            	lastChance = -1
	        	end
	        end
	        if sum <= 99 then
	            table.insert(values, {id = "ZZZZ", prob = 100 - sum})
	        end
			allValues[currentRequiredPopulation] = values
	    end
	end
	local allValuesTrue = {}
	for _, j in pairs(common) do
		table.insert(allValuesTrue, allValues[j])
	end
	allValues = allValuesTrue
	local mergedValues = {}
	for _, values in ipairs(allValues) do
	    local tempDict = {}
	    for _, value in ipairs(values) do
	        if tempDict[value.id] then
	            tempDict[value.id].prob = tempDict[value.id].prob + value.prob
	        else
	            tempDict[value.id] = {id = value.id, prob = value.prob}
	        end
	    end
	
	    local mergedLayer = {}
	    for _, mergedValue in pairs(tempDict) do
	        table.insert(mergedLayer, mergedValue)
	    end
	    table.insert(mergedValues, mergedLayer)
	end
	
	local finalMerged = {}
	for i = #mergedValues, 1, -1 do
	    local layer = mergedValues[i]
	    for _, item in ipairs(layer) do
	        local id = item.id
	        local prob = item.prob
	        if finalMerged[id] then
	            table.insert(finalMerged[id], 1, prob)
	        else
	            finalMerged[id] = {prob}
	        end
	    end
	end
	-- if true then
	-- 	mw.logObject(itemTable)
	-- 		mw.logObject(producesOrder)
	-- 		return ''
	-- 	end
    for i, k in ipairs(producesOrder) do
		local v = itemTable[k]
		local count3 = #itemTable[k].requiredData
		local counting2 = 1
		local test = {}
		local test2 = {}
		for _, x in pairs(finalMerged[k]) do
			if not tableContains(test2, x) then
				table.insert(test2, x)
				table.insert(test, x)
			end
		end
		for j = #test, 1, -1 do
			itemTable[k].requiredData[counting2]["probability"] = test[j]
			itemTable[k].requiredData[counting2]["priority"] = nil
			counting2 = counting2 + 1
		end
    end
    -- mw.logObject(itemTable)
    EN = EN:gsub(":", "")
    local itemDesc = utils.expandTemplate("模板:Name",{EN, nil, class = "inline"}) or nil
    if contains(itemDesc, "Blank") then itemDesc = nil end
    
    for sim, k in ipairs(producesOrder) do
    	local v = itemTable[k]
    	local count3 = #itemTable[k].requiredData
    	local counting2 = 1
    	local test = {}
		local test2 = {}
		local final = ""
		for _, x in pairs(finalMerged[k]) do
			if not tableContains(test2, x) then
				table.insert(test2, x)
				table.insert(test, x)
			end
		end
		local start = 1
		local startProb = 0
		local endCount = 10
		local endProb = 0
		local totalLength = 0
		local last1 = ''
		local last2 = ''
		local firstElement = v.item
		if contains(firstElement, "File:Roe.png") and promised_name ~= "Roe" then
			firstElement = firstElement:gsub("File:Roe.png", "File:" .. promised_name .. ".png")
		end
		local smallTable = {firstElement, k}
		for j = 1, #test do
			local x = itemTable[k].requiredData[counting2]
			if j == 1 then
				startProb = x.probability
			end
			if j == 1 and x.rangeA ~= 1 then
				start = x.rangeA
				local length2 = x.rangeA - 1
				totalLength = totalLength + length2
				local prob2 = "—" -- / 
				table.insert(smallTable, length2)
				table.insert(smallTable, toPercentage(prob2, false, 1))
				-- if final == "" then final = length2 else final = final .. "," .. length2 end
				-- final = final .. "," .. prob2
			end
			
			local length = x.rangeB - x.rangeA +1
			local prob = x.probability
			table.insert(smallTable, length)
			table.insert(smallTable, toPercentage(prob, false, 1))
			-- if final == "" then final = length else final = final .. "," .. length end
			-- final = final .. "," .. prob
			endCount = x.rangeB
			if x.probability ~= 0 then
				endProb = x.probability
			end
			counting2 = counting2 + 1
			if length == 0 then totalLength = totalLength + 1 end
			totalLength = totalLength + length
			
		end
		if totalLength ~= maxPopulation - 1 then
			local smallTableL = #smallTable
			if smallTableL >= 3 then
				-- mw.log(smallTable[smallTableL])
				if smallTable[smallTableL-1] == 0 then
					smallTable[smallTableL-1] = 2
				else
					if true then -- smallTable[smallTableL] == "0%"
						-- smallTable[smallTableL-1] = smallTable[smallTableL-1] + 1
						smallTable[smallTableL-1] = smallTable[smallTableL-1] + maxPopulation - 1 - totalLength
					else
						-- mw.log("maxPopulation - 1", maxPopulation - 1, "totalLength", totalLength)
						table.insert(smallTable, maxPopulation - 1 - totalLength)
						table.insert(smallTable, toPercentage(0))
					end
				end
				-- mw.log(smallTable[smallTableL-1],smallTable[smallTableL])
				-- if smallTable[smallTableL -1 ]
			end
		end
		-- mw.log(start, endCount)

		
		local cal1 = toPercentage((start * 0.08 + 0.15) * startProb / 100, true)
		local cal2 = toPercentage((endCount * 0.08 + 0.15) * endProb / 100, true)
		local calString = ""
		if cal1 == cal2 then
			calString = cal2 .. "%"
		else
			if cal2 < cal1 then
				cal1, cal2 = cal2, cal1
			end
			calString = cal1 .. " ~ " .. cal2 .. "%"
		end
		if k == "ZZZZ" then calString = "—" end
		table.insert(smallTable, calString)
		if v.experience == "—" then
			table.insert(smallTable, "—")
		else
			table.insert(smallTable, math.floor(v.experience))
		end
		final = table.concat(smallTable, ",")
		-- mw.log(final)
		local insertContent = generateRowLocal(final or "无,无,无,无")
        if sim == 1 then
        	if displayFishName == "" or displayFishName == nil then
        		displayFishName = utils.expandTemplate("模板:Name",{name, nil, class = "inline"})
        	end
			insertContent = insertContent:gsub('<tr><td data', '<tr><td rowspan="'.. #producesOrder ..'">' .. displayFishName .. '</td><td data')
    	end
		table.insert(result, insertContent)
	
    end
    content = table.concat(result, "\n")
    -- cache.set(cacheKey, content, EXP_TIME)
    return content
end

return p