Build a Budget App - Build a Budget App - Step 19

Tell us what’s happening:

I can’t seem to get Step 19 to pass. The output looks good, the percentages are rounded down to the nearest 10. Can anyone help out? Thanks!

Your code so far

total_spent = 0 ; 

class Category:
    def __init__(self, name):
        self.name = name
        self.ledger = []
        self.spent = 0
    
    def deposit(self, amount, description=''):
        self.ledger.append({'amount': amount, 'description': description})

    def withdraw(self, amount, description=''):
        global total_spent
        if self.check_funds(amount):
            self.ledger.append({'amount': -amount, 'description': description})
            self.spent += amount
            total_spent += amount
            return(True)              
        else: 
            return(False)

    def get_balance(self):
        balance = 0
        for transaction in self.ledger:
            balance += transaction['amount']
        return(balance)

    def transfer(self, amount, other_cat):      
        if self.check_funds(amount) == True:
            self.ledger.append({'amount': -amount, 'description': f"Transfer to {other_cat.name}"})
            other_cat.ledger.append({'amount': amount, 'description': f"Transfer from {self.name}"})            
            return(True)                    
        else: 
            return(False)


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

    def __str__(self):
        self.stars_left = round((30 - len(self.name)) / 2) ;
        self.stars_right = round((30 - len(self.name)) / 2) ;
        self.title_line = '*' * self.stars_left + self.name + '*' * self.stars_right + '\n'
        ledger_contents = ''
        for transaction in self.ledger:
            if "." in str(transaction['amount']):
                amount = str(transaction['amount'])
            else:
                amount = str(transaction['amount']) + '.00'  
            if len(transaction['description']) >= 23:
                description = transaction['description'][:23]
                spaces = 7 - len(amount)
            else:
                description = transaction['description']
                spaces = 30 - len(description) - len(amount)
            ledger_contents += description + " " * spaces + amount + "\n"
        return self.title_line + ledger_contents + "Total: " + str(self.get_balance())

def create_spend_chart(categories):
    lines = 'Percentage spent by category\n'
    nb_cat = len(categories)
    for i in range(100,-10,-10):
        current_line = str(i).rjust(3) + "|"
        for cat in categories:
            perc = 100 * cat.spent / total_spent
            perc = int(perc/10) * 10
            if i == 0:
                current_line += " o "
            elif (perc > 0 and perc % i == 0) or perc >=i:
                current_line += " o "
            else:
                current_line += "   "
        lines += current_line + '\n'
    lines += "    " + "_"* nb_cat * 3 + "_\n"
    max_cat_length = 0
    for cat in categories:
        if len(cat.name) > max_cat_length:
            max_cat_length = len(cat.name)

    for i in range(0, max_cat_length):
        current_line = '    '
        for cat in categories:
            if len(cat.name) >= i+1 :
                current_line += ' ' + cat.name[i] + ' '
            else:
                current_line += '   '
        lines += current_line + '\n'
    return lines
    



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')
clothing.deposit(300, 'pay day')
clothing.withdraw(158.39, "new outfit")
food.transfer(50, clothing)
print(food)
print('')
print(create_spend_chart([food, clothing]))

Your browser information:

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

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

Try using hyphens rather than underscores for the chart’s horizontal line.

I replaced the underscores with hyphens but Step 19 still doesn’t pass

Have you taken transfers into consideration for the withdrawals?

I didn’t because I didn’t seem like transfers were “spent” money. I’ve included transfers as spent money, and Step 19 still doesn’t pass

total_spent = 0 ; 

class Category:
    def __init__(self, name):
        self.name = name
        self.ledger = []
        self.spent = 0
    
    def deposit(self, amount, description=''):
        self.ledger.append({'amount': amount, 'description': description})

    def withdraw(self, amount, description=''):
        global total_spent
        if self.check_funds(amount):
            self.ledger.append({'amount': -amount, 'description': description})
            self.spent += amount
            total_spent += amount
            return(True)              
        else: 
            return(False)

    def get_balance(self):
        balance = 0
        for transaction in self.ledger:
            balance += transaction['amount']
        return(balance)

    def transfer(self, amount, other_cat):      
        global total_spent
        if self.check_funds(amount) == True:
            self.ledger.append({'amount': -amount, 'description': f"Transfer to {other_cat.name}"})
            other_cat.ledger.append({'amount': amount, 'description': f"Transfer from {self.name}"})
            self.spent += amount   
            total_spent += amount         
            return(True)                    
        else: 
            return(False)


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

    def __str__(self):
        self.stars_left = round((30 - len(self.name)) / 2) ;
        self.stars_right = round((30 - len(self.name)) / 2) ;
        self.title_line = '*' * self.stars_left + self.name + '*' * self.stars_right + '\n'
        ledger_contents = ''
        for transaction in self.ledger:
            if "." in str(transaction['amount']):
                amount = str(transaction['amount'])
            else:
                amount = str(transaction['amount']) + '.00'  
            if len(transaction['description']) >= 23:
                description = transaction['description'][:23]
                spaces = 7 - len(amount)
            else:
                description = transaction['description']
                spaces = 30 - len(description) - len(amount)
            ledger_contents += description + " " * spaces + amount + "\n"
        return self.title_line + ledger_contents + "Total: " + str(self.get_balance())

