Build a Budget App Project - Build a Budget App Project

Tell us what’s happening:

I don’t like asking for help on this one but the code seems to be doing what is required but still fails the last two tests. I can’t see that my formatting is any different but perhaps it is or maybe I’m just not understanding exactly what is wanted.

Your code so far

import math

class Category:
    def __init__(self, category):
        self.ledger = []
        self.category = category
        self.total = 0

    def __repr__(self):
        header = self.category.center(30, '*')
        output_string = header + '\n'
        for item in self.ledger:
            amount = item['amount']
            amount_str = f'{amount:.2f}'
            desc_str = (item['description'][:28 - (len(amount_str))] + '..') if len(item['description']) > 28 - (len(amount_str)) else item['description']
            spaces = " " * (30 - (len(desc_str) + len(amount_str)))
            output_string += f'{desc_str:<}{spaces}{amount_str:>}\n'
        output_string += "Total: " + f'{self.total:.2f}'
        return output_string

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

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

    def get_withdrawls(self):
        withdrawl_amt = 0
        for i in self.ledger:
            if i["amount"] < 0 and not i["description"].startswith("Transfer"):
                withdrawl_amt += i["amount"]
        return withdrawl_amt

    def get_balance(self):
        return self.total

    def transfer(self, amount, instance):
        if self.check_funds(amount):
            self.total -= amount
            self.ledger.append({'amount': -amount, 'description': 'Transfer to ' + instance.category})
            instance.total += amount
            instance.ledger.append({'amount': amount, 'description': 'Transfer from ' + self.category})
            return True
        else:
            return False

    def check_funds(self, amount):
        return amount <= self.total

def get_total_withdrawls(categories):
    total_withdrawls = 0
    for category in categories:
        total_withdrawls += category.get_withdrawls()
    return total_withdrawls

def create_spend_chart(categories):
    total_withdrawls = get_total_withdrawls(categories)
    if total_withdrawls == 0:
        return []

    percent_per_cat = []
    for c in categories:
        percentage = (c.get_withdrawls() / total_withdrawls) * 100
        rounded_percentage = math.floor(percentage / 10) * 10
        percent_per_cat.append({c.category: rounded_percentage})
    
    output_string = "Percentage spent by category\n"
    for i in range(11):
        output_string += str(100 - i * 10).rjust(3) + "| "
        for percent in percent_per_cat:
            if list(percent.values())[0] >= 100 - i * 10:
                output_string += "o  "
            else:
                output_string += "   "
        output_string += "\n"
    
    output_string += "    " + "-" * (len(categories) * 3 + 1) + "\n"
    
    max_len = max(len(c.category) for c in categories)
    for i in range(max_len):
        output_string += "     "
        for c in categories:
            if i < len(c.category):
                output_string += c.category[i] + "  "
            else:
                output_string += "   "
        output_string += "\n"
    
    return output_string

food = Category('Food')
food.deposit(100, 'deposit')
food.withdraw(10, 'groceries')
food.withdraw(15, 'restaurant and more food for dessert')
clothing = Category('Clothing')
clothing.deposit(500, 'deposit')
clothing.withdraw(100, 'jeans')
auto = Category('Auto')
auto.deposit(500, 'deposit')
auto.withdraw(130, 'tyres')

rent = Category('Rent')
rent.deposit(500, 'deposit')
rent.withdraw(430, 'January')


categories = [food, clothing, auto, rent]

#print(food.get_withdrawls())
#print(clothing.get_balance())
print(food)
#print(f"Total withdrawals across all categories: {get_total_withdrawls(categories):.2f}")

spend_chart = create_spend_chart(categories)
print(spend_chart)

Your browser information:

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

Challenge Information:

Build a Budget App Project - Build a Budget App Project

I’m down to just the last test failing now (tiny spacing issue with the first chart) but I can’t see what’s wrong with the withdrawal report

Check the browser console (F12) for a more detailed error. (look for the assertion error.)

Thank you but I’m afraid it means absolutely nothing to me .
I have no idea what this is: AssertionError: ‘Perc[364 chars] m \n e \n n \n t \n’ != 'Perc[364 chars] m \n e \n n \n t ’

An assertion error 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

- 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!

The part where it says “[364 chars]” means that the next 364 characters are the same in both

Thank you very much for your help. You made it all much clearer.
1 new line at the end of vertical category name columns that was obviously added by the for loop.
It feels a bit pedantic as its almost impossible to see the space at the end but I did learn about assertion errors which is good.
Is MS Edge better or worse at displaying errors compared to other consoles? I found it very difficult to navigate my way around the console.
Thanks again.

1 Like

I see what you mean but it’s just an exercise to practice coding. There also needs to be a clear and consistent output from everyone to test.