এই মডিউলের জন্য মডিউল:number list/data/fi/নথি-এ নথিপত্র তৈরি করা হয়ে থাকতে পারে

local export = {numbers = {}}

local numbers = export.numbers

export.additional_number_types = {
	{key = "colloquial_counting_form", after = "cardinal"},
	{key = "colloquial_ordinal", after = "ordinal"},
	{key = "digit_name", after = "ordinal_abbr"},
}

numbers[0] = {
	cardinal = "nolla",
	ordinal = "nollas",
	colloquial_counting_form = "nol",
	digit_name = "nolla",
}

numbers[1] = {
	cardinal = "yksi",
	ordinal = "ensimmäinen",
	adverbial = {"kerran", "yhdesti<q:mathematics>"},
	multiplier = "yksinkertainen",
	distributive = "yksittäin",
	colloquial_counting_form = "yy",
	colloquial_ordinal = {"eka", "ensin"},
	digit_name = "ykkönen",
}

numbers[2] = {
	cardinal = "kaksi",
	ordinal = "toinen",
	adverbial = "kahdesti",
	fractional = "puolikas",
	multiplier = "kaksinkertainen",
	distributive = "kaksittain",
	colloquial_counting_form = "kaa",
	colloquial_ordinal = "toka",
	digit_name = "kakkonen",
}

numbers[3] = {
	cardinal = "kolme",
	ordinal = "kolmas",
	adverbial = {"kolmesti", "kolmasti"},
	fractional = {"kolmasosa", "kolmannes"},
	multiplier = "kolminkertainen",
	distributive = "kolmittain",
	colloquial_counting_form = {"koo", "kol"},
	colloquial_ordinal = "kolkki",
	digit_name = "kolmonen",
}

numbers[4] = {
	cardinal = "neljä",
	ordinal = "neljäs",
	adverbial = "neljästi",
	fractional = {"neljäsosa", "neljännes"},
	multiplier = "nelinkertainen",
	colloquial_counting_form = {"nee", "nel"},
	colloquial_ordinal = "nelkki",
	digit_name = "nelonen",
}

numbers[5] = {
	cardinal = "viisi",
	ordinal = "viides",
	adverbial = "viidesti",
	fractional = {"viidesosa", "viidennes"},
	multiplier = "viisinkertainen",
	colloquial_counting_form = "vii",
	colloquial_ordinal = "viikki",
	digit_name = "viitonen",
}

numbers[6] = {
	cardinal = "kuusi",
	ordinal = "kuudes",
	adverbial = "kuudesti",
	fractional = {"kuudesosa", "kuudennes"},
	multiplier = "kuusinkertainen",
	colloquial_counting_form = "kuu",
	colloquial_ordinal = "kuukki",
	digit_name = "kuutonen",
}

numbers[7] = {
	cardinal = "seitsemän",
	ordinal = "seitsemäs",
	adverbial = "seitsemästi",
	fractional = {"seitsemäsosa", "seitsemännes"},
	multiplier = "seitsenkertainen",
	colloquial_counting_form = "see",
	colloquial_ordinal = {"seikki", "seiska"},
	digit_name = {"seiska<qq:informal>", "seitsikko", "seitsemäinen"},
}

numbers[8] = {
	cardinal = "kahdeksan",
	ordinal = "kahdeksas",
	adverbial = "kahdeksasti",
	fractional = {"kahdeksasosa", "kahdeksannes"},
	multiplier = "kahdeksankertainen",
	colloquial_counting_form = "kasi",
	colloquial_ordinal = "kakki",
	digit_name = {"kahdeksikko", "kahdeksainen"},
}

numbers[9] = {
	cardinal = "yhdeksän",
	ordinal = "yhdeksäs",
	adverbial = "yhdeksästi",
	fractional = {"yhdeksäsosa", "yhdeksännes"},
	multiplier = "yhdeksänkertainen",
	colloquial_counting_form = "ysi",
	colloquial_ordinal = "ykki",
	digit_name = {"yhdeksikkö", "yhdeksäinen"},
}

