This module depends on the following other modules: |
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