Test 17 - Build a Budget App - Python - Failure

Tell us what’s happening:

I have been working through the build a budget app project in the python course, however I’ve come to a halt where I can’t pass through test17, through testing, when I try and return the string after calling get_percentages(categories), it raises the failure, returning before works fine. P.S I am aware I haven’t completed the rest of the tests past the percentages part.

Your code so far

class Category:
    def __init__(self, name):
        self.name = name
        self.ledger = []
        self.total_spent = 0

    def get_balance(self):
        balance = 0
        for receipt in self.ledger:
            amount = round(receipt['amount'], 2)
            balance += amount
        
        return balance

    def check_funds(self, amount):
        if self.get_balance() - amount < 0.00:
            return False
        else:
            return True
        
    def deposit(self, amount, desc=""):
        receipt = {
            'amount': round(amount, 2),
            'description': desc
        }
        self.ledger.append(receipt)

    def withdraw(self, amount, desc=""):
        if self.check_funds(amount) == True:    
            receipt = {
                'amount': round(-amount, 2),
                'description': desc
            }
            self.ledger.append(receipt)
            return True
        else:
            return False

    def transfer(self, amount, recipient):
        withdraw_desc = f'Transfer to {recipient.name}'

        if self.withdraw(amount, withdraw_desc) == True:
            deposit_desc = f'Transfer from {self.name}'
            recipient.deposit(amount, deposit_desc)
            return True

        else:
            return False
        

        
    def __str__(self):
        category_summary = ''
        bound_1 = (30 - len(self.name)) // 2
        if bound_1 * 2 + len(self.name) == 30:
            bound_2 = bound_1
        else:
            bound_2 = bound_1 + 1

        header = '*' * bound_1 + self.name + '*' * bound_2 + '\n'
        category_summary += f'{header:^}'
        for receipt in self.ledger:

            desc = receipt["description"]
            desc = desc[:23]
            amount = receipt["amount"]
            amount = f'{amount:.2f}'
            desc_to_end = 30 - len(amount) - len(desc) 
            

            category_summary += f'{desc}' + ' '*desc_to_end +  f'{amount}\n'
        category_summary += f"Total: {self.get_balance()}"

        return category_summary


def sum_totals(catergories):
    for category in categories:
        category_total = 0
        
        for receipt in category.ledger:
            amount = receipt['amount']
            if amount < 0.00:
                category_total += -amount
        
        category.total_spent = round(category_total, 2)

def get_percentages(categories):
    total_expenses = 0
    percentages = []
    for cat in categories:
        total_expenses += cat.total_spent
    for cat in categories:
        percentage = round(cat.total_spent / total_expenses * 100,-1)
        percentage = int(percentage)
        percentages.append(percentage)
    
    return percentages


def create_spend_chart(categories):
    bar_chart_string = 'Percentage spent by category\n'
    sum_totals(categories)
    y_axis_string = ''
    x_axis_string = ''

    percentages = get_percentages(categories)
    
    
    for x in range(100, -10, -10):
        digits = len(str(x))
        y_axis_string += ' ' * (3 - digits) + str(x) + '|' + ' '
        for p in percentages:
            if x <= p:
                y_axis_string += 'o  '
            else:
                y_axis_string += '   '

        y_axis_string += '\n'

    

    bar_chart_string += y_axis_string
    return bar_chart_string

                

food = Category('Food')
food.deposit(1000, 'initial deposit')
food.withdraw(10.15, 'groceries')
food.withdraw(15.89, 'restaurant and more food for dessert')

clothing = Category('Clothing')
travel = Category('Travel')
travel.deposit(500, 'Travel allowance')
travel.withdraw(29.99, 'Train ticket')
food.transfer(50, clothing)

categories = []
categories.append(food)
categories.append(clothing)
categories.append(travel)
print(create_spend_chart(categories))

print(food)

Lesson URL (copy - paste from your browser’s address bar)

Welcome to the forum @EvanJrDev,

Please post a link to this challenge.

In the future, when you have a question, please use the “Help” button, which will send us your formatted code and a link to the challenge.

Happy coding

Please check your browser’s console. You have a “Division by Zero” error here:

Also, round will not give you the correct percentage. In the instructions it says:

The percentage should be the percentage of the amount spent for each category to the total spent for all categories (rounded down to the nearest 10).

That means if your total withdrawals for a category divided by total withdrawals for all categories totals $29.17, the percentage would be 20.

