Module:Character Template

-- 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.Strength) or not h.isempty(args.Weaknesses) or list_of_power_grids[pagename] ~= nil then table.insert( output, design.add_header('Powers and Abilities', 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('Physical Strength', args.Strength, 3) ) table.insert( output, design.add_section('Weaknesses', args.Weaknesses, 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.UnusualSkinColour2) 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) then output = 'Outdated Fields/Character' end

return output end

-- function p.get_current_alias(frame) local args = getArgs (frame) local value = args.CurrentAlias local ref = args.CurrentAliasRef or ''

return value..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..' '..list[i]) end end end output = mw.text.listToText(output, ' ', ' ')

return 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..' '..list[i]) end end end output = mw.text.listToText(output, ' ', ' ') return design.add_infobox_row_collapsible({output}) end

-- function p.get_living_status(frame) local args = getArgs (frame) local living_status = args.Status local output_categories = {} local output = '' if not h.isempty(args.Death) then table.insert(output_categories, 'Deceased Characters') output = h.LinkToCategory('Deceased Characters', 'Deceased') else table.insert(output_categories, 'Living Characters') output = h.LinkToCategory('Living Characters', 'Alive') if not h.isempty( p.get_cause_of_death(frame) ) then output = output..'; '..h.LinkToCategory('Formerly Deceased', 'formerly deceased') table.insert(output_categories, 'Formerly Deceased') end end if not h.isempty(living_status) then output = output..' '..living_status 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 = ' \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, ', ', ', ') 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) 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, ', ', ', ') 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, ', ', ', ') 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 eyeballs_color(value) local category = '' local output = '' if not h.isempty(value) then category = value..' Eyeballs' output = h.LinkToCategory(category, value) end return output, category end local function iris_color(value) local category = '' local output = '' if not h.isempty(value) then value = string.gsub(value, 'Gray', 'Grey') category = value..' Eyes' if h.pages_in_category(category, 'pages') > 0 then output = h.LinkToCategory(category, value) elseif value == 'No Iris' then category = 'No visible Irises or Pupils' output = h.LinkToCategory(category, 'No Visible') elseif value == 'No Eyes' then category = 'No Eyes' output = h.LinkToCategory(category, 'No Eyes At All') else category = '' end end return output, category end local function get_value_and_remainder(value) local i		local j		local remainder = '' i, j = string.find(value, 'No Iris') if j ~= nil then i = string.find(value, ' ', j)			else value = string.gsub(value, '^n%/a', 'No') value = string.gsub(value, '^None', 'No') value = string.gsub(value, '^No Eyes', 'No') value = string.gsub(value, '^No', 'No Eyes') i, j = string.find(value, '^No Eyes') if j ~= nil then i = string.find(value, ' ', j)					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 return value, remainder end local args = getArgs (frame) local eyes = args.Eyes local eyes2 = args.Eyes2 local eyeballs = args.Eyeballs local list = {} local category = '' local value local remainder 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 = get_value_and_remainder(h.trim(list[i])) value, category = iris_color(value) table.insert(output_categories, category) table.insert(eyes, '\n* '..value..remainder) end eyes = mw.text.listToText(eyes, , ) --if not h.isempty(eyes2) --	then eyes = eyes..' '..eyes2 --end 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 = get_value_and_remainder(h.trim(list[i])) value, category = eyeballs_color(value) table.insert(output_categories, category) table.insert(eyeballs, '\n* '..value..remainder) 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 get_value_and_remainder(value) local exceptions_list = {'light brown', 'platinum blond', 'strawberry blond', 'no hair'} local i		local j		local k		local dyed = false local remainder = ''

value = string.gsub(value, '^n%/a', 'No') value = string.gsub(value, '^None', 'No') value = string.gsub(value, '^No Hair', 'No') value = string.gsub(value, '^No', 'No Hair') i, j = string.find(value, 'Dyed ') if j ~= nil then dyed = true value = string.gsub(value, 'Dyed ', '') 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

return value, remainder, dyed end local function hair_color(value, dyed) local category = '' local output_categories = {} local output = '' if not h.isempty(value) then value = string.gsub(value, 'Gray', 'Grey') value = string.gsub(value, 'Blonde', 'Blond') value = string.gsub(value, 'Fair', 'Blond') value = string.gsub(value, 'Reddish Brown', 'Auburn') if value == 'Bald' then category = 'Bald' else category = value..' Hair' end if h.pages_in_category(category, 'pages') > 0 then output = h.LinkToCategory(category, value) elseif value == 'No Hair' then category = 'No Hair' output = h.LinkToCategory(category, 'No Hair At All') else category = '' end table.insert(output_categories, category) if dyed == true then table.insert(output_categories, 'Dyed Hair') output = h.LinkToCategory('Dyed Hair', 'Dyed')..' '..output end end return output, output_categories end local args = getArgs (frame) local hair = args.Hair local hair2 = args.Hair2 local category = '' local value local remainder local dyed 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, remainder, dyed = get_value_and_remainder(h.trim(list[i])) value, category = hair_color(value, dyed) output_categories = h.join_tables(output_categories, category) table.insert(output, value..remainder) end output = mw.text.listToText(output, ', ', ', ') end --if not h.isempty(hair2) --	then output = output..' '..hair2 --end return output..h.add_categories(output_categories) end

-- function p.get_skin(frame) local function get_value_and_remainder(value) local exceptions_list = {'light green', 'green, yellow', 'no skin'} local i		local j		local k		local remainder = ''

value = string.gsub(value, '^n%/a', 'No') value = string.gsub(value, '^None', 'No') value = string.gsub(value, '^No Skin', 'No') value = string.gsub(value, '^No', 'No Skin')

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

return value, remainder end local function skin_color(value) local category = '' local output_categories = {} local output = '' if not h.isempty(value) then value = string.gsub(value, 'Gray', 'Grey') category = value..' Skin' if h.pages_in_category(category, 'pages') > 0 then output = h.LinkToCategory(category, value) elseif value == 'No Skin' then category = 'No Skin' output = h.LinkToCategory(category, 'No Skin At All') else category = '' end table.insert(output_categories, category) end return output, output_categories end local args = getArgs (frame) local skin = args.UnusualSkinColor or args.UnusualSkinColour --local skin2 = args.UnusualSkinColour2 local category = '' local value local remainder 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 = get_value_and_remainder(h.trim(list[i])) value, category = skin_color(value) output_categories = h.join_tables(output_categories, category) table.insert(output, value..remainder) end output = mw.text.listToText(output, ', ', ', ') end --if not h.isempty(skin2) --	then output = output..' '..skin2 --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, ', ', ', ') 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.valid, list.exceptions) return value..h.add_categories(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, exceptions) local output = {}

if not h.isempty(value) -- Field isn't blank then -- Grab a valid pair and use it			for validKey, validValue in pairs(valid) do				-- If you find the validKey in the field, and there are no exceptions for this validKey, then categorize if string.find(string.lower(value), validKey) ~= nil and type(exceptions[validKey]) ~= "table" then for valueKey, valueCategoryName in ipairs( validValue ) do							table.insert(output, valueCategoryName) end end end end return output end

return p