Untitled

mail@pastecode.io avatar
unknown
rust
3 years ago
5.6 kB
3
Indexable
Never
use std::io;

const ABC_BANK_CHARGES: f64 = 0.5;

struct Account {
    balance: f64,
}

impl Account {
    fn deposit(&mut self, amount: f64) -> bool {
        if amount <= 0.0 {
            println!("ERROR: Transaction not permitted. Deposit amount must be positive!");
            return false;
        }
        // can be written as `self.balance += amount`
        self.balance = self.balance + amount;
        true
    }

    fn withdraw(&mut self, amount: f64) -> bool {

        if amount <= 0.0 {
            // It is always a good practice to print error messages to `stderr`
            // Use `eprintln!` instead of `println!`
            println!("ERROR: Transaction not permitted. Withdraw amount must be positive!");
            return false;
        }
        if self.balance < amount {
            // It is always a good practice to print error messages to `stderr`
            // Use `eprintln!` instead of `println!`
            println!("ERROR: Transaction not permitted. Insufficient balance!");
            return false;
        }

        // can be written as `self.balance -= amount`
        self.balance = self.balance - amount;
        true
    }

    fn open_account(balance: f64) -> Account {
        Account {
            balance
        }
    }
}

struct ABCBankAccount {
    account: Account,
    bank_charges: f64,
}

impl ABCBankAccount {
    // Why not accept `amount` as f64 ? No need of casting variables.
    fn deposit(&mut self, amount: u64) -> bool {
        let balance = self.account.balance + amount as f64;
        if balance > 2000.0 {
            // It is always a good practice to print error messages to `stderr`
            // Use `eprintln!` instead of `println!`
            println!("ERROR: Balance cannot be greater than 2000");
            return false;
        }
        self.account.deposit(amount as f64);
        true
    }

    // What kind of bank is this ? Why can't I withdraw 10.5 ?
    fn withdraw(&mut self, amount: u64) -> bool {
        if amount % 5 != 0 {
            // It is always a good practice to print error messages to `stderr`
            // Use `eprintln!` instead of `println!`
            println!("ERROR: Withdraw amount must be a multiple of 5");
            return false
        }

        self.account.withdraw(amount as f64 + self.bank_charges);
        true
    }

    fn open_account(initial_balance: f64) -> ABCBankAccount {
        let mut account: Account = Account::open_account(0.0);

        if !account.deposit(initial_balance) {
            panic!("Invalid operation. Terminating.");
        }

        ABCBankAccount {
            // `account: account` replace with `account`
            account: account,
            bank_charges: ABC_BANK_CHARGES,
        }
    }
}


fn main() {
    let mut pooja_account: ABCBankAccount;
    let mut _flag: bool;
    loop{
        println!("Please input the starting balance: ");
        // This causes an allocation for every iteration in the loop.
        // Allocation involves calls to kernel which are expensive.
        // Instead declare this variable in main scope which limits it to a single allocation.
        // You can reuse variable by clearing its content in loop's defer stage.
        let mut initial_balance = String::new();
        io::stdin()
            .read_line(&mut initial_balance)
            .expect("Failed to accept input");

        // No need to explicitly specify `f64` compiler can figure it out.
        let initial_balance = match initial_balance.trim().parse() {
            Ok(num) => num,
            Err(_) => {
                // It is always a good practice to print error messages to `stderr`
                // Use `eprintln!` instead of `println!`
                println!("ERROR: Invalid input provided. Please provide a number less than equal to 2000$");
                continue;
                },
        };

        pooja_account = ABCBankAccount::open_account(initial_balance);
        break;
    }

    loop {
        println!("Please input the withdraw amount: ");
        // This causes an allocation for every iteration in the loop.
        // Allocation involves calls to kernel which are expensive.
        // Instead declare this variable in main scope which limits it to a single allocation.
        // You can reuse variable by clearing its content in loop's defer stage.
        let mut withdraw_amount = String::new();
        io::stdin()
            .read_line(&mut withdraw_amount)
            .expect("Failed to accept input");

        // No need to explicitly specify `u64` compiler can figure it out.
        let withdraw_amount = match withdraw_amount.trim().parse() {
            Ok(num) => num,
            Err(_) => {
                // It is always a good practice to print error messages to `stderr`
                // Use `eprintln!` instead of `println!`
                println!("ERROR: Invalid input provided. Please provide a number.");
                continue;
                },
        };

        _flag = pooja_account.withdraw(withdraw_amount);
        if !_flag{
            continue;
        }
        println!("Flag is {}", _flag);
        println!("Balance after transaction is {}", pooja_account.account.balance);

        println!("Do you want to continue (Y/N)?  ");
        let mut choice = String::new();
        io::stdin()
            .read_line(&mut choice)
            .expect("Failed to accept input");

        if choice.trim() == "N" {
            println!("Thank you for transacting with us! Bye!");
            break;
        }
    }
}