Happy coding

Wow, I can’t believe I missed that zero error! Thanks so much!
I will remember to use the ‘Help’ button next time.

Tell us what’s happening:

Test 19 is failing, but I’m sure I have rounded down to the nearest 10 (line 117) for each percentage before appending to my bar chart strings. Any help would be greatly appreciated, thanks.

Your code so far

class Category:
    def __init__(self, name):
        self.name = name
        self.ledger = []
        self.total_spent = 0

    def get_balance(self):
        balance = 0
        for receipt in self.ledger:
            amount = round(receipt['amount'], 2)
            balance += amount
        
        return balance

    def check_funds(self, amount):
        if self.get_balance() - amount < 0.00:
            return False
        else:
            return True
        
    def deposit(self, amount, desc=""):
        receipt = {
            'amount': round(amount, 2),
            'description': desc
        }
        self.ledger.append(receipt)

    def withdraw(self, amount, desc=""):
        if self.check_funds(amount) == True:    
            receipt = {
                'amount': round(-amount, 2),
                'description': desc
            }
            self.ledger.append(receipt)
            return True
        else:
            return False

    def transfer(self, amount, recipient):
        withdraw_desc = f'Transfer to {recipient.name}'

        if self.withdraw(amount, withdraw_desc) == True:
            deposit_desc = f'Transfer from {self.name}'
            recipient.deposit(amount, deposit_desc)
            return True

        else:
            return False
        

        
    def __str__(self):
        category_summary = ''
        bound_1 = (30 - len(self.name)) // 2
        if bound_1 * 2 + len(self.name) == 30:
            bound_2 = bound_1
        else:
            bound_2 = bound_1 + 1

        header = '*' * bound_1 + self.name + '*' * bound_2 + '\n'
        category_summary += f'{header:^}'
        for receipt in self.ledger:

            desc = receipt["description"]
            desc = desc[:23]
            amount = receipt["amount"]
            amount = f'{amount:.2f}'
            desc_to_end = 30 - len(amount) - len(desc) 
            

            category_summary += f'{desc}' + ' '*desc_to_end +  f'{amount}\n'
        category_summary += f"Total: {self.get_balance()}"

        return category_summary


def sum_totals(catergories):
    for category in categories:
        category_total = 0
        
        for receipt in category.ledger:
            amount = receipt['amount']
            if amount < 0.00:
                category_total += -amount
        
        category.total_spent = round(category_total, 2)

def get_percentages(categories):
    total_expenses = 0
    percentages = []
    for cat in categories:
        total_expenses += cat.total_spent
    for cat in categories:
        if cat.total_spent == 0:
            percentage = 0
        else:
            percentage = round((cat.total_spent / total_expenses) * 100, 2)
        percentages.append(percentage)
    
    return percentages


def create_spend_chart(categories):
    bar_chart_string = 'Percentage spent by category\n'
    sum_totals(categories)
    y_axis_string = ''
    x_axis_string = ''

    percentages = get_percentages(categories)
    
    for x in range(100, -10, -10):
        digits = len(str(x))
        y_axis_string += ' ' * (3 - digits) + str(x) + '|' + ' '
        for p in percentages:
            p = (p // 10) * 10
            print(p)
            
            if x <= p:
                y_axis_string += 'o  '
            else:
                y_axis_string += '   '

        y_axis_string += '\n'

    

    bar_chart_string += y_axis_string
    return bar_chart_string

                

food = Category('Food')
food.deposit(1000, 'initial deposit')
food.withdraw(10.15, 'groceries')
food.withdraw(15.89, 'restaurant and more food for dessert')

clothing = Category('Clothing')
travel = Category('Travel')
travel.deposit(500, 'Travel allowance')
travel.withdraw(29.99, 'Train ticket')
food.transfer(50, clothing)

categories = []
categories.append(food)
categories.append(clothing)
categories.append(travel)
print(create_spend_chart(categories))

print(food)

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36

Challenge Information:

Build a Budget App - Build a Budget App

GitHub Link: freeCodeCamp/curriculum/challenges/english/blocks/lab-budget-app/5e44413e903586ffb414c94e.md at main · freeCodeCamp/freeCodeCamp · GitHub

I went ahead and combined your posts for you. In the future, just reply to the original thread to add further updates.

Please review my previous post about this:

I am not sure the tests are able to test an half done chart, please add also the bottom half

Thanks, I’ll continue with the rest then.