# Scientific Computing with Python Projects - Budget App

Hello everybody!
I have a serious problem with this exercise, I succeeded all the tests but when I test with my own tests it does not work.
The problem is at the level of the last function, in the test everything is ok but when I try it with the code for the exercise all the lines are offset from a space except line 0.
I would be very grateful to you to enlighten me on this problem which seems to me to be like magic …

link to the code “boilerplate-budget-app - Replit

My code :

``````import math
class Category:
def __init__(self, name):
self.name = name
self.ledger = []

def __str__(self):
# line 1
name = str(self.name)
len_name = len(name)
stars = '*' * int((30 - len_name) / 2)
line_1 = stars + name + stars + '\n'
# line 2
line_2 = ''
for operation in self.ledger:
description_str = operation['description'][0:23]
amount_str = "{:.2f}".format(operation['amount'])[:7]
len_description = len(description_str)
len_amount = len(amount_str)
space = 30 - len_description - len_amount
line_2 += description_str + (' ' * space) + amount_str + '\n'
# line 3
line_3 = 'Total: ' + str(self.get_balance())
# result
result = line_1 + line_2 + line_3
return str(result)

def deposit(self, amount, description=''):
self.ledger.append({'amount': amount, 'description': description})

def withdraw(self, amount, description=''):
fund_enough = self.check_funds(amount)
if not fund_enough:
return False
else:
self.ledger.append(
{'amount': - amount, 'description': description})
return True

def get_balance(self):
total = 0
for operation in self.ledger:
# print(operation)
total += operation['amount']

def transfer(self, amount, category):
fund_enough = self.check_funds(amount)
if not fund_enough:
return False
else:
self.withdraw(amount, 'Transfer to ' + str(category.name))
category.deposit(amount, 'Transfer from ' + str(self.name))
return True

def check_funds(self, amount):
total = self.get_balance()
if total - amount < 0:
return False
else:
return True

def create_spend_chart(categories):
line_4 = ''
list_name = []
len_category = 0
for category in categories:
name = str(category.name)
list_name.append(name)
if len(name) > len_category:
len_category = len(name)
# calcul percentage
arr_only_depenses = []
for category in categories:
arr_only_depenses.append(get_only_depenses(category))
# print('arr_only_depenses: ', arr_only_depenses)

total_only_depenses = 0
for depense in arr_only_depenses:
total_only_depenses += abs(depense)

# print('total_only_depenses: ', total_only_depenses)

arr_percentage = []
for category in categories:
depense_positif = abs(get_only_depenses(category))
percentage = depense_positif / total_only_depenses * 100
percentage_round = math.floor(percentage / 10) * 10
arr_percentage.append(percentage_round)

print('arr_percentage: ', arr_percentage)

# line1
line_1 = 'Percentage spent by category' + '\n'
# line_2
line_2 = ''
i = 110
max_len = (len(list_name) * 3) + 1
print('max_len: ', max_len)
while i > 0:
i -= 10
space_before_calcul = abs(int(len(str(i))) - 3)
space_before = '*' * space_before_calcul
space_after = '*' * max_len
line_actuel = space_before + str(i) + '|' + space_after + '\n'
print('line_actuel: ', line_actuel)

for j, percentage in enumerate(arr_percentage):
if i <= percentage:
arr_line_actuel = line_actuel.split('*')
print('arr_line_actuel: ', arr_line_actuel)
calcul = 3 + (j*2)
print('j: ', j)
print('calcul: ', calcul, i)
arr_line_actuel[calcul] = 'o'
arr_line_actuel.pop(-3)
# print('arr_line_actuel: ', arr_line_actuel)
line_actuel = '*'.join(arr_line_actuel)
# print('line_actuel: ', line_actuel)
line_actuel = line_actuel.replace('*', ' ')
line_2 += line_actuel
# line_3
len_categories = len(categories)
# print('len_categories: ', len_categories)
dash = '-' * ((len_categories * 3) + 1)
# print('dash: ', dash)
line_3 = '    ' + dash

i = 0
for character in range(len_category):
line_5 = ''
for name in list_name:
space = ' ' * list_name.index(name)
# print('space: ', space)
if len(name) > i:
line_5 += ' ' + name[i] + ' '
else:
line_5 += '   '
line_4 += '\n' + '    ' + line_5 + ' '
i += 1

# result
result = line_1 + line_2 + line_3 + line_4
return str(result)

def get_only_depenses(category):
only_depenses = 0
for operation in category.ledger:
# print(operation)
if operation['amount'] < 0:
only_depenses += operation['amount']
return only_depenses
``````

Challenge: Scientific Computing with Python Projects - Budget App

What tests are you using that seem not to work?

This is pretty interesting. I see in the part composing the line there’s splitting, assigning, popping and replacing, while having at the beginning percent indication. If the `o` character is being written to a specific index, what is being popped off (also why the 3rd character from the end?) and why? That’s a bit complicated and introducing many moving and not moving parts.

Try to simplify it and limit number of things that can affect specific point of line composing. For example, the percent indication and new line character could be added only after the part of the line with bars is completed.

In the exercise given there is a main.py file with an example, it is this one that does not work (i.e. all the 'o’s in the lines are shifted by 1 space except line 0).

Here is the code that is in main.py:

``````food = budget.Category("Food")

food.deposit(1000, "initial deposit")

food.withdraw(10.15, "groceries")

food.withdraw(15.89, "restaurant and more food for dessert")

# print(food.get_balance())

clothing = budget.Category("Clothing")

food.transfer(50, clothing)

clothing.withdraw(25.55)

clothing.withdraw(100)

auto = budget.Category("Auto")

auto.deposit(1000, "initial deposit")

auto.withdraw(15)

# print(food)

# print(clothing)

print(create_spend_chart([food, clothing, auto]))
``````

Thank you for your reply. You are right pop(-2) is enough on the other hand I cannot understand why in the exercise and in the tests the results are different.
I think I could rewrite this code differently so that there is no longer this problem but I would like to understand this “magic”.

It’s not really magic, it’s a bug lurking somewhere in the code. Or few of them, each one impacting the output in a little way. So it’s not that easy to point to a single place and say this is the reason. The less complexity, the easier is to do that.