diff --git a/bank.cpp b/bank.cpp index ba6b72d..cd77a33 100644 --- a/bank.cpp +++ b/bank.cpp @@ -1,7 +1,6 @@ #include "bank.h" #include #include -#include // rand(), srand() using namespace std; double @@ -17,18 +16,16 @@ 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 +auto Bank::countEmployees () { - cout << employees.size () << " employees." << endl; + return employees.size (); +} + +auto +Bank::countClients () +{ + return clients.size (); } bool @@ -54,8 +51,8 @@ Bank::closeAccount (Client &x) { 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 if (this->withdraw (x, this->getCurrent (x)) == -3) + return false; // Bank can't pay for withdrawal and wasn't bailed out. else { clients.erase (i); @@ -124,17 +121,23 @@ 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. + return 0; // Can't be negative. for (auto i = clients.begin (); i != clients.end (); i++) - if (i->current < amount) - return 0; - else + if (i->id == x.id) { + if (i->current < amount) + return 0; + if (current < amount) + { + 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. + } + } i->current -= amount; x.underMattress += amount; current -= amount; @@ -210,7 +213,7 @@ Gov::reserveWithdraw (Bank &x, const double amount) return 0; if (amount < 0) return 0; // Can't be negative. - if (x.creditable < amount * FACTOR) + if (x.creditable < (amount * FACTOR)) return -3; // Bank can't repay. x.creditable -= amount * FACTOR; reserve -= amount; @@ -218,6 +221,32 @@ Gov::reserveWithdraw (Bank &x, const double amount) return amount; } +// Functions for simulating giving and receiving back loans (no interest). Used +// for testing until loans are implemented. +bool +Bank::loan (const double amount) +{ + if (amount == 0) + return 0; + if (creditable < amount) + return 0; + creditable -= amount; + credited += amount; + return amount; +} + +bool +Bank::unloan (const double amount) +{ + if (amount == 0) + return 0; + if (credited < amount) + return 0; + creditable += amount; + credited -= amount; + return amount; +} + // Gov bailout for Bank's unfulfillable Client withdrawals. 50% chance, seeded // with time since last bailout. bool @@ -239,58 +268,122 @@ main () { Client abdul ("abdul"); abdul.earn (666); - - Employee dude ("dude"); - Employee gal ("gal"); + abdul.earn (10); + if (abdul.getMattress () != 676) + exit (1); Gov fed; Bank boa (&fed); - cout << fed.associate (&boa) << endl; // Can't associate twice. + if (fed.associate (&boa)) + exit (1); // Can't associate twice. - cout << boa.openAccount (abdul) << endl; - boa.countEmployees (); // Insufficient employee capacity. + if (boa.openAccount (abdul)) + exit (1); // Over employee capacity. + Employee dude ("dude"); + Employee gal ("gal"); boa.hire (dude); - boa.countEmployees (); + if (boa.countEmployees () != 1) + exit (1); boa.fire (gal); // Can't fire non-employed. - boa.countEmployees (); + if (boa.countEmployees () != 1) + exit (1); boa.fire (dude); - boa.countEmployees (); + if (boa.countEmployees () != 0) + exit (1); boa.hire (gal); boa.hire (dude); boa.hire (dude); // Can't hire employed. - boa.countEmployees (); + if (boa.countEmployees () != 2) + exit (1); - cout << boa.openAccount (abdul) << endl; - cout << boa.openAccount (abdul) - << endl; // Can't open existing client account. - boa.listClients (); + if (boa.openAccount (abdul) != 1) + exit (1); + if (boa.openAccount (abdul) != 0) + exit (1); // Can't open existing client account. + if (boa.countClients () != 1) + exit (1); - cout << abdul.getMattress () << " under mattress." << endl; + if (abdul.getMattress () != 676) + exit (1); 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; + if (boa.getCurrent (abdul) != 500) + exit (1); + if (abdul.getMattress () != 176) + exit (1); + if (boa.getCurrent () != 500) + exit (1); 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; + if (boa.getCurrent (abdul) != 470) + exit (1); + if (abdul.getMattress () != 206) + exit (1); + if (boa.getCurrent (jane) != 500) + exit (1); + if (jane.getMattress () != 500) + exit (1); + if (boa.getCurrent () != 970) + exit (1); 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 (); + boa.openAccount (frank); // Not added (5th client). + if (boa.countClients () != 4) + exit (1); // Over employee capacity. + boa.closeAccount (abdul); // Success + if (boa.countClients () != 3) + exit (1); + if (boa.getCurrent () != 500) + exit (1); + if (abdul.getMattress () != 676) + exit (1); + + fed.reserveDeposit (boa, 250); + if (fed.getReserve () != 250) + exit (1); + if (boa.getCreditable () != 1500) + exit (1); + fed.reserveWithdraw (boa, 125); + fed.reserveWithdraw (boa, 1000); // Can't repay. + if (fed.getReserve () != 125) + exit (1); + if (boa.getCreditable () != 750) + exit (1); + + boa.loan (250); + bool bailed = boa.closeAccount (jane); // Bank can't pay, Gov may bail out. + + if (bailed == 0 // Not bailed out. + && (jane.getMattress () != 500 || boa.getCreditable () != 500 + || boa.getCredited () != 250 || boa.getCurrent () != 375)) + exit (1); + if (bailed == 1 // Bailed out. + && (jane.getMattress () != 1000 || boa.getCreditable () != 500 + || boa.getCredited () != 250 || boa.getCurrent () != 0)) + exit (1); + + joe.earn (1000); + boa.deposit (joe, 1000); + fed.reserveDeposit (boa, 500); + boa.loan (100); + + boa.withdraw (joe, 50); // Test withdrawal bank can pay. + if (joe.getMattress () != 50) + exit (1); + + boa.withdraw ( + joe, 500); // Test withdrawal bank can pay by withdrawing from reserves. + if (joe.getMattress () != 550) + exit (1); + + // Run until both 0 and 1 are seen, in order to test both code paths for + // bailout. + cout << "Bailed out: " << bailed << ", all others successful." << endl; return 0; } diff --git a/bank.h b/bank.h index 6ddb55c..b3650f7 100644 --- a/bank.h +++ b/bank.h @@ -22,7 +22,7 @@ public: private: time_t lastBailout = 0; // Time since last bailout. - double reserve = 0; // Total in bank reserves. + double reserve = 0; // Total in bank reserves. std::vector banks; }; @@ -42,13 +42,17 @@ public: bool fire (Employee &x); bool openAccount (Client &x); bool closeAccount (Client &x); - bool newCredit (const std::string id, const double amount, - const int installments, const int days, - const float interest); // interest is additional interest on - // top of Gov rate. - double payInstallment (const int index); - void countEmployees (); - void listClients (); + // TODO: implement loans, for now there is placeholder loan() and unloan(), + // in order to simulate loaning and test bailout mechanism. + + // bool newCredit (const std::string id, const double amount, + // const int installments, const int days, + // const float interest); + // double payInstallment (const int index); + auto countEmployees (); + auto countClients (); + bool loan (const double amount); + bool unloan (const double amount); private: Gov *centralBank; @@ -56,13 +60,13 @@ private: double current = 0; // Total current accts. of clients. double creditable = 0; // Amount able to be loaned to clients. double credited = 0; // Amount loaned. - struct creditRecord + struct creditRecord // TODO: implement loans, currently this struct is a dud. { - time_t start; - long interval; // Interval of payments in number of seconds. - double amount; - int installments; - float interest; + // time_t start; + // long interval; // Interval of payments in number of seconds. + // double amount; + // int installments; + // float interest; }; struct clientRecord {