This is from: https://www.freecodecamp.org/learn/scientific-computing-with-python/scientific-computing-with-python-projects/budget-app
Hi there, it might be me missing something so i’m sorry if it’s my mistake.
This function is supposed to return the percentage of the spent amount, rounded to nearest 10 multiple, for example 55 rounds to 60, 54 to 50.
In this case we have 900$ initially and then spend 105.55$, so as I understood the percentage should be (105.55 / 900) * 100 = ~12% which would round to 10%.
And in the unit test it says the expected result in this one is for the spent percentage to be rounded to 70%…
There is also another case like this one, on the same test.
If you could check it I would be very grateful.
I will leave my code below, and after the unit test:
import math
class Category:
def __init__(self, name):
self.name = name
self.ledger = []
def getname(self):
return self.name
def getledger(self):
return self.ledger
def deposit(self, amount, description=""):
self.ledger.append({"amount": amount, "description": description})
def withdraw(self, amount, description=""):
if self.check_funds(amount) == False:
return False
else:
self.ledger.append({"amount": -amount, "description": description})
return True
def get_balance(self):
balance = 0
for movement in self.getledger():
balance += movement["amount"]
return balance
def get_spent_percentage(self):
gain = 0
for movement in self.getledger():
gain += movement["amount"] if movement["amount"] > 0 else 0
return math.floor( 10 - ((self.get_balance() / gain) * 10)) * 10
def transfer(self, amount, other_budget):
if self.check_funds(amount):
self.withdraw(amount, f"Transfer to {other_budget.getname()}")
other_budget.deposit(amount, f"Transfer from {self.getname()}")
return True
else:
return False
def check_funds(self, amount):
if amount > self.get_balance():
return False
else:
return True
def __str__(self):
s = ''
s += f"*************{self.getname()}*************\n"
for move in self.getledger():
desc = move["description"]
amnt = move["amount"]
#lim = 23 if len(move["description"]) > 23
s += f"{desc[:23] :23}"
s += f"{amnt :7.2f}\n"
s += f"Total: {self.get_balance()}"
return s
def create_spend_chart(categories):
s = "Percentage spent by category\n"
spent_percentages = [cat.get_spent_percentage() for cat in categories]
sep = ' '
for i in range(100, -1, -10):
s += f"{i :>3}|"
for z in range(0, len(categories)):
s += sep
s += "o" if spent_percentages[z] >= i else sep
s += sep
s += f'{sep}\n'
s += f' {"---" * len(categories)}--\n'
for n in range(max([len(cat.getname()) for cat in categories])):
s += f"{sep :>5}"
for cat in categories:
s += sep
s += cat.getname()[n] if len(cat.getname()) - 1 >= n else sep
s += sep
s += f'\n'
return s
This is the unit test (each of the self objects is a Category object):
def test_create_spend_chart(self):
self.food.deposit(900, "deposit")
self.entertainment.deposit(900, "deposit")
self.business.deposit(900, "deposit")
self.food.withdraw(105.55)
self.entertainment.withdraw(33.40)
self.business.withdraw(10.99)
actual = create_spend_chart([self.business, self.food, self.entertainment])
expected = "Percentage spent by category\n100| \n 90| \n 80| \n 70| o \n 60| o \n 50| o \n 40| o \n 30| o \n 20| o o \n 10| o o \n 0| o o o \n ----------\n B F E \n u o n \n s o t \n i d e \n n r \n e t \n s a \n s i \n n \n m \n e \n n \n t "
self.assertEqual(actual, expected, 'Expected different chart representation. Check that all spacing is exact.')
As you can see on the expected variable in the unit test, it has a ‘o’ on the 70, related to the food object. Which is the example i cited in the beginning.