Module:family tree

ពីWiktionary

Documentation for this module may be created at Module:family tree/doc

local m_families = mw.loadData('Module:families/data')
local m_languages_old = mw.loadData('Module:languages/alldata')
local export = {}

local function build_tree()
	local tree = {}

	for code, data in pairs(m_families) do
		if not tree[data.family] then
			tree[data.family] = {}
		end
		if code ~= data.family then
			table.insert(tree[data.family], code)
		end
	end

	for code, data in pairs(m_languages_old) do
		if not tree[data.family] then
			tree[data.family] = {}
		end
		if code ~= data.family then
			table.insert(tree[data.family], code)
		end
	end

	return tree
end

local type_map = {
	["reconstructed"       ] = 0,
	["family"              ] = 1,
	["regular"             ] = 2,
	["appendix-constructed"] = 2
}

local function make_list(code, tree, with_parents)
	local result = {}
	local stars = '*'

	local function format_family(code)
		local catname = m_families[code].names[1]
		if not catname:find("[Ll]anguages$") then
			catname = catname .. ' languages'
		end
		return ("[[:Category:%s|%s]] (<code>%s</code>)"):format(catname, catname, code)
	end

	local function format_lang(code)
		local catname = m_languages_old[code].names[1]
		if not catname:find("[Ll]anguage$") then
			catname = catname .. ' language'
		end
		return ("%s[[:Category:%s|%s]]%s (<code>%s</code>)"):format(
			(m_languages_old[code].type == "reconstructed") and "*" or
			((m_languages_old[code].type == "appendix-constructed") and "''" or ""),
			catname, m_languages_old[code].names[1],
			(m_languages_old[code].type == "appendix-constructed") and "''" or "",
			code
		)
	end

	local function add_item(code)
		if m_families[code] then
			table.insert(result, stars .. ' ' .. format_family(code))
		elseif m_languages_old[code] then
			table.insert(result, stars .. ' ' .. format_lang(code))
		end
		
		if tree[code] then
			stars = stars .. '*'
			table.sort(tree[code], function (apple, orange)
				local appl_lang = m_languages_old[apple]
				local orng_lang = m_languages_old[orange]

				local appl_name = appl_lang and appl_lang.names[1] or m_families[apple].names[1]
				local orng_name = orng_lang and orng_lang.names[1] or m_families[orange].names[1]
				
				local appl_type = appl_lang and appl_lang.type or "family"
				local orng_type = orng_lang and orng_lang.type or "family"

				if type_map[appl_type] < type_map[orng_type] then
					return true
				elseif type_map[appl_type] > type_map[orng_type] then
					return false
				else
					return appl_name < orng_name
				end
			end)
			for i, item in ipairs(tree[code]) do
				add_item(item)
			end
			stars = stars:sub(1, #stars - 1)
		end
	end

	if with_parents then
		local fcode = (m_families[code] and m_families[code].family) or (m_languages_old[code] and m_languages_old[code].family) or error("Not a valid language or family code")
		local dcode, depth, itnum = fcode, 0, 0

		while (dcode ~= "qfa-und") and (dcode ~= "qfa-not") do
			dcode = m_families[dcode].family
			depth = depth + 1
			stars = stars .. "*"
		end

		while itnum < depth do
			table.insert(result, 1, stars:sub(1, depth - itnum) .. ' ' .. format_family(fcode))
			fcode = m_families[fcode].family
			itnum = itnum + 1
		end
	end

	add_item(code)

	return table.concat(result, "\n")
end

function export.show(frame)
	local tree = build_tree()
	local root = frame.args[1] or "qfa-not"

	return make_list(root, tree, frame.args.with_parents)
end

return export