module Data.Elocrypt.Utils where import Data.Char (isAlphaNum, isSpace) import Data.Maybe (fromMaybe) import Data.Ratio import qualified Data.Map as M import Control.Monad.Random (MonadRandom(), fromList) -- |A mapping from letters to numbers that look like them numeralConversions = M.fromList [ ('o', ['0']), ('l', ['1']), ('z', ['2']), ('e', ['3']), ('a', ['4']), ('s', ['5']), ('g', ['6', '9']), ('t', ['7']), ('b', ['8'])] -- |A mapping from letters to symbols that look like them symbolConversions = M.fromList [ ('a', ['@']), ('l', ['!']), ('s', ['$'])] -- |Map a letter to one or more digits, if possible toDigit :: Char -> String toDigit c = fromMaybe [c] (numeralConversions M.!? c) -- |Map a letter to one or more symbols, if possible toSymbol :: Char -> String toSymbol c = fromMaybe [c] (symbolConversions M.!? c) -- |Selects special characters isSymbol :: Char -> Bool isSymbol c = not (isAlphaNum c || isSpace c) -- |Randomly update characters at the specified probability updateR :: MonadRandom m => (Char -> m Char) -> Rational -> String -> m String updateR f prob = mapM f' where f' ch = do ch' <- f ch fromList [ (ch, toRational $ denominator prob), (ch', toRational $ numerator prob)] -- |Update character at position pos update1 :: Monad m => (Char -> m Char) -- ^ Update function -> String -- ^ the string to update -> Int -- ^ the position to update -> m String update1 _ "" _ = return "" update1 f s pos = (\ch' -> prefix ++ ch' : suffix) <$> f ch where (prefix, ch : suffix) = splitAt pos s