Module:User:Kephir/family tree

From Wiktionary, the free dictionary
Jump to navigation Jump to search

Lua error at line 36: table index is nil


local m_families = mw.loadData('Module:families/data')
local m_languages = mw.loadData('Module:languages/data/all')
local m_etym_languages = require('Module:etymology languages/data')
local etym_othercodes = {}
local export = {}

local function build_tree()
	local tree = {}

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

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

	for code, data in pairs(m_etym_languages) do
		if not etym_othercodes[data] then
			etym_othercodes[data] = { code }
			if not tree[data.parent] then
				tree[data.parent] = {}	
			end
			if code ~= data.parent then
				table.insert(tree[data.parent], code)
			end
		else
			table.insert(etym_othercodes[data], code)
		end
	end

	for _, list in pairs(etym_othercodes) do
		table.sort(list)	
	end

	return tree
end

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

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

	local function format_family(code)
		local catname = m_families[code].canonicalName
		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 data = m_languages[code]
		local catname = data[1]
		if not catname:find("[Ll]anguage$") then
			catname = catname .. ' language'
		end
		return ("%s[[:Category:%s|%s]]%s (<code>%s</code>)"):format(
			(data.type == "reconstructed") and "*" or
			((data.type == "appendix-constructed") and "''" or ""),
			catname, data[1],
			(data.type == "appendix-constructed") and "''" or "",
			code
		)
	end

	local function format_etym_lang(code)
		local codes = {}
		for _, code in ipairs(etym_othercodes[m_etym_languages[code]]) do
			table.insert(codes, ("<code>%s</code>"):format(code))
		end
		return ("<small>%s (%s)</small>"):format(
			m_etym_languages[code].canonicalName,
			table.concat(codes, ", ")
		)
	end

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

				local appl_type = (m_etym_languages[apple ] and "etymology") or (appl_lang and appl_lang.type) or "family"
				local orng_type = (m_etym_languages[orange] and "etymology") or (orng_lang and orng_lang.type) or "family"

				local appl_name = appl_lang and appl_lang.canonicalName or m_families[apple ].canonicalName
				local orng_name = orng_lang and orng_lang.canonicalName or m_families[orange].canonicalName
				
				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)
			if depth ~= 0 then
				depth = depth - 1
				for i, item in ipairs(tree[code]) do
					add_item(item)
				end
				depth = depth + 1
			end
			stars = oldstars
		end
	end

	if with_parents then
		local fcode =
			(m_families[code] and m_families[code].family) or
			(m_languages[code] and m_languages[code].family) or
			(m_etym_languages[code] and m_etym_languages[code].parent) 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"
	local depth = frame.args.depth and tonumber(frame.args.depth)

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

return export