xxx
🧩 Syntax:
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
class Date {
private:
int day;
int month;
int year;
public:
Date() {}
Date(int day, int month, int year) {
this->day = day;
this->month = month;
this->year = year;
}
void set_date(const string& date_str) {
// Extract day, month, and year from the date string
int day = stoi(date_str.substr(0, 2));
int month = stoi(date_str.substr(3, 2));
int year = stoi(date_str.substr(6, 4));
// Set the date
this->day = day;
this->month = month;
this->year = year;
cout << "date: " << day << "-" << month << "-" << year << endl;
}
int get_day() const {
return day;
}
int get_month() const {
return month;
}
int get_year() const {
return year;
}
};
class Bill {
public:
Bill(double amt) : amount(amt), paid(false) {}
virtual string get_type() const = 0;
double get_amount() const { return amount; }
bool is_paid() const { return paid; }
void mark_paid() { paid = true; }
private:
double amount;
bool paid;
};
class WaterBill : public Bill {
public:
WaterBill(double amt) : Bill(amt) {}
string get_type() const override { return "Water Bill"; }
};
class ElectricityBill : public Bill {
public:
ElectricityBill(double amt) : Bill(amt) {}
string get_type() const override { return "Electricity Bill"; }
};
class Account {
public:
Account() {}
Account(int num, double bal) : account_num(num), balance(bal) {}
virtual string get_account_type() const { return "hoi"; }
virtual ~Account() {} // add virtual destructor
int get_account_num() const { return account_num; }
double get_balance() const { return balance; }
void deposit(double new_balance) { balance += new_balance; }
void withdraw(double new_balance) { balance -= new_balance; }
private:
int account_num;
double balance;
};
class CheckingAccount : public Account {
public:
CheckingAccount() : Account() {}
CheckingAccount(int num, double bal) : Account(num, bal) {}
string get_account_type() const override { return "Checking Account"; }
};
class SavingsAccount : public Account {
public:
SavingsAccount() : Account() {}
SavingsAccount(int num, double bal) : Account(num, bal) {}
string get_account_type() const override { return "Savings Account"; }
};
class CreditCard : public Account {
private:
Account* linked_account;
public:
CreditCard(int account_num, double bal, Account* linked_account)
: Account(account_num, bal), linked_account(linked_account) {}
string get_account_type() const override { return "Creditcard Account"; }
Account* get_linked_account() const {
return linked_account;
}
~CreditCard() {
}
};
class User {
public:
User(string username, string password, string role) :
username(username), password(password), role(role) {}
string get_username() const {
return username;
}
string get_password() const {
return password;
}
string get_role() const {
return role;
}
vector<shared_ptr<Account>>& get_accounts() {
return accounts;
}
void add_account(shared_ptr<Account> account) {
accounts.push_back(account);
}
private:
vector<shared_ptr<Account>> accounts;
string username;
string password;
string role;
};
class Bank {
private:
vector<CheckingAccount> checking_accounts;
vector<SavingsAccount> savings_accounts;
vector<CreditCard> creditcard_accounts;
vector<User> users;
User* current_user;
string current_user_role;
unordered_map<string, vector<Account*>> user_accounts;
vector<Bill*> open_bills;
unordered_map<string, vector<Bill*>> user_bills;
public:
Bank() {
// create some initial accounts
checking_accounts.push_back(CheckingAccount(123, 1000.0));
checking_accounts.push_back(CheckingAccount(444, 200.0));
savings_accounts.push_back(SavingsAccount(456, 5000.0));
checking_accounts.push_back(CheckingAccount(789, 2500.0));
savings_accounts.push_back(SavingsAccount(321, 4000.0)); // added savings account for alice
// initialize bills for henk and alice accounts
user_bills["alice"].push_back(new WaterBill(75.0)); // bill for alice
user_bills["alice"].push_back(new ElectricityBill(100.0)); // bill for alice
user_bills["henk"].push_back(new WaterBill(50.0)); // bill for henk
user_bills["henk"].push_back(new ElectricityBill(80.0)); // bill for henk
// create some initial users
users.push_back(User("alice", "pass1", "customer"));
users.push_back(User("henk", "zomer", "customer"));
users.push_back(User("bob", "pass2", "cashier"));
users.push_back(User("charlie", "pass3", "director"));
// add creditcard accounts for alice and henk
CheckingAccount* alice_linked_acc = nullptr;
CheckingAccount* henk_linked_acc = nullptr;
for (auto& acc : checking_accounts) {
if (acc.get_account_num() == 123) {
alice_linked_acc = &acc;
}
else if (acc.get_account_num() == 789) {
henk_linked_acc = &acc;
}
}
creditcard_accounts.push_back(CreditCard(8888, -500.0, alice_linked_acc));
creditcard_accounts.push_back(CreditCard(9999, -1000.0, henk_linked_acc));
// populate the user_accounts map with the accounts of each user
for (auto& user : users) {
if (user.get_username() == "alice") { // add alice's accounts
user_accounts[user.get_username()].push_back(&checking_accounts[0]);
user_accounts[user.get_username()].push_back(&savings_accounts[0]);
user_accounts[user.get_username()].push_back(&creditcard_accounts[0]);
}
else if (user.get_username() == "henk") { // add henk's accounts
user_accounts[user.get_username()].push_back(&checking_accounts[1]);
user_accounts[user.get_username()].push_back(&checking_accounts[2]);
user_accounts[user.get_username()].push_back(&savings_accounts[1]);
user_accounts[user.get_username()].push_back(&creditcard_accounts[1]);
}
else {
for (auto& acc : checking_accounts) {
user_accounts[user.get_username()].push_back(&acc);
}
for (auto& acc : savings_accounts) {
user_accounts[user.get_username()].push_back(&acc);
}
}
}
}
// function to find user by username and password
User* find_user(string username, string password) {
for (auto& user : users) {
if (user.get_username() == username && user.get_password() == password) {
return &user;
}
}
return nullptr;
}
bool login(string username, string password) {
User* user = find_user(username, password);
if (user != nullptr) {
current_user = user;
current_user_role = user->get_role();
return true;
}
else {
return false;
}
}
void logout() {
current_user = nullptr;
current_user_role = "";
}
bool is_logged_in() const {
return current_user != nullptr;
}
string get_current_user_role() const {
return current_user_role;
}
bool has_access_to_account(Account* account) const {
if (!is_logged_in()) {
return false;
}
// check if the account belongs to the current user
for (auto acc : user_accounts.at(current_user->get_username())) {
if (acc == account) {
return true;
}
}
// check if the user has the required role to access the account
if (current_user_role == "cashier") {
return true;
}
else if (current_user_role == "director") {
return true;
}
else {
return false;
}
}
// function to deposit money into an account
void deposit(int account_num, double amount) {
for (auto acc : user_accounts.at(current_user->get_username())) {
if (acc->get_account_type() == "Creditcard Account") {
acc->deposit(amount-0.5);
cout << "deposit of " << amount << " made to credit card account " << account_num << endl;
return;
}
else if (acc->get_account_num() == account_num) {
acc->deposit(amount);
cout << "deposit of " << amount << " made to credit card account " << account_num << endl;
}
}
}
// function to withdraw money from an account
bool withdraw(int account_num, double amount) {
for (auto acc : user_accounts.at(current_user->get_username())) {
if (acc->get_account_type() == "Creditcard Account") {
acc->withdraw(amount + 0.5);
cout << "withdrawal of " << amount << " from credit card account " << account_num << endl;
return true;
}
else if (acc->get_account_num() == account_num) {
acc->withdraw(amount);
cout << "withdrawal of " << amount << " from credit card account " << account_num << endl;
return true;
}
}
return false;
}
void view_balance(int account_num) {
bool found = false;
for (auto& acct : user_accounts[current_user->get_username()]) {
if (acct->get_account_num() == account_num) {
cout << "Balance: $" << acct->get_balance() << endl;
found = true;
break;
}
}
if (!found) {
cout << "Account not found." << endl;
}
}
void view_bills() {
for (auto bill : open_bills) {
cout << bill->get_type() << ": $" << bill->get_amount() << endl;
}
}
void add_bill(Bill * bill) {
open_bills.push_back(bill);
cout << bill->get_type() << " added." << endl;
}
void pay_bill(Bill* bill, int account_num) {
// find the account with the given account number
Account* account = nullptr;
for (auto& acc : user_accounts[current_user->get_username()]) {
if (acc->get_account_num() == account_num) {
account = acc;
break;
}
}
if (account == nullptr) {
cout << "Account not found." << endl;
return;
}
if (account->get_account_type() == "Creditcard Account") {
bill->mark_paid();
account->withdraw(-(bill->get_amount()+0.5));
}
else {
// check if there are sufficient funds in the account
if (bill->get_amount() > account->get_balance()) {
cout << "Insufficient funds." << endl;
return;
}
// mark the bill as paid and deduct the amount from the account
bill->mark_paid();
account->withdraw(bill->get_amount());
}
}
vector<Account*> get_user_accounts() const {
vector<Account*> accounts;
if (!is_logged_in()) {
return accounts;
}
// retrieve the accounts associated with the current user
auto user_account_ptrs = user_accounts.at(current_user->get_username());
for (auto account_ptr : user_account_ptrs) {
accounts.push_back(account_ptr);
}
return accounts;
}
vector<Bill*> get_user_bills(string username) {
return user_bills[username];
}
void add_interest(Date current_date) {
if (current_date.get_month() == 12 && current_date.get_day() == 31) {
for (CheckingAccount& checking_account : checking_accounts) {
double interest_rate = 0.01;
double interest = checking_account.get_balance() * interest_rate;
checking_account.deposit(interest); // double interest if it's 31st December
}
for (SavingsAccount& savings_account : savings_accounts) {
double interest_rate = 0.05;
double interest = savings_account.get_balance() * interest_rate;
savings_account.deposit(interest); // double interest if it's 31st December
}
cout << "Interest added to accounts" << endl;
}
else {
cout << "No interest added today." << endl;
}
}
void negative_monthly_interest(Date current_date) {
if (current_date.get_day() == 28) {
for (CheckingAccount& checking_account : checking_accounts) {
if (checking_account.get_balance() < 0) {
double interest_rate = 0.03;
double interest = checking_account.get_balance() * interest_rate;
checking_account.withdraw(interest); // Negative interest added to checking account, due to balance being negative
cout << "Negative interest added to checking accounts" << endl;
}
}
}
}
void deduce_creditcard_balance(const Date& current_date) {
if (current_date.get_day() >= 28) {
for (CreditCard& creditcard_account : creditcard_accounts) {
auto linked_acc = creditcard_account.get_linked_account();
double cc_balance = creditcard_account.get_balance();
if (cc_balance < 0) {
linked_acc->withdraw((-1 * cc_balance));
}
else { linked_acc->deposit((cc_balance)); }
if (cc_balance <= 0) {
creditcard_account.deposit(-1 * cc_balance);
}
else {
creditcard_account.withdraw(cc_balance);
}
cout << "creditcard balance is deducted from checking account." << endl;
}
}
}
User* get_user(const string& username) {
for (auto& user : users) {
if (user.get_username() == username) {
return &user;
}
}
return nullptr;
}
bool add_account(const string& username) {
User* user = get_user(username);
if (user == nullptr) {
cout << "Error: User not found." << endl;
return false;
}
int choice;
bool added = false;
do {
cout << endl << "Select account type to add: " << endl;
cout << "1. Checking Account" << endl;
cout << "2. Savings Account" << endl;
cout << "3. Credit Card Account" << endl;
cout << "4. Cancel" << endl;
cout << "Choice: ";
cin >> choice;
cout << endl;
switch (choice) {
case 1: {
int account_num;
double balance;
cout << "Enter account number: ";
cin >> account_num;
cout << "Enter balance: ";
cin >> balance;
auto acc = make_shared<CheckingAccount>(account_num, balance);
user->add_account(acc);
cout << "Checking account added successfully." << endl;
added = true;
break;
}
case 2: {
int account_num;
double balance;
cout << "Enter account number: ";
cin >> account_num;
cout << "Enter balance: ";
cin >> balance;
auto acc = make_shared<SavingsAccount>(account_num, balance);
user->add_account(acc);
cout << "Savings account added successfully." << endl;
added = true;
break;
}
case 3: {
int account_num;
double balance;
int linked_account_num;
cout << "Enter account number: ";
cin >> account_num;
cout << "Enter balance: ";
cin >> balance;
cout << "Enter checking account number to link creditcard account to: ";
cin >> linked_account_num;
CreditCard* user_linked_acc = nullptr;
for (auto& acc : creditcard_accounts) {
if (acc.get_account_num() == linked_account_num) {
user_linked_acc = &acc;
break;
}
}
auto acc = make_shared<CreditCard>(account_num, balance, user_linked_acc);
if (user_linked_acc == nullptr) {
cout << "Error: Invalid linked account number. Credit card account not added." << endl;
}
else {
user->add_account(acc);
cout << "Credit card account added successfully." << endl;
added = true;
}
break;
}
case 4:
break;
default:
cout << "Invalid choice. Please try again." << endl;
break;
}
} while (choice != 4 && !added);
return added;
}
vector<Account*> get_user_accounts(const string& username) const {
vector<Account*> accounts;
auto it = user_accounts.find(username);
if (it != user_accounts.end()) {
for (auto account : it->second) {
accounts.push_back(account);
}
}
return accounts;
}
void list_accounts(const string& username) {
User* user = get_user(username);
if (user == nullptr) {
cout << "Error: User not found." << endl;
return;
}
vector<shared_ptr<Account>> accounts;
for (auto acc : user_accounts[username]) {
if (auto ca = dynamic_cast<CheckingAccount*>(acc)) {
accounts.push_back(make_shared<CheckingAccount>(*ca));
}
else if (auto sa = dynamic_cast<SavingsAccount*>(acc)) {
accounts.push_back(make_shared<SavingsAccount>(*sa));
}
else if (auto cca = dynamic_cast<CreditCard*>(acc)) {
accounts.push_back(make_shared<CreditCard>(*cca));
}
}
cout << "Number of accounts for user " << username << ": " << accounts.size() << endl;
for (auto acc : accounts) {
cout << "Account number for user " << username << ": " << acc->get_account_num() << endl;
}
cout << endl << "Accounts for user " << username << ":" << endl;
for (auto acc : accounts) {
if (auto ca = dynamic_pointer_cast<CheckingAccount>(acc)) {
cout << ca->get_account_type() << " (" << ca->get_account_num() << "): " << ca->get_balance() << endl;
}
else if (auto sa = dynamic_pointer_cast<SavingsAccount>(acc)) {
cout << sa->get_account_type() << " (" << sa->get_account_num() << "): " << sa->get_balance() << endl;
}
else if (auto cca = dynamic_pointer_cast<CreditCard>(acc)) {
cout << cca->get_account_type() << " (" << cca->get_account_num() << "): " << cca->get_balance() << endl;
}
}
}
};
int main() {
Bank bank;
string username, password;
Date date(1, 1, 2022); // creates a date object with values 1, 1, 2022
while (true) {
cout << "Welcome to the bank. Please login to continue." << endl;
cout << "1. Login" << endl;
cout << "2. set date" << endl;
cout << "3. Quit" << endl;
cout << "Enter choice (1-3: ";
int choice;
cin >> choice;
if (choice == 3) {
break;
}
else if (choice == 1) {
cout << "Username: ";
cin >> username;
cout << "Password: ";
cin >> password;
if (bank.login(username, password)) {
cout << "Login successful!" << endl;
bank.add_interest(date);
bank.deduce_creditcard_balance(date);
bank.negative_monthly_interest(date);
}
else {
cout << "Invalid username or password. Please try again." << endl;
continue;
}
}
else if (choice == 2) {
cout << "date should be in format dd-mm-yyyy" << endl;
cout << "set date: ";
string input_date;
cin >> input_date;
date.set_date(input_date);
continue;
}
else {
cout << "Invalid choice. Please try again." << endl;
continue;
}
User* user = bank.get_user(username);
if (user->get_role() == "customer") {
// The user is a customer
while (true) {
cout << endl << "What would you like to do?" << endl;
cout << "1. View bank accounts" << endl;
cout << "2. View bills" << endl;
cout << "3. Log out" << endl;
cout << "Enter choice (1-3): ";
cin >> choice;
if (choice == 3) {
bank.logout();
break;
}
else if (choice == 2) {
cout << "Your bills:" << endl;
for (auto bill : bank.get_user_bills(username)) {
cout << bill->get_type() << " - $" << bill->get_amount() << endl;
}
}
else if (choice == 1) {
vector<Account*> accounts = bank.get_user_accounts();
cout << endl << "Your accounts:" << endl;
int i = 1;
map<int, Account*> account_map;
for (auto acc : accounts) {
cout << i << ". " << acc->get_account_type() << " (" << acc->get_account_num() << "): " << acc->get_balance() << endl;
account_map[i] = acc;
i++;
}
cout << i << ". Go back" << endl;
cout << "Select an account (1-" << i << "): ";
int account_choice;
cin >> account_choice;
if (account_choice == i) {
continue;
}
Account* account = account_map[account_choice];
cout << "Selected account: " << account->get_account_type() << " (" << account->get_account_num() << ")" << endl;
while (true) {
cout << endl << "What would you like to do?" << endl;
cout << "1. Deposit" << endl;
cout << "2. Withdraw" << endl;
cout << "3. Pay bill" << endl;
cout << "4. Go back to main menu" << endl;
cout << "Enter choice (1-5): ";
cin >> choice;
if (choice == 1) {
cout << "Enter amount to deposit: ";
double amount;
cin >> amount;
bank.deposit(account->get_account_num(), amount);
cout << "Deposit successful. New balance: " << account->get_balance() << endl;
}
else if (choice == 2) {
cout << "Enter amount to withdraw: ";
double amount;
cin >> amount;
if (bank.withdraw(account->get_account_num(), amount)) {
cout << "Withdrawal successful. New balance: " << account->get_balance() << endl;
}
else {
cout << "Insufficient funds. Withdrawal unsuccessful." << endl;
}
}
else if (choice == 3) {
cout << "Your bills:" << endl;
vector<Bill*> user_bills = bank.get_user_bills(username);
for (int i = 0; i < user_bills.size(); i++) {
cout << i + 1 << ". " << user_bills[i]->get_type() << " - $" << user_bills[i]->get_amount() << endl;
}
cout << "Select bill: ";
int bill_index;
cin >> bill_index;
if (bill_index <= 0 || bill_index > user_bills.size()) {
cout << "Invalid selection." << endl;
return 0;
}
Bill* bill = user_bills[bill_index - 1];
bank.pay_bill(bill, account->get_account_num());
cout << "Bill paid." << endl;
}
else if (choice == 4) {
break;
}
else {
cout << "Invalid choice. Please try again." << endl;
}
}
}
}
}
else if (user->get_role() == "cashier") {
while (true) {
cout << endl << "What would you like to do?" << endl;
cout << "1. View all accounts of a user" << endl;
cout << "2. Open a new account for a user" << endl;
cout << "3. Log out" << endl;
cout << "Enter choice (1-3): ";
int choice;
cin >> choice;
if (choice == 3) {
bank.logout();
break;
}
else if (choice == 1) {
cout << "Enter username: ";
string username;
cin >> username;
vector<Account*> accounts = bank.get_user_accounts(username);
if (accounts.empty()) {
cout << "No accounts found for user " << username << endl;
}
else {
cout << endl << "Accounts for user " << username << ":" << endl;
for (auto acc : accounts) {
cout << acc->get_account_type() << " (" << acc->get_account_num() << "): " << acc->get_balance() << endl;
}
}
}
else if (choice == 2) {
cout << "Enter username: ";
string username;
cin >> username;
if (bank.add_account(username)) {
cout << "Account successfully opened for user " << username << endl;
bank.list_accounts(username);
}
else {
cout << "Failed to open account for user " << username << endl;
}
}
}
}
else if (user->get_role() == "director") {
// The user is a director
}
}
return 0;
}