• Welcome to the Kancolle Wiki!
  • If you have any questions regarding site content, account registration, etc., please visit the KanColle Wiki Discord

Difference between revisions of "Module:MapRewards"

From Kancolle Wiki
Jump to navigation Jump to search
 
(16 intermediate revisions by 2 users not shown)
Line 8: Line 8:
 
!style="background-color:#3baef5;color:white;width:40%%"|Ship
 
!style="background-color:#3baef5;color:white;width:40%%"|Ship
 
|colspan="4" style="background-color:#eef2f7"|%s<br>[[%s]]]=],
 
|colspan="4" style="background-color:#eef2f7"|%s<br>[[%s]]]=],
 +
choice_header = [=[|-
 +
!style="background-color:#3baef5;color:white;width:40%"|Choice
 +
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|丁<br>Casual
 +
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|丙<br>Easy
 +
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|乙<br>Medium
 +
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|甲<br>Hard]=],
 
choice = [=[|-
 
choice = [=[|-
 
!style="background-color:#eef2f7;color:red"|OR
 
!style="background-color:#eef2f7;color:red"|OR
 
|colspan="4" style="background-color:#eef2f7"|]=],
 
|colspan="4" style="background-color:#eef2f7"|]=],
-- TODO: class="sortable"
+
choice_separator = [=[|-
item_header = [[{|style="text-align:center;width:100%"
+
!style="background-color:#eee;color:blue"|THEN
!style="background-color:#3baef5;color:white;width:40%"|Item/Equipment
+
|colspan="4" style="background-color:#eee"|]=],
 +
item_header = [[{|style="text-align:center;width:100%" class="sortable"
 +
!style="background-color:#3baef5;color:white;width:40%"|Reward
 
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|丁<br>Casual
 
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|丁<br>Casual
 
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|丙<br>Easy
 
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|丙<br>Easy
Line 24: Line 32:
 
|style="background-color:#eef2f7;font-size:18px"|%s
 
|style="background-color:#eef2f7;font-size:18px"|%s
 
|style="background-color:#eef2f7;font-size:18px"|%s]=],
 
|style="background-color:#eef2f7;font-size:18px"|%s]=],
item_row_choice_top = [=[|-
 
|data-sort-value="%s" style="background-color:#eef2f7;font-size:12px;line-height:14px;border-top:4px solid grey"|%s<br>[[%s]]]=],
 
item_row_choice_middle = [=[|-
 
|data-sort-value="%s" style="background-color:#eef2f7;font-size:12px;line-height:14px;"|%s<br>[[%s]]]=],
 
item_row_choice_bottom = [=[|-
 
|data-sort-value="%s" style="background-color:#eef2f7;font-size:12px;line-height:14px;border-bottom:4px solid grey"|%s<br>[[%s]]]=],
 
item_row_amount_top    = [=[|style="background-color:#eef2f7;font-size:18px;border-top:4px solid grey"|%s]=],
 
item_row_amount_middle = [=[|style="background-color:#eef2f7;font-size:18px;"|%s]=],
 
item_row_amount_bottom = [=[|style="background-color:#eef2f7;font-size:18px;border-bottom:4px solid grey"|%s]=],
 
item_style_top    = [=[|data-sort-value="%s" style="background-color:#eef2f7;color:red;font-size:12px;line-height:14px;width:auto;border-top:4px solid grey"|]=],
 
item_style_bottom = [=[|data-sort-value="%s" style="background-color:#eef2f7;color:red;font-size:12px;line-height:14px;width:auto;border-bottom:4px solid grey"|]=],
 
 
}
 
}
  
local assetTypes = { item = 'Item Icon', equipment = 'Equipment Card', ship = 'Ship Banner' }
+
local assetType = { item = 'Item Icon', equipment = 'Equipment Card', ship = 'Ship Banner' }
  
local assetSizes = { item = '75px', equipment = '75px', ship = '240px' }
+
local assetSize = { item = '75px', equipment = '75px', ship = '160px', large_ship = '240px' }
  
 
local function render(frame, event, map)
 
