Moduł:Sandbox/Draco flavus/Test10

Z Wikiźródeł, wolnej biblioteki

Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:Sandbox/Draco flavus/Test10/opis

local p = {}

-- kilka funkcji w module
--    1. prywatne funkcje :
--          a. porzadkowe     ( liczbę zamienia na liczebnik porządkowy: np. 31 → trzydziesty/a/e pierwszy/a/e )
--          b. porzadkowe2dec ( liczebnik porządkowy zamienia na liczbę: np. trzdzieste trzecie → 33 )
--          c. HighRoman      ( liczbę zamienia na liczbę rzymską  np. 31 → XXXI )
--          d. HighRoman2dec  ( liczbę rzymską zamienia na liczbę np. XXXIII → 33 )
--          e. decMix         ( liczbę zamienia na liczbę z końcówką: np. 29 → 29-ty/a/e )
--          f. HighRomanMix   ( liczbę zamienia na liczbę z końcówką: np. 51 → LI-szy/a/e )
--       Wspólne fragmenty kodu znajdują się w funkcjach prywatnych
--          α. typprefixnr    ( rozpoznaje typ liczby, liczbę, rodzaj gr. np. Opowiadanie trzecie → porządkowy, opowiadanie, 3, y )
--          β. przyrostekMix  ( podaje końcówkę dla mieszanych liczebników (np. LI-szy))
--    2. funkcje używane przez szablony
--          a. poprzedni ( próbuje znaleźć pasującą nazwę poprzedniego rozdziału np. domniemuje, że przed Ciekawa książka/Rozdział XXI jest Ciekawa książka/Rozdział XX )
--          b. bieżący ( oddziela końcowy fragment nazwy dający się konwertować na liczbę i przedstawia go jako liczbę np. Ciekawa książka/Rozdział XXI → 21 )
--          a. nastepny ( próbuje znaleźć pasującą nazwę następnego rozdziału np. domniemuje, że po Ciekawa książka/Rozdział XXI jest Ciekawa książka/Rozdział XXII )
--
-- dla liczb rzymskich i liczebników porządkowych dostępny jest zakres 1÷3999
-- w celu testu możliwe jest wywołanie na przykład {{#invoke:Liczebniki|poprzedni|Ciekawa książka/Tom I/Rozdział ósmy}}
--                                                 {{#invoke:Liczebniki|nastepny|Ciekawa książka/Tom I/Rozdział ósmy}}
--                                                 {{#invoke:Liczebniki|biezacy|Rozdział ósmy}} {{#invoke:Liczebniki|biezacy|IX}} {{#invoke:Liczebniki|biezacy|Tom 21}}


function p.poprzedni(frame)
	a = tostring(frame.args[1])
	t, p, n, g = typprefixnr(a)
	if t == 'arabskie' then
		return p .. (n - 1)
	elseif t == 'HR' then
		return p .. HighRoman(n - 1)
	elseif t == 'porządkowy' then
		return p .. porzadkowe(n - 1, g)
	elseif t == 'HRmix' then
		return p .. HighRomanMix(n - 1, g)
	elseif t == 'armix' then
		return p .. decMix(n - 1, g)
	else
		return a
	end
end
function p.biezacy(frame)
	a = tostring(frame.args[1])
	t, p, n, g = typprefixnr(a)
	if t == 'arabskie'
		or t == 'HR'
		or t == 'porządkowy'
		or t == 'HRmix'
		or t == 'armix' then
		return n
	else
		return a
	end
end
function p.nastepny(frame)
	a = tostring(frame.args[1])
	t, p, n, g = typprefixnr(a)
	if t == 'arabskie' then
		return p .. (n + 1)
	elseif t == 'HR' then
		return p .. HighRoman(n + 1)
	elseif t == 'porządkowy' then
		return p .. porzadkowe(n + 1, g)
	elseif t == 'HRmix' then
		return p .. HighRomanMix(n + 1, g)
	elseif t == 'armix' then
		return p .. decMix(n + 1, g)
	else
		return a
	end
end
function p.test(frame)
	return typprefixnr(frame.args[1])
end
function typprefixnr(str)
	local a = str
    poz = a:find('%d+$')                                             -- czy na końcu cyfra
	if poz == nil then
		-- na końcu nie ma cyfry (rzymskie, słowne lub nienumeryczne)
		poz = a:find('[MDCLXVI]+$')                                  -- czy na końcu rzymskie
		if poz == nil then
			-- na końcu nie ma cyfry ani rzymskiej (słowne, mix lub nienumeryczne)
			poz = a:find('[MDCLXVI]+-[cgmnst][iz]?[aeiy]$')
			if poz and poz > 1 then
				-- na końcu coś typu VII-my
				num = HighRoman2dec(a:sub(poz, a:find('-[^-]+$') - 1))
				gen = a:sub(-1, -1)
				regen = HighRomanMix(num, gen)
				if a:sub(-regen:len() - 1) ~= (' ' .. regen) or a:len() < regen:len() + 2 then
					return 'Error'
				else
					return 'HRmix', a:sub(1, poz - 1), num, a:sub(-1)
				end
			else
				poz = a:find('%d+-[cgmnst][iz]?[aeiy]$')
				if poz and poz > 1 then
					-- na końcu coś typu 27-my
					num = a:sub(poz, a:find('-[^-]+$') - 1)
					gen = a:sub(-1, -1)
					regen = decMix(num, gen)
					if a:sub(-regen:len() - 1) ~= (' ' .. regen) or a:len() < regen:len() + 2 then
						return 'Error'
					else
						return 'armix', a:sub(1, poz - 1), num, a:sub(-1)
					end
				else
					num = porzadkowe2dec(a)
					gen = a:sub(-1, -1)
					regen = porzadkowe(num, gen)
					poz = a:find(' ' .. regen .. '$')
					if poz == nil or poz == 1 then                    -- czy na końcu liczebnik (słownie)
						-- nie jest to numeryczne
						return 'Error'
						else
						-- na końcu liczebnik porządkowy
						return 'porządkowy', a:sub(1, poz), num, a:sub(-1)
					end
				end
			end
		else
			-- na końcu rzymskie
			num = HighRoman2dec(a:sub(poz))
			regen = HighRoman(num)
			if (a:sub(poz - 1, poz - 1) == ' ' or poz == 1) and regen == a:sub(poz) then
				return 'HR', a:sub(1, poz- 1), num, 'ø'
			else
				return 'błąd', 0, 0
			end
		end
	else
		-- na końcu cyfry
		num = tonumber(a:sub(poz))
		return 'arabskie', a:sub(1, poz - 1), num, 'ø'
	end
end
function porzadkowe2dec(str)
	local b = 0
	local c = ''
	local liczebniki = {['tysięczn'] = 1000, ['dwutysięczn'] = 2000, ['trzytysięczn'] = 3000, ['tysią'] = 1000, ['dw'] = 2000, ['trz'] = 3000, ['setn'] = 100, ['dwusetn'] = 200, ['trzysetn'] = 300, ['czterysetn'] = 400, ['pięćsetn'] = 500, ['sześćsetn'] = 600, ['siedemsetn'] = 700, ['osiemsetn'] = 800, ['dziewięćsetn'] = 900, ['st'] = 100, ['dwieści'] = 200, ['trzyst'] = 300, ['czteryst'] = 400, ['pięćse'] = 500, ['sześćse'] = 600, ['siedemse'] = 700, ['osiemse'] = 800, ['dziewięćse'] = 900, ['pierwsz'] = 1, ['drugi'] = 2, ['drug'] = 2, ['trzeci'] = 3, ['trzec'] = 3, ['czwart'] = 4, ['piąt'] = 5, ['szóst'] = 6, ['siódm'] = 7, ['ósm'] = 8, ['dziewiąt'] = 9, ['dziesiąt'] = 10, ['jedenast'] = 11, ['dwunast'] = 12, ['trzynast'] = 13, ['czternast'] = 14, ['piętnast'] = 15, ['szesnast'] = 16, ['siedemnast'] = 17, ['osiemnast'] = 18, ['dziewiętnast'] = 19, ['dwudziest'] = 20, ['trzydziest'] = 30, ['czterdziest'] = 40, ['pięćdziesiąt'] = 50, ['sześćdziesiąt'] = 60, ['siedemdziesiąt'] = 70, ['osiemdziesiąt'] = 80, ['dziewięćdziesiąt'] = 90}  
	for t in string.gmatch(str, "([^"..' '.."]+)") do
		c = c .. '@' .. string.sub(t, 1, -2)
        b = b + tonumber(liczebniki[string.sub(t, 1, -2)] or 0)
	end
	return b
end

function porzadkowe(num, rodzaj)
	local fullthousends = {'tysięczn', 'dwutysięczn', 'trzytysięczn'}
	local thousends = {'tysiąc ', 'dwa tysiące ', 'trzy tysiące '}
	local fullhundreds = {'setn', 'dwusetn', 'trzysetn', 'czterysetn', 'pięćsetn', 'sześćsetn', 'siedemsetn', 'osiemsetn', 'dziewięćsetn'}
	local hundreds = {'sto ', 'dwieście ', 'trzysta ', 'czterysta ', 'pięćset ', 'sześćset ', 'siedemset ', 'osiemset ', 'dziewięćset '}
	local onetonineteen = {'pierwsz', 'drugi', 'trzeci', 'czwart', 'piąt', 'szóst', 'siódm', 'ósm', 'dziewiąt', 'dziesiąt', 'jedenast', 'dwunast', 'trzynast', 'czternast', 'piętnast', 'szesnast', 'siedemnast', 'osiemnast', 'dziewiętnast'}
	local tens = {'dziesiąt', 'dwudziest', 'trzydziest', 'czterdziest', 'pięćdziesiąt', 'sześćdziesiąt', 'siedemdziesiąt', 'osiemdziesiąt', 'dziewięćdziesiąt'}
	local k
	local r = {}
	if rodzaj == 'i' then 
		rodzaj = 'y'
	end
	local sdj = num % 1000
	local t = (num - sdj) / 1000
	local dj = sdj % 100
	local s = (sdj - dj) / 100
	local j = dj % 10
	local d = (dj - j) / 10
	if num < 1 or num > 3999 then
		return 'error'
	else
		if sdj == 0 then
			r[1] = fullthousends[t]
			r[2] = rodzaj
		else
			if t == 0 then
				r[1] = ''
			else
				r[1] = thousends[t]
			end
			if dj == 0 then
				r[2] = fullhundreds[s]
				if s == 0 then
					r[3] = ''
				else
					r[3] = rodzaj
				end
			else
				if s == 0 then
					r[2] = ''
				else
					r[2] = hundreds[s]
				end
				if dj >= 10 and dj <= 19 then
					r[3] = onetonineteen[dj]
					r[4] = rodzaj
				else
					if dj < 10 then
						r[3] = ''
						r[4] = ''
					else
						r[3] = tens[d]
						if j == 0 then
							r[4] = rodzaj
						else
							r[4] = rodzaj .. ' '
						end
					end
					if j == 0 then
						r[5] = ''
					else
						r[5] = onetonineteen[j]
						r[6] = rodzaj
					end
					if r[6] == 'y' and (r[5] == 'drugi' or r[5] == 'trzeci') then
						r[6] = ''
					end
					if r[6] == 'a' and r[5] == 'drugi' then
						r[5] = 'drug'
					end
				end
			end	
		end
	end
	return table.concat(r,'')
end

function p.main(frame)
	return HighRoman(500).. '  ' .. HighRoman2dec('MMLXIV')
end

local HighRomans = {
    { 1000, 'M' },
    { 900, 'CM' }, { 500, 'D' }, { 400, 'CD' }, { 100, 'C' },
    {  90, 'XC' }, {  50, 'L' }, {  40, 'XL' }, {  10, 'X' },
    {   9, 'IX' }, {   5, 'V' }, {   4, 'IV' }, {   1, 'I' }
}


function HighRoman(num)
    local ret = {}
    for _, v in ipairs(HighRomans) do
        local val, letter = unpack(v)
        while num >= val do
            num = num - val
            table.insert(ret, letter)
        end
    end
    return table.concat(ret)
end

local HighRomans2dec = {['M'] = 1000, ['D'] = 500, ['C'] = 100, ['L'] = 50, ['X'] = 10, ['V'] = 5, ['I'] = 1 }

function HighRoman2dec(str)
    local ret = '0'
    local actsign = '0'
    local lastsign = 0
    local i = 1
	for i = #str, 1, -1 do
		actsign = HighRomans2dec[str:sub(i,i)]
		ret = ret + (actsign < lastsign and -actsign or actsign)
		lastsign = actsign
	end
	return ret
end

function HighRomanMix(num, rodzaj)
	return HighRoman(num) .. przyrostekMix(num, rodzaj)
end

function decMix(num, rodzaj)
	return tostring(num) .. przyrostekMix(num, rodzaj)
end

function przyrostekMix(num, rodzaj)
	dj = num % 100
	j = dj % 10
	d = (dj - j) / 10
	if rodzaj == 'i' then 
		rodzaj = 'y'
	end
	if num == 0 then
		return '-'
	else
		if dj == 0 then
			return '-n' .. rodzaj
		else
			if dj >= 9 and dj <= 20 then
				return '-t' .. rodzaj
			else
				if j == 1 then
					return '-sz' .. rodzaj
				else
					if j == 2 then
						return (rodzaj == 'y' and '-gi' or (rodzaj == 'a' and '-ga' or '-gie'))
					else 
						if j == 3 then
							return (rodzaj == 'y' and '-ci' or (rodzaj == 'a' and '-cia' or '-cie'))
						else
							if j == 7 or j == 8 then
								return '-m' .. rodzaj
							else
								return '-t' .. rodzaj
							end
						end
					end
				end
			end
		end
	end
end

function p.tes(frame)
	a = tonumber(frame.args[1])
	return a .. ' ' .. porzadkowe(a,'y') .. ' ' .. porzadkowe(a,'a') .. ' ' .. porzadkowe(a,'e') .. ' ' .. decMix(a,'y') .. ' ' .. decMix(a,'a') .. ' ' .. decMix(a,'e') .. ' ' .. HighRomanMix(a,'y') .. ' ' .. HighRomanMix(a,'a') .. ' ' .. HighRomanMix(a,'e') .. ' ' .. tostring(porzadkowe2dec(porzadkowe(a,'y')) == porzadkowe2dec(porzadkowe(a,'a')) and porzadkowe2dec(porzadkowe(a,'y')) == porzadkowe2dec(porzadkowe(a,'e')) and porzadkowe(a, 'y'):sub(-2) == decMix(a,'y'):sub(-2) and porzadkowe(a, 'a'):sub(-2) == decMix(a,'a'):sub(-2)  and porzadkowe(a, 'e'):sub(-2) == decMix(a,'e'):sub(-2) and porzadkowe2dec(porzadkowe(a,'y')) == a and HighRoman2dec(HighRoman(a)) == a) .. ' ' .. HighRoman(a)
end
function p.basename(frame)
	a = tostring(frame.args[1])
	return a:gsub('/[^/]*$', '') .. 'xxx'
end
return p