Module:Roman-cd explained

--local p =

--[============[ Private data --]

]-- See CLDR data /common/rbnf/root.xml for "roman-upper" rules. However we still don't-- use the rarely supported Roman extension digits after 'M' (in U+2160..2188), but use-- the more common notation with diacritical overlines ('ↁ'='V̅', 'ↂ'='X̅', etc.).-- Please avoid using HTML with "text-decoration:overline" style, but use plain-text-- combining characters (U+0304 and/or U+0305).local decimalRomans = local romanDecimals =

--[=================[ Private functions --]

]

--[==[ This function returns a string containing the input value formatted as a Roman numeral. It works for non-negative integers lower than 5 billions (up to 4 999 999 999: this covers all unsigned 32-bit integers), otherwise it returns the number formatted using Latin digits. The result string will be an UTF-8-encoded plain-text alphabetic string. ]

]--local function convertArabicToRoman(value) if value >= 1 and value <= 4999999999 and value

math.floor(value) then local d0, d1, d2, d3, d4, d5, d6, d7, d8 d0, value = value % 10, math.floor(value / 10) d1, value = value % 10, math.floor(value / 10) d2, value = value % 10, math.floor(value / 10) d3, value = value % 10, math.floor(value / 10) d4, value = value % 10, math.floor(value / 10) d5, value = value % 10, math.floor(value / 10) d6, value = value % 10, math.floor(value / 10) d7, value = value % 10, math.floor(value / 10) d8, value = value % 10, math.floor(value / 10) return table.concat elseif value

0 then return 'N' -- for adverbs "nec" or "non" in Classical Latin (which had no zero) end return tostring(value)end

--[==[ This function converts a plain-text string containing a Roman numeral to an integer. It works for values between 0 (N) and 4 999 999 999 (M̿M̿M̿M̿C̿M̿X̿C̿I̿X̿C̅M̅X̅C̅I̅X̅CMXCIX). ]

]--local function convertRomanToArabic(roman) if roman

then return nil end local result, prevRomanDecimal, multiplier = 0, 0, 1 for i = mw.ustring.len(roman), 1, -1 do local currentRomanDecimal = romanDecimals[mw.ustring.sub(roman, i, i)] if currentRomanDecimal

nil then return nil elseif currentRomanDecimal < 0 then multiplier = multiplier * -currentRomanDecimal else currentRomanDecimal, multiplier = currentRomanDecimal * multiplier, 1 if currentRomanDecimal < prevRomanDecimal then result = result - currentRomanDecimal else result = result + currentRomanDecimal prevRomanDecimal = currentRomanDecimal end end end return resultend

--[==[ This function converts a string containing a Roman numeral to an integer. It works for values between 0 and 4999999999. The input string may contain HTML tags using style="text-decoration:overline" (not recommended). ]

]--local function convertRomanHTMLToArabic(roman) local result = convertRomanToArabic(roman) if result

nil then result = tonumber(roman) end return result [==[ DISABLED FOR NOW, NOT REALLY NEEDED AND NOT CORRECTLY TESTED local result = 0 local overline_start_len = mw.ustring.len(overline_start) if mw.ustring.sub(roman, 1, overline_start_len) == overline_start then local end_tag_start, end_tag_end = mw.ustring.find(roman, overline_end, overline_start_len, true) if end_tag_start ~= nil then local roman_high = mw.ustring.sub(roman, overline_start_len + 1, end_tag_start - 1) local roman_low = mw.ustring.sub(roman, end_tag_end + 1, mw.ustring.len(roman)) or '' if (mw.ustring.find(roman_high, "^[mdclxvi]+$") ~= nil) and (mw.ustring.find(roman_low, "^[mdclxvi]*$") ~= nil) then result = convertRomanToArabic(roman_high) * 1000 + convertRomanToArabic(roman_low) end end end return result ]

]end

--[==[ Helper function to handle error messages. ]

]--local function outputError(message) return table.concatend

--[================[ Public functions --]

=]

--[==[ isRoman Tests if the trimmed input is a valid Roman numeral. Returns true if so, false if not. For the purposes of this function, the empty string (after trimming whitespaces) is not a Roman numeral. Parameters s: string to test if it is a valid Roman numeral Error Handling: If the input is not a valid Roman numeral this function returns false. ]

]--function p.isRoman(s) return type(s)

'string' and convertRomanToArabic(mw.text.trim(s)) ~= nilend

--[==[ toArabic This function converts a Roman numeral into an Arabic numeral. It works for values between 0 and 4999999999. 'N' is converted to 0 and the empty string is converted to nil. Parameters roman: string containing value to convert into an Arabic numeral Error Handling: If the input is not a valid Roman numeral this function returns nil. ]

]--function p.toArabic(roman) if type(roman)

'string' then roman = mw.text.trim(roman) local result = convertRomanToArabic(roman) if result

nil then result = tonumber(roman) end return result elseif type(roman)

'number' then return roman else return nil endend

--[==[ _Numeral This function returns a string containing the input value formatted as a Roman numeral. It works for values between 0 and 4999999999. Parameters value: integer or string containing value to convert into a Roman numeral Error Handling: If the input does not look like it contains a number or the number is outside of the supported range an error message is returned. ]

]--function p._Numeral(value) if value

nil then return outputError('missing value') end if type(value)

'string' then value = tonumber(value) elseif type(value) ~= 'number' then return outputError('unsupported value') end return convertArabicToRoman(value)end

--[==[ Numeral This function for MediaWiki converts an Arabic numeral into a Roman numeral. It works for values between 0 and 4999999999 (includes the whole range of unsigned 32-bit integers). Arabic numeral zero is output as 'N' (for Latin negation adverbs "nec" or "non"). Usage: {{#invoke:Roman|Numeral|<value>}} {{#invoke:Roman|Numeral}} - uses the caller's parameters Parameters 1: Value to convert into a Roman numeral. Must be at least 0 and less than 5,000,000. Error Handling: If the input does not look like it contains a number or the number is outside of the supported range an error message is returned. ]

]--function p.Numeral(frame) -- if no argument provided than check parent template/module args local args = frame.args if args[1]

nil then args = frame:getParent.args end return p._Numeral(args[1])end

return p