Module:Sandbox/User:Californ1a/T/Professions

From Brighter Shores Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Sandbox/User:Californ1a/T/Professions/doc

require('strict')
require('Module:Mw.html extension')
local pt = require('Module:Paramtest')
local yn = require('Module:Yesno')
local lang = mw.language.getContentLanguage()
local p = {}

local icon_size = 20
local ep_icon_size = 16

-- List episodes with their professions
local episodes = {
	hopeport = {"guard", "chef", "fisher", "forager", "alchemist"},
	hopeforest = {"scout", "gatherer", "woodcutter", "carpenter"},
	mine = {"minefighter", "bonewright", "miner", "blacksmith", "stonemason"},
	crenopolis = {"watchperson", "detective", "leatherworker", "merchant"}
}

local ep_dict = {
	hopeport = 'Hopeport',
	hopeforest = 'Hopeforest',
	mine = 'Mine of Mantuban',
	crenopolis = 'Crenopolis'
}

local ep_color = {
	hopeport = '#b99f46',
	hopeforest = '#84b876',
	mine = '#68ABF1',
	crenopolis = '#979797'
}

-- Get professions levels given an episode name
function p.filter_by_episode(professions, episodeName, goals)
	goals = goals or false
	local filtered = {}
	local episodeProfessions = episodes[episodeName]

	if not episodeProfessions then
		error('Invalid episode name: ' .. tostring(episodeName))
	end

	-- Add the professions and the total for the episode
	for _, profession in ipairs(episodeProfessions) do
		local val = profession
		if goals then
			val = profession..' goal'
		end
		if professions[val] ~= nil then
			filtered[val] = professions[val]
		end
	end

	-- Add the total for the episode
	if professions[episodeName] ~= nil then
		filtered[episodeName] = professions[episodeName]
	end

	return filtered
end

-- Template entrypoint
function p.main(frame)
	return p._main(frame:getParent().args)
end

function p._main(args)
	-- Create main profession and goals lists
	local professions = {
		total = 0
	}
	local goals = {}
	
	-- Build the professions + goals lists
	for episode, keys in pairs(episodes) do
		professions[episode] = 0
		for _, key in ipairs(keys) do
			-- Add the profession and goal to their respective lists
			professions[key] = pt.default_to(tonumber(args[key]), 0)
			goals[key] = pt.default_to(tonumber(args[key..' goal']), 0)
			
			-- Add this profession's level to the episode's total
			local value = professions[key] or 0
			professions[episode] = professions[episode] + value
		end
		-- Add this episode's total to the overall total
		professions.total = professions.total + professions[episode]
	end
	
	-- Non-profession config params
	local other = {
		vertical = yn(pt.default_to(args.vertical, true), true),
		free = yn(pt.default_to(args.free, false), false),
		date = pt.default_to(args.date, ''),
		right = yn(pt.default_to(args.right, false), false)
	}
	
	--local debug_str = '<pre>'..mw.text.jsonEncode(professions, mw.text.JSON_PRETTY)..', '..mw.text.jsonEncode(goals, mw.text.JSON_PRETTY)..'</pre>'

	return tostring(p.create_table(professions, goals, other))--..debug_str
end

function p.create_row(tbl, episode, professions, goals, vertical)
	if vertical then
		tbl:tag('tr')
	end
	
	-- Create icons
	local cache = {}
	for _,profession in ipairs(episodes[episode]) do
		local PRO = pt.ucflc(profession)
		local size = icon_size
		if profession == 'alchemist' then -- Alchemist icon is a bit larger than others
			size = icon_size - 5
		end
		local icon = mw.ustring.format('[[File:%s small icon.png|link=%s|%spx]]', PRO, PRO, size)
		cache[profession] = {
			name = PRO,
			icon = icon
		}
		if vertical then
			tbl:tag('td')
				:css({border='none'})
				:wikitext(icon)
			:done()
		end
	end
	
	if vertical then
		tbl:done() -- /tr
	end
	tbl:tag('tr')
	
	-- Create levels
	for _,profession in ipairs(episodes[episode]) do
		local PRO = cache[profession].name
		local lvl = tostring(professions[profession])
		if goals[profession] ~= 0 then
			lvl = lvl..'/'..tostring(goals[profession])
		end
		
		if vertical then
			tbl:tag('td')
				:css({border='none'})
				:wikitext(lvl)
			:done()
		else
			tbl:tag('td')
				:wikitext(cache[profession].icon..' '..lvl)
			:done()
		end
	end
	
	return tbl:done()
end

function p.create_episode_table(episode, professions, goals, other)
	local profession_count = #episodes[episode]
	local EP = ep_dict[episode]
	local out = mw.html.create('tr'):tag('td'):tag('table')
		:addClass('wikitable')
		:addClass('center')
		:css({margin='0', padding='0'})
		:tag('tr')
			:tag('th')
				:css({['background-color']=ep_color[episode]})
				:attr({colspan = profession_count})
				:wikitext(mw.ustring.format('[[File:%s episode icon.png|link=%s|%spx]] [[%s]] (%s)', EP, EP, ep_icon_size, EP, professions[episode]))
			:done()
		:done()
		
	out = p.create_row(out, episode, professions, goals, other.vertical)
	
	return out:done():done():done() -- /table /td /tr
end

function p.create_table(professions, goals, other)
	local ep_tbl = {}
	for episode in pairs(episodes) do
		local ep_lvls = p.filter_by_episode(professions, episode)
		local ep_goals = p.filter_by_episode(goals, episode)
		ep_tbl[episode] = p.create_episode_table(episode, ep_lvls, ep_goals, other)
	end
	
	local out = mw.html.create('table')
		:tag('caption')
			:css({['font-weight']='bold'})
			:wikitext(mw.ustring.format('[[File:Professions icon.png|link=Professions|%spx]] [[Professions]] (%s)', ep_icon_size, professions.total))
		:done()
		
		-- Inner episode tables
		:node(ep_tbl.hopeport)
		:node(ep_tbl.hopeforest)
		:IF(not other.free)
			:node(ep_tbl.mine)
			:node(ep_tbl.crenopolis)
		:END()
		
		:IF(pt.has_content(other.date))
			:tag('tr')
				:tag('td')
					:css({['text-align']='center'})
					:tag('small')
						:tag('b')
							:wikitext('Last Updated:')
						:done()
						:tag('br'):done()
						:IF(other.date == 'now')
							:wikitext(lang:formatDate('j F Y', mw.getCurrentFrame():preprocess('{{REVISIONTIMESTAMP}}')))
						:ELSE()
							:wikitext(other.date)
						:END()
					:done()
				:done()
			:done()
		:END()
		
	out:allDone()
	
	local div = out
	if other.right then
		div = mw.html.create('div')
			:css({float='right'})
			:node(out)
		:done()
	end
	
	return div
end

return p