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

Module:MapRewards

From Kancolle Wiki
Revision as of 22:51, 16 August 2023 by がか (talk | contribs)
Jump to navigation Jump to search

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 '??'
				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.ifind(choice1Index, name1) then table.insert(choice1Index, name1) end
				if not U.ifind(choice2Index, name2) then table.insert(choice2Index, name2) end
				if not U.ifindBy(choiceIndex, function(e) return e[1] == name1 and e[2] == name2 end) then table.insert(choiceIndex, {name1, name2}) 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)
		return ((tbl[name] or {})[diff] or {}).count or 0
	end
	local function getLevel(name, diff)
		local level = ((tbl[name] or {})[diff] or {}).level
		return level and string.format(" (★%d)", level) or ''
	end
	local function getCell(name, diff)
		local count = getCount(name, diff)
		return (count == 0 and '' or count) .. getLevel(name, diff)
	end
	local function getAsset(name, size)
		return string.format("[[File:%s %s.png|%s|link=%s]]", assetType[types[name]] or '??', name, assetSize[size or types[name]] or '??', name)
	end
	setData('Hard')
	setData('Medium')
	setData('Easy')
	setData('Casual')
	local deep_plot1 = {}
	local deep_plot2 = {}
	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
	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
		else
			if #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.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 2022 Event', 'E-1'))
	-- mw.log(render(nil, 'Early Spring 2023 Event', 'E-1'))
	mw.log(render(nil, 'Summer 2023 Event', 'E-3'))
end

return { render = render, test = test }

-- TEST: p.test()