Module:MathRoman07

La bibliothèque libre.

La documentation pour ce module peut être créée à Module:MathRoman07/Documentation

-- Module:MathRoman or MathRoman2
local p = {}

--[[ Module:MathRoman
local CA = require(p.ModuleNS .. "ControlArgs") -- ControlArgs requires also all the submodules and manage all versions
p.modules_versions = { -- Modules dependencies. Dependencias del módulo. Dépendances du module.
	versionName = "MathRoman", versionNumber = "2.01", versionDate = "2015-11-19 12:12",
	selector = " MathRoman ControlArgs ", -- Asked module and submodules versions
	all_versions = " MathRoman,MathRoman,MathRoman2 * CA,ControlArgs,ControlArgs1 ",
}
--]]

--[ [ Module:MathRoman2
p.modules_versions = { -- Modules dependencies. Dependencias del módulo. Dépendances du module.
	versionName = "MathRoman2", versionNumber = "2.01", versionDate = "2015-12-03 21:16",
	selector = " MathRoman2 ControlArgs1 ", -- Asked module and submodules versions
	all_versions = " MathRoman,MathRoman,MathRoman2 * CA,ControlArgs,ControlArgs1 ",
}
--] ]

p.ModuleNS = mw.site.namespaces.Module.name .. ":"
CA = require(p.ModuleNS .. "ControlArgs1") -- ControlArgs requires also all the submodules and manage all versions

p.versions = {}
local versions = p.versions
p.versions.vn = p.modules_versions
CA = CA.modules_binder(p, p.modules_versions) -- local CA : Activate the right versions of all submodules
if not CA then CA = require(p.ModuleNS .. "ControlArgs1") end -- DEBUG

local function require_pcall( version ) -- require() can fail without blocking page.
	if type(version) == "string" then
		version = string.gsub( version, p.ModuleNS, "" )
		version = p.ModuleNS .. version -- example Module:ControlArgs/I18N
	end
	local success, module = pcall( require, version ) -- pcall or xpcall can run any function without blocking page.
	if success then return module else return nil end
end

--[[
This module:MathRoman:
	converts integers to Roman numerals and vice versa,
	generates precise errors on the incoming number,
	generates errors on conversion limitations,
	displays tests of these functions.

Este módulo:MathRoman:
	convierte enteros a números romanos y viceversa,
	genera los errores precisos sobre el número entrante,
	genera errores en las limitaciones de conversión,
	displays probar estas funciones.

Ce Module:MathRoman :
	convertit des nombres entiers en nombres romains et vice-versa,
	genere des erreurs precises sur le nombre entrant,
	genere des erreurs sur les limites de conversion,
	permet d'afficher des tests de ces fonctions.
]]--

------------------------------------------------------------
-- Tables des traductions des paramètres et messages dans les langues : en, es, fr.
-- Tables of translations of settings and messages in the languages : en, es, fr.
-- Mesas traducciones parámetros y mensajes en los idiomas : en, es, fr.
--
-- i18n translations tables to extend and update in calling modules
------------------------------------------------------------

p.i18n = {} -- translations tables known in the module

p.i18n.en = {
	err_errors_head				= "Error: ",
	err_roman_error				= "Roman error: ",
	err_value_error				= "Value error: ",
	err_J_before_end			= "character J before the end",
	err_char_X_in_N				= "character %1 in %2",
	err_char_increasing			= "3 increasing characters",
	err_more_than_4999			= "value > 4999",
	err_null_value				= "null value",
	roman_to_digital_test_title	= "Test from roman to digital numbers",
	digital_to_roman_test_title	= "Test from digital to roman numbers",
} -- p.i18n.en

p.i18n.es = {
	err_errors_head				= "Error: ",            
	err_roman_error				= "Error de romano: ",
	err_value_error				= "Error de valor: ",
	err_J_before_end			= "carácter J antes del fin",
	err_char_X_in_N				= "carácter 1% en %2",
	err_char_increasing			= "3 crecientes caracteres",
	err_more_than_4999			= "valor > 4999",
	err_null_value				= "valor null",
	roman_to_digital_test_title	= "Prueba de números romanos a números decimales",
	digital_to_roman_test_title	= "Prueba de números decimales a números romanos",
} -- p.i18n.es

