Module:Check ISIN

-- Module to check ISIN numbers. -- Example usage: --  -- Console example: --  mw.log(p.check({args={isin="IE00B4L5Y983"}}))

require('Module:No globals')

local p = {}

-- https://en.wikipedia.org/wiki/International_Securities_Identification_Number#Examples -- Letter mapping is base-36: A->10 to Z->35 local function _make_numeric(isin) local numeric = "" for c in isin:gmatch(".") do numeric = numeric .. tostring(tonumber(c, 36)) end return numeric end

-- https://en.wikipedia.org/wiki/Luhn_algorithm local function _check_luhn(string_) local rev, sum = string_:reverse, 0 for i = 1, rev:len do		local digit = ((i % 2) == 0 and 2 or 1) * tonumber(rev:sub(i, i)) sum = sum + digit - (digit > 9 and 9 or 0) end return (sum % 10) == 0 end

local function _check_isin(isin) isin = isin:upper if isin:len == 12 and isin:match("^%u%u[%u%d]+%d$") then return _check_luhn(_make_numeric(isin)) end return false end

local function __check_isin(isin, valid, invalid) return _check_isin(isin) and valid or invalid end

-- Table structure is: {[argument_name]={argument_position, default_value}, ...} local _arguments_table = { ["isin"] = {1, ""}, ["valid"] = {2, "valid"}, ["invalid"] = {3, "invalid"} }

local function _arguments(frame) local args = frame.args local parent_args = frame.getParent and frame:getParent.args or {} return function(name) local index, default = unpack(_arguments_table[name]) return args[name] or args[index] or parent_args[name] or parent_args[index] or default end end

function p.check(frame) local _a = _arguments(frame) return __check_isin(_a("isin"), _a("valid"), _a("invalid")) end

return p