Module:family tree/nested data/sandbox

Hello, you have come here looking for the meaning of the word Module:family tree/nested data/sandbox. In DICTIOUS you will not only get to know all the dictionary meanings for the word Module:family tree/nested data/sandbox, but we will also tell you about its etymology, its characteristics and you will know how to say Module:family tree/nested data/sandbox in singular and plural. Everything you need to know about the word Module:family tree/nested data/sandbox you have here. The definition of the word Module:family tree/nested data/sandbox will help you to be more precise and correct when speaking or writing your texts. Knowing the definition ofModule:family tree/nested data/sandbox, as well as those of other words, enriches your vocabulary and provides you with more and better linguistic resources.


--[=[

Authors: ], ], ], ]

--]=]

local regular_languages = require("Module:languages/data/all")
local families = require("Module:families/data")

-- Version of ] that chooses the language-
-- codiest code of several codes that have the same data. For instance,
-- it chooses "de-AT" over "Austrian German".
local etymology_languages = require("Module:family tree/etymology languages")

local supplementary_language_and_family_data = require("Module:family tree/data")

local memoize = require("Module:fun").memoize

local make_auto_subtabler = require("Module:auto-subtable")

local function get_data(code)
	return regular_languages or etymology_languages or families
		or error("language code " .. tostring(code) .. " not recognized")
end

local get_sort_value = memoize(function (code)
	local data = get_data(code)
	return (data or data.canonicalName):gsub("Proto%-", "")
end)

-- used in deep_sort
local function compare(code1, code2)
	return get_sort_value(code1) < get_sort_value(code2)
end

local function deep_sort(current)
	local result = {}
	local is_table = {}
	for key, val in pairs(current) do
		if type(key) == "number" then
			table.insert(result, val)
		else
			is_table = true
			table.insert(result, key)
		end
	end
	
	table.sort(result, compare)
	
	for i = 1, #result do
		if is_table] then
			local name = result
			result = deep_sort(current])
			result.name = name
		else
			result = { name = result }
		end
	end
	
	return result
end

-- Reliably get family for etymology language.
local function get_family(code)
	while code do
		local data = get_data(code)
		local family = data or data.family
		if family then -- This is a regular language or family code.
			return family
		end
		-- This is an etymology language code. Go up in the chain of parenthood.
		code = data.parent
	end
end

local function all_in_family(family_code, codes)
	for _, code in ipairs(codes) do
		if get_family(code) ~= family_code then
			return false
		end
	end
	return true
end

local protolanguage_of = memoize(function(fam_code)
	local data = get_data(fam_code)
	if data then
		local proto = data.protoLanguage
		if proto then
			return proto
		end
	end
	
	local proto = fam_code .. "-pro"
	if regular_languages or etymology_languages then
		return proto
	end
end)

-- Key: old parent code
-- Value: new parent code (move all regular languages or families here)
local new_parent_code = {}

-- Key: ancestor of proto-language
-- Value: table, containing
--    Key: proto-language
--    Value: family of proto-language
local protolanguage_to_put_under_family = make_auto_subtabler()

local function find_ancestors(code, val)
	-- First look for the special family tree–only ancestor.
	if supplementary_language_and_family_data and supplementary_language_and_family_data.parent then
		return { supplementary_language_and_family_data.parent }
	
	-- Handle etymology languages.
	elseif etymology_languages then
		local parent = val.parent
		if parent then
			return { parent }
		end
	
	-- Handle regular languages
	-- Return ancestors value if the ancestors belong to the same language
	-- family.
	elseif val.ancestors and (#val.ancestors == 1
	or all_in_family(get_family(code), val.ancestors)) then
		return val.ancestors
	
	-- If the proto-language of a family does not belong to the family (i.e.,
	-- it belongs to the same family as the family does), nest the family
	-- under the proto-language instead of the other way around.
	elseif families then
		local proto = protolanguage_of(code)
		if proto then
			if get_family(proto) == get_family(code) then
				new_parent_code = code
				return { proto }
			end
			
			-- Normally a family is the child of a proto-language or a family,
			-- but if the family's proto-language has an ancestors field, use
			-- that as parent instead.
			local proto_data = get_data(proto)
			if proto_data.ancestors then
				for _, ancestor in ipairs(proto_data.ancestors) do
					protolanguage_to_put_under_family = code
				end
				
				return proto_data.ancestors
			end
		end
	end
	
	-- Handle regular languages and language families.
	-- Return a proto-language if possible, else a language family.
	if get_family(code) then
		-- Go up through the language families that the language or family
		-- belongs to.
		local origin = code
		while true do
			code = get_family(code)
			val = families
			
			-- no family, "not a family", undetermined family
			if not (code and val and code ~= "qfa-not" and code ~= "qfa-und") then
				if code and not val then
					-- Error in data table!
					mw.log("no such family code: " .. code)
				end
				return nil
			end
			
			local proto = protolanguage_of(code)
			if proto and proto ~= origin then
				return { proto }
			else
				return { code }
			end
		end
	end
end

local function make_parent_to_children_map()
	local children = make_auto_subtabler{}
	
	for _, data_module in ipairs { families, regular_languages, etymology_languages } do
		for code, data in pairs(data_module) do
			local ancestors = find_ancestors(code, data)
			if ancestors then
				for _, ancestor in ipairs(ancestors) do
					if ancestor ~= code then
						table.insert(children, code)
					end
				end
			end
		end
	end
	
	-- No more auto subtabling needed.
	return children:un_auto_subtable()
end

-- For instance, Latin is the proto-language of the Romance languages, but
-- belongs to the Italic family. All the children of Latin that are languages
-- or families were initially placed under Latin, but must be placed under the
-- Romance languages.
local function move_children(parent_to_children_map)
	make_auto_subtabler(parent_to_children_map)
	
	for old_code, new_code in pairs(new_parent_code) do
		local old_children = parent_to_children_map
		local new_children = parent_to_children_map
		
		local i = 1
		while old_children do
			local child = old_children
			if child ~= new_code and (regular_languages or families) then
				table.insert(new_children, table.remove(old_children, i))
			else
				i = i + 1
			end
		end
		
		if #old_children == 0 then
			parent_to_children_map = nil
		end
	end
	
	for old_parent, child_to_new_parent in pairs(protolanguage_to_put_under_family) do
		local old_children = parent_to_children_map
		if type(old_children) == "table" then
			local i = 1
			while old_children do
				local child = old_children
				
				local new_parent = child_to_new_parent
				if new_parent then
					table.insert(parent_to_children_map, table.remove(old_children, i))
				else
					i = i + 1
				end
			end
		end
	end
	
	parent_to_children_map:un_auto_subtable()
end

local function reverse_comp(a, b)
	return a > b
end

local function make_nested(data, children)
	local make_nil = {}
	for key, val in pairs(data) do
		if type(key) == "number" then
			if children then
				data = make_nested(children, children)
				table.insert(make_nil, key)
			end
		else
			data = make_nested(val, children)
		end
	end
	if make_nil then -- Make sure larger keys are removed first.
		table.sort(make_nil, reverse_comp)
	end
	for _, key in ipairs(make_nil) do
		table.remove(data, key)
	end
	return data
end

local function main()
	local parent_to_children_map = make_parent_to_children_map()
	
	move_children(parent_to_children_map)
	
	local nested = make_nested(parent_to_children_map, parent_to_children_map)
	
	nested = deep_sort(nested)
	
	return { nested = nested, protolanguage_of = protolanguage_of }
end

return main()