p.i18n.fr = {
	err_errors_head				= "Erreur : ",
	err_roman_error				= "Erreur de romain : ",
	err_value_error				= "Erreur de valeur : ",
	err_J_before_end			= "caractère J avant la fin",
	err_char_X_in_N				= "caractère %1 en %2",
	err_char_increasing			= "3 caractères croissants",
	err_more_than_4999			= "valeur > 4999",
	err_null_value				= "valeur nulle",
	roman_to_digital_test_title	= "Test des nombres romains en nombres décimaux",
	digital_to_roman_test_title	= "Test des nombres décimaux en nombres romains",
} -- p.i18n.fr

function p.error_color(t)
	return '<span style="color:red;" >' .. tostring(t) .. '</span>'
end

function p.pcall_int2roman(val, errs) -- DEBUG : p.int2roman() can fail without blocking page.
--	EBUG: Without this patch the p.int2roman() get the parser error "attempt to call field 'int2roman' ". Patched by Rical 2015-04-20.
--	local event_century_roman = ""
--	word, errx = p.int2roman(val, errs)
	-- See Maniphest T27845 Support loading wiki pages through mediaWiki.loader.load()
	-- DEBUG code:
	local success, word, errs = pcall(p.int2roman, val, errs) -- pcall or xpcall can run any function without blocking page.
	if success then return word, errs else return nil, errs end
end

function p.pcall_roman2int(word, errs) -- DEBUG : p.roman2int() can fail without blocking page.
--	DEBUG: Without this patch the p.int2roman() get the parser error "attempt to call field 'roman2int' ". Patched by Rical 2015-04-20.
--	val, errs = p.roman2int(word, errs)
	local success, val, errs = pcall(p.roman2int, word, errs) -- pcall or xpcall can run any function without blocking page.
	if success then return val, errs else return nil, errs end
end

--	vueRomains : XIJ=12 MCXI=1111 MCDXLIV=1444 MDCLXVI=1666 MCMXCIX=1999 MMCCXXII=2222 MMMMCMXCIX=4999 ERREURS=0 erreur caractere S en 7. XIA=11 erreur caractere A en 3. XJI=12 erreur caractere J avant la fin. IXC=89 erreur caracteres croissants. VLD=445 erreur caracteres croissants. MMMMM=5000 erreur > 4999. MMMMMYJXC=5089 erreur > 4999. erreur caractere Y en 6. erreur caractere J avant la fin.

function p.roman2int(rm, errs)
--	CA.erron = true
	if ( rm == nil ) then rm = '' end
	if ( rm == '' ) then return '' end
	local v = 0 -- valeur totale
	local v1 = 0 -- valeur de derniere lettre
	local v2 = 0 -- valeur de lettre precedente
	local v3 = 0 -- valeur de lettre precedente
	local x = '-' -- caractere en cours d'evaluation
	local i = 1 -- numero du caractere en cours d'evaluation
	local j = 0 -- numero du caractere de reference courant (debut en Lua)
	local k = 0 -- numero du caractere de reference courant (fin en Lua)
	local errs = errs or ""
	local lst = '-MDCLXVIJ' -- caracteres autorises
	x = string.sub(rm, i, i) or ''
	while (x ~= '') do
		v3 = v2
		v2 = v1
		v1 = 0
	--	x = string.sub(rm, i, i)
		if ( x == 'M' ) then v1 = 1000 end
		if ( x == 'D' ) then v1 = 500 end
		if ( x == 'C' ) then v1 = 100 end
		if ( x == 'L' ) then v1 = 50 end
		if ( x == 'X' ) then v1 = 10 end
		if ( x == 'V' ) then v1 = 5 end
		if ( x == 'I' ) then v1 = 1 end
		if ( x == 'J' ) then v1 = 1 end
		if ( x == 'J' ) and ( i < string.len(rm) ) then
			errs = errs .. CA.err_add("err_J_before_end") -- e4 = ' erreur caractere J avant la fin.'
		end
		if ( v1 == 0 ) then
			errs = errs .. CA.err_add("err_char_X_in_N", x, i) -- e3 = ' erreur caractere '..x..' en '..i..'.'
		end
		v = v + v1
		if ( (v1 == 5*v2) or (v1 == 10*v2) ) then v = v - (2*v2) end -- ajuster 4, 9, 40, 90 ...
		j, k = string.find(lst, x)
		if ( j == nil ) then j = -1 end
		if ( k == nil ) then k = -1 end
		if (v1 > v2) and (v2 > v3) and (v3 > 0) then
			errs = errs .. CA.err_add("err_char_increasing") -- e2 = ' caracteres croissants.'
		end
		i = i + 1
		x = string.sub(rm, i, i) or ''
	end
	if ( v == 0 ) then --	e0 = ' valeur nulle.'
		errs = errs .. CA.err_add("err_null_value")
	--	v = 1
	end
	if ( v > 4999 ) then -- e1 = ' valeur > 4999.'
		errs = errs .. CA.err_add("err_more_than_4999")
	--	v = 4999
	end
	return v, errs, cats
