Wiki Spaces

Documentation
Projects
Resources

Get Help from Others

Q&A: Ask OpenMRS
Discussion: OpenMRS Talk
Real-Time: IRC Chat | Slack

Documentation

Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated Python 3 function

...

Code Block
languagegroovy
titleThe modified mod10 algorithm implemented in Groovy
linenumberstrue
def checkdigit(idWithoutCheckDigit) {
	idWithoutCheckDigit = idWithoutCheckDigit.trim().toUpperCase()
	sum = 0
	(0..<idWithoutCheckDigit.length()).each { i ->
    	char ch = idWithoutCheckDigit[-(i+1)]
    	if (!'0123456789ABCDEFGHIJKLMNOPQRSTUVYWXZ_'.contains(ch.toString()))
        	throw new Exception("$ch is an invalid character")
    	digit = (int)ch - 48;
    	sum += i % 2 == 0 ? 2*digit - (int)(digit/5)*9 : digit
  	}
	(10 - ((Math.abs(sum)+10) % 10)) % 10
}

// Validate our algorithm
assert checkdigit('12') == 5
assert checkdigit('123') == 0
assert checkdigit('1245496594') == 3
assert checkdigit('TEST') == 4
assert checkdigit('Test123') == 7
assert checkdigit('00012') == 5
assert checkdigit('9') == 1
assert checkdigit('999') == 3
assert checkdigit('999999') == 6
assert checkdigit('CHECKDIGIT') == 7
assert checkdigit('EK8XO5V9T8') == 2
assert checkdigit('Y9IDV90NVK') == 1
assert checkdigit('RWRGBM8C5S') == 5
assert checkdigit('OBYY3LXR79') == 5
assert checkdigit('Z2N9Z3F0K3') == 2
assert checkdigit('ROBL3MPLSE') == 9
assert checkdigit('VQWEWFNY8U') == 9
assert checkdigit('45TPECUWKJ') == 1
assert checkdigit('6KWKDFD79A') == 8
assert checkdigit('HXNPKGY4EX') == 3
assert checkdigit('91BT') == 2
try {
checkdigit ("12/3")
assert false
} catch(e) { }

Python

Code Block
languagepython
titleImplemented in Python, by Daniel Watsonfor Python 3
linenumberstrue
import math# Works for Python 3 from here: https://gist.github.com/alastairmccormack/e115140ddb1b522059d677f6dbf38f34

def returnget_checkdigit(self, id_without_check):

        # allowable characters within identifier
        valid_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVYWXZ_"
         
        # remove leading or trailing whitespace, convert to uppercase
        id_without_checkdigit = id_without_check.strip().upper()

    # this will be 
a        # this will be a running total
   running total
     sum = 0;
         
        # loop through digits from right to left
        for n, char in enumerate(reversed(id_without_checkdigit)):
            
            if not valid_chars.count(char):
                raise Exception('InvalidIDException')
            
            # our "digit" is calculated using ASCII value - 48
            digit = ord(char) - 48
             
            # weight will be the current digit's contribution to
            # the running total
            weight = None
            if (n % 2 == 0):
                
                # for alternating digits starting with the rightmost, we
                # use our formula this is the same as multiplying x 2 and
                # adding digits together for values 0 to 9.  Using the
                # following formula allows us to gracefully calculate a

            # weight for non-numeric "digits" as well (from their
            # ASCII value - 48).
            ## Use_sparingly: In Python 3, '/' makes floats. '//' fixes it for Python 3.
            ## For cross compatibility, simply int() the result
 # weight for non-numeric "digits" as well (from their
   ##             # ASCII value - 48).
    VVVVVVVVVVVVV
            weight = (2 * digit) - int(digit / 5) * 9
            else:
                # even-positioned digits just contribute their ascii
                # value minus 48
                weight = digit
                
 weight = digit

         # keep a running total of weights
        ## Use_sparingly: removed maths.fabs()
   sum += weight
   ## abs() is sufficient
   
     sum += weight

    # avoid sum less than 10 (if characters below "0" allowed,
        # this could happen)
        sum = math.fabsabs(sum) + 10
         
        # check digit is amount needed to reach next number
        # divisible by ten. Return an integer 
        return int((10 - (sum % 10)) % 10)
 

Perl

Code Block
languageperl
titleImplemented in Perl, by Steve Cayford
linenumberstrue
 sub checkdigit {
     my ( $tocheck ) = @_;

     $tocheck = uc $tocheck;
     die 'Invalid characters' if $tocheck =~ m/ [^0-9A-Z_] /xms;

     my $sum  = 0;
     my $even = 0;

     for my $char ( reverse split( qr//, $tocheck ) ) {
         my $n = ord( $char ) - 48;
         $sum +=
               $even
             ? $n
             : 2 * $n - 9 * int( $n / 5 );
         $even = ( $even + 1 ) % 2;
     }

     $sum = abs $sum + 10;
     return ( 10 - $sum % 10 ) % 10;
 }

...