local function render(frame, event, map)
Line 45: Line 42:
 
local map = map or frame.args[2] or "??"
 
local map = map or frame.args[2] or "??"
 
local success, data = U.loadData("Data/Map/" .. event)
 
local success, data = U.loadData("Data/Map/" .. event)
if not success then return "Unknown event: " .. event end
+
if not success then return "No data for event: " .. event end
 
data = data[map]
 
data = data[map]
if not data then return "Unknown map: " .. map end
+
if not data then return "No data for map: " .. map end
 +
local version = data.version or 1
 
local index = {}
 
local index = {}
 
local tbl = {}
 
local tbl = {}
 
local types = {}
 
local types = {}
-- TODO: assuming 0-1 single ship reward on all difficulties
 
 
local ship = false
 
local ship = false
 +
local choiceIndex = {}
 +
local choice1Index = {}
 +
local choice2Index = {}
 
local function setData(diff)
 
local function setData(diff)
 
for _, v in ipairs(data[diff] or {}) do
 
for _, v in ipairs(data[diff] or {}) do
Line 62: Line 62:
 
types[name1] = v1.item and 'item' or v1.equipment and 'equipment' or v1.ship and 'ship' or '??'
 
types[name1] = v1.item and 'item' or v1.equipment and 'equipment' or v1.ship and 'ship' or '??'
 
types[name2] = v2.item and 'item' or v2.equipment and 'equipment' or v2.ship and 'ship' or '??'
 
types[name2] = v2.item and 'item' or v2.equipment and 'equipment' or v2.ship and 'ship' or '??'
local names = {name1 .. '1', name2 .. '2'}
+
if not U.ifind(choice1Index, name1) then table.insert(choice1Index, name1) end
local name = names[1] .. '||' .. names[2]
+
if not U.ifind(choice2Index, name2) then table.insert(choice2Index, name2) end
types[name] = 'choice'
+
        if version == 0 then
if not U.ifind(index, name) then table.insert(index, name) end
+
        local names = table.concat({name1, name2}, '|')
tbl[name] = tbl[name] or {}
+
        tbl[names] = tbl[names] or {}
tbl[name][diff] = {
+
        tbl[names][diff] = {{ count = v1.count or 1, level = v1.level }, { count = v2.count or 1, level = v2.level }}
{ name = name1, count = v1.count or 1, level = v1.level },
+
        if not U.ifind(choiceIndex, names) then table.insert(choiceIndex, names) end
{ name = name2, count = v2.count or 1, level = v2.level },
+
        else
}
+
        tbl['choice1' .. name1] = tbl['choice1' .. name1] or {}
 +
        tbl['choice1' .. name1][diff] = { count = v1.count or 1, level = v1.level }
 +
        tbl['choice2' .. name2] = tbl['choice2' .. name2] or {}
 +
        tbl['choice2' .. name2][diff] = { count = v2.count or 1, level = v2.level }
 +
        if not U.ifindBy(choiceIndex, function(e) return e[1] == name1 and e[2] == name2 end) then table.insert(choiceIndex, {name1, name2}) end
 +
        end
 
else
 
else
 
local name = v.item or v.equipment or v.ship or '??'
 
local name = v.item or v.equipment or v.ship or '??'
Line 85: Line 90:
 
end
 
end
 
local function getCount(name, diff, i)
 
local function getCount(name, diff, i)
if i then
+
    local data = (tbl[name] or {})[diff] or {}
return (((tbl[name] or {})[diff] or {})[i] or {}).count or 0
+
    return data[i] and (data[i].count or 0) or data.count or 0
else
 
return ((tbl[name] or {})[diff] or {}).count or 0
 
end
 
 
end
 
end
 
local function getLevel(name, diff, i)
 
local function getLevel(name, diff, i)
local level
+
    local data = (tbl[name] or {})[diff] or {}
