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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.idea/
*.pyc
venv/
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
# mock-machine-coding-2
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.

61 changes: 61 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# coding=utf-8
# This is a sample Python script.

# Press ⇧F10 to execute it or replace it with your code.
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
from models.user_ledger import Ledger
from splitwise import SplitWise
from models.user import User


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
splitwise = SplitWise()
'''
Creating Users
'''
u1 = User('Ram', 'ram@gmail.com', 1234567890)
u2 = User('Shyam', 'shyam@gmail.com', 9876543211)
u3 = User('Ghanshyam', 'ghanshyam@gmail.com', 432167890)
u4 = User('shyamshan', 'sh@gmail.com', 43216781290)

'''
Creating ledger entry for each User.
'''
Ledger.crate_ledger_entry(u1, [u2, u3, u4])
Ledger.crate_ledger_entry(u2, [u1, u3, u4])
Ledger.crate_ledger_entry(u3, [u1, u2, u4])
Ledger.crate_ledger_entry(u4, [u1, u2, u3])

'''
Mapping username with object.
'''
user_obj = {"u1": u1, "u2": u2, "u3": u3, "u4": u4}

'''
Start Taking input from here.
'''

while 1:
command = str(raw_input("Enter your input"))
command = command.split(' ')
users = []
split_amount = []

if command[0] == 'EXPENSE':
paid_by = user_obj[command[1]]
total_amount = float(command[2])
total_users = int(command[3])
for i in range(0, total_users):
users.append(user_obj[command[i + 4]])
split_type = command[total_users + 4]

if split_type in ['PERCENT', 'EXACT']:
for i in range(0, total_users):
split_amount.append(float(command[total_users + 5 + i]))
splitwise.add_expense(paid_by, total_amount, users, split_type, split_amount=split_amount)

elif command[0] == "SHOW" and len(command) > 1:
splitwise.show_balance_by_userid(command[1])
else:
splitwise.show_all_balances()
Empty file added models/__init__.py
Empty file.
Empty file added models/expense/__init__.py
Empty file.
16 changes: 16 additions & 0 deletions models/expense/equal_expense.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from models.expense.expense import Expense
from models.user_ledger import Ledger
from utils.utils import is_approx


class EqualExpense(Expense):
def __init__(self, users, total_amount, paid_by, **kwargs):
Expense.__init__(self, total_amount, paid_by, kwargs.get('name'), kwargs.get('note'))
self.users = users
self.amount = total_amount / len(users)
self.update_ledger()

def update_ledger(self):
for i in self.users:
if i.id != self.paid_by.id:
Ledger.update_ledger(self.paid_by, i, self.amount)
23 changes: 23 additions & 0 deletions models/expense/exact_expense.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from models.expense.expense import Expense
from models.user_ledger import Ledger
from utils.utils import is_approx


class ExactExpense(Expense):
def __init__(self, users, total_amount, paid_by, amount_list, **kwargs):
Expense.__init__(self, total_amount, paid_by, kwargs.get('name'), kwargs.get('note'))
self.users = users
self.amount_list = amount_list
self.update_ledger()

def update_ledger(self):
for i in range(0, len(self.users)):
if not self.users[i].id == self.paid_by.id:
Ledger.update_ledger(self.paid_by, self.users[i], self.amount_list[i])

@staticmethod
def validate(total_amount, amounts_list):
sum_amount = 0
for amount in amounts_list:
sum_amount += amount
return is_approx(sum_amount, total_amount)
27 changes: 27 additions & 0 deletions models/expense/expense.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from abc import ABCMeta, abstractmethod


class Expense:
id_count = 0
user_expense = {}
settled = False

def __init__(self, total_amount, paid_by, note, name):
self.id = Expense.id_count
Expense.id_count += 1
self.name = name
self.paid_by = paid_by
self.total_amount = total_amount
self.note = note

@abstractmethod
def update_ledger(self):
pass

def mark_as_settled(self):
self.settled = True

@staticmethod
@abstractmethod
def validate(total_amount, split_amount):
pass
21 changes: 21 additions & 0 deletions models/expense/percentage_expense.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from models.expense.expense import Expense
from models.user_ledger import Ledger
from utils.utils import is_approx


