Module:Romain

De Wikirouge
Aller à la navigation Aller à la recherche

La documentation pour ce module peut être créée à Module:Romain/doc

local p = {}

-- barre horizontale au-dessus des nombres élevés
local function overline( s )
    return '<span style="text-decoration:overline">' .. s .. '</span>'
end

-- Gets the Roman numerals for a given numeral table. Returns both the string of
-- numerals and the value of the number after it is finished being processed.
local function getLetters( num, t )
    local ret = {}
    for _, v in ipairs( t ) do
        local val, letter = unpack( v )
        while num >= val do
            num = num - val
            table.insert( ret, letter )
        end
    end
    return table.concat( ret ), num
end


function p.toRoman( num, default )
    num = tonumber( num )
    if not num or num < 1 or num == math.huge then
        return
    end
    num = math.floor( num )
    
    -- Return a message for numbers too big to be expressed in Roman numerals.
    if num >= 5000000 then
        return default or 'N/A'
    end
    
    local ret = ''
    -- Find the Roman numerals for the large part of numbers 5000 and bigger.
    -- The if statement is not strictly necessary, but makes the algorithm 
    -- more efficient for smaller numbers.
    if num >= 5000 then
        local bigRomans = {
            { 1000000, 'M' },
            { 900000, 'CM' }, { 500000, 'D' }, { 400000, 'CD' }, { 100000, 'C' },
            { 90000, 'XC' }, { 50000, 'L' }, { 40000, 'XL' }, { 10000, 'X' },
            { 5000, 'V' }
        }
        local bigLetters
        bigLetters, num = getLetters( num, bigRomans )
        ret = overline( bigLetters )
    end
    
    -- Find the Roman numerals for numbers 4999 or less.
    local smallRomans = {
        {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"} 
    }
    local smallLetters = getLetters( num, smallRomans )
    ret = ret .. smallLetters
    
    return ret

end

function p.fromRoman( str, default )
	local strOrig = str
	str = str:upper()
	if not str:find( '^[MDCLXVI]+$' ) then
		return tonumber( str ) or default or strOrig
	end
	local smallRomans = { I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000 }
	local result = 0
	local old, n = 0
	for i = str:len(), 1, -1  do
		n = smallRomans[ str:sub( i, i ) ]
		if n < old then
			result = result - n
		else
			result = result + n
			old = n
		end
	end
	return result
end

-- compatibility with [[en:Module:Roman]]
function p._main(args)
	return p.toRoman( args[1] )
end

function p.main( frame )
	return p.nombreEnRomain( frame )
end

-- functions to call the module from a template (takes the #invoke first arg or the template first arg)
function p.nombreEnRomain( frame )
	local num
	if frame == mw.getCurrentFrame() then
		num = frame.args[1] or frame:getParent().args[1]
	else
		num = frame
	end
	return p.toRoman( mw.text.trim( num or '' ) )
end

function p.nombreDepuisRomain( frame )
	local str
	if frame == mw.getCurrentFrame() then
		str = frame.args[1] or frame:getParent().args[1]
	else
		str = frame
	end
	return p.fromRoman( mw.text.trim( str or '' ) )
end
	
return p