end -- function p.roman2int(rm, err)

function p.roman_to_digital_test(t, word) -- Unitary tests of p.roman2int
	t = t or "roman_to_digital_test"
	t = "\n:*<b>" .. t .. "</b>:"
--	t = t .. CA.Th() .. CA.Tc("Nombre romain") .. CA.Tc("Valeur décimale (et corrigée)") .. CA.Tc("Erreur")
	t = t .. CA.Th() .. CA.Tc("Roman number") .. CA.Tc("Digital value (and corrected)") .. CA.Tc("Error")
	function roman_to_digital_test1(t, word)
		local val, errs = p.pcall_roman2int(word) -- DEBUG : p.roman2int() can fail without blocking page.
		if not val then errs = errs .. " p " .. CA.err_add(errs) end
		local wordX, errsX = p.pcall_int2roman(val) -- DEBUG : p.roman2int() can fail without blocking page.
		if wordX then val = tostring(val) .. " ( = " .. tostring(wordX) .. " ) " end
		t = (t or "") .. CA.Tr() .. CA.Td(word) .. CA.Td(val or "") .. CA.Td(errs)
		return t
	end
	t = roman_to_digital_test1( t, "-X")
	t = roman_to_digital_test1( t, "0")
	t = roman_to_digital_test1( t, "MCXI")
	t = roman_to_digital_test1( t, "XIJ")
	t = roman_to_digital_test1( t, "XJI")
	t = roman_to_digital_test1( t, "XIA")
	t = roman_to_digital_test1( t, "VLD")
	t = roman_to_digital_test1( t, "IXC")
	t = roman_to_digital_test1( t, "MMMMCMXCIX")
	t = roman_to_digital_test1( t, "MMMMM")
	t = roman_to_digital_test1( t, "MMMMMYJXC")
	t = t .. CA.Te()
	return t
end -- function p.roman_to_digital_test( t, args_known)

function p.romani2r(i, j)
	if ( j == nil ) then j = '' end
	local rm=''
	if ( i == 1000 ) then rm = 'M' end
	if ( i == 500 ) then rm = 'D' end
	if ( i == 100 ) then rm = 'C' end
	if ( i == 50 ) then rm = 'L' end
	if ( i == 10 ) then rm = 'X' end
	if ( i == 5 ) then rm = 'V' end
	if ( i == 1 ) then
		rm = 'I'
		if ( j == 'J' ) then  rm = 'J' end
	end
	return rm
end -- function p.romani2r(i, j)