if i then
+
    local level = data[i] and data[i].level or data.level
level = (((tbl[name] or {})[diff] or {})[i] or {}).level
 
else
 
level = ((tbl[name] or {})[diff] or {}).level
 
end
 
 
return level and string.format(" (★%d)", level) or ''
 
return level and string.format(" (★%d)", level) or ''
 
end
 
end
Line 104: Line 102:
 
return (count == 0 and '' or count) .. getLevel(name, diff, i)
 
return (count == 0 and '' or count) .. getLevel(name, diff, i)
 
end
 
end
local function getAsset(name)
+
local function getAsset(name, size)
return string.format("[[File:%s %s.png|%s|link=%s]]", assetTypes[types[name]] or '??', name, assetSizes[types[name]] or '??', name)
+
local fname = name:gsub('/', ' ')
 +
return string.format("[[File:%s %s.png|%s|link=%s]]", assetType[types[name]] or '??', fname, assetSize[size or types[name]] or '??', name)
 
end
 
end
 
setData('Hard')
 
setData('Hard')
Line 111: Line 110:
 
setData('Easy')
 
setData('Easy')
 
setData('Casual')
 
setData('Casual')
 +
local deep_plot1 = {}
 +
local deep_plot2 = {}
 +
if version >= 2 then
 +
for _, choice in ipairs(choiceIndex) do
 +
deep_plot1[choice[1]] = deep_plot1[choice[1]] or {}
 +
table.insert(deep_plot1[choice[1]], 1, choice[2])
 +
deep_plot2[choice[2]] = deep_plot2[choice[2]] or {}
 +
table.insert(deep_plot2[choice[2]], 1, choice[1])
 +
end
 +
end
 +
if version >= 3 then
 +
    for _, name in ipairs(index) do
 +
    for diff in pairs(tbl[name] or {}) do
 +
        if tbl['choice1' .. name] and not tbl['choice1' .. name][diff] and not tbl['choice2' .. name] or
 +
        tbl['choice2' .. name] and not tbl['choice2' .. name][diff] and not tbl['choice1' .. name] then
 +
        local spot = tbl['choice1' .. name] or tbl['choice2' .. name]
 +
        spot[diff] = tbl[name][diff]
 +
        U.removekey(tbl[name], diff)
 +
        end
 +
    end
 +
    end
 +
    local newIndex = {}
 +
    for _, name in ipairs(index) do
 +
    if U.size(tbl[name]) == 0 then
 +
        U.removekey(tbl, name)
 +
    else
 +
        table.insert(newIndex, name)
 +
    end
 +
    end
 +
    index = newIndex
 +
end
 
local result = { string.format(template.header, mw.uri.encode(event, 'WIKI')) }
 
local result = { string.format(template.header, mw.uri.encode(event, 'WIKI')) }
 
if ship then
 
if ship then
table.insert(result, string.format(template.ship_row, getAsset(ship), ship))
+
table.insert(result, string.format(template.ship_row, getAsset(ship, 'large_ship'), ship))
 +
end
 +
if #choiceIndex > 0 then
 +
table.insert(result, template.choice_header)
 +
if version >= 2 then
 +
local done = {}
 +
local first = true
 +
for i, names in ipairs(choiceIndex) do
 +
if not done[names[1] .. '|' .. names[2]] then
 +
if first then
 +
first = false
 +
else
 +
table.insert(result, template.choice_separator)
 +
end
 +
local size1 = #deep_plot1[names[1]]
 +
local size2 = #deep_plot2[names[2]]
 +
if size1 > size2 then
 +
table.insert(result, string.format(template.item_row, 0, getAsset(names[1]), names[1],
 +
getCell('choice1' .. names[1], 'Casual'), getCell('choice1' .. names[1], 'Easy'), getCell('choice1' .. names[1], 'Medium'), getCell('choice1' .. names[1], 'Hard')))
 +
table.insert(result, template.choice)
 +
