Module:MathRoman2
Apparence
La documentation pour ce module peut être créée à Module:MathRoman2/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 = "2016-01-08 18:24",
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.
-- CA is a global alias and can be replaced by ControlArgs itself to manage versions of itself.
-- Because the bug T122752 : #invoke seems do not record the module, for some weeks.
-- https://phabricator.wikimedia.org/T122752 Rical created this task.Via Web ·Sat, Jan 2, 2016-01-02 23:08
-- #invoke do not record the main module in package.loaded
-- Replace the missing of record of the module by : (Todo also in other modules)
_G[p.ModuleNS .. p.modules_versions.versionName] = p -- like _G["Module:Author3"] = p
-- in _G to DEBUG T122752 : #invoke do not record the main module in package.loaded
p.versions = {}
-- local versions = p.versions -- forbiden, this mask : _G["versions"] = {} -- Simulate Library:versions or p.versions for other modules.
p.versions.vn = p.modules_versions
-- CA = CA.modules_binder(p, p.modules_versions) -- deprecated, Todo later in p.base(frame) -- 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) -- Alias of function for solf transition from deprecated to testsomeromans
return p.testsomeromans(view)
end
function p.testsomeromans(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.testsomeromans(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