Module:Card

From Sekaipedia

To generate {{Card}}, invoke using the main function.


--------------------------
-- Module for [[Template:Card]]
------------------------
local constants = require('Module:Constants')
local utils     = require('Module:Utilities')
local icons     = require('Module:Icons')._main

local p = {}
local categories = ""

local palette = {
	['background-color'] = '#000',
	['color'] = '#fff'
}

local tagmap = {
	th = 'th',
	td = 'td',
	argth = 'th',
	argtd = 'td'
}

function shouldShow(args, param_names)
    if param_names and #param_names > 0 then
    	local actual_values = {}
	    for i,v in ipairs(param_names) do
	    	if args[v] and args[v] ~= '' then
	        	table.insert(actual_values, args[v])
        	end
	    end
        
        if #actual_values == 0 then
            return false
        end
    end
    
    return true
end


function createRow(args, cols, options)
	local default_css = nil
    if options then
        if not shouldShow(args, options.hideIfEmpty) then
        	return nil
        end
		if options.default_css then
			default_css = options.default_css
		end
    end
	
	local _row = mw.html.create('tr')
	for _,v in ipairs(cols) do
		local _cell = _row:tag(tagmap[v.tag] or 'td')
		
		if v.attr then
			_cell:attr(v.attr)
		end
		if v.colspan then
			_cell:attr('colspan', v.colspan)
		end
		if v.rowspan then
			_cell:attr('rowspan', v.rowspan)
		end
		if default_css then
			_cell:css(default_css)
		end
		if v.css then
			_cell:css(v.css)
		end
		
		if v.tag == 'th' or v.tag == 'td' then
			_cell:wikitext(v.content)
		elseif v.tag == 'argth' or v.tag == 'argtd' then
			local content = args[v.content]
			
			if v.func and content and content ~= '' then
				if type(v.func) == "function" then
					content = v.func(content)
				elseif type(v.func) == "table" then
					content = v.func[content]
				end
			end
			
			if content and content ~= '' then
				_cell:wikitext(content)
			else
				_cell:tag('span'):addClass('plainlinks')
				:wikitext(
					string.format("[%s?action=edit ? (edit)]",
						tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
					)
				)
			end
		end
	end
	
	return _row
end


local function editIfNil(value, func)
	if value and value ~= '' then
		if func then
			return func(value)
		end
		
		return value
	end
	
	return string.format(
		"<span class=\"plainlinks\">[%s?action=edit ? (edit)]</span>",
		tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
	)
end


local function makeHeader(header)
	return mw.html.create('div')
		:css({
			['text-align'] = 'center',
			['font-weight'] = 'bold',
			['padding'] = '0.2em 0',
			['margin-bottom'] = '1em'
		})
		:css(palette)
		:wikitext(header):done()
end