for _, name in ipairs(deep_plot1[names[1]]) do
 +
table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
 +
getCell('choice2' .. name, 'Casual'), getCell('choice2' .. name, 'Easy'), getCell('choice2' .. name, 'Medium'), getCell('choice2' .. name, 'Hard')))
 +
done[names[1] .. '|' .. name] = true
 +
end
 +
elseif size2 > size1 then
 +
for _, name in ipairs(deep_plot2[names[2]]) do
 +
table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
 +
getCell('choice1' .. name, 'Casual'), getCell('choice1' .. name, 'Easy'), getCell('choice1' .. name, 'Medium'), getCell('choice1' .. name, 'Hard')))
 +
done[name .. '|' .. names[2]] = true
 +
end
 +
table.insert(result, template.choice)
 +
table.insert(result, string.format(template.item_row, 0, getAsset(names[2]), names[2],
 +
getCell('choice2' .. names[2], 'Casual'), getCell('choice2' .. names[2], 'Easy'), getCell('choice2' .. names[2], 'Medium'), getCell('choice2' .. names[2], 'Hard')))
 +
else
 +
table.insert(result, string.format(template.item_row, 0, getAsset(names[1]), names[1],
 +
getCell('choice1' .. names[1], 'Casual'), getCell('choice1' .. names[1], 'Easy'), getCell('choice1' .. names[1], 'Medium'), getCell('choice1' .. names[1], 'Hard')))
 +
table.insert(result, template.choice)
 +
table.insert(result, string.format(template.item_row, 0, getAsset(names[2]), names[2],
 +
getCell('choice2' .. names[2], 'Casual'), getCell('choice2' .. names[2], 'Easy'), getCell('choice2' .. names[2], 'Medium'), getCell('choice2' .. names[2], 'Hard')))
 +
done[names[1] .. '|' .. names[2]] = true
 +
end
 +
end
 +
end
 +
elseif version == 0 then
 +
for i, names in ipairs(choiceIndex) do
 +
local names_ = U.split(names, '|')
 +
for j, name in ipairs(names_) do
 +
table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
 +
getCell(names, 'Casual', j), getCell(names, 'Easy', j), getCell(names, 'Medium', j), getCell(names, 'Hard', j)))
 +
if j < #names_ then
 +
table.insert(result, template.choice)
 +
end
 +
end
 +
if i < #choiceIndex then
 +
table.insert(result, template.choice_separator)
 +
end
 +
end
 +
elseif #choice1Index == #choice2Index then
 +
for i, e in ipairs(choiceIndex) do
 +
local name = e[1]
 +
        table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
 +
        getCell('choice1' .. name, 'Casual'), getCell('choice1' .. name, 'Easy'), getCell('choice1' .. name, 'Medium'), getCell('choice1' .. name, 'Hard')))
 +
table.insert(result, template.choice)
 +
name = e[2]
 +
  table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
 +
getCell('choice2' .. name, 'Casual'), getCell('choice2' .. name, 'Easy'), getCell('choice2' .. name, 'Medium'), getCell('choice2' .. name, 'Hard')))
 +
if i < #choiceIndex then
 +
table.insert(result, template.choice_separator)
 +
end
 +
end
 +
else
 +
for i, name in ipairs(choice1Index) do
 +
table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
 +
getCell('choice1' .. name, 'Casual'), getCell('choice1' .. name, 'Easy'), getCell('choice1' .. name, 'Medium'), getCell('choice1' .. name, 'Hard')))
 +
end
 +
table.insert(result, template.choice)
 +
for i, name in ipairs(choice2Index) do
 +
table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
 +
getCell('choice2' .. name, 'Casual'), getCell('choice2' .. name, 'Easy'), getCell('choice2' .. name, 'Medium'), getCell('choice2' .. name, 'Hard')))
 +
end
 +
end
 
end
 
end
 
table.insert(result, template.footer)
 
table.insert(result, template.footer)
 
table.insert(result, template.item_header)
 
