Module:Namefag categorizer

From Soyjak Wiki, the free ensoyclopedia
Jump to navigationJump to search

local p = {}
local core = require('Module:Infobox categorizer')
local yesno = require('Module:Yesno')
local config = mw.loadData('Module:Namefag categorizer/config')
local countryData = mw.loadData('Module:Infobox categorizer/countries')
local stateData = mw.loadData('Module:Infobox categorizer/states')

local where = 'Module:Namefag categorizer/config'
local dims = core.need(config, 'dimensions', where)
local maintenance = core.need(config, 'maintenance', where)
local invalidOverrideCat = core.need(maintenance, 'invalidOverride', where .. '.maintenance')
local usingOverrideCat = core.need(maintenance, 'usingOverride', where .. '.maintenance')

local D = {}
for _, key in ipairs({
	'wikiAccount',
	'booruAccount',
	'nationality',
	'state', -- USA
	'site',
	'first',
	'final',
	'status',
	'jakked',
	'gender',
}) do
	D[key] = core.need(dims, key, where .. '.dimensions')
end

local sites = core.compileAliasSet({ mw.loadData('Module:Infobox categorizer/sites') })
local countries = core.compileAliasSet({ countryData })
local states = core.compileAliasSet({ stateData })
local statuses = core.compileAliasSet({ core.need(config, 'statuses', where) })
local genders = core.compileAliasSet({ core.need(config, 'genders', where) })
local accountSites = config.accountSites or {}

local countryCode = {}
local countryName = {}

for _, entry in ipairs(countryData) do
	countryCode[string.upper(entry.category)] = entry.category
	countryName[entry.category] = entry.name or entry.category

	for _, code in ipairs(entry.codes or {}) do
		countryCode[string.upper(code)] = entry.category
	end
end

local function countryCanon(value)
	local code = string.upper(core.trim(value))
	if code == '' then return nil end
	local prefix = string.match(code, '^(%w+)%-')
	return countryCode[code] or (prefix and countryCode[prefix]) or nil
end

local stateName = {}

for _, entry in ipairs(stateData) do
	stateName[string.upper(entry.category)] = entry.name or entry.category
end

local function stateCanon(value)
	local code = string.upper(core.trim(value))
	if stateName[code] then return code end
end

local function aliasOverride(compiled)
	return function(value)
		return core.parseAliasSetOverride(value, compiled)
	end
end

local function maint(dim, key)
	return dim.maintenance and dim.maintenance[key]
end

local function bail()
	local title = mw.title.getCurrentTitle()
	if title.namespace == 0 and title.isSubpage then return true end
	return mw.ustring.find(mw.ustring.lower(title.text), '^lists? of ') ~= nil
end

function p._state(args)
	local codes = core.readDataAttr(args.nationality, 'nationality')
	local nationality = core.resolve {
		candidates = #codes > 0 and codes or core.matchAliasSets(args.nationality, countries),
		override = args.category_nationality,
		parse = aliasOverride(countries),
		canon = countryCanon,
	}
	local state = core.resolve {
		candidates = codes,
		override = args.category_state,
		parse = aliasOverride(states),
		canon = stateCanon,
	}
	local siteMatches = core.matchAliasSets(args.frequented_sites, sites)
	local site = core.resolve {
		candidates = siteMatches,
		override = args.category_site,
		parse = aliasOverride(sites),
		filter = function(value)
			return not accountSites[value]
		end,
	}
	local first = core.resolve {
		candidates = core.findYears(args.first_appearance),
		override = args.category_first,
		parse = core.parseYearOverride,
		max = 1,
	}
	local final = core.resolve {
		candidates = core.findYears(args.final_appearance),
		override = args.category_final,
		parse = core.parseYearOverride,
		max = 1,
	}
	local status = core.resolve {
		candidates = core.matchAliasSets(args.status, statuses),
		override = args.category_status,
		parse = aliasOverride(statuses),
		max = 1,
	}
	local gender = core.resolve {
		candidates = core.matchAliasSets(args.gender, genders),
		override = args.category_gender,
		parse = aliasOverride(genders),
	}

	return {
		wikiAccount = core.trim(args.wiki_account) ~= '',
		booruAccount = core.trim(args.booru_account) ~= '',
		jakked = yesno(core.trim(mw.text.split(core.clean(args['IAS?']), ',', true)[1])),
		siteMatched = #siteMatches > 0,
		nationality = nationality,
		state = state,
		site = site,
		first = first,
		final = final,
		status = status,
		gender = gender,
	}
end

function p._categories(args)
	local out = core.newList()
	if bail() then return out end -- bail out on mainspace subpages and list of pages to avoid catspam
	local state = p._state(args)

	local function has(field)
		return core.trim(args[field]) ~= ''
	end

	local function emit(dim, dimState, names)
		for _, value in ipairs(dimState.values) do
			out:add(core.fill(dim.name, names and names[value] or value))
		end
	end

	if state.wikiAccount then out:add(D.wikiAccount.name) end
	if state.booruAccount then out:add(D.booruAccount.name) end

	emit(D.nationality, state.nationality, countryName)
	if state.nationality.source == 'detected' and has('nationality') and state.nationality.undetected then
		out:add(maint(D.nationality, 'unrecognized'))
	end

	emit(D.state, state.state, stateName)

	emit(D.site, state.site)
	if state.site.source == 'detected' and has('frequented_sites') and not state.siteMatched then
		out:add(maint(D.site, 'unrecognized'))
	end

	emit(D.first, state.first)
	if state.first.overflow then out:add(maint(D.first, 'overflow')) end

	emit(D.final, state.final)
	if state.final.overflow then out:add(maint(D.final, 'overflow')) end

	emit(D.status, state.status)
	if state.status.source == 'detected' and has('status') and state.status.undetected then
		out:add(maint(D.status, 'unrecognized'))
	end

	local departed = has('final_appearance') or has('death_date')
	if state.status.values[1] ~= nil and state.status.values[1] == D.status.active and departed then
		out:add(maint(D.status, 'conflicting'))
	end
	if state.status.values[1] ~= nil and state.status.values[1] ~= D.status.active and not departed then
		out:add(maint(D.status, 'noDeparture'))
	end

	if state.jakked == true then out:add(D.jakked.name) end
	if has('IAS?') and state.jakked == nil then out:add(maint(D.jakked, 'unrecognized')) end

	emit(D.gender, state.gender)

	if
		core.anyCustomized(
			state.nationality,
			state.state,
			state.site,
			state.first,
			state.final,
			state.status,
			state.gender
		)
	then
		out:add(usingOverrideCat)
	end
	if
		core.anyInvalid(
			state.nationality,
			state.state,
			state.site,
			state.first,
			state.final,
			state.status,
			state.gender
		)
	then
		out:add(invalidOverrideCat)
	end
	return out
end

p.main = core.makeMain(p._categories, config.namespaces)

return p