numbers[10] = {
	cardinal = "kymmenen",
	ordinal = "kymmenes",
	adverbial = "kymmenesti",
	fractional = {"kymmenesosa", "kymmenennes"},
	multiplier = "kymmenkertainen",
	colloquial_counting_form = {"kymppi", "kybä"},
}

-- Cardinals and ordinals for 11-19 are set down below.
numbers[11] = {
	colloquial_counting_form = "yytoo",
}

numbers[12] = {
	colloquial_counting_form = "kaatoo",
}

numbers[13] = {
	colloquial_counting_form = "kootoo",
}

numbers[14] = {
	colloquial_counting_form = "neetoo",
}

numbers[15] = {
	colloquial_counting_form = "viitoo",
}

numbers[16] = {
	colloquial_counting_form = "kuutoo",
}

numbers[17] = {
	colloquial_counting_form = "seetoo",
}

numbers[18] = {
	colloquial_counting_form = "kasitoo",
}

numbers[19] = {
	colloquial_counting_form = "ysitoo",
}

numbers[20] = {
	colloquial_counting_form = "kakskyt",
}

numbers[30] = {
	colloquial_counting_form = "kolkyt",
}

numbers[40] = {
	colloquial_counting_form = "nelkyt",
}

numbers[50] = {
	colloquial_counting_form = "viiskyt",
}

numbers[60] = {
	colloquial_counting_form = "kuuskyt",
}

numbers[70] = {
	colloquial_counting_form = {"seiskyt", "seitkyt"},
}

numbers[80] = {
	colloquial_counting_form = "kasikyt",
}

numbers[90] = {
	colloquial_counting_form = "ysikyt",
}

numbers[100] = {
	cardinal = "sata",
	ordinal = "sadas",
}

numbers[1000] = {
	cardinal = "tuhat",
	ordinal = "tuhannes",
}

numbers[1000000] = {
	cardinal = "miljoona",
	ordinal = "miljoonas",
}

local function power_of(n)
	return "1" .. string.rep("0", n)
end

export.numbers[power_of(9)] = {
	cardinal = "miljardi",
	ordinal = "miljardis",
}

export.numbers[power_of(12)] = {
	cardinal = "biljoona",
	ordinal = "biljoonas",
}

export.numbers[power_of(15)] = {
	cardinal = "biljardi",
	ordinal = "biljardis",
}

export.numbers[power_of(18)] = {
	cardinal = "triljoona",
	ordinal = "triljoonas",
}

export.numbers[power_of(21)] = {
	cardinal = "triljardi",
	ordinal = "triljardis",
}

export.numbers[power_of(24)] = {
	cardinal = "kvadriljoona",
	ordinal = "kvadriljoonas",
}

export.numbers[power_of(30)] = {
	cardinal = "kvintiljoona",
	ordinal = "kvintiljoonas",
}

export.numbers[power_of(36)] = {
	cardinal = "sekstiljoona",
	ordinal = "sekstiljoonas",
}

export.numbers[power_of(42)] = {
	cardinal = "septiljoona",
	ordinal = "septiljoonas",
}

export.numbers[power_of(48)] = {
	cardinal = "oktiljoona",
	ordinal = "oktiljoonas",
}

local alt_ordinal = { "yhdes", "kahdes" }

local nth_decades = {
	"toista", "kolmatta", "neljättä", "viidettä", "kuudetta",
	"seitsemättä", "kahdeksatta", "yhdeksättä", "kymmenettä"
}

local partitives = {
	[10] = "kymmentä",
	[100] = "sataa",
	[1000] = "tuhatta",
	[1000000] = "miljoonaa",
	[1000000000] = "miljardia",
	[1000000000000] = "biljoonaa"	
}

