• 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:DropList"

From Kancolle Wiki
Jump to navigation Jump to search
(Katori had been added to normal construction for close to half year already)
Line 8: Line 8:
 
'Akitsushima', 'Akizuki', 'Amagi', 'Isokaze', 'Katsuragi', 'Littorio', 'Prinz Eugen', 'Roma', 'Tokitsukaze',
 
'Akitsushima', 'Akizuki', 'Amagi', 'Isokaze', 'Katsuragi', 'Littorio', 'Prinz Eugen', 'Roma', 'Tokitsukaze',
 
'Akitsu Maru', 'Bismarck', 'Musashi', 'Noshiro', 'Yamato', 'Taihou',
 
'Akitsu Maru', 'Bismarck', 'Musashi', 'Noshiro', 'Yamato', 'Taihou',
'Agano', 'Akashi', 'Amatsukaze', 'Asagumo', 'Asashimo', 'Harusame', 'Hatsukaze', 'Hayashimo', 'I-401', 'Katori', 'Kiyoshimo', 'Maruyu',
+
'Agano', 'Akashi', 'Amatsukaze', 'Asagumo', 'Asashimo', 'Harusame', 'Hatsukaze', 'Hayashimo', 'I-401', 'Kiyoshimo', 'Maruyu',
 
'Mikuma', 'Nowaki', 'Ooyodo', 'Sakawa', 'Taigei', 'Takanami', 'U-511', 'Unryuu', 'Uzuki', 'Yahagi',
 
'Mikuma', 'Nowaki', 'Ooyodo', 'Sakawa', 'Taigei', 'Takanami', 'U-511', 'Unryuu', 'Uzuki', 'Yahagi',
 
'Z1', 'Z3', 'Tanikaze', 'Maikaze',
 
'Z1', 'Z3', 'Tanikaze', 'Maikaze',

Revision as of 21:37, 12 February 2016

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

local format = require('Module:StringInterpolation').format
local getArgs = require('Module:GetArgs')
local Ship = require('Module:Ship')
local Formatting = require('Module:Formatting')

-- http://kancolle.wikia.com/wiki/Thread:295964
local rare_ships = {
	'Akitsushima', 'Akizuki', 'Amagi', 'Isokaze', 'Katsuragi', 'Littorio', 'Prinz Eugen', 'Roma', 'Tokitsukaze',
	'Akitsu Maru', 'Bismarck', 'Musashi', 'Noshiro', 'Yamato', 'Taihou',
	'Agano', 'Akashi', 'Amatsukaze', 'Asagumo', 'Asashimo', 'Harusame', 'Hatsukaze', 'Hayashimo', 'I-401', 'Kiyoshimo', 'Maruyu',
	'Mikuma', 'Nowaki', 'Ooyodo', 'Sakawa', 'Taigei', 'Takanami', 'U-511', 'Unryuu', 'Uzuki', 'Yahagi',
	'Z1', 'Z3', 'Tanikaze', 'Maikaze',
	'Libeccio', 'Mizuho', 'Kazagumo', 'Umikaze', 'Kawakaze', 'Hayasui', 'Teruzuki', 'Graf Zeppelin', 'Arashi', 'Kashima', 'Hagikaze', 'Okinami'
}

local ignored_ships = {
	'Fubuki',
}

local args_grammar = {
	node           = '^%s*(%a)%s*$',
	comma_list     = '[^,]+',
	ship_and_nodes = '^%s*(.-)%s*:%s*(.-)%s*$',
	just_node      = '^%s*(%a)%s*$',
	node_and_diff  = '^%s*(%a)%s*/%s*(%S-)%s*$',
	-- TODO:
	-- * Add battle ranks:
	-- node_diff_rank = '^%s*(%a)%s*/%s*(%S-)%s*/%s*(%a)%s*$',
	-- * Hide difficulty:
	-- node_rank = '^%s*(%a)%s*//%s*(%a)%s*$',
	-- * Tooltips with extra info?
}

local diff_colors = {
	['Easy']   = '5a5',
	['Medium'] = 'da6',
	['Hard']   = 'd33',
	['?']      = '0ff'
}

local diff_names = {
	['Easy']   = 'Easy+',
	['Medium'] = 'Medium+',
	['Hard']   = 'Hard+',
	['?']      = '?'
}

function find(tbl, v_, k_)
	for _, v in pairs(tbl) do
		if k_ and v[k_] == v_ or not k_ and v == v_ then
			return true
		end
	end
	return false
end

