{- |
Personalausweisnummer

<https://de.wikipedia.org/wiki/Ausweisnummer>
-}
module Math.Checksum.CitizenCard.Germany (construct) where

import qualified Data.List.HT as ListHT
import Math.Checksum.Utility (decomposePositional)


digits :: Int -> Int -> [Int]
digits :: Int -> Int -> [Int]
digits Int
n Int
x = forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ forall a. a -> Int -> [a] -> [a]
ListHT.padRight Int
0 Int
n forall a b. (a -> b) -> a -> b
$ forall a. Integral a => a -> a -> [a]
decomposePositional Int
10 Int
x

check3 :: [Int] -> Int
check3 :: [Int] -> Int
check3 = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Integral a => a -> a -> a
mod Int
10 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. Num a => a -> a -> a
(*) (forall a. [a] -> [a]
cycle [Int
7,Int
3,Int
1])

addCheck3 :: [Int] -> [Int]
addCheck3 :: [Int] -> [Int]
addCheck3 [Int]
xs = [Int]
xs forall a. [a] -> [a] -> [a]
++ [[Int] -> Int
check3 [Int]
xs]

string :: [Int] -> String
string :: [Int] -> String
string = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall a. Show a => a -> String
show

{- |
> construct city no birthDate expiration
> construct 1234 56789 980706 180706 == "1234567897D<<9807062<1807066<<<<<<<8"
-}
construct :: Int -> Int -> Int -> Int -> String
construct :: Int -> Int -> Int -> Int -> String
construct Int
city Int
no Int
birth Int
expire =
   let dno :: [Int]
dno     = [Int] -> [Int]
addCheck3 forall a b. (a -> b) -> a -> b
$ Int -> Int -> [Int]
digits Int
4 Int
city forall a. [a] -> [a] -> [a]
++ Int -> Int -> [Int]
digits Int
5 Int
no
       dbirth :: [Int]
dbirth  = [Int] -> [Int]
addCheck3 forall a b. (a -> b) -> a -> b
$ Int -> Int -> [Int]
digits Int
6 Int
birth
       dexpire :: [Int]
dexpire = [Int] -> [Int]
addCheck3 forall a b. (a -> b) -> a -> b
$ Int -> Int -> [Int]
digits Int
6 Int
expire
   in  [Int] -> String
string [Int]
dno forall a. [a] -> [a] -> [a]
++ String
"D<<" forall a. [a] -> [a] -> [a]
++
       [Int] -> String
string [Int]
dbirth forall a. [a] -> [a] -> [a]
++ String
"<" forall a. [a] -> [a] -> [a]
++
       [Int] -> String
string [Int]
dexpire forall a. [a] -> [a] -> [a]
++ forall a. Int -> a -> [a]
replicate Int
7 Char
'<' forall a. [a] -> [a] -> [a]
++
       forall a. Show a => a -> String
show ([Int] -> Int
check3 forall a b. (a -> b) -> a -> b
$ [Int]
dno forall a. [a] -> [a] -> [a]
++ [Int]
dbirth forall a. [a] -> [a] -> [a]
++ [Int]
dexpire)