local MAXIMUM_ONES = 121
local MAXIMUM_FACTORS_MNZ = MAXIMUM_ONES
local MAXIMUM_FACTORS_MT1 = 100000000
local MAXIMUM_FACTORS_ANY = 1000000000

local function set_number(number, cardinal, ordinal)
	if not numbers[number] then
		numbers[number] = {}
	end
	numbers[number].cardinal = cardinal
	numbers[number].ordinal = ordinal
end

local function prepend(prefix, items)
	if type(items) == "table" then
		local result = {}
		for _, item in ipairs(items) do
			table.insert(result, prefix .. item)
		end
		return result
	else
		return prefix .. items
	end
end

local function append(items, suffix)
	if type(items) == "table" then
		local result = {}
		for _, item in ipairs(items) do
			table.insert(result, item .. suffix)
		end
		return result
	else
		return items .. suffix
	end
end

local function more_than_one_nonzero(...)
	local count = 0
	for _, v in ipairs(arg) do
		if v ~= 0 then count = count + 1 end
	end
	return count > 1
end

local function make_factor(factor, base, separator)
	local factorbase = factor * base
	local factor_ord = alt_ordinal[factor] or numbers[factor].ordinal
	if factorbase > MAXIMUM_FACTORS_ANY then return false end
	set_number(factorbase,
		numbers[factor].cardinal .. separator .. partitives[base],
		append(factor_ord, separator .. numbers[base].ordinal)
	)
	return true
end

local function make_factors(base)
	local separator = base >= 1000000 and " " or ""
	for factor = 2,9 do
		if not make_factor(factor, base, separator) then break end
	end
end

local function past_maximum(base, hundreds, tens, units)
	local factor = hundreds + tens + units
	local factorbase = factor * base
	if factorbase > MAXIMUM_FACTORS_MNZ and more_than_one_nonzero(hundreds, tens, units) then
		return true
	end
	if factorbase > MAXIMUM_FACTORS_MT1 and math.max(hundreds, tens, units) > 1 then
		return true
	end
	return factorbase > MAXIMUM_FACTORS_ANY
end

local function make_factors_tens_hundreds(base)
	local separator = base >= 1000000 and " " or ""
	for hundreds=0,900,100 do
		for tens=0,90,10 do
			if past_maximum(base, hundreds, tens, 0) then break end
			for units=0,9 do
				if past_maximum(base, hundreds, tens, units) then break end
				local factor = hundreds + tens + units
				if factor >= 2 then
					if not make_factor(factor, base, separator) then break end
				end
			end
		end
	end
end

local function make_first_decade(base)
	local separator = base >= 1000 and " " or ""
	for ones = 1,9 do
		if base + ones > MAXIMUM_ONES then break end
		local alt_ord = alt_ordinal[ones]
		set_number(base + ones,
			numbers[base].cardinal .. separator .. numbers[ones].cardinal,
			alt_ord and {
				numbers[base].ordinal .. separator .. alt_ord,
				numbers[base].ordinal .. separator .. numbers[ones].ordinal
			} or numbers[base].ordinal .. separator .. numbers[ones].ordinal
		)
	end
end

local function make_hundreds()
	local base = 100
	make_factors(base)
	
	for factor = 1,9 do
		local factorbase = factor * base
		if factorbase > MAXIMUM_ONES then break end
		make_first_decade(factorbase)
		for offset = 10,base-1 do
			local n = factorbase + offset
			if n > MAXIMUM_ONES then break end
			set_number(n,
				prepend(numbers[factorbase].cardinal, numbers[offset].cardinal),
				prepend(numbers[factorbase].ordinal, numbers[offset].ordinal)
			)
		end
	end
end

