From b757b3e26190cddf413d5898ecc94ec3d78bc0bd Mon Sep 17 00:00:00 2001 From: Soumya Ghosh Dastidar Date: Mon, 28 Oct 2019 16:48:44 +0530 Subject: [PATCH] solved split wise --- src/com/soumya/splitwise/ExpenseManager.java | 209 +++++++++++++++++++ src/com/soumya/splitwise/SplitWiseApp.java | 38 ++++ src/com/soumya/splitwise/User.java | 48 +++++ 3 files changed, 295 insertions(+) create mode 100644 src/com/soumya/splitwise/ExpenseManager.java create mode 100644 src/com/soumya/splitwise/SplitWiseApp.java create mode 100644 src/com/soumya/splitwise/User.java diff --git a/src/com/soumya/splitwise/ExpenseManager.java b/src/com/soumya/splitwise/ExpenseManager.java new file mode 100644 index 0000000..d666b4c --- /dev/null +++ b/src/com/soumya/splitwise/ExpenseManager.java @@ -0,0 +1,209 @@ +package com.soumya.splitwise; + +import java.util.*; + +// ExpenseManager : Handles the User Registration and Book keeping tasks. Core functionality of Split Wise. +public class ExpenseManager { + + private Map users; // Map of registered Users, uid:User + private Map expenses; // Map of Expenses "uid_borrower uid_lender":amount + private int userCount; // Keeps count of registered users + + // Default Constructor + public ExpenseManager() { + users = new HashMap<>(); + expenses = new HashMap<>(); + userCount = 0; + } + + // Register Users + public void registerUser(String name, String email, String mob_no) { + userCount++; + String uid="u"+userCount; + users.put(uid, new User(uid,name,email,mob_no)); + } + + // Display all registered Users + public void displayRegisteredUsers() { + if(users.size()==0) { + System.out.println("No Users Registgered"); + return; + } + System.out.println("UID\t\tNAME\t\tEMAIL\t\t\tMOBILE NO."); + users.forEach((key, value)->{ + System.out.println(value.getUid()+"\t\t"+value.getName()+"\t\t"+value.getEmail()+"\t\t"+value.getMob_no()); + }); + } + + // Add new or update "uid_borrower uid_lender":amount entry in expenses + private void registerExpense(String uid_borrow, String uid_lend, float amt) { + // If uid_lend has previous entry of owing money to uid_borrow + String key=uid_lend+" "+uid_borrow; + if(expenses.containsKey(key)) { + expenses.put(key, expenses.get(key)-amt); + if(expenses.get(key)==0) + expenses.remove(key); + } + else { + // If uid_borrow has previous entry of owing money to uid_lend + key=uid_borrow+" "+uid_lend; + if(expenses.containsKey(key)) + expenses.put(key, expenses.get(key)+amt); + else // Create entry + expenses.put(key, amt); + if(expenses.get(key)==0) // If amount==0 delete expense entry from the map + expenses.remove(key); + } + } + + // Display all expense entries + private void showAllBalances() { + if(expenses.size()==0) { + System.out.println("No balances"); + return; + } + expenses.forEach((key, value) -> { + String usrs[] = key.split(" "); + User user1 = users.get(usrs[0]), user2=users.get(usrs[1]); + float val=(float)(Math.round(Math.abs(value) * Math.pow(10, 2)) / Math.pow(10, 2)); + if(value>0) + System.out.println(user1.getName()+" owes "+user2.getName()+": "+val); + else + System.out.println(user2.getName()+" owes "+user1.getName()+": "+val); + }); + } + + // Display expense entries for specific user + private void showBalanceForUser(String uid) { + if(!users.containsKey(uid)) { + System.out.println("ERROR: Unknown User !"); + return; + } + int flag[]= {0}; + expenses.forEach((key, value) -> { + if(!key.contains(uid)) + return; + flag[0]++; + String usrs[] = key.split(" "); + User user1 = users.get(usrs[0]), user2=users.get(usrs[1]); + if(value>0) + System.out.println(user1.getName()+" owes "+user2.getName()+": "+value); + else + System.out.println(user2.getName()+" owes "+user1.getName()+": "+Math.abs(value)); + }); + if(flag[0]==0) + System.out.println("No balances"); + } + + // Handles EXACT distribution flow + private String exactDistribute(String expense[], String uid, float amt, int share_count, int indx) { + float sum=(float) 0.0; + for(int i=indx+1;i<=indx+share_count;i++) + sum+=Float.parseFloat(expense[i]); + if(sum!=amt) + return "ERROR: Expenses do not Add Up !"; + for(int i=1,uindx=3,pindx=indx;i<=share_count;i++) + if(!expense[uindx+i].equals(uid)) + registerExpense(expense[uindx+i],uid,Float.parseFloat(expense[pindx+i])); + return "UPDATED"; + + } + + // Handles EQUAL distribution flow + private String equalDistribute(String expense[], String uid, float amt, int share_count, int indx) { + float val=amt/share_count; + for(int uindx=4;uindx<4+share_count;uindx++) + if(!expense[uindx].equals(uid)) + registerExpense(expense[uindx],uid,val); + return "UPDATED"; + } + + // Handles PERCENT distribution flow + private String percentDistribute(String expense[], String uid, float amt, int share_count, int indx) { + float sum=(float) 0.0; + for(int i=indx+1;i<=indx+share_count;i++) + sum+=Float.parseFloat(expense[i]); + if(sum!=100.0) + return "ERROR: Expenses do not Add Up !"; + for(int i=1,uindx=3,pindx=indx;i<=share_count;i++) { + float val=(float) (amt*1.0*Float.parseFloat(expense[pindx+i])/100); + if(!expense[uindx+i].equals(uid)) + registerExpense(expense[uindx+i],uid,val); + } + return "UPDATED"; + + } + + // Handles SHARE distribution flow + private String shareDistribute(String expense[], String uid, float amt, int share_count, int indx) { + float sum=(float) 0.0; + for(int i=indx+1;i<=indx+share_count;i++) + sum+=Float.parseFloat(expense[i]); + for(int i=1,uindx=3,pindx=indx;i<=share_count;i++) { + float val=(float) (amt*1.0*Float.parseFloat(expense[pindx+i])/sum); + if(!expense[uindx+i].equals(uid)) + registerExpense(expense[uindx+i],uid,val); + } + return "UPDATED"; + + } + + // Driver for the EXPENSE flow, also performs data validation + private String computeExpenses(String expense[]) { + try { + String uid_lend=expense[1]; + if(!users.containsKey(uid_lend)) + return "ERROR: Unknown UID- "+uid_lend+" !"; + float amt = Float.parseFloat(expense[2]); + int share_count=Integer.parseInt(expense[3]); + int indx=4+share_count; + for(int uindx=4;uindx<4+share_count;uindx++) + if(!users.containsKey(expense[uindx])) + return "ERROR: Unknown UID- "+expense[uindx]+" !"; + if(expense[indx].equalsIgnoreCase("EQUAL")) { + return equalDistribute(expense, uid_lend, amt, share_count, indx); + } + else if(expense[indx].equalsIgnoreCase("EXACT")) { + return exactDistribute(expense, uid_lend, amt, share_count, indx); + } + else if(expense[indx].equalsIgnoreCase("PERCENT")) { + return percentDistribute(expense, uid_lend, amt, share_count, indx); + } + else if(expense[indx].equalsIgnoreCase("SHARE")) { + return shareDistribute(expense, uid_lend, amt, share_count, indx); + } + else + return "ERROR: Unknown Expense Code !"; + } + catch(ArrayIndexOutOfBoundsException e) { + return "ERROR: Malformed Input !"; + } + + } + + // Handler to parse the requests and call appropriate functions + public void handleRequest(String request) { + +/* --DEBUGGING PURPOSE-- + * + * System.out.println("HANDLING REQUEST FOR : "+request); + * System.out.println(expenses); + */ + String req[]=request.split(" "),resp=""; + if(req[0].equalsIgnoreCase("EXPENSE")) { + if(!(resp=computeExpenses(req)).equals("UPDATED")) + System.out.println(resp); + } + else if(req[0].equalsIgnoreCase("SHOW")) { + if(req.length==1) + showAllBalances(); + else if(req.length==2) + showBalanceForUser(req[1]); + else + System.out.println("ERROR: Malformed Input !"); + } + else + System.out.println("ERROR: Malformed Input !"); + } + +} diff --git a/src/com/soumya/splitwise/SplitWiseApp.java b/src/com/soumya/splitwise/SplitWiseApp.java new file mode 100644 index 0000000..02d07d5 --- /dev/null +++ b/src/com/soumya/splitwise/SplitWiseApp.java @@ -0,0 +1,38 @@ +package com.soumya.splitwise; + +// Driver Application +public class SplitWiseApp { + + public static void main(String[] args) { + // Initializing ExpenseManager Object + ExpenseManager expman = new ExpenseManager(); + + // Hard Coded Users + expman.registerUser("User1", "user1@hello.com", "+918685483458"); + expman.registerUser("User2", "user2@hello.com", "+918085483643"); + expman.registerUser("User3", "user3@hello.com", "+919056783458"); + expman.registerUser("User4", "user4@hello.com", "+919885434258"); + + // Display Registered Users with UID + expman.displayRegisteredUsers(); + + // TEST - Taken from SAMPLE INPUT Section + expman.handleRequest("SHOW"); + expman.handleRequest("SHOW u1"); + // EQUAL + expman.handleRequest("EXPENSE u1 1000 4 u1 u2 u3 u4 EQUAL"); + expman.handleRequest("SHOW u4"); + expman.handleRequest("SHOW u1"); + // EXACT + expman.handleRequest("EXPENSE u1 1250 2 u2 u3 EXACT 370 880"); + expman.handleRequest("SHOW"); + // PERCENT + expman.handleRequest("EXPENSE u4 1200 4 u1 u2 u3 u4 PERCENT 40 20 20 20"); + expman.handleRequest("SHOW u1"); + expman.handleRequest("SHOW"); + // SHARE + expman.handleRequest("EXPENSE u4 1200 4 u1 u2 u3 u4 SHARE 2 1 1 1"); + expman.handleRequest("SHOW"); + } + +} diff --git a/src/com/soumya/splitwise/User.java b/src/com/soumya/splitwise/User.java new file mode 100644 index 0000000..e6cf844 --- /dev/null +++ b/src/com/soumya/splitwise/User.java @@ -0,0 +1,48 @@ +package com.soumya.splitwise; + +// Defines the characteristics of a user +public class User { + + private String name,uid,email,mob_no; + + public User(String uid, String name, String email, String mob_no) { + super(); + this.name = name; + this.uid = uid; + this.email = email; + this.mob_no = mob_no; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getMob_no() { + return mob_no; + } + + public void setMob_no(String mob_no) { + this.mob_no = mob_no; + } + +}