module Faker.CreditCard ( visa , mastercard , discover , americanExpress , dinersClub , jcb , switch , solo , dankort , maestro , forbrugsforeningen , laser ) where import Data.Char (digitToInt, isDigit) import Faker.Utils visa :: IO String visa = randomCardNumber "visa" mastercard :: IO String mastercard = randomCardNumber "mastercard" discover :: IO String discover = randomCardNumber "discover" americanExpress :: IO String americanExpress = randomCardNumber "american_express" dinersClub :: IO String dinersClub = randomCardNumber "dinersClub" jcb :: IO String jcb = randomCardNumber "jcb" switch :: IO String switch = randomCardNumber "switch" solo :: IO String solo = randomCardNumber "solo" dankort :: IO String dankort = randomCardNumber "dankort" maestro :: IO String maestro = randomCardNumber "maestro" forbrugsforeningen :: IO String forbrugsforeningen = randomCardNumber "forbrugsforeningen" laser :: IO String laser = randomCardNumber "laser" randomCardNumber :: String -> IO String randomCardNumber attr = randomValue "credit_card" attr >>= evalRegex >>= addLuhnSum addLuhnSum :: String -> IO String addLuhnSum numberString = do let numbers = collectNumbers numberString luhnSum = countLuhnSum numbers 2 luhnDigit = (10 - (luhnSum `mod` 10)) `mod` 10 return $ init numberString ++ show luhnDigit countLuhnSum :: [Int] -> Int -> Int countLuhnSum [] _ = 0 countLuhnSum (x:xs) m = let nextM = if m == 2 then 1 else 2 in luhnStep x m + countLuhnSum xs nextM luhnStep :: Int -> Int -> Int luhnStep x m = sum $ map digitToInt (show (x * m)) collectNumbers :: String -> [Int] collectNumbers [] = [] collectNumbers str = foldl (\a x -> if isDigit x then digitToInt x : a else a) [] str