local function makeInformation(args)

	local function formatThumbnail(image)
		return string.format('<div style="display: inline-block; margin: 0 5px">[[File:%s|130px]]</div>', image)
	end
	
	local thumbnail = mw.html.create('td'):attr({
		['colspan'] = 2,
		['height'] = '145px',
	}):css({
		['text-align'] = 'center'
	});
	
	if args['character'] then
		categories = categories .. string.format('[[Category:%s Cards]]', args['character'])
	end
	
	if args['rarity'] then
		if tonumber(args['rarity']) <= 2 then
			thumbnail = thumbnail:wikitext(editIfNil(args['thumbnail'], formatThumbnail))
			
		elseif tonumber(args['rarity']) <= 4 then
			thumbnail = thumbnail:wikitext(
				editIfNil(args['thumbnail'], formatThumbnail)
				..
				editIfNil(args['thumbnail trained'], formatThumbnail)
			)
		end
		
		if tonumber(args['rarity']) == 1 then
			categories = categories .. '[[Category:1☆ Cards]]'
		elseif tonumber(args['rarity']) == 2 then
			categories = categories .. '[[Category:2☆ Cards]]'
		elseif tonumber(args['rarity']) == 3 then
			categories = categories .. '[[Category:3☆ Cards]]'
		elseif tonumber(args['rarity']) == 4 then
			categories = categories .. '[[Category:4☆ Cards]]'
		end
	else
		thumbnail = thumbnail:wikitext(string.format(
			"<span class=\"plainlinks\">[%s?action=edit ? (edit)]</span>",
			tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
		))
	end
	
	if args['attribute'] then
		if args['attribute'] == 'cool' then
			categories = categories .. '[[Category:Cool Cards]]'
		elseif args['attribute'] == 'cute' then
			categories = categories .. '[[Category:Cute Cards]]'
		elseif args['attribute'] == 'happy' then
			categories = categories .. '[[Category:Happy Cards]]'
		elseif args['attribute'] == 'mysterious' then
			categories = categories .. '[[Category:Mysterious Cards]]'
		elseif args['attribute'] == 'pure' then
			categories = categories .. '[[Category:Pure Cards]]'
		end
	end
	
	if args['status'] then
		if args['status'] == 'Permanent' then
			categories = categories .. '[[Category:Permanent Cards]]'
		elseif args['status'] == 'Limited' then
			categories = categories .. '[[Category:Limited Cards]]'
		end
	end
	
	
	local function formatUnitIcon(unit)
		return string.format(
			"%s [[%s]]",
			icons({ unit, size = '20px' }),
			constants.get_unit(unit)
		)
	end
	
	local support_unit = nil
	if constants.get_unit(args['unit']) == 'VIRTUAL SINGER' then
		support_unit = createRow(args, 
			{
				{ tag = 'th', content = 'Support Unit', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'support unit', func = formatUnitIcon }
			}, { hideIfEmpty = { 'support unit' } }
		)
	end
	
	
	return mw.html.create('table')
			:addClass('wikitable')
			:css('width', '100%')
			:tag('tr')
				:node(thumbnail)
				:done()
			:node(createRow(args, {
				{ tag = 'th', content = 'Japanese', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'japanese' }
			}))
			:node(createRow(args, {
				{ tag = 'th', content = 'Romaji', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'romaji' }
			}))
			:node(createRow(args, {
				{ tag = 'th', content = 'English', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'card name' }
			}))
			:tag('tr')
				:tag('td'):attr('colspan', 2):done()
				:done()
			:node(createRow(args, {
				{ tag = 'th', content = 'Character', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'character', func = 
					function (value) return string.format('[[%s]]', value) end
				}
			}))
			:node(createRow(args, {
				{ tag = 'th', content = 'Attribute', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'attribute', func = 
					function (value)
						return string.format(
							"%s %s",
							icons({ value, size = '20px' }),
							utils.capitalize(value)
						)
					end
				}
			}))
			:node(createRow(args, {
				{ tag = 'th', content = 'Rarity', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'rarity', func = 
					function (value)
						return icons({ value .. " star", size = '20px' })
					end
				}
			}))
			:node(createRow(args, {
				{ tag = 'th', content = 'Unit', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'unit', func = formatUnitIcon }
			}))	
			:node(support_unit)
			:tag('tr')
				:tag('td'):attr('colspan', 2):done()
				:done()
			:node(createRow(args, {
				{ tag = 'th', content = 'Status', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'status', func = utils.capitalize }
			}))
			:node(createRow(args, {
				{ tag = 'th', content = 'Release Date', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'date' }
			}))
			:node(createRow(args, {
				{ tag = 'th', content = 'Obtainment Method', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'obtain' }
			}))
			:node(createRow(args, 
				{
					{ tag = 'th', content = 'Associated Event', attr = { width = '150px' } },
					{ tag = 'argtd', content = 'event', func = 
						function (value) return string.format('[[%s]]', value) end
					}
				},
				{ hideIfEmpty = { 'event' } }
			))
			:node(createRow(args,
				{
					{ tag = 'th', content = 'Debut Banner', attr = { width = '150px' } },
					{ tag = 'argtd', content = 'banner' }
				},
				{ hideIfEmpty = { 'banner' } }
			))
			:done()