def create_spend_chart(categories):
    lines = 'Percentage spent by category\n'
    nb_cat = len(categories)
    for i in range(100,-10,-10):
        current_line = str(i).rjust(3) + "|"
        for cat in categories:
            perc = 100 * cat.spent / total_spent
            perc = int(perc/10) * 10
            if i == 0 or (perc > 0 and perc % i == 0) or perc >=i:
                current_line += " o "
            else:
                current_line += "   "
        lines += current_line + ' \n'
    lines += "    " + "-"* nb_cat * 3 + "-\n"
    max_cat_length = 0
    for cat in categories:
        if len(cat.name) > max_cat_length:
            max_cat_length = len(cat.name)

    for i in range(0, max_cat_length):
        current_line = '    '
        for cat in categories:
            if len(cat.name) >= i+1 :
                current_line += ' ' + cat.name[i] + ' '
            else:
                current_line += '   '
        lines += current_line + '\n'
    return lines
    



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')
clothing.deposit(300, 'pay day')
clothing.withdraw(158.39, "new outfit")
food.transfer(50, clothing)
print(food)
print('')
print(create_spend_chart([food, clothing]))

It looks like your percentages are not being calculated correctly…are you rounding down to the nearest 10?

If you run the tests, then open your browser’s console, you will see helpful error information. It’s a bit cryptic though, so here’s an explanation on how to interpret it:

The assertion error and diff gives you a lot of information to track down a problem. For example:

AssertionError: 'Year' != 'Years'
- Year
+ Years
?     +

Your output comes first, and the output that the test expects is second.

AssertionError: ‘Year’ != ‘Years’

Your output: Year does not equal what’s expected: Years

This is called a diff, and it shows you the differences between two files or blocks of code:

- Year
+ Years
?     +

- Dash indicates the incorrect output
+ Plus shows what it should be
? The Question mark line indicates the place of the character that’s different between the two lines. Here a + is placed under the missing s .

Here’s another example:

E       AssertionError: Expected different output when calling "arithmetic_arranger()" with ["3801 - 2", "123 + 49"]
E       assert '  3801      123    \n   - 2     + 49    \n------    -----    \n' == '  3801      123\n-    2    +  49\n------    -----'
E         -   3801      123
E         +   3801      123    
E         ?                ++++
E         - -    2    +  49
E         +    - 2     + 49    
E         - ------    -----
E         + ------    -----    
E         ?                +++++

The first line is long, and it helps to view it as 2 lines in fixed width characters, so you can compare it character by character:

'  3801      123    \n   - 2     + 49    \n------    -----    \n'
'  3801      123\n-    2    +  49\n------    -----'

Again, your output is first and the expected output is second. Here it’s easy to see extra spaces or \n characters.

E         -   3801      123
E         +   3801      123    
E         ?                ++++

Here the ? line indicates 4 extra spaces at the end of a line using four + symbols. Spaces are a little difficult to see this way, so it’s useful to use both formats together.

I hope this helps interpret your error!

Unfortunately the interpreter stuff flew right above my head, I opened the browser console and couldn’t find anything similar to your examples. I did, however, figure out how to fix my problem: instead of using a global variable “total_spent” and adding to it every time there was a withdrawal or transfer, I got rid of it and simply did a sum of the spent amount for each Category. With either method, the rounded values and display was correct (I verified the rounding with print statements), but for whatever reason using the global variable would not allow me to pass the test. Thanks for your help!

Glad you figured out what needed to be fixed. Good job!

Hard to say without geting your data but I passed that step once I realized that the percentages had to be rounded down to the nerest 10 which means that if the percentage turned out to b say 7.12% it had to become 0% after rounding. Hope that helps.

Edit: Looks like you are doing it right though (perc = int(perc/10) * 10)