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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ Welcome to the 2nd Mock Machine Coding Round by [workat.tech](http://workat.tech

Please visit [this link](https://workat.tech/machine-coding/practice/splitwise-problem-0kp2yneec2q2) to participate.

Compile and package:
mvn clean package

Run
java -jar target/splitwise-1.0-SNAPSHOT.jar
63 changes: 63 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mc-prep</artifactId>
<groupId>com.sameerpandit</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>splitwise</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<main>com.sameerpandit.Main</main>
</properties>

<dependencies>
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>hk2-locator</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${main}</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.glassfish.hk2</groupId>
<artifactId>hk2-inhabitant-generator</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<goals>
<goal>generate-inhabitants</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
76 changes: 76 additions & 0 deletions src/main/java/com/sameerpandit/Driver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.sameerpandit;

import com.sameerpandit.db.InMemRepository;

import org.jvnet.hk2.annotations.Service;

import jakarta.inject.Inject;

@Service
public class Driver {
@Inject
Splitwise splitwise;
@Inject
InMemRepository repository;
public void run(){
System.out.println("Running Driver");
test1();
repository.clear();
test2();
}

public void test1(){
System.out.println("------------------------------------------------------");
String user1 = splitwise.addUser("User1", "user1@gmail.com", "9986368688");
String user2 = splitwise.addUser("User2", "user2@gmail.com", "9986368689");
String user3 = splitwise.addUser("User3", "user3@gmail.com", "9986368682");
String user4 = splitwise.addUser("User4", "user4@gmail.com", "9986368683");
splitwise.show();
// System.out.println("------------------------------------------------------");
splitwise.show(user1);
// System.out.println("------------------------------------------------------");
//EXPENSE u1 1000 4 u1 u2 u3 u4 EQUAL
splitwise.addExpense(1000,"EQUAL",user1, new String[]{user1, user2, user3,user4});
splitwise.show(user4);
// System.out.println("------------------------------------------------------");
splitwise.show(user1);
// System.out.println("------------------------------------------------------");
//EXPENSE u1 1250 2 u2 u3 EXACT 370 880
splitwise.addExpense(1250,"EXACT",user1, new String[]{user1, user2, user3}, new Integer[]{0, 370, 880});
splitwise.show();
// System.out.println("------------------------------------------------------");
//EXPENSE u4 1200 4 u1 u2 u3 u4 PERCENT 40 20 20 20
splitwise.addExpense(1200,"PERCENT",user4, new String[]{user1, user2, user3, user4}, new Integer[]{40, 20, 20, 20});
splitwise.show(user1);
// System.out.println("------------------------------------------------------");
splitwise.show();
// System.out.println("------------------------------------------------------");
}

public void test2(){
System.out.println("------------------------------------------------------");
String user1 = splitwise.addUser("User1", "user1@gmail.com", "9986368688");
String user2 = splitwise.addUser("User2", "user2@gmail.com", "9986368689");
String user3 = splitwise.addUser("User3", "user3@gmail.com", "9986368682");
splitwise.show();
// System.out.println("------------------------------------------------------");
splitwise.show(user1);
// System.out.println("------------------------------------------------------");
//EXPENSE u1 1000 4 u1 u2 u3 u4 EQUAL
splitwise.addExpense(1000,"EQUAL",user1, new String[]{user1, user2, user3});
splitwise.show(user3);
// System.out.println("------------------------------------------------------");
splitwise.show(user1);
// System.out.println("------------------------------------------------------");
//EXPENSE u1 1250 2 u2 u3 EXACT 370 880
splitwise.addExpense(1250,"EXACT",user1, new String[]{user1, user2,user3 }, new Integer[]{0, 370, 880});
splitwise.show();
// System.out.println("------------------------------------------------------");
//EXPENSE u4 1200 4 u1 u2 u3 u4 PERCENT 40 20 20 20
splitwise.addExpense(1200,"PERCENT",user3, new String[]{user1, user2, user3}, new Integer[]{60, 20, 20});
splitwise.show(user1);
// System.out.println("------------------------------------------------------");
splitwise.show();
// System.out.println("------------------------------------------------------");
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/sameerpandit/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.sameerpandit;

import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;

public class Main {
public static void main(String[] args){
ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator();
Driver driver = locator.getService(Driver.class);
driver.run();
}
}
38 changes: 38 additions & 0 deletions src/main/java/com/sameerpandit/Splitwise.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.sameerpandit;

import com.sameerpandit.service.ExpenseManagerService;
import com.sameerpandit.service.UserService;

import org.jvnet.hk2.annotations.Service;

import jakarta.inject.Inject;

@Service
public class Splitwise {

@Inject
ExpenseManagerService expenseManagerService;

@Inject
UserService userService;

public String addUser(String name, String email, String phone) {
return userService.addUser(name,email,phone);
}

public void addExpense(Integer amount, String type, String initiatorId, String[] participants){
expenseManagerService.addExpense(amount,type,initiatorId,participants);
}

public void addExpense(Integer amount, String type, String initiatorId, String[] participants, Integer[] splits){
expenseManagerService.addExpense(amount,type,initiatorId,participants,splits);
}

public void show(){
expenseManagerService.show();
}

public void show(String userId){
expenseManagerService.show(userId);
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/sameerpandit/business/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.sameerpandit.business;

public class Constants {
public static Integer PERCENT_SCALE = 100;
public static Integer EXPENSE_SCALING_FACTOR = 100;
}
33 changes: 33 additions & 0 deletions src/main/java/com/sameerpandit/business/EqualSplitStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.sameerpandit.business;

import com.sameerpandit.models.Expense;

import org.jvnet.hk2.annotations.Service;

import jakarta.inject.Named;

@Service
@Named("EQUAL")
public class EqualSplitStrategy implements SplitStrategy{
@Override
public Integer[] split(Expense expense) {
int amountUnScaled = expense.getUnscaledAmount();
int totalParts = (expense.getParticipants().length);
boolean cleanSplit = (amountUnScaled%totalParts == 0);
Integer[] splitAmounts = new Integer[totalParts];
int start = 0;
if(!cleanSplit){
while(amountUnScaled!=0){
int part = amountUnScaled/(totalParts-start);
splitAmounts[start] = part;
amountUnScaled-=part;
start++;
}
}else{
for(;start<splitAmounts.length;start++){
splitAmounts[start] = (amountUnScaled/totalParts);
}
}
return splitAmounts;
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/sameerpandit/business/ExactStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.sameerpandit.business;

import com.sameerpandit.models.Expense;

import org.jvnet.hk2.annotations.Service;

import jakarta.inject.Named;

@Service
@Named("EXACT")
public class ExactStrategy implements SplitStrategy {

@Override
public Integer[] split(Expense expense) {
return expense.getUnscaledSplitAmounts();
}
}
26 changes: 26 additions & 0 deletions src/main/java/com/sameerpandit/business/PercentSplitStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.sameerpandit.business;

import com.sameerpandit.models.Expense;

import org.jvnet.hk2.annotations.Service;

import jakarta.inject.Named;

@Service
@Named("PERCENT")
public class PercentSplitStrategy implements SplitStrategy {
@Override
public Integer[] split(Expense expense) {
int amountUnScaled = expense.getUnscaledAmount();
int totalParts = (expense.getParticipants().length);
Integer[] splitUnscaledPercentages = expense.getSplitPercentages();
Integer[] splitAmounts = new Integer[totalParts];
int total = 0;
for (int i = 0; i < splitAmounts.length; i++) {
splitAmounts[i] = (splitUnscaledPercentages[i] * amountUnScaled) / Constants.PERCENT_SCALE;
total += splitAmounts[i];
}
splitAmounts[0] += (amountUnScaled - total);
return splitAmounts;
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/sameerpandit/business/SplitStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.sameerpandit.business;

import com.sameerpandit.models.Expense;

import org.jvnet.hk2.annotations.Contract;

@Contract
public interface SplitStrategy {
public Integer[] split(Expense expense);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.sameerpandit.business.validator;

public class ExpenseConfigurationValidator {
}
82 changes: 82 additions & 0 deletions src/main/java/com/sameerpandit/db/InMemRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.sameerpandit.db;

import com.sameerpandit.models.Expense;
import com.sameerpandit.models.Transaction;
import com.sameerpandit.models.User;

import org.jvnet.hk2.annotations.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import jakarta.inject.Singleton;

@Service
@Singleton
public class InMemRepository {
private ConcurrentHashMap<String, List<Transaction>> creditorMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, List<Transaction>> debitorMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, User> userMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, List<Expense>> expenseInitiatorMap = new ConcurrentHashMap<>();
private AtomicInteger userIdNumber = new AtomicInteger(0);

public void clear(){
creditorMap = new ConcurrentHashMap<>();
debitorMap = new ConcurrentHashMap<>();
userMap = new ConcurrentHashMap<>();
expenseInitiatorMap = new ConcurrentHashMap<>();
userIdNumber = new AtomicInteger(0);
}

public List<Transaction> getCreditTransactionsByUserId(String userId) {
return creditorMap.getOrDefault(userId, new LinkedList<>());
}

public List<Transaction> getDebitTransactionsByUserId(String userId) {
return debitorMap.getOrDefault(userId, new LinkedList<>());
}

public List<Expense> getExpensesInitiatedByUserId(String userId) {
return expenseInitiatorMap.get(userId);
}

public User getUserDetailsById(String userId) {
return userMap.get(userId);
}

public List<User> getUsers(){
LinkedList<User> users = new LinkedList<>();
users.addAll(userMap.values());
return users;
}

public String addUser(String name, String email, String phone) {
String userId = "u" + userIdNumber.incrementAndGet();
userMap.put(userId, new User(userId, name, email, phone));
return userId;
}

public Expense addExpense(Integer amount, String type, String initiatorId, String[] participants) {
Expense expense = new Expense(amount, type, initiatorId, participants);
expenseInitiatorMap.computeIfAbsent(initiatorId, k -> new LinkedList<>()).add(expense);
return expense;
}

public Expense addExpense(Integer amount, String type, String initiatorId, String[] participants, Integer[] splits) {
Expense expense = new Expense(amount, type, initiatorId, participants,splits);
expenseInitiatorMap.computeIfAbsent(initiatorId, k -> new LinkedList<>()).add(expense);
return expense;
}


public void addCreditorTransaction(String creditorId, Transaction tx) {
creditorMap.computeIfAbsent(creditorId, k -> new LinkedList<>()).add(tx);
}

public void addDebitorTransaction(String debitorId, Transaction tx) {
debitorMap.computeIfAbsent(debitorId, k -> new LinkedList<>()).add(tx);
}

}
Loading