end	

local function makeSkillName(args)
	return mw.html.create('table'):addClass('wikitable'):css('width', '100%')
		:node(createRow(args, {
			{ tag = 'th', content = 'Skill Name', colspan = 2 }
		}))
		:node(createRow(args, {
			{ tag = 'th', content = 'Japanese', attr = { width = '150px' } },
			{ tag = 'argtd', content = 'skill name japanese' }
		}))
		:node(createRow(args, {
			{ tag = 'th', content = 'Romaji', attr = { width = '150px' } },
			{ tag = 'argtd', content = 'skill name romaji' }
		}))
		:node(createRow(args, {
			{ tag = 'th', content = 'English', attr = { width = '150px' } },
			{ tag = 'argtd', content = 'skill name english' }
		}))
		:done()
end

local function makeSkillEffect(args)
	local skill_types = {
		['scorer']  = {
			effect = "%d%% score boost for 5 seconds.",
			['1'] = { { 20 }, { 25 }, { 30 }, { 40 } },
			['2'] = { { 30 }, { 35 }, { 40 }, { 50 } },
			['3'] = { { 60 }, { 65 }, { 70 }, { 80 } },
			['4'] = { { 100 }, { 105 }, { 110 }, { 120 } }
		},
		['plocker'] = {
			effect = "All %ss and higher will become PERFECTs for  %.1f seconds; %d%% score boost for 5 seconds.",
			['2'] = { { 'GREAT', 4.5, 10 }, { 'GREAT', 5, 15 }, { 'GREAT', 5.5, 20 }, { 'GREAT', 6, 30 } },
			['3'] = { { 'GOOD', 5, 40 }, { 'GOOD', 5.5, 45 }, { 'GOOD', 6, 50 }, { 'GOOD', 6.5, 60 } },
			['4'] = { { 'BAD', 5.5, 80 }, { 'BAD', 6, 85 }, { 'BAD', 6.5, 90 }, { 'BAD', 7, 100 } }
		},
		['healer']  = {
			effect = "Recover %d life; %d%% score boost for 5 seconds.",
			['2'] = { { 150, 10 }, { 200, 15 }, { 250, 20 }, { 300, 30 } },
			['3'] = { { 250, 40 }, { 300, 45 }, { 350, 50 }, { 400, 60 } },
			['4'] = { { 350, 80 }, { 400, 85 }, { 450, 90 }, { 500, 100 } }
		},
		['pscorer'] = {
			effect = "%d%% score boost for 5 seconds for PERFECTs only.",
			['4'] = { { 110 }, { 115 }, { 120 }, { 130 } }
		},
		['fes scorer'] = {
			effect = "For 5 seconds, %d%% score boost if life is less than 800 or %d%% score boost if life is 800. For every +10 life above 800, score boost increased by +1%% (up to %d%%)",
			['4'] = { { 70, 100, 120 }, { 75, 105, 125 }, { 80, 110, 130 }, { 90, 120, 140 } }
		},
		['fes pscorer'] = {
			effect = "%d%% score boost for 5 seconds. If you hit GREAT or lower, score boost will be reduced to %d%%.",
			['4'] = { { 120, 70 }, { 125, 75 }, { 130, 80 }, { 140, 90 } }
		}
	}
	
	local function skill_value(skill_level)
		if args['skill type'] and 
			args['rarity'] and
			skill_types[args['skill type']]	and
			skill_types[args['skill type']][args['rarity']] then
			
			return string.format(
				skill_types[args['skill type']]['effect'],
				unpack(skill_types[args['skill type']][args['rarity']][skill_level])
			)
		end
	
		return string.format("<span class=\"plainlinks\">[%s?action=edit ? (edit)]</span>",
			tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
		)
	end
	
	local root = mw.html.create('table'):addClass('wikitable'):css('width', '100%')
		:tag('tr')
			:tag('th'):attr('colspan', 2):wikitext('Skill Effect'):done()
			:done()
		:tag('tr')
			:tag('th'):attr('width', '150px'):wikitext('Level 1'):done()
			:tag('td'):wikitext(skill_value(1)):done()
			:done()
		:tag('tr')
			:tag('th'):attr('width', '150px'):wikitext('Level 2'):done()
			:tag('td'):wikitext(skill_value(2)):done()
			:done()
		:tag('tr')
			:tag('th'):attr('width', '150px'):wikitext('Level 3'):done()
			:tag('td'):wikitext(skill_value(3)):done()
			:done()
		:tag('tr')
			:tag('th'):attr('width', '150px'):wikitext('Level 4'):done()
			:tag('td'):wikitext(skill_value(4)):done()
			:done()
		:done()
		
	return root
