-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathAtm.hs
executable file
·185 lines (148 loc) · 4.49 KB
/
Atm.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
{-# LANGUAGE CPP #-}
module Main where
import Prelude hiding (div)
import Transient.Base
#ifdef ghcjs_HOST_OS
hiding ( option,runCloud')
#endif
import GHCJS.HPlay.View
#ifdef ghcjs_HOST_OS
hiding (map)
#else
hiding (map, option,runCloud')
#endif
import Transient.Move
import Transient.Move.Utils
import Control.Applicative
import Control.Monad
import Data.Typeable
import Data.IORef
import Control.Concurrent (threadDelay)
import Control.Monad.IO.Class
import Control.Concurrent.MVar
import System.Random
import System.IO.Unsafe
data Operation= Operation String
-- Follows http://www.math-cs.gordon.edu/courses/cs211/ATMExample/
-- to demostrate how it is possible to program at the user requiremente level
-- the program follows closely the specifications and be clear enough to be understood
-- by the client
main= keep $ initNode atm
atm= do
card <- waitCard
pin <- enterPIN
validateBank pin card
setData card
performTransactions <|> cancel
returnCard
performTransactions = do
clearScreen
operation <- withdrawal <|> deposit <|> transfer <|> balanceInquiry
printReceipt operation
return ()
withdrawal= do
local . render $ wlink () $ toElem "withdrawall"
local . render $ wprint "choose bank account"
account <- chooseAccount
wprint "Enter the quantity"
quantity <- getInt Nothing
if quantity `rem` 20 /= 0
then do
wprint "multiples of $20.00 please"
stop
else do
r <- approbalBank account quantity
case r of
False -> do
wprint "operation denied. sorry"
wprint "Another transaction?"
r <- wlink True (b "yes ") <|> wlink False << (b "No")
if not r then return ()
else performTransactions
True -> giveMoney r
deposit= do
wlink () $ b "Deposit "
wprint "choose bank account"
account <- chooseAccount
r <- approbalBankDeposit account
case r of
False -> do wprint "operation denied. sorry"
stop
True -> do
r <- waitDeposit <|> timeout
case r of
False -> do wprint "timeout, sorry"; stop
True -> return ()
transfer= do
wlink () $ b "Transfer "
wprint "From"
ac <- chooseAccount
wprint "amount"
amount <- inputDouble Nothing
wprint "To"
ac' <- chooseAccount
transferAccBank ac ac' amount
return()
balanceInquiry= do
wprint "From"
ac <- chooseAccount
r <- getBalanceBank ac
wprint $ "balance= "++ show r
validateBank pin card = atRemote $ validate' pin card (0 :: Int)
where
validate' pin card times= local $ do
r <- verifyPinBank pin card
if r then return () else do
if times ==2
then do
wprint ("three tries. card will be retained" :: String)
stop
else validate' pin card $ times + 1
rtotal= unsafePerformIO $ newEmptyMVar
ractive= unsafePerformIO $ newMVar False
switchOnOff= on <|> off
where
on= do
wbutton () "On"
wprint "enter total amount of money"
total <- getInt Nothing
liftIO $ do
tryTakeMVar rtotal
putMVar rtotal total
off= do
wbutton () "Off"
active <- liftIO $ readMVar ractive
if active then stop else wprint "ATM stopped"
type AccountNumber= String
newtype Card= Card [AccountNumber] deriving Typeable
waitCard = local $ render $ wbutton Card "enter card"
enterPIN= local $ do
wprint "Enter PIN"
render $ getInt Nothing `fire` OnChange
cancel= wbutton () "Cancel"
returnCard= wprint "Card returned"
clearScreen= wraw $ forElems "body" $ this >> clear
printReceipt= do
Operation str <- getSData <|> error "no operation"
wprint $ "receipt: Operation:"++ str
chooseAccount= do
Card accounts <- getSData <|> error "transfer: no card"
wprint "choose an account"
mconcat[wlink ac (fromStr $ ' ':show ac) | ac <- accounts]
approbalBank ac quantity= return True
giveMoney n= wprint $ "Your money : " ++ show n ++ " Thanks"
approbalBankDeposit ac= return True
transferAccBank ac ac' amount= wprint $ "transfer from "++show ac ++ " to "++show ac ++ " done"
getBalanceBank ac= liftIO $ do
r <- rand
return $ r * 1000
verifyPinBank _ _= liftIO $ do
liftIO $ print "verifyPinBank"
r <- rand
if r > 0.2 then return True else return False
waitDeposit = do
n <- liftIO rand
if n > 0.5 then return True else return False
rand:: IO Double
rand= randomRIO
timeout t= threadDelay $ t * 1000000