UNPKG

qiprofile

Version:

Quantitative Imaging Profile ( QiPr) web application

97 lines (81 loc) 3.39 kB
# Functions to convert between an integer and a roman numeral. # This module is freely adapted from the suggestions offered at # http://stackoverflow.com/questions/9083037/convert-a-number-into-a-roman-numeral-in-javascript. define ['lodash'], (_) -> # @param s the string to repeat # @param n the number of repititions # @returns the string repeated n times repeat = (s, n) -> new Array(n + 1).join(s) # @param one the one character # @param five the five character # @param ten the ten character # @param max the number of roman numerals to generate # (0 to 10, default 10) # @returns an array of the roman numerals # @throws Error if one of the characters or the max is invalid genRomans = (one, five, ten, max=10) -> # @param n the input integer # @returns the corresponding roman numeral # in one, five and ten units genRoman = (n) -> ones = n % 5 if n < 4 or not five repeat(one, n) else if n < 6 repeat(one, 5 - n) + five else if n < 9 five + repeat(one, n - 5) else repeat(one, 10 - n) + ten if max <= 0 or max > 10 throw new RangeError("The roman numeral generator count must be in" + " the range 1 to 10: #{ max }") if not one throw new Error("The roman numeral generator is missing a one character") if five and not ten throw new Error("The roman numeral generator is missing a ten character") if ten and not five throw new Error("The roman numeral generator is missing a five character") [0..max].map(genRoman) ONES = genRomans('I', 'V', 'X') TENS = genRomans('X', 'L', 'C') HUNDREDS = genRomans('C', 'D', 'M') THOUSANDS = genRomans('M', '', '') ROMANS = [ONES, TENS, HUNDREDS, THOUSANDS] # The maximum supported value. incrementMax = (sum, place) -> (sum * 10) + ROMANS[place].length - 1 MAX = _.reduceRight([0...ROMANS.length], incrementMax, 0) # @param s the input string or integer # @returns the roman numeral string # @throws TypeError if the input value is not a string consisting of # positive digits romanize: (s) -> s = s.toString() n = parseInt(s) if not n or n < 0 throw new RangeError("The romanize input value cannot be converted" + " to a positive integer: #{ s }") if n > MAX throw new RangeError("The romanize input value exceeds the maximum" + " supported value of #{ MAX }: #{ s }") # The string digits. # Note: cannot use parseInt directly as the map argument, since the # second parseInt argument is incorrectly interpreted as a radix # (cf. http://stackoverflow.com/questions/262427/javascript-arraymap-and-parseint) digits = s.split('').map((n) -> parseInt(n)) # The place indexes. places = [0...digits.length] # Prepends the roman numeral conversion of the right-most digit to the # given roman numeral. This function removes the right-most digit from # the digits array. # # @param roman the roman numeral to augment # @param place the ROMANS place index # @returns the augmented roman numeral prepend = (roman, place) -> digit = digits.pop() ROMANS[place][digit] + roman # Make the roman numeral by converting each digit from right to left. _.reduce(places, prepend, '')