Tell us what’s happening:
The code works perfectly fine and the outputs match exactly (from what I can tell) what it’s asking for, yet no matter what, I’m still getting the same two failures from freecodecamp saying:
“Failed: Printing a Category instance should give a different string representation of the object.
Failed: create_spend_chart should print a different chart representation. Check that all spacing is exact.”
Anyone have any ideas on how to fix it? I have also tried calling and not calling the functions. Many thanks!
Your code so far
class Category:
def __init__(self,name):
self.name = name # Name, so like 'food'
self.ledger = [] # List of all expenses
self.withdrawls = []
def __str__(self):
# Writes the title
budget = ''
star_length = 30 - len(self.name)
left_side = (star_length // 2) + (star_length % 2) # Finds one length, and adds the remainder so that the length of the title adds to 30 characters
right_side = star_length - left_side
# Adds the stars to the string
for star in range(left_side):
budget += '*'
budget += self.name
for star in range(right_side):
budget += '*'
for expense in self.ledger:
spaces = ''
description = expense['description']
amount = round(expense['amount'],2)
# Truncates the strings
new_desc = self.truncate_string(description,23)
new_amnt = self.truncate_string(str(amount),7)
space_length = 30 - (len(new_desc) + len(new_amnt))
# Adds spaces
for space in range(space_length):
spaces += ' '
# Adds line to the string
budget += f'\n{new_desc}{spaces}{new_amnt}'
# Repeats previous steps except for the total line
spaces = ''
total_amnt = str(round(self.get_balance(),2))
space_length = 30 - (len('Total: ') + len(total_amnt))
for space in range(space_length):
spaces += ' '
total = f'\nTotal: {spaces}{total_amnt}'
budget += total
return budget
# Truncates strings over a certain length
def truncate_string(self,string,length):
return string[:length]
def get_balance(self):
total_budget = 0 # Resets the total budget
for expenses in self.ledger:
total_budget += expenses['amount']
return total_budget
# Checks if there are enough funds
def check_funds(self,amount):
if amount > self.get_balance():
return False
else:
return True
def deposit(self,amount,description=''):
expense = {'amount': amount, 'description': description} # Formats it into a dictionary
self.ledger.append(expense) # Adds the expense to the ledger list
def withdraw(self,amount,description=''):
if self.check_funds(amount): # If there is enough money
expense = {'amount': -amount, 'description': description} # Formats it into a dictionary
self.ledger.append(expense) # Adds the expense to the ledger list
self.withdrawls.append(expense)
return True
else:
return False
def transfer(self,amount,category):
if self.check_funds(amount): # If there is enough money for transfer
self.withdraw(amount, f'Transfer to {category.name}')
category.deposit(amount, f'Transfer from {self.name}')
return True
else:
return False
def create_spend_chart(categories):
total_spent = 0
spent_by_category = {}
percentage_by_category = {}
categories_list = []
line1 = '100|'
line2 = ' 90|'
line3 = ' 80|'
line4 = ' 70|'
line5 = ' 60|'
line6 = ' 50|'
line7 = ' 40|'
line8 = ' 30|'
line9 = ' 20|'
line10 = ' 10|'
line11 = ' 0|'
line12 = ' '
for category in categories:
categories_list.append(category.name)
# Finds the total and individual expendature
category_spent = 0
for withdrawl in category.withdrawls: # For each withdrawl in the list
category_spent += withdrawl['amount'] # Totals it
total_spent += category_spent # Adds the total the the total_spent
spent_by_category[category.name] = category_spent # Assings the category and amount spent to a dictionary for later use
max_length = len(max(categories_list, key=len)) # Finds the category with the longest name length
name_lines = [' ' for _ in range(max_length)] # Lines for the names of the categories
for category in categories: # Must let the previous code run for all categories before this
# Adds the names into a list per each line and adds spaces
for i in range(max_length):
if i < len(category.name):
name_lines[i] += f' {category.name[i]}'
else:
name_lines[i] += ' '
# Finds the percentage of each category, and rounds it down to the nearest 10 using integer division
percentage = ((((spent_by_category[category.name] / total_spent) * 100) // 10) *10)
percentage_by_category[category.name] = percentage
# Creates the bar chart
if category == categories[0]:
spaces = ' '
else:
spaces = ' '
if percentage_by_category[category.name] == 100:
line1 += f'{spaces}o'
if percentage_by_category[category.name] >= 90:
line2 += f'{spaces}o'
if percentage_by_category[category.name] >= 80:
line3 += f'{spaces}o'
if percentage_by_category[category.name] >= 70:
line4 += f'{spaces}o'
if percentage_by_category[category.name] >= 60:
line5 += f'{spaces}o'
if percentage_by_category[category.name] >= 50:
line6 += f'{spaces}o'
if percentage_by_category[category.name] >= 40:
line7 += f'{spaces}o'
if percentage_by_category[category.name] >= 30:
line8 += f'{spaces}o'
if percentage_by_category[category.name] >= 20:
line9 += f'{spaces}o'
if percentage_by_category[category.name] >= 10:
line10 += f'{spaces}o'
if percentage_by_category[category.name] >= 0:
line11 += f'{spaces}o'
line12 += '---'
line0 = 'Percentage spent by category'
line12 = f'{line12}-'
name_lines = '\n'.join(name_lines)
return f'{line0}\n{line1}\n{line2}\n{line3}\n{line4}\n{line5}\n{line6}\n{line7}\n{line8}\n{line9}\n{line10}\n{line11}\n{line12}\n{name_lines}'
Your browser information:
User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6.1 Safari/605.1.15
Challenge Information:
Build a Budget App Project - Build a Budget App Project