#include "bank.h" #include #include #include // rand(), srand() using namespace std; double Client::earn (const double amount) { underMattress += amount; return amount; } double Client::getMattress () { return underMattress; } void Bank::listClients () { for (auto i : clients) cout << "Name: " << i.id << " Current: " << i.current << endl; cout << clients.size () << " accounts." << endl; } void Bank::countEmployees () { cout << employees.size () << " employees." << endl; } bool Bank::openAccount (Client &x) { if (employees.size () * CLIENT_EMPLOYEE <= clients.size ()) return false; // Insufficient employee capacity. for (auto i : x.accounts) if (i == this) return false; clientRecord newClient; newClient.id = x.id; clients.push_back (newClient); x.accounts.push_back (this); return true; } bool Bank::closeAccount (Client &x) { for (auto i = clients.begin (); i != clients.end (); i++) if (i->id == x.id) { if (i->loans.size () != 0) return false; // Can't close account with outstanding loans. else if (this->withdraw (x, this->getCurrent (x)) == -2) return false; // Bank can't pay for withdrawal. else { clients.erase (i); for (auto j = x.accounts.begin (); j != x.accounts.end (); j++) if (*j == this) { auto position = j - x.accounts.begin (); x.accounts.erase (x.accounts.begin () + position); return true; } } } return false; // Account doesn't exist. } bool Bank::hire (Employee &x) { if (x.employer != nullptr) return false; employees.push_back (&x); x.employer = this; return true; } bool Bank::fire (Employee &x) { for (auto i = employees.begin (); i != employees.end (); i++) if (*i == &x) { employees.erase (i); x.employer = nullptr; return true; } return false; // Can't fire unemployed. } // Deposit money from under the mattress, return amount. double Bank::deposit (Client &x, const double amount) { if (amount == 0) return 0; if (amount < 0) return 0; // Can't be negative. if (x.underMattress < amount) return 0; for (auto i = clients.begin (); i != clients.end (); i++) if (i->id == x.id) { x.underMattress -= amount; i->current += amount; current += amount; return amount; } return -1; // No such account. } // Withdraw from current account, if bank doesn't have amount in current, will // attempt to withdraw required amount from Gov. If unable, will attempt // bailout. double Bank::withdraw (Client &x, const double amount) { if (amount == 0) return 0; if (amount < 0) return 0; // Can't be negative. if (current < amount) // TODO: bailout mechanism. if (this->centralBank->reserveWithdraw (*this, ceil (amount - current)) < 0) if (!this->centralBank->bailout (*this, ceil (amount - current))) return -3; // Bank unable to pay, wasn't bailed out. for (auto i = clients.begin (); i != clients.end (); i++) if (i->current < amount) return 0; else { i->current -= amount; x.underMattress += amount; current -= amount; return amount; } return -1; // No such account. } double Bank::getCurrent () { return current; } double Bank::getCreditable () { return creditable; } double Bank::getCredited () { return credited; } double Bank::getCurrent (const Client &x) { for (auto i : clients) if (i.id == x.id) return i.current; cout << "Client doesn't have an account at bank." << endl; return 0; } bool Gov::associate (Bank *const x) { for (auto i = banks.begin (); i != banks.end (); i++) if (*i == x) return false; // Can't associate twice. x->centralBank = this; banks.push_back (x); return true; } double Gov::getReserve () { return reserve; } double Gov::reserveDeposit (Bank &x, const double amount) { if (amount == 0) return 0; if (amount < 0) return 0; // Can't be negative. if (x.current < amount) return 0; x.current -= amount; reserve += amount; x.creditable += amount * FACTOR; return amount; } double Gov::reserveWithdraw (Bank &x, const double amount) { if (amount == 0) return 0; if (amount < 0) return 0; // Can't be negative. if (x.creditable < amount * FACTOR) return -3; // Bank can't repay. x.creditable -= amount * FACTOR; reserve -= amount; x.current += amount; return amount; } // Gov bailout for Bank's unfulfillable Client withdrawals. 50% chance, seeded // with time since last bailout. bool Gov::bailout (Bank &x, const double amount) { auto now = time (0); srand (now - lastBailout); if (rand () > (RAND_MAX / 2)) { lastBailout = now; x.current += amount; // Just like magic. return true; } return false; } int main () { Client abdul ("abdul"); abdul.earn (666); Employee dude ("dude"); Employee gal ("gal"); Gov fed; Bank boa (&fed); cout << fed.associate (&boa) << endl; // Can't associate twice. cout << boa.openAccount (abdul) << endl; boa.countEmployees (); // Insufficient employee capacity. boa.hire (dude); boa.countEmployees (); boa.fire (gal); // Can't fire non-employed. boa.countEmployees (); boa.fire (dude); boa.countEmployees (); boa.hire (gal); boa.hire (dude); boa.hire (dude); // Can't hire employed. boa.countEmployees (); cout << boa.openAccount (abdul) << endl; cout << boa.openAccount (abdul) << endl; // Can't open existing client account. boa.listClients (); cout << abdul.getMattress () << " under mattress." << endl; boa.deposit (abdul, 500); cout << boa.getCurrent (abdul) << " in bank account." << endl; cout << abdul.getMattress () << " under mattress." << endl; cout << boa.getCurrent () << " in bank current accounts." << endl; boa.withdraw (abdul, 30); Client jane ("jane"); jane.earn (1000); cout << jane.getMattress () << " under mattress." << endl; boa.openAccount (jane); boa.deposit (jane, 500); cout << boa.getCurrent (abdul) << " in bank account." << endl; cout << abdul.getMattress () << " under mattress." << endl; cout << boa.getCurrent (jane) << " in bank account." << endl; cout << jane.getMattress () << " under mattress." << endl; cout << boa.getCurrent () << " in bank current accounts." << endl; Client joe ("joe"), bob ("bob"), frank ("frank"); boa.openAccount (joe); boa.openAccount (joe); // Second open call. boa.openAccount (bob); boa.openAccount (frank); // Insufficient employee capacity. Sorry frank. boa.listClients (); boa.closeAccount (abdul); boa.listClients (); return 0; }