function p.int2roman(i, errs)
	local n = 0
	if ( i == nil ) then n = 0 else n = i end -- anti nill
	if ( type(n) ~= 'number' ) then n = tonumber(n) end
	if ( type(n) ~= 'number' ) then n = 0 end
	n = math.floor(n) -- input:89: bad argument #1 to 'floor' (number expected, got nil)
	if type(errs) ~= 'string' then errs = "" end -- anti nill, to text
	local v100 = 100
	local v500 = v100*5
	local v1000 = v100*10 -- roman cycle romain 1000, 100, 10, 1
	local v, v1, v2, v3 = 0, 0, 0, 0 -- Total value, last, and previous. Valeur totale, derniere, et precedentes.
	local reste, reduction = 0, 0 -- Rest to convert, last reduction. Reste a convertir, derniere reduction.
	local rm = ''
	local roman = '' -- chiffre et nombre romain resultant
	local errs = errs or ""
	reste = n
	if ( n > 4999 ) then
		errs = errs .. CA.err_add("err_more_than_4999") -- e1 = ' valeur > 4999.'
		reste = 0
		roman = "" -- 'ERROR'
	end
	if ( n < 1 ) then
		n = 0
		errs = errs .. CA.err_add("err_null_value") -- e2 = ' valeur < 1.'
		reste = 0
		roman = "" -- 'ERROR'
	end
	-- return ' test ' -- temporaire
	while (reste > 0) do
		v3 = v2
		v2 = v1
		v1 = reste
		reduction = 0
		if ( reste >= v1000 ) then
			reduction = v1000
		elseif ( reste >= v100*9 ) then
			reduction = v100
			reste = reste + v100*2
		elseif ( reste >= v500 ) then
			reduction = v500
		elseif ( reste >= v100*4 ) then
			reduction = v100
			reste = reste + v100*2
		elseif ( reste >= v100 ) then
			reduction = v100
		elseif ( reste >= 1000 ) then
			v100 = 100
			v1000 = 1000
			reduction = v1000
		end
		rm = p.romani2r(reduction)
		roman = roman .. rm
		reste = reste - reduction
		if ( reste < v100 ) then
			if ( v100 >= 10 ) then
			v100 = v100/10
			v500 = v100*5
			v1000 = v100*10
			end
		end
	end
	return roman, errs -- avec ou sans erreurs
end -- function p.int2roman(in, err)

function p.digital_to_roman_test(t, val) -- Unitary tests of p.int2roman
	t = t or "digital_to_roman_test"
	t = "\n:*<b>" .. t .. "</b>:"
--	t = t .. CA.Th() .. CA.Tc("Nombre décimal") .. CA.Tc("Nombre romain") .. CA.Tc("Erreur")
	t = t .. CA.Th() .. CA.Tc("Digital value") .. CA.Tc("Roman number") .. CA.Tc("Error")
	function digital_to_roman_test1( t, val)
		local word, errs = p.pcall_int2roman(val,  "  ") -- DEBUG : p.int2roman() can fail without blocking page.
		t = (t or "") .. CA.Tr() .. CA.Td(val) .. CA.Td(word or "") .. CA.Td(errs)
		return t
	end
	t = digital_to_roman_test1( t, -10)
	t = digital_to_roman_test1( t, 0)
	t = digital_to_roman_test1( t, 12)
	t = digital_to_roman_test1( t, 17)
	t = digital_to_roman_test1( t, "18")
	t = digital_to_roman_test1( t, "19")
	t = digital_to_roman_test1( t, 111)
	t = digital_to_roman_test1( t, 444)
	t = digital_to_roman_test1( t, 555)
	t = digital_to_roman_test1( t, "777")
	t = digital_to_roman_test1( t, "1111")
	t = digital_to_roman_test1( t, "4999")
	t = digital_to_roman_test1( t, "5000")
	t = t .. CA.Te()
	return t
end -- function p.digital_to_roman_test(t, val)

function p.test_one_roman(r1)
	r1 = r1 or ''
	local i, err_r = p.roman2int(r1)
	err_r = err_r or " "
	if err_r ~= " " then err_r = CA.error_color( err_r ) end -- CA.str_vars("err_roman_error") ..
	local j, err_i = p.int2roman(i)
	if err_i ~= "" then err_i = CA.error_color( err_i ) end --  CA.str_vars("err_value_error") ..
	return "\n* '''" .. tostring(r1) .. "''' -> '''" .. tostring(i) .. "''', " .. err_r .. " '''-''' " .. err_i
end -- function p.test_one_roman(r1)

function p.error_one_roman(r1, view)
	if ( r1 == nil ) then r1 = '' end
	if ( view == nil ) then view = '' end
	if ( view == '' ) then view = '%s' end
	local i, erri = p.roman2int(r1, ' Erreur r2i : ')
	local s = " - " .. r1 .. " -> '''" .. i .. "''' "
	if ( erri == nil ) then erri = '' end
	if ( erri ~= '' ) then
		s = s .. ' -> ' .. CA.error_color( erri )
	end
	return string.format(view, s)
	-- return string.format("Hello, %s!", s)
end -- function p.error_one_roman(r1, view)

