Module:Sandbox/trappist the monk/check digit

require('strict');

local function err_msg_make (msg)

return 'error: ' .. msg .. ''

end

local function is_valid_isxn_13 (isxn_str)

local temp=0;

isxn_str = { isxn_str:byte(1, 13) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39

for i, v in ipairs( isxn_str ) do

temp = temp + (3 - 2*(i % 2)) * tonumber( string.char(v) ); -- multiply odd index digits by 1, even index digits by 3 and sum; includes check digit

end

return temp % 10 == 0; -- sum modulo 10 is zero when isbn-13/ismn is correct

end

local function check_digit_calc (id_str)

local temp=0;

id_str = { id_str:byte(1, 12) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39

for i, v in ipairs( id_str ) do

temp = temp + (3 - 2*(i % 2)) * tonumber( string.char(v) ); -- multiply odd index digits by 1, even index digits by 3 and sum; includes check digit

end

temp = 10 - (temp % 10); -- subtract sum modulo 10 from 10 to get the check digit

return (10 == temp) and 0 or temp; -- if the result is 10, return 0; return result else

end

local function main (frame)

local id = frame.args[1]; -- get the id string

local id_str = id; -- copy that we will modify to do check digit calculations

local check_digit;

if id_str:match ('%D') then -- look for characters that are not digits

return err_msg_make ('id has non-digit characters: ' .. id_str);

end

if '' == id_str then -- make sure id is not the empty string

return err_msg_make ('id is empty');

end

if 12 < id_str:len() then -- make sure that the id is no longer than 12 digits

return err_msg_make ('id has too many characters (' .. id_str:len() .. '): ' .. id_str);

end

if 0 == tonumber(id_str) then -- make sure that the id is not 0

return err_msg_make ('id may not be zero');

end

id_str = string.rep ('0', 12-id:len()) .. id; -- left fill with 0s to a string length of 12

check_digit = check_digit_calc (id_str); -- calculate the check digit

if is_valid_isxn_13 (id_str .. check_digit) then -- append check digit to 12-digit id and validate

return id .. '.' .. check_digit; -- return original id with dot-separated check digit

else

return err_msg_make ('calculation failure: ' .. check_digit) -- did not validate

end

end

return {main = main}