Module:Character infobox
From Absit Omen Lexicon
Documentation for this module may be created at Module:Character infobox/doc
local p = {}
local ib = require("Module:Infobox")
local cfg = mw.loadData( "Module:Character infobox/config" )
local categories = {}
local indicators = {}
local trackingCats = {}
local comments = ''
function p._infobox(args)
processArgs(args)
local html = ib.infoboxtable('character')
local image = args.image or 'avatar.png'
local title = args.biography and
'[' .. args.biography .. ' ' .. args.fullName .. ']' or args.fullName
html:node(ib.addHeader(image,title))
for _, section in ipairs(cfg.sectionOrder) do
if (section == 'education' and args.house ~= 'None') or section ~= 'education' then
html:node(ib.addSection(cfg[section], cfg[section .. '_label'], cfg.specialRows, args, args.debug))
end
end
-- Footer
args.memberBoard = args.memberBoard and args.memberBoard or ''
html:tag('tr')
:addClass('ib-footer')
:tag('td')
:attr('colspan', '2')
:wikitext('[' .. args.memberBoard .. ' ' .. args.member .. ']')
:node(processCategories(args))
:wikitext(frame:callParserFunction('DEFAULTSORT', {args.sort_by}))
ib.cargoStore(args, cfg.cargo.Characters, 'Characters')
local wrapper = ib.infoboxdiv('character')
wrapper:node(html)
wrapper:tag('div')
:css('display', 'none')
:wikitext(comments)
return tostring(wrapper)
end
function p.infobox(frame)
local getArgs = require('Module:Arguments').getArgs
local args = getArgs(frame)
return p._infobox(args)
end
function processArgs(args)
local Date = require("Module:Date")._Date
args.status = args.status and args.status or 'inactive'
if args.status == 'npc' then
args.npc = args.npc and args.npc or 'closed'
end
-- create dates from parts, can be a partial date, year required
local birthDate = Date(args.birthYear, args.birthMonth or 'partial', args.birthDay or 'partial')
local deathDate = Date(args.deathYear, args.deathMonth or 'partial', args.deathDay or 'partial')
-- Set current date for age calculation to either current date or death date
local currentDate = deathDate or Date('currentdate')
local dateDiff = currentDate:subtract(birthDate, 'wantrange')
-- if dateDiff:age returns a table, age is a range otherwise just one number
if dateDiff then
args.age = type(dateDiff:age('y', {['range'] = true})) == 'table' and
table.concat(dateDiff:age('y', {['range'] = true}), '-') or dateDiff:age('y')
args.ageCargo = dateDiff:age('y')
if args.age == nil then
args.age = ''
table.insert(trackingCats, 'Age Calculation Issue')
end
if args.ageCargo == nil then
args.ageCargo = ''
table.insert(trackingCats, 'Age Calculation Issue')
end
end
if birthDate then
args.birthDate = birthDate:text()
args.birthDateCargo = birthDate:text('ymd')
if not(deathDate) then
args.birthDate = args.birthDate .. ', ' .. args.age
end
end
if deathDate then
args.deathDate = deathDate:text() .. ', ' .. args.age
args.deathDateCargo = deathDate:text('ymd')
end
-- Full name
-- If givenname and surname arent set, use the page title
if args.givenname and args.surname then
local nameOrder = {'givenname', 'middlename', 'surname', 'suffix', 'maidenname'}
local sortOrder = {'surname', 'givenname', 'middlename', 'suffix'}
local name = {}
local sort = {}
-- Loop through name parts in args in proper order
for i = 1, #nameOrder do
-- If its the pre-married name, add () around it
if nameOrder[i] == 'maidenname' and args[nameOrder[i]] then
table.insert(name, '(' .. args[nameOrder[i]] .. ')')
-- otherwise if the part of the name is set, add it to the table
elseif args[nameOrder[i]] then
table.insert(name, args[nameOrder[i]])
end
end
-- Loop through name parts in args in sort order
for i = 1, #sortOrder do
-- if the part of the name is set, add it to the table
if args[sortOrder[i]] then
table.insert(sort, args[sortOrder[i]])
end
end
-- Concat and add the full name to args
args.fullName = table.concat(name, ' ')
args.sort_by = table.concat(sort, ' ')
else
args.fullName = mw.title.getCurrentTitle().text
args.sort_by = mw.title.getCurrentTitle().text
end
-- Grad Year
if args.birthYear and args.birthMonth and args.hideYear ~= 'Yes' then
args.gradYear = args.birthYear + 11 + 7
if tonumber(args.birthMonth) >= 9 then
args.gradYear = args.gradYear + 1
end
end
-- School Year
if not(args.deathDate) and args.gradYear then
year = args.gradYear - currentDate:text('%{year}')
if tonumber(currentDate:text('%{month}')) <= 8 then
year = year + 1
end
if year > 0 and year < 8 then
local yearTxt = {'Seventh Year', 'Sixth Year', 'Fifth Year', 'Fourth Year', 'Third Year', 'Second Year', 'First Year'}
args.schoolYear = yearTxt[year]
end
end
-- School
if args.house then
args.house = args.house:gsub("(%a)([%w_']*)", ib.tchelper)
end
schoolCheck(args)
-- Bio/Network/Thread links
if args.biography or args.network or args.threads then
html = mw.html.create('ul')
html:addClass('hlist')
if args.biography then
html:tag('li'):wikitext('[' .. args.biography .. ' Biography]')
html:done()
end
if args.network then
html:tag('li'):wikitext('[' .. args.network .. ' Network]')
html:done()
end
if args.threads then
html:tag('li'):wikitext('[' .. args.threads .. ' Threads]')
html:done()
end
args.links = tostring(html)
end
-- Family Processing
frame = mw.getCurrentFrame()
--Parents
args.fatherProcessed = args.father and frame:callParserFunction('#formredlink', {'test', target=args.father, form="Character"})
args.stepmotherProcessed = args.stepmother and frame:callParserFunction('#formredlink', {'test', target=args.stepmother, form="Character"})
args.stepfatherProcessed = args.stepfathr and frame:callParserFunction('#formredlink', {'test', target=args.stepfather, form="Character"})
args.motherProcessed = args.mother and frame:callParserFunction('#formredlink', {'test', target=args.mother, form="Character"})
args.adoptiveFatherProcessed = args.adoptiveFather and frame:callParserFunction('#formredlink', {'test', target=args.adoptiveFather, form="Character"})
args.adoptiveMotherProcessed = args.adoptiveMother and frame:callParserFunction('#formredlink', {'test', target=args.adoptiveMother, form="Character"})
-- Siblings
if args.siblings then
siblings = mw.html.create('ul')
siblingsCargo = {}
for name in string.gmatch(args.siblings, '([^\n]+)\n?') do
siblings:tag('li')
:wikitext(frame:callParserFunction('#formredlink', {'test', target=name, form="Character"}))
:done()
table.insert(siblingsCargo, name)
end
args.siblingsProcessed = tostring(siblings)
args.siblingsCargo = table.concat( siblingsCargo, ";")
end
-- Children
if args.children then
children = mw.html.create('ul')
childrenCargo = {}
for name in string.gmatch(args.children, '([^\n]+)\n?') do
children:tag('li')
:wikitext(frame:callParserFunction('#formredlink', {'test', target=name, form="Character"}))
:done()
table.insert(childrenCargo, name)
end
args.childrenProcessed = tostring(children)
args.childrenCargo = table.concat( childrenCargo, ";")
end
-- Extended Family
if args.extFamily then
extFamily = mw.html.create()
for name, relation in string.gmatch(args.extFamily, '([^%(%)]+)%s+%(([^\n]+)%)\n?') do
extFamily:tag('li')
:wikitext(frame:callParserFunction('#formredlink', {'test', target=name, form="Character"}) .. ' (' .. relation .. ')')
:done()
end
args.extFamilyProcessed = tostring(extFamily)
end
-- Family Tree
-- Weirdness with parser required removing http(s) from link so that it would not be processed and duplicated
if args.familyTree then
familyTree = string.match(args.familyTree or '', '^https?:(.*)')
if familyTree then
args.familyTree = '['.. familyTree .. ' Family Tree]'
end
end
-- Categories based on parameters except occupation
if args.deathDate then
table.insert(categories, 'Deceased')
if args.species and string.lower(args.species) == 'ghost' then
table.insert(categories, 'Characters')
else
table.insert(categories, 'Retired Characters')
end
else
table.insert(categories, 'Characters')
status = args.status and string.lower(args.status)
if status == 'retired' then
table.insert(categories, 'Retired Characters')
elseif status == 'active' then
table.insert(categories, 'Active')
elseif status == 'inactive' then
table.insert(categories, 'Inactive')
elseif status == 'secondary' then
table.insert(categories, 'Secondary Characters')
elseif status == 'npc' then
table.insert(categories, 'Non-Player Character')
table.insert(indicators, {'character',
'[[File:' .. args.npc .. '.svg|x35px|link=NPC Permissions|alt=' .. args.npc .. ' permission]]'})
end
end
if (dateDiff and dateDiff.partial) or args.birthDate == nil then
table.insert(trackingCats, 'Unknown Birthdate')
end
if args.species then table.insert(categories, args.species) end
if args.canon == 'yes' then
table.insert(categories, 'Canon')
table.insert(indicators, {'canon', '[[File:Canon.svg|x35px|link=Canon|alt=Canon Character]]'})
end
if args.blood then
table.insert(categories, args.blood)
else
table.insert(trackingCats, 'Unknown Blood Status')
end
if args.specialAbilities then
if string.find(args.specialAbilities, ',') then
for ability in mw.text.gsplit(args.specialAbilities, ',', true) do
table.insert(categories, ability)
end
else
table.insert(categories, args.specialAbilities)
end
end
if args.biography == nil and args.status ~= 'npc' then
table.insert(trackingCats, 'Missing Biography')
end
end
function schoolCheck(args)
if args.hideYear == 'Yes' then
table.insert(trackingCats, 'HideYear Tracker')
end
for _, value in ipairs(cfg.schools.Hogwarts) do
if args.house == value then
args.school = 'Hogwarts'
args.house = args.house
table.insert(indicators, {'house', '[[File:' .. args.house .. '.png|x35px|link=' .. args.house .. ']]'})
yearCategories(args)
return
end
end
for _, value in ipairs(cfg.schools.Schools) do
if args.house == value then
args.school = args.house
args.house = nil
if args.school == 'Durmstrang Institute' or args.school == 'Beauxbatons Academy' then
table.insert(indicators, {'house', '[[File:' .. args.school .. '.png|x35px|link=' .. args.school .. ']]'})
end
yearCategories(args)
return
end
end
if args.house == 'Home Schooled' then
args.homeschool = 'Home Schooled'
args.house = nil
table.insert(categories, 'Home Schooled')
elseif args.house == 'Undecided' then
args.schoolHouse = args.house
args.house = nil
table.insert(categories, 'Undecided House or School')
elseif args.house == 'Other' or args.house == 'Other School' then
args.school = args.house
args.house = nil
table.insert(categories, 'Other School')
elseif args.house == 'None' then
table.insert(trackingCats, 'Hidden Education Tracker')
else
args.schoolHouse = 'Unknown House or School'
args.house = nil
table.insert(trackingCats, 'Unknown House or School')
end
end
function yearCategories(args)
local house = args.house and args.house or args.school
if args.gradYear then
table.insert(categories, 'Class of ' .. args.gradYear)
table.insert(categories, house .. ' Class of ' .. args.gradYear)
end
if args.schoolYear then
table.insert(categories, args.schoolYear)
table.insert(categories, house)
table.insert(categories, house .. ' ' .. args.schoolYear)
else
table.insert(categories, house .. ' Alumni')
end
end
function p.getParams(args)
local tbl = {}
for k, v in pairs(args) do
tbl[#tbl+1] = ('*%s: %s'):format(k, v)
end
return table.concat(tbl, '\n')
end
--Sections
function p.classes(frame)
local getArgs = require('Module:Arguments').getArgs
local args = getArgs(frame)
ib.cargoStore(args, cfg.cargo.Classes, 'Classes')
return '<div style="display:none">Classes Included</div>'
end
function p.occupation(frame)
local getArgs = require('Module:Arguments').getArgs
local args = getArgs(frame)
local occupationOrder = {'office', 'division', 'department', 'organization'}
local occupation_label = {}
occupation_label.title = args.current == 'no' and 'Former Title' or 'Title'
processOccupationArgs(args, occupation_label)
local html = mw.html.create()
if args.title then
html
:tag('dt')
:wikitext(occupation_label.title .. ': ' .. args.title)
:done()
end
if args.startDate or args.endDate then
html
:tag('dd')
:wikitext((args.startDate or '') .. '-' .. (args.endDate or ''))
:done()
end
for _, value in ipairs(occupationOrder) do
if args[value] then
if occupation_label[value] then
html
:tag('dd')
:wikitext(occupation_label[value] .. ': [[' .. args[value] .. ']]')
:done()
else
html
:tag('dd')
:wikitext('[[' .. args[value] .. ']]')
:done()
end
end
end
html:node(processCategories(args))
ib.cargoStore(args, cfg.cargo.Occupations, 'Occupations')
return html
end
function processOccupationArgs(args, label)
local Date = require("Module:Date")._Date
if args.current == 'yes' then
args.endDate = nil
elseif args.endDate then
endDate = mw.text.split(args.endDate, '%p')
endDate = Date(endDate[1], endDate[2] or 'partial', endDate[3] or 'partial')
args.endDate = endDate:text()
args.endDateISO = endDate:text('ymd')
end
if args.startDate then
startDate = mw.text.split(args.startDate, '%p')
startDate = Date(startDate[1], startDate[2] or 'partial', startDate[3] or 'partial')
args.startDate = startDate:text()
args.startDateISO = startDate:text('ymd')
end
if args.type == 'Ministry' then
args.organization = 'Ministry of Magic'
args.office = args.ministryOffice
args.division = args.ministryDivision
args.department = args.ministryDepartment
label.office = 'Office'
label.division = 'Division'
label.department = 'Department'
if args.office == 'Auror Office' then
table.insert(categories, 'Aurors')
elseif args.office == 'Wizengamot' then
table.insert(categories, 'Wizengamot Members')
end
if args.ministryDepartment then
table.insert(categories, args.ministryDepartment .. ' Personnel')
end
table.insert(categories, 'Ministry Personnel')
args.ministryOffice = nil
args.ministryDivision = nil
args.ministryDepartment = nil
elseif args.type == 'St. Mungos' then
args.organization = "St. Mungo's Hospital"
args.department = args.mungosFloor
label.department = 'Floor'
table.insert(categories, args.department)
table.insert(categories, "St. Mungo's Hospital")
args.mungosFloor = nil
elseif args.type == 'Hogwarts' then
args.organization = 'Hogwarts'
args.department = args.schoolSubject
label.department = 'Subject'
if args.schoolSubject then
table.insert(categories, 'Hogwarts Professor')
else
table.insert(categories, 'Hogwarts Staff')
end
args.schoolSubject = nil
elseif args.type == 'Quidditch' then
args.organization = args.quidditchLeague
args.department = args.quidditchTeam
label.department = 'Team'
if args.quidditchTeam then
table.insert(categories, args.quidditchTeam)
end
table.insert(categories, 'Quidditch')
args.quidditchLeague = nil
args.quidditchTeam = nil
elseif args.type == 'Other School' then
args.organization = args.school
args.department = args.schoolSubject
label.department = 'Subject'
if args.school then
table.insert(categories, args.school .. ' Staff')
end
args.school = nil
args.schoolSubject = nil
elseif args.type == 'Other' or type == 'Criminal' then
args.organization = args.employer
label.organization = 'Employer'
args.employer = nil
elseif args.type == 'Journalist' then
args.organization = args.publication
label.organization = 'Publication'
table.insert(categories, 'Journalist')
args.title = args.title and args.title or 'Journalist'
args.publication = nil
elseif args.type == 'Criminal' then
args.organization = args.employer
label.organization = 'Employer'
args.title = args.title and args.title or 'Criminal'
table.insert(categories, 'Criminal')
args.employer = nil
elseif args.type == 'Gringotts' then
args.organization = 'Gringotts Wizarding Bank'
table.insert(categories, 'Gringotts')
elseif args.type == 'Business Owner' then
args.organization = args.business
label.organization = 'Business'
args.title = args.title and args.title or 'Owner'
table.insert(categories, 'Business Owner')
args.business = nil
end
args.title = args.title and args.title or 'Employee'
end
function p.wand(frame)
local getArgs = require('Module:Arguments').getArgs
local args = getArgs(frame)
html = mw.html.create('li')
args.wand = args.wand or 'Wand'
if args.wandmaker then
html:wikitext(('%s (Made by %s)'):format(args.wand, args.wandmaker))
else
html:wikitext(args.wand)
end
ib.cargoStore(args, cfg.cargo.Wands, 'Wands')
return html
end
function p.relationship(frame)
local Date = require("Module:Date")._Date
local getArgs = require('Module:Arguments').getArgs
local args = getArgs(frame)
if not(args.relationshipWith) then
return
end
if args.relationshipType and args.endDate then
relationshipType = 'Dated'
else
relationshipType = 'Dating'
end
if args.endType == 'Divorce' then
endType = '(Divorced)'
elseif args.endType == 'Separation' then
endType = '(Separated)'
elseif args.endType == 'Death' then
endType = '(Widowed)'
else
endType = ''
end
html = mw.html.create('li')
if args.relationshipType then
html
:wikitext(args.relationshipType .. ': ')
end
if args.relationshipWith then
html
:wikitext('[[' .. args.relationshipWith .. ']] ' .. endType)
end
ib.cargoStore(args, cfg.cargo.Relationships, 'Relationships')
return html
end
function processCategories(args)
if args.hideCategories then
return
end
html = mw.html.create('')
for _,value in ipairs(categories) do
html:wikitext(('[[Category:%s]]'):format(value))
end
for _,value in ipairs(trackingCats) do
html:wikitext(('[[Category:%s]]'):format(value))
end
for _,value in ipairs(indicators) do
local indicator = frame:extensionTag{ name = 'indicator', content = value[2], args = { name = value[1]} }
html:wikitext(indicator)
end
return html
end
return p