function p.testerDesRomains(view)
	if ( view == nil ) then view = '' end
	if ( view == '' ) then view = '%s' end
	view = '\n* %s'
	local s = ''
	s = s .. "\n;Tests sans erreurs :"
	s = s .. p.test_one_roman('XIJ', view)
	s = s .. p.test_one_roman('XIJ', view)
	s = s .. p.test_one_roman('MCXI', view)
	s = s .. p.test_one_roman('MCDXLIV', view)
	s = s .. p.test_one_roman('MDCLXVI', view)
	s = s .. p.test_one_roman('MCMXCIX', view)
	s = s .. p.test_one_roman('MMCCXXII', view)
	s = s .. p.test_one_roman('MMMMCMXCIX', view)
	s = s .. "\n;Tests avec erreurs :"
	s = s .. p.test_one_roman('i', view)
	s = s .. p.test_one_roman('XIA', view)
	s = s .. p.test_one_roman('XJI', view)
	s = s .. p.test_one_roman('IXC', view)
	s = s .. p.test_one_roman('VLD', view)
	s = s .. p.test_one_roman('', view)
	s = s .. p.test_one_roman(nil)
	s = s .. p.error_one_roman('XIA', view)
	s = s .. p.error_one_roman('XJI', view)
	s = s .. p.error_one_roman('IXC', view)
	s = s .. p.error_one_roman('VLD', view)
	s = s .. "\n;Nombres hors limites :"
	s = s .. p.test_one_roman('MMMMM', view)
	s = s .. p.test_one_roman('MMMMMYJXC', view)
	s = s .. p.error_one_roman('MMMMM', view)
	s = s .. p.error_one_roman('MMMMMYJXC', view)
	s = s .. p.test_one_roman('ERREURS', view)
	s = s .. p.error_one_roman('ERREURS', view)
	return s
end -- function p.testerDesRomains(view)

--  p.testerDesRomains('x') -- lance le test

-- Interface http://scribunto.wmflabs.org/

------------------------------------------------------------
-- Tests internes. Internal tests.
------------------------------------------------------------

function p.trc(fn_mode, t)
	local res = ""
	-- to put in comment to desactivate
--	res = res .. "<br/>* " .. t .. CA.ta("fn_mode", fn_mode) .. CA.ta("CA.mode_name", CA.mode_name) .. CA.ta("CA.mode_options", CA.mode_options) .. CA.ta("CA.invoke_options", CA.invoke_options)
	return res
end

-- Basic use, only translate and verify arguments, without use of options, modes and resulting text
-- Uso básico, sólo traducir y verificar argumentos, sin el uso de opciones, modos y texto resultante
-- Utilisation de base, seulement traduire et vérifier les arguments, sans utilisation d'options, modes et texte résultant
function p.base(frame, mode_name, args_known_default)
	-- The base function only imports, translates and verifies arguments.
	-- It imports arguments from wikidata, module and template with increasing priorities.
	CA.frame = frame
	local res = ""
	CA.time1 = os.clock()
	args_known_default = args_known_default or CA.args_known_default
	local source_mode_name, source_key, try_lang = CA.get_arg_mode(mode_name) -- CA.mode_name from args source
	CA.mode_name = mode_name or CA.mode_name or "normal"
	CA.versions.find_main_module(p) -- Find the MainModule from package.loaded
	CA.versions.bind_verif_modules(p) -- Test of binding of the modules and versions control bind_verif_modules_report
	CA.versions.bind_verif_modules_report() -- Test of binding of the modules and versions control bind_verif_modules_report
	local t, tbl = CA.versions.init_i18n()
	CA.module_init(frame)
	local args_source = CA.args_source
--	CA.categories_init() -- initialize the category list
	CA.verif_i18n()
	p.errors_list = {} -- Table to collect errors and messages
	CA.options_for_modes = p.options_for_modes
	local source_mode_name, source_key, try_lang = CA.get_arg_mode(mode_name) -- CA.mode_name from args source
	CA.mode_name = source_mode_name or CA.mode_name or "normal"

	CA.init_args( args_known_default, CA.args_source, lang, msgs_list)
	CA.args_wikidata, t = CA.import_wikidata(CA.args_known)
	CA.args_import, t = CA.import_arguments(args_known_default, CA.args_source )
	CA.args_final = CA.args_import
	CA.args_final.mode = CA.mode_name
	CA.time2 = os.clock()
	if type(CA.args_import.c) == "string" then
		CA.invoke_options = CA.args_import.c
	end
	if type(CA.args_import.mode) == "string" then
		mode_name = CA.args_import.mode
	end
	CA.invoke_options = CA.args_import.c or ""
	CA.mode_options = CA.options_from_mode(source_mode_name or mode_name)
	CA.init_wiki_user_lang()
	res = res .. CA.report_bind_verif_modules_details
	return res
