class Account {
private double balance;
private final int id;
private final String holderName;
private final boolean zakatApplicable;
Account(double balance, int id, String holderName, boolean zakatApplicable) {
this.balance = balance;
this.id = id;
this.holderName = holderName;
this.zakatApplicable = zakatApplicable;
}
void deposit(double amount) {
balance += amount;
}
void withdraw(double amount) {
balance -= amount;
}
void deductZakat() {
balance -= balance * 0.025;
}
double getBalance() {
return balance;
}
public String getHolderName() {
return holderName;
}
}
class CurrentAccount extends Account {
CurrentAccount(double balance, int id, String holderName, boolean zakatApplicable) {
super(balance, id, holderName, zakatApplicable);
}
}
abstract class EarningAccount extends Account {
private final boolean filer;
EarningAccount(double balance, int id, String holderName, boolean zakatApplicable, boolean filer) {
super(balance, id, holderName, zakatApplicable);
this.filer = filer;
}
@Override
void withdraw(double amount) {
if (filer) {
super.withdraw(amount * 1.02);
} else {
super.withdraw(amount * 1.04);
}
}
abstract double getTotalEarnings();
static double getTotalProfitPaid(EarningAccount... accounts) {
double profit = 0;
for (EarningAccount account: accounts) {
profit += account.getTotalEarnings() - account.getBalance();
}
return profit;
}
}
class SavingsAccount extends EarningAccount {
enum Category {
YOUNG(6),
ADULT(7),
SENIOR_CITIZEN(8);
private final int profitRatio;
Category(int profitRatio) {
this.profitRatio = profitRatio;
}
int getProfitRatio() {
return profitRatio;
}
}
private final Category category;
SavingsAccount(double balance, int id, String holderName, boolean zakatApplicable, boolean filer, int age) {
super(balance, id, holderName, zakatApplicable, filer);
category = age < 35? Category.YOUNG: age <= 50? Category.ADULT: Category.SENIOR_CITIZEN;
}
@Override
double getTotalEarnings() {
return getBalance() * (1 + category.getProfitRatio()/100.0);
}
}
class InvestmentAccount extends EarningAccount {
enum Type {
ONE_YEAR(10),
THREE_YEAR(12),
FIVE_YEAR(14);
private final int profitRatio;
Type(int profitRatio) {
this.profitRatio = profitRatio;
}
double getProfitRatio() {
return profitRatio;
}
}
private final Type type;
InvestmentAccount(double balance, int id, String holderName, boolean zakatApplicable, boolean filer, Type type) {
super(balance, id, holderName, zakatApplicable, filer);
this.type = type;
}
@Override
void withdraw(double amount) {
super.withdraw(amount * 1.04);
}
@Override
double getTotalEarnings() {
return switch (type) {
case ONE_YEAR -> getBalance() * (1 + type.getProfitRatio()/100.0);
case THREE_YEAR -> getBalance() * Math.pow(1 + type.getProfitRatio()/100.0, 3);
case FIVE_YEAR -> getBalance() * Math.pow(1 + type.getProfitRatio()/100.0, 5);
};
}
}
public class Main {
public static void main(String[] args) {
SavingsAccount account1 = new SavingsAccount(10000, 1, "Holder 1", false, false, 20);
System.out.println(account1.getHolderName() + " total earnings: " + account1.getTotalEarnings());
CurrentAccount account2 = new CurrentAccount(1000, 2, "Holder 2", true);
account2.deductZakat();
System.out.println(account2.getHolderName() + " balance after deducting zakat: " + account2.getBalance());