Marvel Database
Register
Advertisement

Documentation for this module may be created at Module:Character Template/doc

-- module for Marvel Database:Character Template
local p = {}
local getArgs = require('Module: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 = {}

	table.insert(output_categories, p.lua_get_outdated_fields(args) )
-- 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)
	local output = ''
	
	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 output = 'Outdated Fields/Character'
	end

	return output	
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.Nicknames, args.Impersonations, args.Aliases}
	local labels = {'Codenames', 'Editorial Names', 'Nicknames', 'Impersonations', 'Other Aliases'}
	local i
	local output = {}

	for i = 1, 5 do
		if not h.isempty(list[i])
			then
				if labels[i] == 'Other Aliases' and table.concat(output) == '' 
					then table.insert(output, list[i])
					else table.insert(output, design.span(labels[i]..':').bold..'<br>'..list[i])
				end
		end
	end
	output = mw.text.listToText(output, '<br>', '<br>') 

	return design.add_infobox_row_collapsible({output})
end


--------------------------------------------------------------------------------------------------
function p.get_relatives(frame)
	local args = getArgs (frame)
	local list = {args.Ancestors, args.Grandparents, args.Parents, args.Siblings, args.Spouses, args.Children, args.Descendants, args.Relatives}
	local labels = {'Ancestors', 'Grandparents', 'Parents', 'Siblings', 'Spouses', 'Children', 'Descendants', 'Other Relatives'}
	local i
	local output = {}
	
	for i = 1, 8 do
		if not h.isempty(list[i])
			then
				if labels[i] == 'Other Relatives' and table.concat(output) == '' 
					then table.insert(output, list[i])
					else table.insert(output, design.span(labels[i]..':').bold..'<br>'..list[i])
				end
		end
	end
	output = mw.text.listToText(output, '<br>', '<br>') 
	
	return design.add_infobox_row_collapsible({output})
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 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)
				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
	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', 'Engaged', '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
						for i, category in ipairs(v) do
							table.insert(output_categories, category)
						end
				end
			end
			output = value
	end

	return design.add_infobox_row_collapsible({value})..h.add_categories(output_categories)
end


--------------------------------------------------------------------------------------------------
function p.get_citizenship(frame)
	local args = getArgs (frame)
	local citizenship = require('Module:Citizenship')
	local value1 = args.Citizenship
	local value2 = args.Citizenship2
	local valueUpper
	local valueLower
	local value
	local substitute
	local list = {}
	local i
	local output_categories = {}
	local output = {}
	
	if not h.isempty(value1)
		then 
			list = h.explode(';', value1)
			if string.find(value1, ';', 1, true) ~= nil
				then table.insert(output_categories, 'Multiple Citizenship')
			end
	end

	for i = 1, #list do
		value = h.trim(list[i])
		valueUpper = h.firstToUpper(value)
		valueLower = string.lower(value)
		value = citizenship.valid[valueUpper]
		substitute = citizenship.substitutes[valueLower]
		if value == true 
			then 
				table.insert(output, h.LinkToCategory(valueUpper, valueUpper) )
				table.insert(output_categories, valueUpper)
			elseif type(substitute) == "string" 
				then 
					table.insert(output, h.LinkToCategory(substitute, valueUpper) )
					table.insert(output_categories, substitute)
			else 
				table.insert(output, list[i])
		end
	end
	
	output = mw.text.listToText(output, ', ', ', ')
	
	if not h.isempty(value2)
		then output = output..' '..value2
	end

	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, value2)
	local function round(m)
		return tonumber( string.format("%.2f", m) )
	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

			if metres < 1
				then output = round(metres * 100)..' cm'
				elseif metres >= 1000
					then output = round(metres / 1000)..' km'
				else output = round(metres)..' m'
			end
	
			if inches ~= '0'
				then output = feet..'′'..inches..'″'..' ('..output..')'
				else output = feet..'′'..' ('..output..')'
			end
		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

	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)
		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, ' 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 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 = p.get_values_for_color_and_remainder(h.trim(list[i]), {}, ' Eyes')
				value, category = iris_color(value, remainder, former_color, original_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 = 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, ' 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, remainder)
		local category = ''
		local output_categories = {}
		local output = ''
		if not h.isempty(value)
			then
				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 '..value)..remainder
					elseif former_color == true
						then output = h.LinkToCategory(category, value)..remainder..' (formerly)'
					elseif original_color == true
						then output = 'originally '..h.LinkToCategory(category, value)..remainder
					else
						output = h.LinkToCategory(category, value)..remainder
				end
				table.insert(output_categories, category)
		end
		return output, output_categories
	end
	local args = getArgs (frame)
	local hair = args.Hair
	local exceptions_list = {'light brown', 'platinum blond', 'strawberry blond'}
	local category = ''
	local value = ''
	local remainder
	local dyed = false
	local former_color = false
	local original_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 = p.get_values_for_color_and_remainder(value, exceptions_list, ' Hair')
				value, category = hair_color(value, dyed, former_color, original_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 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 = 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, ' 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 value..output_categories
end


--------------------------------------------------------------------------------------------------
function p.get_ctry(frame)
	local substitutes = require('Module:CharacterInfoboxCtry')
	local args = getArgs (frame)
	local value = args[1]
	local output = ''
	
	if not h.isempty(value)
		then
			output = value
			if string.find(value, "%[%[.+%]%]") == nil 
				then
					if type(substitutes[value]) == "string" 
						then output = h.Link(substitutes[value])
					end
			end
	end
	
	return output
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)
			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
	
	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

	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
end

--------------------------------------------------------------------------------------------------
function p.get_color_value_and_category(value, remainder, former_color, original_color, s_type)
	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 former_color == true or original_color == true
						then 
							category = 'Formerly '..value..s_type
							if former_color == true
								then output = h.LinkToCategory(category, value)..remainder..' (formerly)'
								else output = 'originally '..h.LinkToCategory(category, value)..remainder
							end
						else
							category = value..s_type
							output = h.LinkToCategory(category, value)..remainder
					end
			end
	end
	
	return output, category
end


return p
Advertisement