table.insert(result, template.item_header)
--[[
 
 
local sortedIndex = U.imap(index, function(name, i) return { name = name, i = i, typ = types[name] } end)
 
local sortedIndex = U.imap(index, function(name, i) return { name = name, i = i, typ = types[name] } end)
 
table.sort(sortedIndex, function (x, y)
 
table.sort(sortedIndex, function (x, y)
Line 127: Line 237:
 
return x.i < y.i
 
return x.i < y.i
 
end)
 
end)
local sortValues = {}
+
-- local sortValues = {}
for i, e in ipairs(sortedIndex) do sortValues[e.name] = i end
+
-- for i, e in ipairs(sortedIndex) do sortValues[e.name] = i end
]]--
+
for i, e in ipairs(sortedIndex) do
-- sortValues[name]
+
table.insert(result, string.format(template.item_row, e.i, getAsset(e.name), e.name,
for i, name in ipairs(index) do
+
getCell(e.name, 'Casual'), getCell(e.name, 'Easy'), getCell(e.name, 'Medium'), getCell(e.name, 'Hard')))
if types[name] == 'choice' then
 
local names = U.split(name, '||')
 
 
local subNames = {}
 
for j=1, #names do
 
subNames[j] = names[j]:sub(1, -2)
 
end
 
 
local difficulty = {'Casual', 'Easy', 'Medium', 'Hard'}
 
 
for c=1, #names do
 
local str = ""
 
 
if      c==1      then str = template.item_row_choice_top
 
elseif  c==#names then str = template.item_row_choice_bottom
 
else            str = template.item_row_choice_middle end
 
table.insert(result, string.format(str, 0, getAsset(subNames[c]), subNames[c]))
 
 
str = ""
 
for d=1, #difficulty do
 
if      c==1      then str = template.item_row_amount_top
 
elseif  c==#names then str = template.item_row_amount_bottom
 
else            str = template.item_row_amount_middle end
 
table.insert(result, string.format(str, getCell(name, difficulty[d], c), c))
 
end
 
 
if c~=#names then table.insert(result, template.choice) end
 
end
 
 
else
 
table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
 
getCell(name, 'Casual'), getCell(name, 'Easy'), getCell(name, 'Medium'), getCell(name, 'Hard')))
 
end
 
 
end
 
end
 
table.insert(result, template.footer)
 
table.insert(result, template.footer)
Line 171: Line 248:
  
 
local function test()
 
local function test()
mw.log(render(nil, 'Summer 2022 Event', 'E-1'))
+
mw.log(render(nil, 'Summer 2023 Event', 'E-7'))
 
end
 
end
  
 
return { render = render, test = test }
 
return { render = render, test = test }
 +
 +
-- TEST: p.test()

Latest revision as of 17:35, 6 September 2023

Documentation for this module may be created at Module:MapRewards/doc

local U = require('Module:Core')

