From 5194cd2e1f44af9d61dc5c7ce720db48bf093223 Mon Sep 17 00:00:00 2001 From: shishiruniyal Date: Sat, 21 Sep 2019 22:05:29 +0530 Subject: [PATCH] mock machine 2 submission --- src/com/expense/EqualExpense.java | 34 ++++++++ src/com/expense/ExactExpense.java | 34 ++++++++ src/com/expense/Expense.java | 12 +++ src/com/expense/ExpenseFactory.java | 13 +++ src/com/expense/ExpenseLog.java | 68 +++++++++++++++ src/com/expense/PercentExpense.java | 42 +++++++++ src/com/expenseSharing/model/User.java | 85 +++++++++++++++++++ src/com/expenseSharing/model/Wallet.java | 26 ++++++ .../service/ExpenseSharingService.java | 79 +++++++++++++++++ src/com/launcher/Launcher.java | 65 ++++++++++++++ 10 files changed, 458 insertions(+) create mode 100644 src/com/expense/EqualExpense.java create mode 100644 src/com/expense/ExactExpense.java create mode 100644 src/com/expense/Expense.java create mode 100644 src/com/expense/ExpenseFactory.java create mode 100644 src/com/expense/ExpenseLog.java create mode 100644 src/com/expense/PercentExpense.java create mode 100644 src/com/expenseSharing/model/User.java create mode 100644 src/com/expenseSharing/model/Wallet.java create mode 100644 src/com/expenseSharing/service/ExpenseSharingService.java create mode 100644 src/com/launcher/Launcher.java diff --git a/src/com/expense/EqualExpense.java b/src/com/expense/EqualExpense.java new file mode 100644 index 0000000..58878bc --- /dev/null +++ b/src/com/expense/EqualExpense.java @@ -0,0 +1,34 @@ +package com.expense; + +import java.util.ArrayList; +import java.util.List; + +public class EqualExpense extends Expense{ + + @Override + public List splitExpense(String expenseDetails) { + String[] details = expenseDetails.split(" "); + String paidByUserId = details[1]; + double amount = Double.parseDouble(details[2]); + int totalUsersInvolved = Integer.parseInt(details[3]); + double eachContribution = Double.parseDouble(decimalFormat.format(amount/totalUsersInvolved)); + double amountDistributed = 0.0; + List expenseLogList = new ArrayList(); + for(int i = 0 ; i < totalUsersInvolved ; i++ ) { + String userId = details[4+i]; + ExpenseLog expenseLog = new ExpenseLog(paidByUserId, userId, eachContribution); + expenseLogList.add(expenseLog); + amountDistributed += eachContribution; + } + // calculated offset and add it to first user + double contributionByFirstUser = expenseLogList.get(0).getAmount()+(amount - amountDistributed); + expenseLogList.get(0).setAmount(contributionByFirstUser); + return expenseLogList; + } + + @Override + public boolean validateExpense(String expenseDetails) { + return true; + } + +} diff --git a/src/com/expense/ExactExpense.java b/src/com/expense/ExactExpense.java new file mode 100644 index 0000000..f2bee51 --- /dev/null +++ b/src/com/expense/ExactExpense.java @@ -0,0 +1,34 @@ +package com.expense; + +import java.util.ArrayList; +import java.util.List; + +public class ExactExpense extends Expense { + + @Override + public List splitExpense(String expenseDetails) { + String[] details = expenseDetails.split(" "); + String paidByUserId = details[1]; + int totalUsersInvolved = Integer.parseInt(details[3]); + List expenseLogList = new ArrayList(); + for(int i = 0 ; i < totalUsersInvolved ; i++ ) { + String userId = details[4+i]; + double contibution = Double.parseDouble(details[4+totalUsersInvolved+i+1]); + ExpenseLog expenseLog = new ExpenseLog(paidByUserId, userId, contibution); + expenseLogList.add(expenseLog); + } + return expenseLogList; + } + + @Override + public boolean validateExpense(String expenseDetails) { + String[] details = expenseDetails.split(" "); + double amount = Double.parseDouble(details[2]); + int totalUsersInvolved = Integer.parseInt(details[3]); + for(int i = 0 ; i < totalUsersInvolved; i++) { + amount -= Double.parseDouble(details[4+totalUsersInvolved+i+1]); + } + return (amount == 0.0)?true:false; + } + +} diff --git a/src/com/expense/Expense.java b/src/com/expense/Expense.java new file mode 100644 index 0000000..8ee50ad --- /dev/null +++ b/src/com/expense/Expense.java @@ -0,0 +1,12 @@ +package com.expense; + +import java.text.DecimalFormat; +import java.util.List; + +public abstract class Expense { + protected String pattern = "##.##"; + protected DecimalFormat decimalFormat = new DecimalFormat(pattern); + public abstract boolean validateExpense(String expenseDetails); + public abstract List splitExpense(String expenseDetails); + +} diff --git a/src/com/expense/ExpenseFactory.java b/src/com/expense/ExpenseFactory.java new file mode 100644 index 0000000..27dcfad --- /dev/null +++ b/src/com/expense/ExpenseFactory.java @@ -0,0 +1,13 @@ +package com.expense; + +public class ExpenseFactory { + public static Expense getExpense(String expenseDetails) throws Exception { + if(expenseDetails.contains("EQUAL")) + return new EqualExpense(); + else if(expenseDetails.contains("PERCENT")) + return new PercentExpense(); + else if(expenseDetails.contains("EXACT")) + return new ExactExpense(); + throw new Exception("Unspoorted expense"); + } +} diff --git a/src/com/expense/ExpenseLog.java b/src/com/expense/ExpenseLog.java new file mode 100644 index 0000000..72d9221 --- /dev/null +++ b/src/com/expense/ExpenseLog.java @@ -0,0 +1,68 @@ +package com.expense; + +public class ExpenseLog { + private String piadby; + private String owedBy; + private double amount; + public ExpenseLog(String piadby, String owedBy, double amount) { + this.piadby = piadby; + this.owedBy = owedBy; + this.amount = amount; + } + + public String getPiadby() { + return piadby; + } + public void setPiadby(String piadby) { + this.piadby = piadby; + } + public String getOwedBy() { + return owedBy; + } + + public void setOwedBy(String owedBy) { + this.owedBy = owedBy; + } + public double getAmount() { + return amount; + } + public void setAmount(double amount) { + this.amount = amount; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(amount); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + ((owedBy == null) ? 0 : owedBy.hashCode()); + result = prime * result + ((piadby == null) ? 0 : piadby.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ExpenseLog other = (ExpenseLog) obj; + if (Double.doubleToLongBits(amount) != Double.doubleToLongBits(other.amount)) + return false; + if (owedBy == null) { + if (other.owedBy != null) + return false; + } else if (!owedBy.equals(other.owedBy)) + return false; + if (piadby == null) { + if (other.piadby != null) + return false; + } else if (!piadby.equals(other.piadby)) + return false; + return true; + } + +} diff --git a/src/com/expense/PercentExpense.java b/src/com/expense/PercentExpense.java new file mode 100644 index 0000000..972862b --- /dev/null +++ b/src/com/expense/PercentExpense.java @@ -0,0 +1,42 @@ +package com.expense; + +import java.util.ArrayList; +import java.util.List; + +public class PercentExpense extends Expense { + + @Override + public List splitExpense(String expenseDetails) { + String[] details = expenseDetails.split(" "); + String paidByUserId = details[1]; + double amount = Double.parseDouble(details[2]); + int totalUsersInvolved = Integer.parseInt(details[3]); + List expenseLogList = new ArrayList(); + double amountDistributed = 0.0; + for(int i = 0 ; i < totalUsersInvolved ; i++ ) { + String userId = details[4+i]; + double percentContibution = Double.parseDouble(details[4+totalUsersInvolved+i+1]); + double userContribution = Double.parseDouble(decimalFormat.format((amount*percentContibution)/100)); + amountDistributed += userContribution; + ExpenseLog expenseLog = new ExpenseLog(paidByUserId, userId, userContribution); + expenseLogList.add(expenseLog); + } + // calculated offset and add it to first user + double contributionByFirstUser = expenseLogList.get(0).getAmount()+(amount - amountDistributed); + expenseLogList.get(0).setAmount(contributionByFirstUser); + return expenseLogList; + } + + @Override + public boolean validateExpense(String expenseDetails) { + String[] details = expenseDetails.split(" "); + int totalUsersInvolved = Integer.parseInt(details[3]); + double totalPercent = 100; + for(int i = 0 ; i < totalUsersInvolved ; i++ ) { + double percentContibution = Double.parseDouble(details[4+totalUsersInvolved+i+1]); + totalPercent -=percentContibution; + } + return (totalPercent == 0.0)?true:false; + } + +} diff --git a/src/com/expenseSharing/model/User.java b/src/com/expenseSharing/model/User.java new file mode 100644 index 0000000..5602209 --- /dev/null +++ b/src/com/expenseSharing/model/User.java @@ -0,0 +1,85 @@ +package com.expenseSharing.model; + +public class User { + private String userName; + private String userId; + private String email; + private long mobileNumber; + private Wallet wallet; + public User(String userName, String userId, String email, long mobileNumber) { + this.wallet = new Wallet(); + this.userName = userName; + this.userId = userId; + this.email = email; + this.mobileNumber = mobileNumber; + } + public Wallet getWallet() { + return wallet; + } + public void setWallet(Wallet wallet) { + this.wallet = wallet; + } + public String getUserName() { + return userName; + } + public void setUserName(String userName) { + this.userName = userName; + } + public String getUserId() { + return userId; + } + public void setUserId(String userId) { + this.userId = userId; + } + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + public long getMobileNumber() { + return mobileNumber; + } + public void setMobileNumber(long mobileNumber) { + this.mobileNumber = mobileNumber; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((email == null) ? 0 : email.hashCode()); + result = prime * result + (int) (mobileNumber ^ (mobileNumber >>> 32)); + result = prime * result + ((userId == null) ? 0 : userId.hashCode()); + result = prime * result + ((userName == null) ? 0 : userName.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + User other = (User) obj; + if (email == null) { + if (other.email != null) + return false; + } else if (!email.equals(other.email)) + return false; + if (mobileNumber != other.mobileNumber) + return false; + if (userId == null) { + if (other.userId != null) + return false; + } else if (!userId.equals(other.userId)) + return false; + if (userName == null) { + if (other.userName != null) + return false; + } else if (!userName.equals(other.userName)) + return false; + return true; + } + +} diff --git a/src/com/expenseSharing/model/Wallet.java b/src/com/expenseSharing/model/Wallet.java new file mode 100644 index 0000000..d346014 --- /dev/null +++ b/src/com/expenseSharing/model/Wallet.java @@ -0,0 +1,26 @@ +package com.expenseSharing.model; + +import java.util.HashMap; +import java.util.Map; + +public class Wallet { + private final Map ledger; + + public Wallet() { + this.ledger = new HashMap(); + } + public Map getLedger() { + return ledger; + } + + public void addOwedTo(String userId, double amount) { + if(ledger.get(userId) == null) + ledger.put(userId, 0.0); + ledger.put(userId, ledger.get(userId)+amount); + } + public void addOwedFrom(String userId, double amount) { + if(ledger.get(userId) == null) + ledger.put(userId, 0.0); + ledger.put(userId, ledger.get(userId)-amount); + } +} diff --git a/src/com/expenseSharing/service/ExpenseSharingService.java b/src/com/expenseSharing/service/ExpenseSharingService.java new file mode 100644 index 0000000..8a8dd5b --- /dev/null +++ b/src/com/expenseSharing/service/ExpenseSharingService.java @@ -0,0 +1,79 @@ +package com.expenseSharing.service; + +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.expense.Expense; +import com.expense.ExpenseFactory; +import com.expense.ExpenseLog; +import com.expenseSharing.model.User; + +public class ExpenseSharingService { + Map userMap; + String pattern = "##.##"; + DecimalFormat decimalFormat = new DecimalFormat(pattern); + public ExpenseSharingService() { + userMap = new HashMap(); + } + public void addUser(User user) { + userMap.put(user.getUserId(), user ); + } + public User getUser(String userId) { + return userMap.get(userId); + } + public void showBalance() { + System.out.println("Printing whole Blance"); + for(Map.Entry userEntry: userMap.entrySet()) { + Map userLedger = userEntry.getValue().getWallet().getLedger(); + if(userLedger.size() == 0) { + System.out.println("No Balance"); + return; + } + for(Map.Entry expenseDetails : userLedger.entrySet()) { + // Every user print how much others owes him + String otherUser = expenseDetails.getKey(); + if(expenseDetails.getValue() > 0) + { + System.out.println(otherUser+" owes "+userEntry.getKey()+" : "+decimalFormat.format(expenseDetails.getValue())); + } + } + } + } + public void showBalance(String userId) { + System.out.println("Printing Blance for userID "+userId); + User user = userMap.get(userId); + Map userLedger = user.getWallet().getLedger(); + if(userLedger.size() == 0) { + System.out.println("No Balance"); + return; + } + for(Map.Entry expenseDetails : userLedger.entrySet()) { + String otherUser = expenseDetails.getKey(); + if(expenseDetails.getValue() < 0) + { + System.out.println(userId+" owes "+otherUser+" : "+decimalFormat.format(-1*expenseDetails.getValue())); + } + else { + System.out.println(otherUser+" owes "+userId+" : "+decimalFormat.format(expenseDetails.getValue())); + } + } + } + + public void splitExpense(String expenseDetails) throws Exception { + Expense expense = ExpenseFactory.getExpense(expenseDetails); + if(!expense.validateExpense(expenseDetails)) { + throw new Exception("validation failure"); + } + List spitDetails = expense.splitExpense(expenseDetails); + for(ExpenseLog expenseLog :spitDetails) { + if(expenseLog.getPiadby().equals(expenseLog.getOwedBy())) + continue; + User paidByUser = userMap.get(expenseLog.getPiadby()); + User owedByUser = userMap.get(expenseLog.getOwedBy()); + paidByUser.getWallet().addOwedTo(owedByUser.getUserId(), expenseLog.getAmount()); + owedByUser.getWallet().addOwedFrom(paidByUser.getUserId(), expenseLog.getAmount()); + } + } +} diff --git a/src/com/launcher/Launcher.java b/src/com/launcher/Launcher.java new file mode 100644 index 0000000..caf30c5 --- /dev/null +++ b/src/com/launcher/Launcher.java @@ -0,0 +1,65 @@ +package com.launcher; + +import com.expenseSharing.model.User; +import com.expenseSharing.service.ExpenseSharingService; + +public class Launcher { + /* + * SHOW +SHOW u1 +EXPENSE u1 1250 4 u1 u2 u3 u4 EQUAL +SHOW u4 +SHOW u1 +EXPENSE u1 1250 2 u2 u3 EXACT 370 880 +SHOW +EXPENSE u4 1200 4 u1 u2 u3 u4 PERCENT 40 20 20 20 +SHOW u1 +SHOW + */ + private static ExpenseSharingService service; + public static void main(String args[]) { + service = new ExpenseSharingService(); + User u1 = new User("User1", "u1", "u1@email", 9999999999L); + User u2 = new User("User2", "u2", "u2@email", 9999999999L); + User u3 = new User("User3", "u3", "u3@email", 9999999999L); + User u4 = new User("User4", "u4", "u4@email", 9999999999L); + service.addUser(u1); + service.addUser(u2); + service.addUser(u3); + service.addUser(u4); + + String[] inputs = new String[10]; + inputs[0] = "SHOW"; + inputs[1] = "SHOW u1"; + inputs[2] = "EXPENSE u1 1000 3 u2 u1 u3 EQUAL"; + inputs[3] = "SHOW u4"; + inputs[4] = "SHOW u1"; + inputs[5] = "EXPENSE u1 1250 2 u2 u3 EXACT 370 880"; + inputs[6] = "SHOW"; + inputs[7] = "EXPENSE u4 1200 4 u1 u2 u3 u4 PERCENT 40 20 20 20"; + inputs[8] = "SHOW u1"; + inputs[9] = "SHOW"; + + processInput(inputs); + } + + private static void processInput(String[] inputs) { + for(String input : inputs) { + if(input.contains("EXPENSE")) { + try { + service.splitExpense(input); + } catch (Exception e) { + System.out.println("Exception occured"); + } + } + else if(input.equals("SHOW")) + service.showBalance(); + else { + String userId = input.split(" ")[1]; + service.showBalance(userId); + } + } + + } + +}