diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..0548357
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..ca9c70c
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..797acea
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mock-machine-coding-2.iml b/mock-machine-coding-2.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/mock-machine-coding-2.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/Driver.class b/out/production/mock-machine-coding-2/com/gaurparas/Driver.class
new file mode 100644
index 0000000..c99549a
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/Driver.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/EqualExpense.class b/out/production/mock-machine-coding-2/com/gaurparas/EqualExpense.class
new file mode 100644
index 0000000..3cce4fe
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/EqualExpense.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/EqualSplit.class b/out/production/mock-machine-coding-2/com/gaurparas/EqualSplit.class
new file mode 100644
index 0000000..92f3ca7
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/EqualSplit.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/ExactExpense.class b/out/production/mock-machine-coding-2/com/gaurparas/ExactExpense.class
new file mode 100644
index 0000000..b622d9c
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/ExactExpense.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/ExactSplit.class b/out/production/mock-machine-coding-2/com/gaurparas/ExactSplit.class
new file mode 100644
index 0000000..4c4bf29
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/ExactSplit.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/Expense.class b/out/production/mock-machine-coding-2/com/gaurparas/Expense.class
new file mode 100644
index 0000000..33312ff
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/Expense.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/ExpenseManager.class b/out/production/mock-machine-coding-2/com/gaurparas/ExpenseManager.class
new file mode 100644
index 0000000..c707939
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/ExpenseManager.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/ExpenseMetaData.class b/out/production/mock-machine-coding-2/com/gaurparas/ExpenseMetaData.class
new file mode 100644
index 0000000..55f760b
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/ExpenseMetaData.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/ExpenseService$1.class b/out/production/mock-machine-coding-2/com/gaurparas/ExpenseService$1.class
new file mode 100644
index 0000000..222145b
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/ExpenseService$1.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/ExpenseService.class b/out/production/mock-machine-coding-2/com/gaurparas/ExpenseService.class
new file mode 100644
index 0000000..148eac2
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/ExpenseService.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/ExpenseType.class b/out/production/mock-machine-coding-2/com/gaurparas/ExpenseType.class
new file mode 100644
index 0000000..37d3616
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/ExpenseType.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/PercentExpense.class b/out/production/mock-machine-coding-2/com/gaurparas/PercentExpense.class
new file mode 100644
index 0000000..6bc40fa
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/PercentExpense.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/PercentSplit.class b/out/production/mock-machine-coding-2/com/gaurparas/PercentSplit.class
new file mode 100644
index 0000000..b55df7f
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/PercentSplit.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/Split.class b/out/production/mock-machine-coding-2/com/gaurparas/Split.class
new file mode 100644
index 0000000..17208ce
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/Split.class differ
diff --git a/out/production/mock-machine-coding-2/com/gaurparas/User.class b/out/production/mock-machine-coding-2/com/gaurparas/User.class
new file mode 100644
index 0000000..c2b8d70
Binary files /dev/null and b/out/production/mock-machine-coding-2/com/gaurparas/User.class differ
diff --git a/src/com/gaurparas/Driver.java b/src/com/gaurparas/Driver.java
new file mode 100644
index 0000000..94a9721
--- /dev/null
+++ b/src/com/gaurparas/Driver.java
@@ -0,0 +1,61 @@
+package com.gaurparas;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+public class Driver {
+ public static void main(String... args){
+ ExpenseManager expenseManager = new ExpenseManager();
+
+ expenseManager.addUser(new User("u1","User1","paras@gmail.com","+91-00000"));
+ expenseManager.addUser(new User("u2","User2","pushpendra@gmail.com","+91-00001"));
+ expenseManager.addUser(new User("u3","User3","abhinav@gmail.com","+91-00002"));
+ expenseManager.addUser(new User("u4","User4","jancy@gmail.com","+91-00003"));
+
+ Scanner scanner = new Scanner(System.in);
+ while (true) {
+ String command = scanner.nextLine();
+ String[] commands = command.split(" ");
+ String commandType = commands[0];
+
+ switch (commandType){
+ case "SHOW":
+ if (commands.length == 1) {
+ expenseManager.showBalances();
+ } else {
+ expenseManager.showBalance(commands[1]);
+ }
+ break;
+ case "EXPENSE":
+ String paidBy = commands[1];
+ Double amount = Double.parseDouble(commands[2]);
+ int noOfUsers = Integer.parseInt(commands[3]);
+ String expenseType = commands[4 + noOfUsers];
+ List splits = new ArrayList<>();
+ switch (expenseType){
+ case "EXACT":
+ for(int i=0;i splits, ExpenseMetaData metaData) {
+ super(amount, paidBy, splits, metaData);
+ }
+
+ @Override
+ public boolean validate() {
+ List splits = getSplits();
+
+ for(Split split:splits) {
+ if (!(split instanceof EqualSplit)){
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/src/com/gaurparas/EqualSplit.java b/src/com/gaurparas/EqualSplit.java
new file mode 100644
index 0000000..4564b27
--- /dev/null
+++ b/src/com/gaurparas/EqualSplit.java
@@ -0,0 +1,8 @@
+package com.gaurparas;
+
+public class EqualSplit extends Split {
+
+ public EqualSplit(User user) {
+ super(user);
+ }
+}
diff --git a/src/com/gaurparas/ExactExpense.java b/src/com/gaurparas/ExactExpense.java
new file mode 100644
index 0000000..fad806f
--- /dev/null
+++ b/src/com/gaurparas/ExactExpense.java
@@ -0,0 +1,25 @@
+package com.gaurparas;
+
+import java.util.List;
+
+public class ExactExpense extends Expense {
+
+ public ExactExpense(double amount, User paidBy, List splits, ExpenseMetaData metaData) {
+ super(amount, paidBy, splits, metaData);
+ }
+
+ @Override
+ public boolean validate() {
+ List splits = getSplits();
+ double splitsAmount = 0;
+
+ for(Split split:splits) {
+ if (!(split instanceof EqualSplit)){
+ return false;
+ }
+ splitsAmount+=split.getAmount();
+ }
+
+ return splitsAmount == getAmount();
+ }
+}
diff --git a/src/com/gaurparas/ExactSplit.java b/src/com/gaurparas/ExactSplit.java
new file mode 100644
index 0000000..8bb1689
--- /dev/null
+++ b/src/com/gaurparas/ExactSplit.java
@@ -0,0 +1,9 @@
+package com.gaurparas;
+
+public class ExactSplit extends Split {
+
+ public ExactSplit(User user, double amount) {
+ super(user);
+ this.amount = amount;
+ }
+}
diff --git a/src/com/gaurparas/Expense.java b/src/com/gaurparas/Expense.java
new file mode 100644
index 0000000..bad742a
--- /dev/null
+++ b/src/com/gaurparas/Expense.java
@@ -0,0 +1,60 @@
+package com.gaurparas;
+
+import java.util.List;
+
+public abstract class Expense {
+ private String id;
+ private List splits;
+ private User paidBy;
+ private double amount;
+ private ExpenseMetaData metaData;
+
+ public Expense(double amount, User paidBy, List splits, ExpenseMetaData metaData) {
+ this.amount = amount;
+ this.paidBy = paidBy;
+ this.splits = splits;
+ this.metaData = metaData;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public double getAmount() {
+ return amount;
+ }
+
+ public void setAmount(double amount) {
+ this.amount = amount;
+ }
+
+ public User getPaidBy() {
+ return paidBy;
+ }
+
+ public void setPaidBy(User paidBy) {
+ this.paidBy = paidBy;
+ }
+
+ public List getSplits() {
+ return splits;
+ }
+
+ public void setSplits(List splits) {
+ this.splits = splits;
+ }
+
+ public ExpenseMetaData getMetadata() {
+ return metaData;
+ }
+
+ public void setMetadata(ExpenseMetaData metaData) {
+ this.metaData = metaData;
+ }
+
+ public abstract boolean validate();
+}
diff --git a/src/com/gaurparas/ExpenseManager.java b/src/com/gaurparas/ExpenseManager.java
new file mode 100644
index 0000000..dbcaed6
--- /dev/null
+++ b/src/com/gaurparas/ExpenseManager.java
@@ -0,0 +1,83 @@
+package com.gaurparas;
+
+import com.sun.deploy.cache.BaseLocalApplicationProperties;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ExpenseManager {
+
+ List expenses;
+ Map userMap;
+ Map> balanceSheet;
+
+ public ExpenseManager() {
+ expenses = new ArrayList();
+ userMap = new HashMap();
+ balanceSheet = new HashMap>();
+ }
+
+ public void addUser(User user) {
+ userMap.put(user.getId(), user);
+ balanceSheet.put(user.getId(), new HashMap());
+ }
+
+ public void showBalances() {
+ boolean isEmpty = true;
+ for(Map.Entry> allBalance : balanceSheet.entrySet()) {
+ for (Map.Entry userBalance : allBalance.getValue().entrySet()) {
+ if (userBalance.getValue() > 0) {
+ isEmpty = false;
+ printBalance(allBalance.getKey(), userBalance.getKey(), userBalance.getValue());
+ }
+ }
+ }
+ if (isEmpty) {
+ System.out.println("No balances");
+ }
+ }
+
+ public void showBalance(String userId) {
+ boolean isEmpty = true;
+ for(Map.Entry userBalance : balanceSheet.get(userId).entrySet()) {
+ if(userBalance.getValue() != 0){
+ isEmpty = false;
+ printBalance(userId, userBalance.getKey(), userBalance.getValue());
+ }
+ }
+ if (isEmpty) {
+ System.out.println("No balances");
+ }
+ }
+
+ private void printBalance(String user1, String user2, Double amount) {
+ String user1Name = userMap.get(user1).getName();
+ String user2Name = userMap.get(user2).getName();
+ if (amount < 0) {
+ System.out.println(user1Name + " owes " + user2Name + ": " + Math.abs(amount));
+ } else if (amount > 0) {
+ System.out.println(user2Name + " owes " + user1Name + ": " + Math.abs(amount));
+ }
+ }
+
+ public void addExpense(ExpenseType expenseType, Double amount, String paidBy,
+ List splits, ExpenseMetaData metaData) {
+ Expense expense = ExpenseService.createExpense(expenseType, amount, userMap.get(paidBy),
+ splits, metaData);
+ expenses.add(expense);
+
+ Map userBalances = balanceSheet.get(paidBy);
+ for(Split split:splits) {
+ String oweUser = split.getUser().getId();
+ double prevAmount = userBalances.getOrDefault(oweUser,0.0);
+ double currentAmount = split.getAmount();
+ userBalances.put(oweUser,prevAmount + currentAmount);
+
+ Map OweUserBalances = balanceSheet.get(oweUser);
+ prevAmount = OweUserBalances.getOrDefault(paidBy,0.0);
+ OweUserBalances.put(paidBy,prevAmount - currentAmount);
+ }
+ }
+}
diff --git a/src/com/gaurparas/ExpenseMetaData.java b/src/com/gaurparas/ExpenseMetaData.java
new file mode 100644
index 0000000..61dc5ba
--- /dev/null
+++ b/src/com/gaurparas/ExpenseMetaData.java
@@ -0,0 +1,37 @@
+package com.gaurparas;
+
+public class ExpenseMetaData {
+ private String name;
+ private String imgUrl;
+ private String notes;
+
+ public ExpenseMetaData(String name, String imgUrl, String notes) {
+ this.name = name;
+ this.imgUrl = imgUrl;
+ this.notes = notes;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getImgUrl() {
+ return imgUrl;
+ }
+
+ public void setImgUrl(String imgUrl) {
+ this.imgUrl = imgUrl;
+ }
+
+ public String getNotes() {
+ return notes;
+ }
+
+ public void setNotes(String notes) {
+ this.notes = notes;
+ }
+}
diff --git a/src/com/gaurparas/ExpenseService.java b/src/com/gaurparas/ExpenseService.java
new file mode 100644
index 0000000..32738eb
--- /dev/null
+++ b/src/com/gaurparas/ExpenseService.java
@@ -0,0 +1,29 @@
+package com.gaurparas;
+
+import java.util.List;
+
+public class ExpenseService {
+ public static Expense createExpense(ExpenseType expenseType, double amount, User paidBy,
+ List splits, ExpenseMetaData metaData) {
+ switch (expenseType) {
+ case EXACT:
+ return new ExactExpense(amount, paidBy, splits, metaData);
+ case EQUAL:
+ int totalSplits = splits.size();
+ double splitAmount = ((double) Math.round(amount*100/totalSplits))/100.0;
+ for(Split split:splits){
+ split.setAmount(splitAmount);
+ }
+ splits.get(0).setAmount(splitAmount + (amount-splitAmount*totalSplits));
+ return new EqualExpense(amount, paidBy, splits, metaData);
+ case PERCENT:
+ for(Split split:splits){
+ double percentSplit = ((PercentSplit)split).getPercent();
+ split.setAmount(amount*percentSplit/100);
+ }
+ return new PercentExpense(amount, paidBy, splits, metaData);
+ default:
+ return null;
+ }
+ }
+}
diff --git a/src/com/gaurparas/ExpenseType.java b/src/com/gaurparas/ExpenseType.java
new file mode 100644
index 0000000..6eb856c
--- /dev/null
+++ b/src/com/gaurparas/ExpenseType.java
@@ -0,0 +1,7 @@
+package com.gaurparas;
+
+public enum ExpenseType {
+ EQUAL,
+ EXACT,
+ PERCENT
+}
diff --git a/src/com/gaurparas/PercentExpense.java b/src/com/gaurparas/PercentExpense.java
new file mode 100644
index 0000000..a139d71
--- /dev/null
+++ b/src/com/gaurparas/PercentExpense.java
@@ -0,0 +1,27 @@
+package com.gaurparas;
+
+import java.util.List;
+
+public class PercentExpense extends Expense{
+
+
+ public PercentExpense(double amount, User paidBy, List splits, ExpenseMetaData metaData) {
+ super(amount, paidBy, splits, metaData);
+ }
+
+ @Override
+ public boolean validate() {
+ List splits = getSplits();
+ double splitsPercent = 0;
+ double total = 100;
+
+ for(Split split:splits) {
+ if (!(split instanceof PercentSplit)){
+ return false;
+ }
+ splitsPercent+=((PercentSplit) split).getPercent();
+ }
+
+ return splitsPercent == total;
+ }
+}
diff --git a/src/com/gaurparas/PercentSplit.java b/src/com/gaurparas/PercentSplit.java
new file mode 100644
index 0000000..c2dde93
--- /dev/null
+++ b/src/com/gaurparas/PercentSplit.java
@@ -0,0 +1,18 @@
+package com.gaurparas;
+
+public class PercentSplit extends Split {
+ double percent;
+
+ public PercentSplit(User user, double percent) {
+ super(user);
+ this.percent = percent;
+ }
+
+ public double getPercent() {
+ return percent;
+ }
+
+ public void setPercent(double percent) {
+ this.percent = percent;
+ }
+}
diff --git a/src/com/gaurparas/Split.java b/src/com/gaurparas/Split.java
new file mode 100644
index 0000000..c82b81a
--- /dev/null
+++ b/src/com/gaurparas/Split.java
@@ -0,0 +1,26 @@
+package com.gaurparas;
+
+public abstract class Split {
+ private User user;
+ double amount;
+
+ public Split(User user) {
+ this.user = user;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+ public double getAmount() {
+ return amount;
+ }
+
+ public void setAmount(double amount) {
+ this.amount = amount;
+ }
+}
diff --git a/src/com/gaurparas/User.java b/src/com/gaurparas/User.java
new file mode 100644
index 0000000..7e612b4
--- /dev/null
+++ b/src/com/gaurparas/User.java
@@ -0,0 +1,47 @@
+package com.gaurparas;
+
+public class User {
+ private String id;
+ private String name;
+ private String email;
+ private String phone;
+
+ public User(String id, String name, String email, String phone) {
+ this.id = id;
+ this.name = name;
+ this.email = email;
+ this.phone = phone;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+}