class PercentageExpense(Expense):
def __init__(self, users, total_amount, paid_by, percentages, **kwargs):
Expense.__init__(self, total_amount, paid_by, kwargs.get('name'), kwargs.get('note'))
self.users = users
self.percentage = percentages
self.update_ledger()

def update_ledger(self):
for i in range(0, len(self.users)):
if not self.users[i].id == self.paid_by.id:
amount = self.total_amount * (1 - self.percentage[i] / 100)
Ledger.update_ledger(self.paid_by, self.users[i], amount)

@staticmethod
def validate(total_amount, percentages):
return is_approx(sum(percentages), 100)
23 changes: 23 additions & 0 deletions models/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class User:
id_count = 0

def __init__(self, name, email, mobile_no):
self.id = User.id_count
User.id_count += 1
self.name = name
self.email = email
self.mobile_no = mobile_no
self.total_balance = 0
self.total_expense = 0

def get_total_balance(self):
return self.total_balance

def update_total_balance(self, amount):
self.total_balance += amount

def get_total_expense(self):
return self.total_balance

def update_total_expense(self, amount):
self.total_expense += amount
49 changes: 49 additions & 0 deletions models/user_ledger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
class Ledger:
def __init__(self):
pass
'''
{u1 :{u2:-50}
{u2 :{u1:50}
'''
transaction_entry = {}

@staticmethod
def crate_ledger_entry(user, users):
Ledger.transaction_entry[user.id] = {}
for u in users:
Ledger.transaction_entry[user.id][u.id] = 0


@staticmethod
def update_ledger(paid_by, user, amount):
if paid_by.id in Ledger.transaction_entry.keys():
Ledger.transaction_entry[paid_by.id][user.id] -= round(amount, 2)
Ledger.transaction_entry[user.id][paid_by.id] += round(amount, 2)
else:
print("No Account for this user")

@staticmethod
def get_user_balance(user_id):
flag=0
if Ledger.transaction_entry.get(user_id):
ledger = Ledger.transaction_entry[user_id]
for id in ledger:
if ledger[id] > 0:
print "User ", user_id, " owes ", ledger[id], "rupees to ", user_id
flag=1
if flag==0:
print("No Balance")

@staticmethod
def get_all_balances():
flag = 0
if Ledger.transaction_entry:
for user in Ledger.transaction_entry:
transactions = Ledger.transaction_entry.get(user)
if transactions:
for key, val in transactions.items():
if val<0:
print "User ", key, " owes ", abs(val), "rupees to ", user
flag = 1
if flag == 0:
print("NO BALANCE")
29 changes: 29 additions & 0 deletions splitwise.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from models.expense.equal_expense import EqualExpense
from models.expense.exact_expense import ExactExpense
from models.expense.percentage_expense import PercentageExpense
from models.user_ledger import Ledger


class SplitWise:
def __init__(self):
self.expenses = []
self.user_ledgers = {}

def add_expense(self, paid_by, total_paid_amount, users, split_type, **kwargs):
if split_type == 'EQUAL':
expense = EqualExpense(users, total_paid_amount, paid_by)
elif split_type == 'PERCENT' and PercentageExpense.validate(total_paid_amount, kwargs.get('split_amount')):
expense = PercentageExpense(users, total_paid_amount, paid_by, kwargs.get('split_amount'))
elif split_type == 'EXACT' and ExactExpense.validate(total_paid_amount, kwargs.get('split_amount')):
expense = ExactExpense(users, total_paid_amount, paid_by, kwargs.get('split_amount'))
else:
print("Unknown split type.")
return
self.expenses.append(expense)
print("Expense Added successfully!")

def show_balance_by_userid(self, user_id):
Ledger.get_user_balance(int(user_id))

def show_all_balances(self):
Ledger.get_all_balances()
Empty file added utils/__init__.py
Empty file.
2 changes: 2 additions & 0 deletions utils/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def is_approx(a, b):
return int(a * 100) == int(b * 100)