end

local function makeStatsInfo(args)
	local max_levels = {
		['1'] = '20',
		['2'] = '30',
		['3'] = '50',
		['4'] = '60'
	}
	
	assert((tonumber(args['min power']) or 0) == 
			(tonumber(args['min performance']) or 0) +
			(tonumber(args['min stamina']) or 0) +
			(tonumber(args['min technique']) or 0))
		
	local max_level = '?'
	if args['rarity'] ~= nil then
		max_level = max_levels[args['rarity']]
		assert((tonumber(args['max power']) or 0) == 
			(tonumber(args['max performance']) or 0) +
			(tonumber(args['max stamina']) or 0) +
			(tonumber(args['max technique']) or 0))
	end
	
	return mw.html.create('table'):addClass('wikitable'):css('width', '100%')
			:tag('tr')
				:tag('th'):done()
				:tag('th'):wikitext('Level 1'):done()
				:tag('th'):wikitext('Level ' .. max_level):done()
				:done()
			:node(createRow(args, {
				{ 
					tag = 'th', 
					content = string.format(
						"%s %s",
						icons({ 'performance', size ='25px'}),
						'Performance'
					),
					attr = { width = '150px' }
				},
				{ tag = 'argtd', content = 'min performance' },
				{ tag = 'argtd', content = 'max performance' },
			}))
			:node(createRow(args, {
				{ tag = 'th', content = '[[File:Icon stamina.png|25px|link=]] Stamina', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'min stamina' },
				{ tag = 'argtd', content = 'max stamina' }
			}))
			:node(createRow(args, {
				{ tag = 'th', content = '[[File:Icon technique.png|25px|link=]] Technique', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'min technique' },
				{ tag = 'argtd', content = 'max technique' }
			}))
			:node(createRow(args, {
				{ tag = 'th', content = 'Power', attr = { width = '150px' } },
				{ tag = 'argtd', content = 'min power' },
				{ tag = 'argtd', content = 'max power' }
			}))
			:done()
end

local function makeArtSwitch(args)
	local root = mw.html.create('div'):css({ ['text-align'] = 'center' })
	
	local function image_format(image_name)
		return string.format('[[File:%s|600px]]', image_name)
	end
	
	if args['rarity'] then
		if tonumber(args['rarity']) <= 2 then
			return root:wikitext(editIfNil(args['art'], image_format))
			
		elseif tonumber(args['rarity']) <= 4 then
			return root:wikitext(mw.getCurrentFrame():callParserFunction({
				name = '#tag',
				args = {
					'tabber',
					string.format(
						'Untrained=%s|-|Trained=%s',
						editIfNil(args['art'], image_format),
						editIfNil(args['art trained'], image_format)
					)
				}
			}))
		end
	end
	
	return root:tag('span')
		:addClass('plainlinks')
		:wikitext(
			string.format("[%s?action=edit ? (edit)]",
				tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
			)
		):done()
end

