Skip to content
This repository was archived by the owner on May 18, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions src/main/java/Driver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import business.Ledger;
import models.*;

import java.math.BigDecimal;
import java.util.Arrays;

public class Driver {
public static void main(String[] args) {

Ledger ledger = new Ledger();
Users users = new Users();
users.addUser(new User("u1"));
users.addUser(new User("u2"));
users.addUser(new User("u3"));
users.addUser(new User("u4"));
ledger.showBalances();
ledger.getBalancesOfUser(users.getUser("u1"));
Expense expense1 = new EqualExpense(
users.getUser("u1")
,new BigDecimal(1000)
,Arrays.asList(
users.getUser("u1")
,users.getUser("u2")
,users.getUser("u3")
,users.getUser("u4")
)
);
ledger.ProcessExpense(expense1);
ledger.getBalancesOfUser(users.getUser("u4"));
ledger.getBalancesOfUser(users.getUser("u1"));
Expense expense2 = new ExactExpense(
users.getUser("u1")
,new BigDecimal(1250)
,Arrays.asList(
users.getUser("u2")
,users.getUser("u3")
)
,Arrays.asList(
new BigDecimal(370)
, new BigDecimal(880)
)
);
ledger.ProcessExpense(expense2);
ledger.getAllBalances();
Expense expense3 = new PercentExpense(
users.getUser("u4")
,new BigDecimal(1200)
,Arrays.asList(
users.getUser("u1")
,users.getUser("u2")
,users.getUser("u3")
,users.getUser("u4")
)
,Arrays.asList(
new BigDecimal(40)
,new BigDecimal(20)
,new BigDecimal(20)
,new BigDecimal(20)
)
);
ledger.ProcessExpense(expense3);
ledger.getBalancesOfUser(users.getUser("u1"));
ledger.getAllBalances();
}
}
84 changes: 84 additions & 0 deletions src/main/java/business/Ledger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package business;

import models.Balance;
import models.Expense;
import models.User;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class Ledger {
// TODO hashmap implementation for performance
List<Balance> balances;

public Ledger() {
this.balances = new ArrayList<>();
}

public void ProcessExpense(Expense expense) {
List<Balance> balances = expense.getBalances();
for (Balance balance : balances) {
Balance existingBalance = getBalanceOfUsers(balance.getBorrower(), balance.getGiver());
if (existingBalance == null) {
this.balances.add(balance);
continue;
}
if(existingBalance.getBorrower().equals(balance.getBorrower())) {
existingBalance.addAmount(balance.getAmount());
} else {
BigDecimal amount = existingBalance.getAmount().subtract(balance.getAmount());
if(amount.compareTo(new BigDecimal(0))==0) {
this.balances.remove(existingBalance);
} else if(amount.compareTo(new BigDecimal(0))>0) {
existingBalance.setAmount(amount);
} else {
this.balances.remove(existingBalance);
this.balances.add(new Balance(balance.getBorrower(), balance.getGiver(), amount.negate()));
}
}
}
}

private Balance getBalanceOfUsers(User user1, User user2) {
Balance balance = null;
for (Balance balanceLoop : balances) {
if(balanceLoop.isUsersInvolved(user1, user2)) {
balance = balanceLoop;
}
}
return balance;
}

public void showBalances(){
printBalance(balances);
}

public void getBalancesOfUser(User user) {
List<Balance> balancesOfUser = new ArrayList<>();
for (Balance balance : balances) {
if (balance.isUserInvolved(user)) {
balancesOfUser.add(balance);
}
}
printBalance(balancesOfUser);
}

public void getAllBalances() {
printBalance(this.balances);
}

private void printBalance(List<Balance> balances) {
if(balances.isEmpty()) {
System.out.println("No balances");
}
else {
for (Balance balance : balances) {
System.out.println(balance);
}
}
System.out.println("-");
}


}
54 changes: 54 additions & 0 deletions src/main/java/models/Balance.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package models;

import java.math.BigDecimal;

