-- module for Marvel Database:Character Template
local p = {}
local getArgs = require('Dev:Arguments').getArgs
local h = require("Module:HF")
local design = require('Module:Design')
local units = require('Module:Units')
local list_of_power_grids = mw.loadData('Module:Power Grid/List')
function p.main(frame)
local args = getArgs(frame)
local pagename = mw.title.getCurrentTitle().text
local page_type = 'Character'
local value
local categories = {}
local output_categories = {}
local output = {}
output_categories = p.lua_get_outdated_fields(args, pagename)
-- sections
-- adds 'Quote', 'Overview' section, 'TOC' and 'History' section
value, categories = design.add_quote_overview_toc_history(args, page_type)
output_categories = h.join_tables(output_categories, categories)
output = h.join_tables(output, value)
table.insert( output, design.add_section('Personality', args.Personality, 2) )
if not h.isempty(args.Powers)
or not h.isempty(args.Abilities)
or not h.isempty(args.Weaknesses)
or not h.isempty(args.AdditionalAttributes)
or list_of_power_grids[pagename] ~= nil
then
table.insert( output, design.add_header('Attributes', 2) )
if list_of_power_grids[pagename] ~= nil
then
value, categories = require('Module:Power Grid').main(pagename)
output_categories = h.join_tables(output_categories, categories)
table.insert(output, value)
end
table.insert( output, design.add_section('Powers', args.Powers, 3) )
table.insert( output, design.add_section('Abilities', args.Abilities, 3) )
table.insert( output, design.add_section('Weaknesses', args.Weaknesses, 3) )
table.insert( output, design.add_section('Additional Attributes', args.AdditionalAttributes, 3) )
end
if not h.isempty(args.Equipment) or not h.isempty(args.Weapons)or not h.isempty(args.Transportation)
then
table.insert( output, design.add_header('Paraphernalia', 2) )
table.insert( output, design.add_section('Equipment', args.Equipment, 3) )
table.insert( output, design.add_section('Weapons', args.Weapons, 3) )
table.insert( output, design.add_section('Transportation', args.Transportation, 3) )
end
-- adds 'Notes', 'Trivia', 'See Also', 'Recommended Reading' and 'Links and References' sections
---- links to standard sub-pages/categories - "Appearances", "Minor Appearances", Mentions", "Images", "Quotes" and "Gallery"
value, categories = design.add_notes_trivia_see_also_recommended_links_references(args, page_type, pagename)
output_categories = h.join_tables(output_categories, categories)
output = h.join_tables(output, value)
--
output_categories = h.add_categories(output_categories)
output = table.concat(output)
return frame:preprocess(output)..output_categories
end
--------------------------------------------------------------------------------------------------
function p.lua_get_outdated_fields(args, pagename)
local relatives = args.Relatives
local output_categories = {}
if not h.isempty(args.Custom)
or not h.isempty(args.CustomLabel)
or not h.isempty(args.CustomSection1)
or not h.isempty(args.CustomText1)
or not h.isempty(args.CustomSection2)
or not h.isempty(args.CustomText2)
or not h.isempty(args.NotesHeader)
or not h.isempty(args.TriviaHeader)
or not h.isempty(args.LinksHeader)
or not h.isempty(args.HistoryHeader)
or not h.isempty(args.RecommendedHeader)
or not h.isempty(args.PersonalityHeader)
or not h.isempty(args.Height2)
or not h.isempty(args.Weight2)
or not h.isempty(args.Eyes2)
or not h.isempty(args.Hair2)
or not h.isempty(args.Gender2)
or not h.isempty(args.Citizenship2) -- temporarily, to correctly put all citizenships into "Citizenship" field
or not h.isempty(args.UnusualSkinColour)
or not h.isempty(args.UnusualSkinColour2)
or not h.isempty(args.UnusualSkinColor)
or not h.isempty(args.UnusualSkinColor2)
or not h.isempty(args.Skin2)
or not h.isempty(args.MaritalStatus2)
or not h.isempty(args.PowersAbilitiesHeader)
or not h.isempty(args.ParaphernaliaHeader)
or not h.isempty(args.DiscoverAndDiscussHeader)
or not h.isempty(args.OtherMedia)
or not h.isempty(args.UniverseRef)
or not h.isempty(args.Last)
or not h.isempty(args.Strength)
then table.insert(output_categories, 'Outdated Fields/Character')
end
if not h.isempty(relatives)
then
relatives = string.lower(relatives)
if string.find(relatives, '-grandfather', 1, true) or string.find(relatives, '-grandmother', 1, true) or string.find(relatives, '-grandparent', 1, true) or string.find(relatives, 'ancestor')
then table.insert(output_categories, 'Relatives Correction Needed/Ancestors')
elseif string.find(relatives, 'grandfather') or string.find(relatives, 'grandmother') or string.find(relatives, 'grandparent')
then table.insert(output_categories, 'Relatives Correction Needed/Grandparents')
elseif string.find(relatives, 'father') or string.find(relatives, 'mother')
then table.insert(output_categories, 'Relatives Correction Needed/Parents')
end
if string.find(relatives, 'grandson') or string.find(relatives, 'granddaughter') or string.find(relatives, 'grandchild') or string.find(relatives, 'descendant')
then table.insert(output_categories, 'Relatives Correction Needed/Descendants')
elseif string.find(relatives, ' son') or string.find(relatives, '(son', 1, true) or string.find(relatives, 'daughter') or string.find(relatives, 'child')
then table.insert(output_categories, 'Relatives Correction Needed/Children')
end
if string.find(relatives, 'brother') or string.find(relatives, 'sister') or string.find(relatives, 'sibling')
then table.insert(output_categories, 'Relatives Correction Needed/Siblings')
end
if string.find(relatives, 'husband') or string.find(relatives, 'wife') or string.find(relatives, 'spouse')
then table.insert(output_categories, 'Relatives Correction Needed/Spouses')
end
if string.find(relatives, '^host') ~= nil or string.find(relatives, ' host') ~= nil or string.find(relatives, '%(host') ~= nil or ( string.find(relatives, 'symbiote') ~= nil and string.find(pagename, 'Symbiote') == nil )
then table.insert(output_categories, 'Relatives Correction Needed/Hosts')
end
if string.find(relatives, 'clone') ~= nil or string.find(relatives, 'genetic template') ~= nil or string.find(relatives, 'genetic donor') ~= nil
or (not h.isempty(args.Parents) and string.find(args.Parents, 'genetic template') ~= nil)
or (not h.isempty(args.Siblings) and string.find(args.Siblings, 'clone') ~= nil)
then table.insert(output_categories, 'Relatives Correction Needed/Clones')
end
end
return output_categories
end
--------------------------------------------------------------------------------------------------
function p.get_current_alias(frame)
local args = getArgs(frame)
local ref = args.CurrentAliasRef or ''
local output = args.CurrentAlias
if not h.is_link(output) and h.exists(output)
then output = h.Link(output)
end
return output..ref
end
--------------------------------------------------------------------------------------------------
function p.get_aliases(frame)
local args = getArgs (frame)
local list = {args.Codenames, args.EditorialNames, args.Titles, args.Nicknames, args.Impersonations, args.Aliases}
local labels = {'Codenames', 'Editorial Names', 'Titles and Ranks', 'Nicknames', 'Impersonations', 'Other Aliases'}
local value
local i
local output = {}
for i = 1, #labels do
if not h.isempty(list[i])
then
if labels[i] == 'Other Aliases' and table.concat(output) == ''
then
table.insert(output, list[i])
else
if design.count_lines(list[i]) > design.COLLAPSIBLE_MAX_LINES
then value = design.show_hide({header = labels[i]..':', body = '\n'..list[i], collapsed = 'true', expandtext = '+', collapsetext = '-' })
else value = design.span(labels[i]..':').bold..'\n'..tostring( mw.html.create('div'):wikitext('\n'..list[i]) )
end
table.insert(output, value)
end
end
end
output = mw.text.listToText(output, '\n', '\n')
return design.add_infobox_row_collapsible({output, no_collapse = 1})
end
--------------------------------------------------------------------------------------------------
function p.get_relatives(frame)
local args = getArgs (frame)
local list = {args.Ancestors, args.Grandparents, args.Parents, args.Clones, args.Siblings, args.Spouses, args.Children, args.Descendants, args.Relatives, args.InLaw}
local labels = {'Ancestors', 'Grandparents', 'Parents', 'Clones and Donors', 'Siblings', 'Spouses', 'Children', 'Descendants', 'Other Relatives', 'Family-in-Law'}
local value
local i
local output = {}
for i = 1, #labels do
if not h.isempty(list[i])
then
if labels[i] == 'Other Relatives' and table.concat(output) == ''
then
table.insert(output, list[i])
else
if design.count_lines(list[i]) > design.COLLAPSIBLE_MAX_LINES
then value = design.show_hide({header = labels[i]..':', body = '\n'..list[i], collapsed = 'true', expandtext = '+', collapsetext = '-' })
else value = design.span(labels[i]..':').bold..'\n'..tostring( mw.html.create('div'):wikitext('\n'..list[i]) )
end
table.insert(output, value)
end
end
end
output = mw.text.listToText(output, '\n', '\n')
return design.add_infobox_row_collapsible({output, no_collapse = 1})
end
--------------------------------------------------------------------------------------------------
function p.get_living_status(frame)
local args = getArgs (frame)
local cause_of_death = p.get_cause_of_death(frame)
local living_status = args.Status
local output_categories = {}
local output = ''
if living_status == 'Presumed Alive'
then
table.insert(output_categories, 'Presumed Alive Characters')
output = h.LinkToCategory('Presumed Alive Characters', 'Presumed Alive')
elseif living_status == 'Presumed Deceased'
then
table.insert(output_categories, 'Presumed Deceased Characters')
output = h.LinkToCategory('Presumed Deceased Characters', 'Presumed Deceased')
elseif living_status == 'Ghost'
then
table.insert(output_categories, 'Ghosts')
output = h.LinkToCategory('Ghosts', 'Ghost')
elseif living_status == 'Unknown'
then
table.insert(output_categories, 'Characters With Unknown Living Status')
output = h.LinkToCategory('Characters With Unknown Living Status', 'Unknown')
elseif living_status == 'Deceased' or living_status == 'Dead' or not h.isempty(args.Death)
then
table.insert(output_categories, 'Deceased Characters')
output = h.LinkToCategory('Deceased Characters', 'Deceased')
if h.isempty(cause_of_death)
then table.insert(output_categories, 'Cause of Death Needed')
end
if not h.isempty(living_status) and living_status ~= 'Deceased' and living_status ~= 'Dead'
then output = output..' '..living_status
end
else
table.insert(output_categories, 'Living Characters')
output = h.LinkToCategory('Living Characters', 'Alive')
if not h.isempty(cause_of_death)
then
output = output..'; '..h.LinkToCategory('Formerly Deceased', 'formerly deceased')
table.insert(output_categories, 'Formerly Deceased')
end
if not h.isempty(living_status)
then output = output..' '..living_status
end
end
return output..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_cause_of_death(frame)
local args = getArgs (frame)
local killed = args.KilledBy
local casualty = args.CasualtyOf
local suicide = args.Suicide
local sacrifice = args.Sacrifice
local cause = args.CauseOfDeath
local link = ''
local i
local output_categories = {}
local output = ''
if not h.isempty(cause)
then
if #cause > 500
then output = '<br>\n'..cause
else output = cause
end
output = design.add_infobox_row_collapsible({output})
end
if not h.isempty(killed)
then
killed = h.explode(";", killed)
for i = 1,#killed do
link = h.break_link(h.trim(killed[i]), 1)
table.insert(output_categories, 'Killed by '..link)
end
end
if not h.isempty(casualty)
then
casualty = h.explode(";", casualty)
for i = 1,#casualty do
link = h.break_link(h.trim(casualty[i]), 1)
table.insert(output_categories, link..' casualties')
end
end
if not h.isempty(suicide)
then table.insert(output_categories, 'Suicide')
end
if not h.isempty(sacrifice)
then table.insert(output_categories, 'Self-sacrifice')
end
return output..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_marital_status(frame)
local function get_value_and_remainder(value)
local i
local remainder = ''
i = string.find(value, ' ')
if i ~= nil
then
remainder = ' '..string.sub(value, i+1, #value)
value = string.sub(value, 1, i-1)
end
return value, remainder
end
local args = getArgs (frame)
local value = args.MaritalStatus
local value2 = args.MaritalStatus2
local list = {'Married', 'Divorced', 'Separated', 'Single', 'Widowed'}
local l = {}
local output_categories = {}
local output = {}
if not h.isempty(value)
then
output = {}
l = h.explode(';', value)
for i = 1, #l do
value, remainder = get_value_and_remainder(h.trim(l[i]))
if h.in_list(list, value)
then
table.insert(output, h.LinkToCategory(value..' Characters', value)..remainder )
table.insert(output_categories, value..' Characters')
else
table.insert(output, h.LinkToCategory('Marital Status Needing Correction', value) )
end
end
output = mw.text.listToText(output, ',<br>', ',<br>')
end
--if not h.isempty(value2)
-- then table.insert(output, ' '..value2)
--end
return output..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_occupation(frame)
local args = getArgs (frame)
local value = args.Occupation
local occupations = require('Module:CharacterInfoboxOccupation')
local output_categories = {}
local output = ''
if not h.isempty(value)
then
for key, v in pairs(occupations) do
if string.find( string.lower(value), key ) ~= nil
then
if h.in_list({"dancer", "designer"}, key) == false or (key == "dancer" and string.find( string.lower(value), "ballet dancer" ) == nil and string.find( string.lower(value), "exotic dancer" ) == nil) or (key == "designer" and string.find( string.lower(value), "fashion designer" ) == nil and string.find( string.lower(value), "weapon designer" ) == nil and string.find( string.lower(value), "weapons designer" ) == nil and string.find( string.lower(value), "weapon system designer" ) == nil and string.find( string.lower(value), "weapons systems designer" ) == nil)
then
for i, category in ipairs(v) do
table.insert(output_categories, category)
end
end
end
end
end
return design.add_infobox_row_collapsible({value})..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_citizenship(frame)
local data = require('Module:Nation and Citizenship')
local args = getArgs (frame)
local citizenship = args.Citizenship
local info
local value
local valueLower
local formerly
local annulled
local list = {}
local i
local output_categories = {}
local output = {}
if not h.isempty(citizenship)
then
list = h.explode(';', citizenship)
if string.find(citizenship, ';', 1, true) ~= nil
then table.insert(output_categories, 'Multiple Citizenship')
end
end
for i = 1, #list do
value = h.trim(list[i])
valueLower = string.lower(value)
formerly = string.match(valueLower, 'formerly (.+)')
annulled = string.match(valueLower, 'annulled (.+)')
if formerly ~= nil
then
info = data[formerly]
if info ~= nil
then
value = h.LinkToCategory(info.d_categories[1], info.demonym) .. ' (formerly)'
table.insert(output_categories, info.d_categories[1])
end
elseif annulled ~= nil
then
info = data[annulled]
if info ~= nil
then
value = h.LinkToCategory(info.d_categories[1], info.demonym) .. ' (annulled)'
table.insert(output_categories, info.d_categories[1])
end
else
info = data[valueLower]
if info ~= nil
then
value = h.LinkToCategory(info.d_categories[1], info.demonym)
table.insert(output_categories, info.d_categories[1])
end
end
table.insert(output, value)
end
output = mw.text.listToText(output, ', ', ', ')
return output..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_weight_value_and_unit(value)
local list = {'lbs', 'ton', 'oz', 'kg'}
local remainder = ''
local unit = ''
local output = value
if string.find(value, 'Variable') ~= nil
then
output = 'Variable'
remainder = string.match(value, 'Variable(.*)')
else
for i = 1, 4 do
unit = list[i]
output, remainder = string.match(value, '(%d+.*%d*)'..unit..'(.*)')
if output ~= nil
then break
else output = value
end
end
if output == value
then unit = ''
end
end
if h.isempty(remainder)
then remainder = ''
end
return output, unit, remainder
end
--------------------------------------------------------------------------------------------------
function p.get_weight(frame)
local function lbs_to_kg(weightLbs)
return h.round(weightLbs * units['lbs'].kg, 2)
end
local function get_weight_category(weightLbs)
local i
local output
if weightLbs < 10
then output = 'Weight 0-9 lbs ('..lbs_to_kg(10)..' kg)'
elseif weightLbs >= 10 and weightLbs < 20
then output = 'Weight 10-19 lbs ('..lbs_to_kg(10)..'-'..lbs_to_kg(20)..' kg)'
elseif weightLbs >= 20 and weightLbs < 300
then
i = 20
while i <= 280 do
if weightLbs >= i and weightLbs < i + 20
then output = 'Weight '..i..'-'..(i+19)..' lbs ('..lbs_to_kg(i)..'-'..lbs_to_kg(i+20)..' kg)'
end
i = i + 20
end
elseif weightLbs >= 300 and weightLbs < 1000
then
i = 300
while i <= 900 do
if weightLbs >= i and weightLbs < i + 100
then output = 'Weight '..i..'-'..(i+99)..' lbs ('..lbs_to_kg(i)..'-'..lbs_to_kg(i+100)..' kg)'
end
i = i + 100
end
elseif weightLbs >= 1000
then output = 'Weight above 1000 lbs ('..lbs_to_kg(1000)..' kg)'
end
return output
end
local args = getArgs (frame)
local value = args.Weight
--local value2 = args.Weight2
local weight
local weightLbs = 0
local weightKg = 0
local unit = ""
local remainder
local i
local category
local list = {}
local output_categories = {}
local output = {}
if not h.isempty(value)
then
list = h.explode(';', value)
for i = 1, #list do
weight, unit, remainder = p.get_weight_value_and_unit(list[i])
if unit ~= ''
then
weightLbs = h.round( weight * units[unit].lbs , 2 )
weightKg = weight * units[unit].kg
if weightKg < 1
then weightKg = h.round( weightKg * 1000, 2 ) .. " gram"
elseif weightKg > 1000
then weightKg = h.round( weightKg / 1000, 2 ) .. " ton"
else weightKg = h.round( weightKg, 2 ) .. " kg"
end
category = get_weight_category(weightLbs)
table.insert(output_categories, category)
table.insert(output, h.LinkToCategory(category, weightLbs .. " lbs (" .. weightKg .. ")")..remainder)
elseif weight == 'Variable'
then
category = 'Variable Weight'
table.insert(output_categories, category)
table.insert(output, h.LinkToCategory(category, weight)..remainder)
else
table.insert(output, weight..remainder)
end
end
output = mw.text.listToText(output, ',<br>', ',<br>')
end
--if not h.isempty(value2)
-- then output = output.." " ..value2
--end
return output..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_height_value(value)
local function round(m)
return tonumber( string.format("%.2f", m) )
end
local function to_metres(metres)
if metres < 1
then return round(metres * 100)..' cm'
elseif metres >= 1000
then return round(metres / 1000)..' km'
else return round(metres)..' m'
end
end
local function to_feet_and_inches(feet, inches)
if inches ~= '0'
then return feet..'′'..inches..'″'
else return feet..'′'
end
end
local feet = string.match(value, "(%d+)'")
local inches = string.match(value, '(%d+)"')
local metres
local remainder = ''
local output = ''
if feet ~= nil
then
if inches == nil
then
inches = '0'
metres = feet * units['ft'].m
remainder = string.match(value, "%d+'(.+)")
else
metres = (feet * units['ft'].m) + (inches * units['in'].m)
remainder = string.match(value, '%d+"(.+)')
end
output = to_feet_and_inches(feet, inches)..' ('..to_metres(metres)..')'
elseif string.find(value, 'Variable') ~= nil
then
output = 'Variable'
remainder = string.match(value, 'Variable(.*)')
else
feet = string.match(value, "(%d+) mile")
if feet ~= nil
then
output = string.match(value, "%d+ mile[s]?")..' ('..round(feet * 1.609) ..' km)'
remainder = string.match(value, "%d+ mile[s]? (.+)")
feet = 1000 -- value to sort height into correct category
end
metres = string.match(value, "(%d+) cm")
if metres
then
inches = metres/100 / units['in'].m
feet = math.floor(inches / 12)
inches = math.floor(inches - 12*feet)
output = to_feet_and_inches(feet, inches)..' ('..to_metres(metres/100)..')'
remainder = string.match(value, "%d+ cm(.+)")
end
end
if h.isempty(remainder)
then remainder = ''
end
return output, remainder, feet, inches
end
--------------------------------------------------------------------------------------------------
function p.get_height(frame)
local function ft_to_m(heightFt)
return tonumber( string.format("%.2f", heightFt * units['ft'].m) )
end
local function get_height_category(heightFt, heightIn)
local output
heightFt = tonumber(heightFt)
if heightFt < 1
then output = 'Height 0-1 ft. ('..ft_to_m(1)..' m)'
elseif heightFt >= 1 and heightFt < 2
then output = 'Height 1-2 ft. ('..ft_to_m(1)..'-'..ft_to_m(2)..' m)'
elseif heightFt >= 2 and heightFt < 3
then output = 'Height 2-3 ft. ('..ft_to_m(2)..'-'..ft_to_m(3)..' m)'
elseif heightFt >= 3 and heightFt < 4
then output = 'Height 3-4 ft. ('..ft_to_m(3)..'-'..ft_to_m(4)..' m)'
elseif heightFt >= 4 and heightFt < 5
then output = 'Height 4-5 ft. ('..ft_to_m(4)..'-'..ft_to_m(5)..' m)'
elseif heightFt >= 5 and heightFt < 6
then output = 'Height 5 ft. '..heightIn..' in. ('..ft_to_m(5 + heightIn/12)..' m)'
elseif heightFt >= 6 and heightFt < 7
then output = 'Height 6 ft. '..heightIn..' in. ('..ft_to_m(6 + heightIn/12)..' m)'
elseif heightFt >= 7 and heightFt < 8
then output = 'Height 7-8 ft. ('..ft_to_m(7)..'-'..ft_to_m(8)..' m)'
elseif heightFt >= 8
then output = 'Height above 8 ft. ('..ft_to_m(8)..' m)'
end
return output
end
local args = getArgs (frame)
local value = args.Height
local value2 = args.Height2
local height
local height_ft
local height_in
local remainder
local i
local category
local list = {}
local output_categories = {}
local output = {}
if not h.isempty(value)
then
list = h.explode(';', value)
for i = 1, #list do
height, remainder, height_ft, height_in = p.get_height_value(list[i])
if height ~= ''
then
if height_ft ~= nil
then category = get_height_category(height_ft, height_in)
elseif height == 'Variable'
then category = 'Variable Height'
end
table.insert(output_categories, category)
table.insert(output, h.LinkToCategory(category, height)..remainder)
else
table.insert(output, height..remainder)
end
end
output = mw.text.listToText(output, ',<br>', ',<br>')
end
--if not h.isempty(value2)
-- then output = output.." " ..value2
--end
return output..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_eyes(frame)
local function iris_color(value, remainder, former_color, original_color, glowing_color)
local category = ''
local output = ''
if not h.isempty(value)
then
if value == 'No Iris'
then
if former_color == true or original_color == true
then
category = 'Formerly No Visible Irises or Pupils'
if former_color == true
then output = h.LinkToCategory(category, 'No Visible')..remainder..' (formerly)'
else output = 'originally '..h.LinkToCategory(category, 'No Visible')..remainder
end
else
category = 'No Visible Irises or Pupils'
output = h.LinkToCategory(category, 'No Visible')..remainder
end
else
output, category = p.get_color_value_and_category(value, remainder, former_color, original_color, glowing_color, ' Eyes')
end
end
return output, category
end
local args = getArgs (frame)
local eyes = args.Eyes
local eyeballs = args.Eyeballs
local list = {}
local category = ''
local value
local remainder = ''
local former_color = false
local original_color = false
local glowing_color = false
local i
local output_categories = {}
local output = ''
if not h.isempty(eyes)
then
list = h.explode(';', eyes)
eyes = {}
for i = 1, #list do
value, remainder, former_color, original_color, glowing_color = p.get_values_for_color_and_remainder(h.trim(list[i]), {}, ' Eyes')
value, category = iris_color(value, remainder, former_color, original_color, glowing_color)
table.insert(output_categories, category)
table.insert(eyes, '\n* '..value)
end
eyes = mw.text.listToText(eyes, '', '')
output = '\n'..design.span('Irises:').bold..eyes
end
if not h.isempty(eyeballs)
then
list = h.explode(';', eyeballs)
eyeballs = {}
for i = 1, #list do
value, remainder, former_color, original_color, glowing_color = p.get_values_for_color_and_remainder(h.trim(list[i]), {}, ' Eyeballs')
value, category = p.get_color_value_and_category(value, remainder, former_color, original_color, glowing_color, ' Eyeballs')
table.insert(output_categories, category)
table.insert(eyeballs, '\n* '..value)
end
eyeballs = mw.text.listToText(eyeballs, '', '')
output = '\n'..design.span('Eyeballs:').bold..eyeballs..output
end
return output..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_hair(frame)
local function dyed_hair(value)
local dyed = false
local output = value
if string.find(value, 'Dyed ') ~= nil
then
dyed = true
output = string.gsub(value, 'Dyed ', '')
end
return output, dyed
end
local function hair_color(value, dyed, former_color, original_color, glowing_color, remainder)
local glowing
local category = ''
local output_categories = {}
local output = ''
if not h.isempty(value)
then
if glowing_color == true
then glowing = 'Glowing '..value
else glowing = value
end
value = string.gsub(value, 'Blonde', 'Blond')
value = string.gsub(value, 'Fair', 'Blond')
value = string.gsub(value, 'Reddish Brown', 'Auburn')
value = string.gsub(value, 'Greying', 'Grey-haired')
if former_color == true or original_color == true
then category = 'Formerly '
elseif dyed == true
then category = 'Dyed '
end
if value == 'Bald'
then category = category..'Bald'
elseif value == 'Balding'
then category = category..'Balding'
elseif value == 'Grey-haired'
then category = category..'Grey-haired'
else category = category..value..' Hair'
end
if value == 'No Hair'
then
if former_color == true or original_color == true
then category = 'Formerly No Hair'
else category = 'No Hair'
end
output = h.LinkToCategory(category, 'No Hair At All')..remainder
elseif dyed == true
then
output = h.LinkToCategory(category, 'Dyed '..glowing)..remainder
if former_color == true
then output = output..' (formerly)'
end
elseif former_color == true
then output = h.LinkToCategory(category, glowing)..remainder..' (formerly)'
elseif original_color == true
then output = 'originally '..h.LinkToCategory(category, glowing)..remainder
else
output = h.LinkToCategory(category, glowing)..remainder
end
table.insert(output_categories, category)
end
return output, output_categories
end
local args = getArgs (frame)
local hair = args.Hair
local exceptions_list = {'dark blond', 'light brown', 'platinum blond', 'strawberry blond'}
local category = ''
local value = ''
local remainder
local dyed = false
local former_color = false
local original_color = false
local glowing_color = false
local i
local list = {}
local output_categories = {}
local output = ''
if not h.isempty(hair)
then
output = {}
list = h.explode(';', hair)
for i = 1, #list do
value, dyed = dyed_hair(h.trim(list[i]))
value, remainder, former_color, original_color, glowing_color = p.get_values_for_color_and_remainder(value, exceptions_list, ' Hair')
value, category = hair_color(value, dyed, former_color, original_color, glowing_color, remainder)
output_categories = h.join_tables(output_categories, category)
table.insert(output, value)
end
output = mw.text.listToText(output, ',<br>', ',<br>')
end
return output..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_skin(frame)
local args = getArgs (frame)
local skin = args.Skin
local exceptions_list = {'light green', 'green, yellow'}
local category = ''
local value
local remainder = ''
local former_color = false
local original_color = false
local glowing_color = false
local i
local list = {}
local output_categories = {}
local output = ''
if not h.isempty(skin)
then
output = {}
list = h.explode(';', skin)
for i = 1, #list do
value, remainder, former_color, original_color, glowing_color = p.get_values_for_color_and_remainder(h.trim(list[i]), exceptions_list, ' Skin')
value, category = p.get_color_value_and_category(value, remainder, former_color, original_color, glowing_color, ' Skin')
table.insert(output_categories, category)
table.insert(output, value)
end
output = mw.text.listToText(output, ',<br>', ',<br>')
end
return output..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_gender(frame)
local function get_value_and_remainder(value)
local i
local remainder = ''
i = string.find(value, ' ')
if i ~= nil
then
remainder = ' '..string.sub(value, i+1, #value)
value = string.sub(value, 1, i-1)
end
return value, remainder
end
local function gender_category(value)
local category = ''
local output_categories = {}
local output = ''
if not h.isempty(value)
then
category = value..' Characters'
if h.pages_in_category(category, 'pages') > 0
then output = h.LinkToCategory(category, value)
else category = ''
end
table.insert(output_categories, category)
end
return output, output_categories
end
local args = getArgs (frame)
local gender = args.Gender
--local gender2 = args.Gender2
local category = ''
local value
local remainder
local i
local list = {}
local output_categories = {}
local output = ''
if not h.isempty(gender)
then
output = {}
list = h.explode(';', gender)
for i = 1, #list do
value, remainder = get_value_and_remainder(h.trim(list[i]))
value, category = gender_category(value)
output_categories = h.join_tables(output_categories, category)
table.insert(output, value..remainder)
end
output = mw.text.listToText(output, ',<br>', ',<br>')
end
--if not h.isempty(gender2)
-- then output = output..' '..gender2
--end
return output..h.add_categories(output_categories)
end
--------------------------------------------------------------------------------------------------
function p.get_unusual_features(frame)
local args = getArgs (frame)
local value = args.UnusualFeatures
local list = require('Module:CharacterInfoboxUnusualFeatures')
local output_categories = p.get_categories_from_keywords(value, list, {})
output_categories = h.add_categories(output_categories)
if string.find(output_categories, 'Prehensile Tail') ~= nil
then output_categories = string.gsub(output_categories, '%[%[Category:Tail%]%]', '')
end
return design.add_infobox_row_collapsible({value})..output_categories
end
--------------------------------------------------------------------------------------------------
function p.get_origin(frame)
local args = getArgs (frame)
local list = require('Module:CharacterInfoboxOrigins')
local value = args.Origin
local output = ''
if not h.isempty(value)
then
output = p.get_categories_from_keywords(value, list.valid, list.exceptions)
value = design.add_infobox_row_collapsible({value})
output = value..h.add_categories(output)
end
return output
end
--------------------------------------------------------------------------------------------------
function p.get_categories_from_keywords(value, valid_list, exceptions_list)
local function find_value(str, value)
return string.find(str, '[%s%[%|%(]'..value..'[s%]%p%s%)]') ~= nil
or string.find(str, '^'..value..'[s%]%p%s%)]') ~= nil
or string.find(str, '[%s%[%|%(]'..value..'$') ~= nil
or string.find(str, '^'..value..'$') ~= nil
end
local lower_value
local exception_values
local valid
local output = {}
if not h.isempty(value) -- Field isn't blank
then -- Grab a valid pair and use it
lower_value = string.lower(value)
for validKey, validValue in pairs(valid_list) do
exception_values = exceptions_list[validKey]
-- If you find the validKey in the field, and there are no exceptions for this validKey, then categorize
if find_value(lower_value, validKey)
then
valid = true
if exception_values ~= nil
then
for valueKey, valueName in ipairs( exception_values ) do
if find_value(lower_value, valueName)
then valid = false
end
end
end
if valid
then
for valueKey, valueCategoryName in ipairs( validValue ) do
table.insert(output, valueCategoryName)
end
end
end
end
table.sort(output)
end
return output
end
--------------------------------------------------------------------------------------------------
function p.get_values_for_color_and_remainder(value, exceptions_list, s_type)
local i
local j
local k
local remainder = ''
local former_color = false
local original_color = false
local glowing_color = false
exceptions_list = h.join_tables(exceptions_list, string.lower('No'..s_type)) -- exception for 'No <s_type>' to not treat it is as value='No' and comment='<s_type>'
exceptions_list = h.join_tables(exceptions_list, 'no iris') -- exception for 'No Iris' to not treat it is as value='No' and comment='Iris'
i, j = string.find(value, 'Formerly ')
if j ~= nil
then
former_color = true
value = string.gsub(value, 'Formerly ', '')
end
i, j = string.find(value, 'Originally ')
if j ~= nil
then
original_color = true
value = string.gsub(value, 'Originally ', '')
end
i, j = string.find(value, 'Glowing ')
if j ~= nil
then
glowing_color = true
value = string.gsub(value, 'Glowing ', '')
end
value = string.gsub(value, '^n%/a', 'No')
value = string.gsub(value, '^None', 'No')
value = string.gsub(value, '^No'..s_type, 'No')
if string.find(value, 'No Iris') == nil -- exception for 'No Iris' to not change it to 'No Eyes'
then value = string.gsub(value, '^No', 'No'..s_type)
end
for k = 1, #exceptions_list do
i, j = string.find(string.lower(value), exceptions_list[k])
if j ~= nil
then
i = string.find(value, ' ', j)
break
else i = string.find(value, ' ')
end
end
if i ~= nil
then
remainder = ' '..string.sub(value, i+1, #value)
value = string.sub(value, 1, i-1)
end
value = string.gsub(value, 'Gray', 'Grey')
return value, remainder, former_color, original_color, glowing_color
end
--------------------------------------------------------------------------------------------------
function p.get_color_value_and_category(value, remainder, former_color, original_color, glowing_color, s_type)
local glowing
local category = ''
local output = ''
if not h.isempty(value)
then
if value == 'No'..s_type
then
if former_color == true or original_color == true
then
category = 'Formerly '..value
if former_color == true
then output = h.LinkToCategory(category, value..' At All')..remainder..' (formerly)'
else output = 'originally '..h.LinkToCategory(category, value..' At All')..remainder
end
else
category = value
output = h.LinkToCategory(category, value..' At All')..remainder
end
else
if glowing_color == true
then glowing = 'Glowing '..value
else glowing = value
end
if former_color == true or original_color == true
then
category = 'Formerly '..value..s_type
if former_color == true
then output = h.LinkToCategory(category, glowing)..remainder..' (formerly)'
else output = 'originally '..h.LinkToCategory(category, glowing)..remainder
end
else
category = value..s_type
output = h.LinkToCategory(category, glowing)..remainder
end
end
end
return output, category
end
--------------------------------------------------------------------------------------------------
function p.get_hosts(frame)
local args = getArgs (frame)
local list = require('Module:Host')
local output_categories = {}
local output = args.HostOf
for key, value in pairs(list) do
if string.find(output, '[['..key, 1, true) ~= nil
then output_categories = h.join_tables(output_categories, value)
end
end
if string.find(table.concat(output_categories), 'Symbiote') == nil and string.find(string.lower(output), 'symbiote') ~= nil
then table.insert(output_categories, 'Hosts of Symbiotes')
end
return design.add_infobox_row_collapsible({output})..h.add_categories(output_categories)
end
return p