(use goo)
(dc <bank> (<any>))
(dp name (<bank> => <str>))
(dp customers (<bank> => <col>) (vec))
(dc <customer> (<any>))
(dp accounts (<customer> => <col>) (vec))
(dp first-name (<customer> => <str>))
(dp last-name (<customer> => <str>))
(dc <account> (<any>))
(dp balance (<account> => <int>) 0)
(dc <checking-account> (<account>))
(dc <savings-account> (<account>))
(dv *minimum-balance* 100) (dv *minimum-balance-for-no-fee* 1000)
(dv *monthly-fee* 10)
(dv *monthly-interest* 0.02)
(dm credit (account|<account> amount|<int>)
(opf (balance account) (+ _ amount))
#t
)
(dm debit (account|<account> amount|<int> => <log>)
(opf (balance account) (- _ amount))
#t
)
(dm can-handle-debit? (account|<account> amount|<int> => <log>)
(>= (balance account) amount)
)
(dm transfer (from-account|<account> to-account|<account> amount|<int> => <log>)
(when (and (> amount 0)
(can-handle-debit? from-account amount))
(debit from-account amount)
(credit to-account amount)
)
)
(dm charge-monthly-fee (account|<account>)
(when (< (balance account) *minimum-balance-for-no-fee*)
(debit account *monthly-fee*)
)
)
(dm earn-interest (account|<account>)
(credit account (floor (* (balance account) *monthly-interest*)))
)
(dm earn-interest (account|<checking-account>)
)
(dm to-str (account|<account> => <str>)
(cat (if (isa? account <checking-account>)
"Checking "
"Savings ")
"Account: "
(to-str (balance account))
)
)
(dm new-customer (first-name|<str> last-name|<str> => <customer>)
(def customer (new <customer>))
(set (first-name customer) first-name)
(set (last-name customer) last-name)
customer
)
(dm find-customer (customer-list|<col> prop-getter match-val|<any> => (t? <customer>))
(esc found-it
(do (fun (current-customer)
(when (= (prop-getter current-customer) match-val)
(found-it current-customer)
)
)
customer-list)
)
)
(dm to-str (customer|<customer> => <str>)
(def cat-pair-with-newline (fun (str1 str2)
(cat str1 "\n" str2)))
(def prepend-spaces (fun (str)
(cat " " str)))
(cat (last-name customer)
", "
(first-name customer)
"\n"
(fold+ cat-pair-with-newline (map prepend-spaces (map to-str (accounts customer))))
)
)
(dm new-bank (bank-name|<str> => <bank>)
(def bank (new <bank>))
(set (name bank) bank-name)
bank
)
(dm get-all-accounts (bank|<bank> => <col>)
(def all-accounts-in-list-of-lists-form (map accounts (customers bank)))
(def all-accounts-flat (fold+ cat all-accounts-in-list-of-lists-form))
all-accounts-flat
)
(dm charge-monthly-fees (bank|<bank>)
(do charge-monthly-fee
(get-all-accounts bank))
)
(dm earn-monthly-interest (bank|<bank>)
(do earn-interest
(get-all-accounts bank))
)
(dm add-customer (bank|<bank> customer|<customer>)
(add! (customers bank) customer)
)
(dm new-customer-account (bank|<bank> customer|<customer> type|(t< <account>) => (t? <account>))
(when (mem? (customers bank) customer)
(def account (new type))
(add! (accounts customer) account)
account
)
)
(dm to-str (bank|<bank>)
(def cat-pair-with-newline (fun (str1 str2)
(cat str1 "\n" str2)))
(cat (name bank)
"\n"
"-------------\n"
(fold+ cat-pair-with-newline (map to-str (customers bank))))
)
(df do-banking-stuff ()
(def bank (new-bank "Charges'r'us"))
(def alice (new-customer "Alice" "Hax0r"))
(def ben (new-customer "Ben" "Bitdiddle"))
(def beef (new-customer "0x" "deadbeef"))
(add-customer bank alice)
(add-customer bank ben)
(add-customer bank beef)
(def alice-savings (new-customer-account bank alice <savings-account>))
(def alice-checking (new-customer-account bank alice <checking-account>))
(def ben-savings (new-customer-account bank ben <savings-account>))
(def ben-checking (new-customer-account bank ben <checking-account>))
(def beef-savings (new-customer-account bank beef <savings-account>))
(def beef-checking (new-customer-account bank beef <checking-account>))
(credit alice-savings 100) (credit ben-savings 10000) (credit beef-savings 20)
(transfer alice-savings alice-checking 40)
(transfer ben-savings ben-checking 1000)
(transfer beef-savings beef-checking 10)
(charge-monthly-fees bank)
(earn-monthly-interest bank)
(msg out "%s\n" (to-str bank))
)
(export
do-banking-stuff
)