Module:User:Kephir/family tree

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 ("%s "):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%s%s "):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, (" "):format(code)) end return (" %s (%s) "):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