end -- function p.base(frame, mode_name, args_known_default)

function p.normal(frame)
	-- The normal function imports, translates and verifies arguments.
	-- It generates normal text and uses options to include edit or tests
	local res, t = "", ""
	res = res .. p.base(frame, "normal", p.args_known_default)
--	CA.args_final = p.interact_args_final(CA.args_selected or CA.args_import) -- Interactions between argumensts
	CA.args_final.mode = CA.mode_name
	CA.time3 = os.clock()
	CA.init_wiki_user_lang()
	res = res .. "\n* " .. CA.errors_lister()
	res = res .. "<br/><b><b>Résumé</b></b>"
--	res = res .. versions.report_text("treeVersions_debug")
--	function CA.all_versions_text(t, all_versions)
--	res = res .. CA.report_text(t, versions.warning, CA.all_versions_text(t, versions.all_versions), versions.tree_text)
	return res
end -- function p.normal(frame)

function p.roman2integer(frame)
	-- { {#invoke:MathRoman|roman2integer| MMXIJ } }
	local res, t = "", ""
	res = res .. p.base(frame, "normal", p.args_known_default)
	local r = frame.args[1]
	local i, erri = p.roman2int(r, 'roman2int : ')
	res = res .. tostring(i) .. "=" .. erri .. CA.errors_lister()
--	res = res .. p.base(frame, "normal")
	return res
end

function p.r2i(frame) -- shortcut of p.roman2integer
	-- { {#invoke:MathRoman|r2i| MMXIJ } }
	return p.roman2integer(frame)
end

function p.integer2roman(frame)
	-- { {#invoke:MathRoman|integer2roman| 2012 } }
	local res, t = "", ""
	res = res .. p.base(frame, "normal", p.args_known_default)
	local i = frame.args[1]
	local r, errr = p.int2roman(i, ' int2roman : ')
	res = res .. tostring(r) .. "=" .. errr .. CA.errors_lister()
	return res
end

function p.i2r(frame) -- shortcut of integer2roman
	-- { {#invoke:MathRoman|i2r| MMXIJ } }
	return p.integer2roman(frame)
end

function p.testRomans(frame)
	-- { {#invoke:MathRoman|testRomans|': %s<br/>'} }
	local view = frame.args[1]
	if ( view == nil ) then view = '' end
	if ( view == '' ) then view = '%s' end
--	local res = p.testerDesRomains(view)
	local res = CA.dropdown_func(1, "roman_to_digital_test_title", p.roman_to_digital_test)
	res = res .. CA.dropdown_func(1, "digital_to_roman_test_title", p.digital_to_roman_test)
	return res
end

function p.autotests(frame)
	-- { {#invoke:MathRoman|testRomans|': %s<br/>'} }
	local res, t = "", ""
	local res, t = "", ""
	res = res .. p.base(frame, "normal", p.args_known_default)
--	CA.args_final = p.interact_args_final(CA.args_selected or CA.args_import) -- Interactions between argumensts
	CA.args_final.mode = CA.mode_name
	CA.time3 = os.clock()
	CA.init_wiki_user_lang()
	local view = frame.args[1]
	if ( view == nil ) then view = '' end
	if ( view == '' ) then view = '%s' end
--	local s = p.testerDesRomains(1)
	local res = CA.dropdown_func(1, "roman_to_digital_test_title", p.roman_to_digital_test)
	res = res .. CA.dropdown_func(1, "digital_to_roman_test_title", p.digital_to_roman_test)
	res = res .. CA.dropdown_func(1, "Versions management", CA.versions.warning_report)
	res = res .. tostring(s) .. "/" .. CA.errors_lister()
	return res
end

function p.testText(formater, text, n)
	local s = ''
	local N = tonumber(n)
	while ( N > 0 ) do
		s = s .. string.format(formater, text)
		N = N - 1
	end
	return s
end

return p