function parseArgs(args)

	local tbl = { nodes = {}, rows = {}, debug = '' }

	function log(message, value)
		tbl.debug = tbl.debug .. string.format('%s: %s\n', message, value)
	end

	if not args.nodes then
		log('info', 'empty table')
		return tbl
	end

	-- header args
	local boss = args.boss and string.upper(args.boss) or '?'
	for node_ in string.gmatch(args.nodes, args_grammar.comma_list) do
		local node = node_:match(args_grammar.node)
		if node then
			local node = string.upper(node)
			if find(tbl.nodes, node, 'name') then
				log('node duplicate', node)
			else
				table.insert(tbl.nodes, { name = node, boss = node == boss })
			end
		else
			log('node syntax error', node_)
		end
	end
	if not find(tbl.nodes, boss, 'name') then
		log('boss node ignored', boss)
	end

	-- ship args
	for arg_name, ship_and_nodes in pairs(args) do
		if tonumber(arg_name) then
			local ship, nodes = ship_and_nodes:match(args_grammar.ship_and_nodes)
			if ship and nodes then
				local ship_table = Ship:get_table(ship, '')
				if ship_table and ship_table._type then
					if find(tbl.rows, ship, 'ship') then
						log('ship duplicate', ship)
					elseif find(ignored_ships, ship) then
						log('ship ignored', ship)
					else
						table.insert(tbl.rows, {
							ship = ship,
							rare = find(rare_ships, ship),
							type = Formatting:format_ship_code(ship_table._type) or '?',
							nodes = {}
						})
						local row = tbl.rows[#tbl.rows]
						for _, node in pairs(tbl.nodes) do
							row.nodes[node.name] = nil
						end
						for node_and_diff in string.gmatch(nodes, args_grammar.comma_list) do
							local node, diff = node_and_diff:match(args_grammar.node_and_diff)
							if not node or not diff then
								node = node_and_diff:match(args_grammar.just_node)
								diff = nil
							end
							if node then
								local node = string.upper(node)
								if row.nodes[node] then
									log('ship node duplicate', string.format('%s for %s', node, ship))
								elseif not find(tbl.nodes, node, 'name') then
									log('node ignored', string.format('%s for %s', node, ship))
								else
									row.nodes[node] = {
										color = diff and diff_colors[diff] or diff_colors['?'],
										diff = diff and diff_names[diff] or '?'
									}
								end
							else
								log('ship node syntax error', string.format('%s for %s', node_and_diff, ship))
							end
						end
					end
				else
					log('ship ignored', ship)
				end
			else
				log('ship syntax error', ship_and_nodes)
			end
		end
	end

	return tbl

end

local table_format = {
	header           = '{| class="article-table sortable" align="center" width="100%" style="text-align:center"\n!Type\n!Ship\n',
	header_node      = '!${node}\n',
	header_boss_node = '!style="background-color:pink;color:red;"|\'\'\'${node}\'\'\'\n',
	row              = '|- class="drop-list-non-rare-ship"\n',
	rare_row         = '|-\n',
	type_cell        = '|${type}\n',
	-- TODO: japanese tooltips
	ship_cell        = '|[[${ship}]]\n',
	rare_ship_cell   = '|[[${ship}|<span style="color:red;">${ship}</span>]]\n',
	node_cell        = '|style="background-color:#${color};"|${diff}\n',
	empty_cell       = '|\n',
	footer           = '|}\n',
	debugger         = [[{| style="width:100%;" align="center" cellspacing="0" class="article-table mw-collapsible mw-collapsed"
!Script warnings
|-
|<pre>${debug}</pre>
|}]]
}

function showTable(tbl)

	local res = table_format.header

	function add(str)
		res = res .. str
	end

	function add_row(row)
		add(row.rare and table_format.rare_row or table_format.row)
		add(format{table_format.type_cell, type = row.type})
		add(format{
			row.rare and table_format.rare_ship_cell or table_format.ship_cell,
			ship = row.ship
		})
		for _, node in pairs(tbl.nodes) do
			local node = row.nodes[node.name]
			add(node and format{
				table_format.node_cell, color = node.color, diff = node.diff
			} or table_format.empty_cell)
		end
	end

	-- header
	for _, node in pairs(tbl.nodes) do
		add(format{
			node.boss and table_format.header_boss_node or table_format.header_node,
			node = node.name
		})
	end

	-- rows
	for _, row in pairs(tbl.rows) do
		-- TODO: Sort by type/name
		if row.rare then
			add_row(row)
		end
	end
	for key, row in pairs(tbl.rows) do
		-- TODO: Sort by type/name
		if not row.rare then
			add_row(row)
		end
	end

	add(table_format.footer)

	if tbl.debug ~= '' then
		add(format{table_format.debugger, debug = tbl.debug})
	end

	return res

end

local DropList = {}

function DropList.show(frame)
	local args = getArgs{frame = frame:getParent()}
	return showTable(parseArgs(args))
end

return DropList