local function recurse_down(factorbase, unit)
	make_first_decade(factorbase)
	for offset = 10,999 do
		local n = factorbase + offset * unit
		if n > MAXIMUM_ONES then break end
		set_number(n,
			prepend(numbers[factorbase].cardinal .. " ", numbers[offset].cardinal),
			prepend(numbers[factorbase].ordinal .. " ", numbers[offset].ordinal)
		)
	end

	if unit >= 1000 then
		for factor = 0,999 do
			local n = factorbase + factor / 1000
			if n > MAXIMUM_ONES then break end
			recurse_down(n, unit / 1000)
		end
	elseif unit ~= 1 then
		error("Illegal state")
	end
end

local function expand_power(power3)
	local base = 1
	for _ = 1,power3 do base = 1000 * base end

	make_factors_tens_hundreds(base)
	for factor = 1,999 do
		recurse_down(factor * base, base / 1000)
	end
end

local function remove_link_if(form)
	return mw.ustring.find(form, " ") and not mw.ustring.find(form, "%[")
end

-- local function separate_links(form)
-- 	if not mw.ustring.find(form, " ") or mw.ustring.find(form, "%[") then
-- 		return form
-- 	end
-- 	if mw.ustring.find(form, "<") then
-- 		local tag_index = mw.ustring.find(form, "<")
-- 		local before_tag, tag = mw.ustring.sub(form, 1, tag_index - 1), mw.ustring.sub(form, tag_index)
-- 		return separate_links(before_tag) .. tag
-- 	end
-- 	if not mw.ustring.find(form, "[^0-9 .-]") then
-- 		-- TODO (delink completely)
-- 		return form
-- 	end
-- 	return mw.ustring.gsub(form, "[a-zåäöšž]+", "[[%1]]") .. "<link:>"
-- end

for ones = 1,9 do
	local one_ord = alt_ordinal[ones] or numbers[ones].ordinal
	set_number(10 + ones,
		numbers[ones].cardinal .. nth_decades[1],
		one_ord .. nth_decades[1]
	)
end

make_factors(10)
for tens = 20,90,10 do
	make_first_decade(tens)
end

make_hundreds()
expand_power(1)
expand_power(2)

local function make_default_ordinal_abbr(num, data)
	local tbl = { num .. "." }
	local enc = { }
	local function visit(ord)
		local form
		if mw.ustring.match(ord, "nen$") then
			form = num .. ":nen"
		else
			form = num .. ":s"
		end
		if not enc[form] then
			enc[form] = true
			table.insert(tbl, form)
		end
	end
	if type(data.ordinal) == "table" then
		for _, ord in ipairs(data.ordinal) do
			visit(ord)
		end
	else
		visit(data.ordinal)
	end
	return tbl
end

for num, data in pairs(numbers) do
	num = tostring(num)
	if #num < 10 then -- skip large numbers
		if #num >= 4 then
			local num_remainder_digits = #num % 3
			local left_remainder_digits = num:sub(1, num_remainder_digits)
			local right_power_of_3_digits = num:sub(1 + num_remainder_digits)
			num = left_remainder_digits .. right_power_of_3_digits:gsub("(...)", " %1")
		end
		data.ordinal_abbr = data.ordinal_abbr or make_default_ordinal_abbr(num, data)
	end
end

local empty_keys = {}
-- remove entries with spaces. we do not want links to them.
for number, form_types in pairs(export.numbers) do
	for form_type, forms in pairs(form_types) do
		if type(forms) == "string" then
			if remove_link_if(forms) then
				form_types[form_type] = nil
			end
		elseif type(forms) == "table" then
			local source_index = 1
			local source_end = #forms
			local destination_index = 1
			while source_index <= source_end do
				local form = forms[source_index]
				if not remove_link_if(form) then
					forms[destination_index] = form
					destination_index = destination_index + 1
				end
				source_index = source_index + 1
			end
		end
	end
	
	--if not pairs(form_types)(form_types) then
	if not (form_types.cardinal or form_types.ordinal) then
		table.insert(empty_keys, number)
	end
end

for _, number in ipairs(empty_keys) do
	export.numbers[number] = nil
end

for num = 0,19 do
	numbers[num].wplink = ("%s (luku)"):format(num)
end

return export