local template = {
	footer = "|}",
	header = [[{|style="text-align:center;width:100%%"
!colspan="5" style="background-color:#3baef5;color:white;padding:10px"|Rewards<span class="plainlinks" style="float:right">&#x5b;[https://en.kancollewiki.net/Module:Data/Map/%s?action=edit edit]&#x5d;</span>]],
	ship_row = [=[|-
!style="background-color:#3baef5;color:white;width:40%%"|Ship
|colspan="4" style="background-color:#eef2f7"|%s<br>[[%s]]]=],
	choice_header = [=[|-
!style="background-color:#3baef5;color:white;width:40%"|Choice
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|丁<br>Casual
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|丙<br>Easy
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|乙<br>Medium
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|甲<br>Hard]=],
	choice = [=[|-
!style="background-color:#eef2f7;color:red"|OR
|colspan="4" style="background-color:#eef2f7"|]=],
	choice_separator = [=[|-
!style="background-color:#eee;color:blue"|THEN
|colspan="4" style="background-color:#eee"|]=],
	item_header = [[{|style="text-align:center;width:100%" class="sortable"
!style="background-color:#3baef5;color:white;width:40%"|Reward
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|丁<br>Casual
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|丙<br>Easy
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|乙<br>Medium
!class="unsortable" style="background-color:#3baef5;color:white;width:15%"|甲<br>Hard]],
	item_row = [=[|-
|data-sort-value="%s" style="background-color:#eef2f7;font-size:12px;line-height:14px"|%s<br>[[%s]]
|style="background-color:#eef2f7;font-size:18px"|%s
|style="background-color:#eef2f7;font-size:18px"|%s
|style="background-color:#eef2f7;font-size:18px"|%s
|style="background-color:#eef2f7;font-size:18px"|%s]=],
}

local assetType = { item = 'Item Icon', equipment = 'Equipment Card', ship = 'Ship Banner' }

local assetSize = { item = '75px', equipment = '75px', ship = '160px', large_ship = '240px' }

local function render(frame, event, map)
	local event = event or frame.args[1] or "??"
	local map = map or frame.args[2] or "??"
	local success, data = U.loadData("Data/Map/" .. event)
	if not success then return "No data for event: " .. event end
	data = data[map]
	if not data then return "No data for map: " .. map end
	local version = data.version or 1
	local index = {}
	local tbl = {}
	local types = {}
	local ship = false
	local choiceIndex = {}
	local choice1Index = {}
	local choice2Index = {}
	local function setData(diff)
		for _, v in ipairs(data[diff] or {}) do
			if v.choice then
				local v1 = v.choice[1]
				local v2 = v.choice[2]
				local name1 = v1.item or v1.equipment or v1.ship or '??'
				local name2 = v2.item or v2.equipment or v2.ship or '??'
				types[name1] = v1.item and 'item' or v1.equipment and 'equipment' or v1.ship and 'ship' or '??'
				types[name2] = v2.item and 'item' or v2.equipment and 'equipment' or v2.ship and 'ship' or '??'
				if not U.ifind(choice1Index, name1) then table.insert(choice1Index, name1) end
				if not U.ifind(choice2Index, name2) then table.insert(choice2Index, name2) end
        		if version == 0 then
        			local names = table.concat({name1, name2}, '|')
        			tbl[names] = tbl[names] or {}
        			tbl[names][diff] = {{ count = v1.count or 1, level = v1.level }, { count = v2.count or 1, level = v2.level }}
        			if not U.ifind(choiceIndex, names) then table.insert(choiceIndex, names) end
        		else
        			tbl['choice1' .. name1] = tbl['choice1' .. name1] or {}
        			tbl['choice1' .. name1][diff] = { count = v1.count or 1, level = v1.level }
        			tbl['choice2' .. name2] = tbl['choice2' .. name2] or {}
        			tbl['choice2' .. name2][diff] = { count = v2.count or 1, level = v2.level }
        			if not U.ifindBy(choiceIndex, function(e) return e[1] == name1 and e[2] == name2 end) then table.insert(choiceIndex, {name1, name2}) end
        		end
			else
				local name = v.item or v.equipment or v.ship or '??'
				types[name] = v.item and 'item' or v.equipment and 'equipment' or v.ship and 'ship' or '??'
				if v.ship then
					ship = v.ship
				else
					if not U.ifind(index, name) then table.insert(index, name) end
					tbl[name] = tbl[name] or {}
					tbl[name][diff] = { count = v.count or 1, level = v.level }
				end
			end
		end
	end
	local function getCount(name, diff, i)
    	local data = (tbl[name] or {})[diff] or {}
    	return data[i] and (data[i].count or 0) or data.count or 0
	end
	local function getLevel(name, diff, i)
    	local data = (tbl[name] or {})[diff] or {}
    	local level = data[i] and data[i].level or data.level
		return level and string.format(" (★%d)", level) or ''
	end
	local function getCell(name, diff, i)
		local count = getCount(name, diff, i)
		return (count == 0 and '' or count) .. getLevel(name, diff, i)
	end
	local function getAsset(name, size)
		local fname = name:gsub('/', ' ')
		return string.format("[[File:%s %s.png|%s|link=%s]]", assetType[types[name]] or '??', fname, assetSize[size or types[name]] or '??', name)
	end
	setData('Hard')
	setData('Medium')
	setData('Easy')
	setData('Casual')
	local deep_plot1 = {}
	local deep_plot2 = {}
	if version >= 2 then
		for _, choice in ipairs(choiceIndex) do
			deep_plot1[choice[1]] = deep_plot1[choice[1]] or {}
			table.insert(deep_plot1[choice[1]], 1, choice[2])
			deep_plot2[choice[2]] = deep_plot2[choice[2]] or {}
			table.insert(deep_plot2[choice[2]], 1, choice[1])
		end
	end
	if version >= 3 then
    	for _, name in ipairs(index) do
    		for diff in pairs(tbl[name] or {}) do
        		if tbl['choice1' .. name] and not tbl['choice1' .. name][diff] and not tbl['choice2' .. name] or
        			tbl['choice2' .. name] and not tbl['choice2' .. name][diff] and not tbl['choice1' .. name] then
        			local spot = tbl['choice1' .. name] or tbl['choice2' .. name]
        			spot[diff] = tbl[name][diff]
        			U.removekey(tbl[name], diff)
        		end
    		end
    	end
    	local newIndex = {}
    	for _, name in ipairs(index) do
    		if U.size(tbl[name]) == 0 then
        		U.removekey(tbl, name)
    		else
        		table.insert(newIndex, name)
    		end
    	end
    	index = newIndex
	end
	local result = { string.format(template.header, mw.uri.encode(event, 'WIKI')) }
	if ship then
		table.insert(result, string.format(template.ship_row, getAsset(ship, 'large_ship'), ship))
	end
	if #choiceIndex > 0 then
		table.insert(result, template.choice_header)
		if version >= 2 then
			local done = {}
			local first = true
			for i, names in ipairs(choiceIndex) do
				if not done[names[1] .. '|' .. names[2]] then
					if first then
						first = false
					else
						table.insert(result, template.choice_separator)
					end
					local size1 = #deep_plot1[names[1]]
					local size2 = #deep_plot2[names[2]]
					if size1 > size2 then
						table.insert(result, string.format(template.item_row, 0, getAsset(names[1]), names[1],
							getCell('choice1' .. names[1], 'Casual'), getCell('choice1' .. names[1], 'Easy'), getCell('choice1' .. names[1], 'Medium'), getCell('choice1' .. names[1], 'Hard')))
						table.insert(result, template.choice)
						for _, name in ipairs(deep_plot1[names[1]]) do
							table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
								getCell('choice2' .. name, 'Casual'), getCell('choice2' .. name, 'Easy'), getCell('choice2' .. name, 'Medium'), getCell('choice2' .. name, 'Hard')))
							done[names[1] .. '|' .. name] = true
						end
					elseif size2 > size1 then
						for _, name in ipairs(deep_plot2[names[2]]) do
							table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
								getCell('choice1' .. name, 'Casual'), getCell('choice1' .. name, 'Easy'), getCell('choice1' .. name, 'Medium'), getCell('choice1' .. name, 'Hard')))
							done[name .. '|' .. names[2]] = true
						end
						table.insert(result, template.choice)
						table.insert(result, string.format(template.item_row, 0, getAsset(names[2]), names[2],
							getCell('choice2' .. names[2], 'Casual'), getCell('choice2' .. names[2], 'Easy'), getCell('choice2' .. names[2], 'Medium'), getCell('choice2' .. names[2], 'Hard')))
					else
						table.insert(result, string.format(template.item_row, 0, getAsset(names[1]), names[1],
							getCell('choice1' .. names[1], 'Casual'), getCell('choice1' .. names[1], 'Easy'), getCell('choice1' .. names[1], 'Medium'), getCell('choice1' .. names[1], 'Hard')))
						table.insert(result, template.choice)
						table.insert(result, string.format(template.item_row, 0, getAsset(names[2]), names[2],
							getCell('choice2' .. names[2], 'Casual'), getCell('choice2' .. names[2], 'Easy'), getCell('choice2' .. names[2], 'Medium'), getCell('choice2' .. names[2], 'Hard')))
						done[names[1] .. '|' .. names[2]] = true
					end
				end
			end
		elseif version == 0 then
			for i, names in ipairs(choiceIndex) do
				local names_ = U.split(names, '|')
				for j, name in ipairs(names_) do
					table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
						getCell(names, 'Casual', j), getCell(names, 'Easy', j), getCell(names, 'Medium', j), getCell(names, 'Hard', j)))
					if j < #names_ then
						table.insert(result, template.choice)
					end
				end
				if i < #choiceIndex then
					table.insert(result, template.choice_separator)
				end
			end
		elseif #choice1Index == #choice2Index then
			for i, e in ipairs(choiceIndex) do
				local name = e[1]
        		table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
        			getCell('choice1' .. name, 'Casual'), getCell('choice1' .. name, 'Easy'), getCell('choice1' .. name, 'Medium'), getCell('choice1' .. name, 'Hard')))
				table.insert(result, template.choice)
				name = e[2]
		  		table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
					getCell('choice2' .. name, 'Casual'), getCell('choice2' .. name, 'Easy'), getCell('choice2' .. name, 'Medium'), getCell('choice2' .. name, 'Hard')))
				if i < #choiceIndex then
					table.insert(result, template.choice_separator)
				end
			end
		else
			for i, name in ipairs(choice1Index) do
				table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
					getCell('choice1' .. name, 'Casual'), getCell('choice1' .. name, 'Easy'), getCell('choice1' .. name, 'Medium'), getCell('choice1' .. name, 'Hard')))
			end
			table.insert(result, template.choice)
			for i, name in ipairs(choice2Index) do
				table.insert(result, string.format(template.item_row, 0, getAsset(name), name,
					getCell('choice2' .. name, 'Casual'), getCell('choice2' .. name, 'Easy'), getCell('choice2' .. name, 'Medium'), getCell('choice2' .. name, 'Hard')))
			end
		end
	end
	table.insert(result, template.footer)
	table.insert(result, template.item_header)
	local sortedIndex = U.imap(index, function(name, i) return { name = name, i = i, typ = types[name] } end)
	table.sort(sortedIndex, function (x, y)
		if x.typ ~= y.typ then return x.typ > y.typ end
		if getCount(x.name, 'Casual') ~= getCount(y.name, 'Casual') then return getCount(x.name, 'Casual') > getCount(y.name, 'Casual') end
		if getCount(x.name, 'Easy') ~= getCount(y.name, 'Easy') then return getCount(x.name, 'Easy') > getCount(y.name, 'Easy') end
		if getCount(x.name, 'Medium') ~= getCount(y.name, 'Medium') then return getCount(x.name, 'Medium') > getCount(y.name, 'Medium') end
		if getCount(x.name, 'Hard') ~= getCount(y.name, 'Hard') then return getCount(x.name, 'Hard') > getCount(y.name, 'Hard') end
		return x.i < y.i
	end)
	-- local sortValues = {}
	-- for i, e in ipairs(sortedIndex) do sortValues[e.name] = i end
	for i, e in ipairs(sortedIndex) do
		table.insert(result, string.format(template.item_row, e.i, getAsset(e.name), e.name,
			getCell(e.name, 'Casual'), getCell(e.name, 'Easy'), getCell(e.name, 'Medium'), getCell(e.name, 'Hard')))
	end
	table.insert(result, template.footer)
	return table.concat(result, "\n")
end

local function test()
	mw.log(render(nil, 'Summer 2023 Event', 'E-7'))
end

return { render = render, test = test }

-- TEST: p.test()