function p.main(frame)
	local raw_args = frame:getParent().args
	local proc_args = {
		['card id'] = raw_args['card id'],
		['card name'] = raw_args['card name'] or mw.title.getCurrentTitle().text,
		['japanese']   = raw_args['japanese'],
		['romaji']     = raw_args['romaji'],
		['thumbnail'] = raw_args['thumbnail'],
		['thumbnail trained'] = raw_args['thumbnail trained'],
		['character'] = raw_args['character'],
		['attribute'] = raw_args['attribute'],
		['status'] = raw_args['status'],
		['date']   = raw_args['date'],
		['obtain'] = raw_args['obtain'], -- how to obtain?
		['event']  = raw_args['event'],
		['banner'] = raw_args['banner'],
		['unit']    = raw_args['unit'],
		['support unit'] = raw_args['support unit'],
		['skill name japanese'] = raw_args['skill name japanese'],
		['skill name romaji']   = raw_args['skill name romaji'],
		['skill name english']  = raw_args['skill name english'],
		['skill type'] = raw_args['skill type'],
		['min performance'] = raw_args['min performance'],
		['min technique']   = raw_args['min technique'],
		['min stamina']     = raw_args['min stamina'],
		['min power']       = raw_args['min power'],
		['max performance'] = raw_args['max performance'],
		['max technique']   = raw_args['max technique'],
		['max stamina']     = raw_args['max stamina'],
		['max power']       = raw_args['max power'],
		['art']         = raw_args['art'], 
		['art trained'] = raw_args['art trained']
	}
	
	if tonumber(raw_args['rarity']) and
		tonumber(raw_args['rarity']) >= 1 and
		tonumber(raw_args['rarity']) <= 4
	then
		proc_args['rarity'] = raw_args['rarity']
	else
		proc_args['rarity'] = nil
	end
	
	if tonumber(proc_args['base performance']) and
		tonumber(proc_args['base technique']) and
		tonumber(proc_args['base stamina'])
	then
		proc_args['base power'] = proc_args['base performance'] + proc_args['base technique'] + proc_args['base stamina']
	else
		proc_args['base power'] = nil
	end
	
	if proc_args['attribute'] then
		palette = constants.get_attribute_colors(proc_args['attribute']) or palette
	end
	
	
	local top = mw.html.create('div')
		:css({
			['padding'] = '0.8em 0',
			['text-align'] = 'center',
			['font-weight'] = 'bold',
			['font-size'] = '1.15em',
			['line-height'] = '1.5em'
		})
		:css(palette)
		:wikitext(proc_args['card name'])
		:done()
	
	local middle = mw.html.create('div')
			:css({
				['display'] = 'flex',
				['gap'] = '24px',
				['flex-wrap'] = 'wrap',
				['margin'] = '24px 0'
			})
			:tag('div')
				:css('flex', '1 1 600px')
				:node(makeHeader('Card Information'))
				:node(makeInformation(proc_args))
				:done()
			:tag('div')
				:css('flex', '1 1 600px')
				:node(makeHeader('Card Art'))
				:node(makeArtSwitch(proc_args))
				:done()
			:tag('div')
				:css('flex', '1 1 600px')
				:node(makeHeader('Card Skill'))
				:node(makeSkillName(proc_args))
				:node(makeSkillEffect(proc_args))
				:done()
			:tag('div')
				:css('flex', '1 1 600px')
				:node(makeHeader('Card Stats'))
				:node(makeStatsInfo(proc_args))
				:done()
			:tag('div') -- 'hack' to maintain same width in a 3-1 layout
				:css('flex', '1 1 600px')
				:done()
			:tag('div') -- 'hack' to maintain same width in a 3-1 layout
				:css('flex', '1 1 600px')
				:done()
			:done()

	if mw.title.getCurrentTitle().namespace == 0 then
		categories = "[[Category:Cards]]" .. categories
	else
		categories = ""	
	end
	
	return tostring(top) ..
		tostring(middle) ..
		categories
end

return p
Cookies help us deliver our services. By using our services, you agree to our use of cookies.