public class Balance {
User borrower;
User giver;
BigDecimal amount;

public Balance(User borrower, User giver, BigDecimal amount) {
this.borrower = borrower;
this.giver = giver;
this.amount = amount;
}

public User getBorrower() {
return borrower;
}

public User getGiver() {
return giver;
}

@Override
public String toString() {
return String.format("%s owes %s: %s", borrower.getName(), giver.getName(), amount);
}

public boolean isUserInvolved(User user) {
if(borrower.equals(user) || giver.equals(user)) {
return true;
}
return false;
}

public boolean isUsersInvolved(User user1, User user2) {
if((borrower.equals(user1)&& giver.equals(user2))||(borrower.equals(user2)&&giver.equals(user1))) {
return true;
}
return false;
}

public void addAmount(BigDecimal amount) {
this.amount = this.amount.add(amount);
}

public BigDecimal getAmount() {
return amount;
}

public void setAmount(BigDecimal amount) {
this.amount = amount;
}
}
25 changes: 25 additions & 0 deletions src/main/java/models/EqualExpense.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package models;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class EqualExpense extends Expense {

public EqualExpense(User payer, BigDecimal amount, List<User> payee) {
super(payer, amount, payee);
}

@Override
public List<Balance> getBalances() {
List<Balance> balances = new ArrayList<>();
BigDecimal sharedAmount = amount.divide(new BigDecimal(payee.size()));
for (User user : payee) {
if(user.equals(payer)) {
continue;
}
balances.add(new Balance(user,payer,sharedAmount));
}
return balances;
}
}
25 changes: 25 additions & 0 deletions src/main/java/models/ExactExpense.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package models;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class ExactExpense extends Expense{
private List<BigDecimal> amounts;
public ExactExpense(User payer, BigDecimal amount, List<User> payee,List<BigDecimal> amounts) {
super(payer, amount, payee);
this.amounts = amounts;
}

@Override
public List<Balance> getBalances() {
List<Balance> balances = new ArrayList<>();
for (int i = 0; i < payee.size(); i++) {
if(payee.get(i).equals(payer)) {
continue;
}
balances.add(new Balance(payee.get(i),payer,amounts.get(i)));
}
return balances;
}
}
30 changes: 30 additions & 0 deletions src/main/java/models/Expense.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package models;

import java.math.BigDecimal;
import java.util.List;

public abstract class Expense {
protected User payer;
protected BigDecimal amount;
List<User> payee;

public Expense(User payer, BigDecimal amount, List<User> payee) {
if (payer == null) {
throw new IllegalArgumentException("payer must not be null");
}

if(amount.compareTo(new BigDecimal(0))<=0) {
throw new IllegalArgumentException("amount must be positive");
}

if (payee == null || payee.isEmpty() || payee.contains(null)) {
throw new IllegalArgumentException("payee list must not be null or empty or containing null. ");
}

this.payer = payer;
this.amount = amount;
this.payee = payee;
}

abstract public List<Balance> getBalances();
}
27 changes: 27 additions & 0 deletions src/main/java/models/PercentExpense.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package models;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class PercentExpense extends Expense{
private List<BigDecimal> percentages;
public PercentExpense(User payer, BigDecimal amount, List<User> payee, List<BigDecimal> percentages) {
super(payer, amount, payee);
this.percentages = percentages;
}

@Override
public List<Balance> getBalances() {
List<Balance> balances = new ArrayList<>();
for (int i = 0; i < payee.size(); i++) {
if(payee.get(i).equals(payer)) {
continue;
}
BigDecimal percent = percentages.get(i).divide(new BigDecimal(100));
balances.add(new Balance(payee.get(i),payer,amount.multiply(percent)));
}
return balances;

}
}
31 changes: 31 additions & 0 deletions src/main/java/models/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package models;

import java.util.Objects;

public class User {
private String name;

public User(String name) {
if (name == null) {
throw new IllegalArgumentException("name must not be null.");
}
this.name = name;
}

public String getName() {
return name;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return getName().equals(user.getName());
}

@Override
public int hashCode() {
return Objects.hash(getName());
}
}
24 changes: 24 additions & 0 deletions src/main/java/models/Users.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package models;

import java.util.ArrayList;
import java.util.List;

public class Users {
List<User> users;

public Users() {
this.users = new ArrayList<>();
}

public User getUser(String name) {
for (User user : users) {
if (user.getName().equalsIgnoreCase(name)) {
return user;
}
}
return null;
}
public void addUser(User user) {
users.add(user);
}
}