Build a Budget App - Build a Budget App

Tell us what’s happening:

I was just wondering how I could pass the remaining test cases? The output looks identical to the expected output to me


Your code so far

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

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

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

    def withdraw(self,amount, description= ""):

        #checks if its possible to withdraw the specified amount
        if self.check_funds(amount):
            self.ledger.append({"amount": -amount, "description": description})
            self.current_balance -= amount
            return True   
        else:
            return False

    def get_balance(self):
        return self.current_balance

    def transfer(self,amount, destination):
        #checks if transfer is possible
        if self.check_funds(amount):
            self.ledger.append({
                "amount": -amount, 
                "description": f"Transfer to {destination.name}"})
            destination.ledger.append({
                "amount": amount, 
                "description": f"Transfer from {self.name}"})
            self.current_balance -= amount
            destination.current_balance += amount
            return True
        else: 
            return False

    def __str__(self):
        title = self.name
        descriptions = ""
        for i in self.ledger:
            gap = 30 - len(i["description"])
            if len(i["description"]) <= 23:
                descriptions += i["description"]
                decimal_amount = format(i["amount"], ".2f")
                descriptions += f"{str(decimal_amount).rjust(gap)}\n"
            else:
                descriptions += i["description"][0:23]
                decimal_amount = format(i["amount"], ".2f")
                descriptions += f"{str(decimal_amount).rjust(7)}\n" 
        return f"{title.center(30, '*')}\n{descriptions}"


def create_spend_chart(categories):
    spending_in_each = []
    total_spent = 0

    for category in categories:
        category_total = 0
        for i in category.ledger:
            if i["amount"] < 0:
                category_total += abs(i["amount"])

        spending_in_each.append(category_total)
        total_spent += category_total

    percents = []
    
    for spent in spending_in_each:
        percent = (spent / total_spent) * 100
        percents.append(int(percent // 10) * 10)

    x_axis = [100,90,80,70,60,50,40,30,20,10,0]

    #Returns the x axis with o's symbolizing the percentages
    chart = "Percentage spent by category"
    for i in x_axis:
        chart += f"\n{str(i).rjust(3)}|"
        for p in percents:
            if p >= i:
                chart += f" o "

    #builds the bottom dashes
    chart += "\n    " + "-" * (len(categories) * 3 + 1)
    

    chart += "\n"

    max_len = max(len(category.name) for category in categories)

    for i in range(max_len):
        chart += "     "  # 5 spaces for alignment
        
        for category in categories:
            if i < len(category.name):
                chart += category.name[i] + "  "
            else:
                chart += "   "
        if i < max_len -1:
            chart += "\n"
    return chart





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')
food.transfer(50, clothing)
clothing.withdraw(10, 'gucci')
create_spend_chart([food,clothing])
print(food)




Your browser information:

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

Challenge Information:

Build a Budget App - Build a Budget App

*************Food*************
initial deposit        1000.00
groceries               -10.15
restaurant and more foo -15.89
Transfer to Clothing    -50.00
Total: 923.96

In the instructions, you are asked to print a Total, but your code is not doing that.

And the tests are expecting different rounding of the bars in your chart, so review the user story about that.

Doesn’t this round it down to the nearest 10?

percents.append(int(percent // 10) * 10)

Yes. But I think it needs to be applied to each withdrawal when calculating total spend for all categories as well.

I’m a little confused, so I have to put that calculation somewhere else?

Try using it when you create category_total.

For some reason even when I put it here it doesn’t pass the test case:

for category in categories:
        category_total = 0
        for i in category.ledger:
            if i["amount"] < 0:
                category_total += int(abs(i["amount"])//10) * 10

        spending_in_each.append(category_total)
        total_spent += category_total

the rounding needs to be applied to the percentage spending, not to each individual withdrawal

Thanks for that clarification. I guess my solution to this was overkill then. I used it on the withdrawals and on the percentages. So, now I’ll go play with that a bit to see if the change will also pass, or if there’s something else I needed to do there.

Ok now I really don’t know where its suppossed to go since this code does round down each percentage that’s appeneded into the percents list

percents = []
    for spent in spending_in_each:
        percent = (spent / total_spent) * 100
        percents.append(int(percent // 10) * 10)

I am testing the code in the top post, with the same two categories, but in different order

so if they are the same categories, why are the bars like this?

if you have updated the code so far, please post your full new code

the list printed is the spent in each category followed by total spent, those are fine, it’s from there to creating the bars that there is something wrong

You can test what ILM is trying to point out, like this:

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

And this Python Code Visualizer is a great tool for being able to step through your code to see what it’s doing. But it has a 5600-byte limit so you might need to remove something, like the str() method, to test the spend chart functionality.

1 Like

So now I’ve got the mismatched issue sorted and the rounding issue solved. I just seem to be failing test cases 20 and 24 which has to do with spacing? Here’s the updated function:

def create_spend_chart(categories):

    spending_in_each = []

    total_spent = 0

    category_names = []




    data = []




    for category in categories:

        category_total = 0

        for i in category.ledger:

            if i["amount"] < 0:

                category_total += abs(i["amount"])

                

        data.append({

            "name": category.name,

            "spent": category_total

        })




    total_spent = sum(d["spent"] for d in data)




    for d in data:

        percent = (d["spent"] / total_spent) * 100

        d["percent"] = int(percent // 10)  * 10




    x_axis = [100,90,80,70,60,50,40,30,20,10,0]




    #Returns the x axis with o's symbolizing the percentages

    chart = "Percentage spent by category"

    for i in x_axis:

        chart += f"\n{str(i).rjust(3)}|"

        for d in data:

            if d["percent"] >= i:

                chart += f" o "

            else:

                chart += "   "




    #builds the bottom dashes

    chart += "\n    " + "-" * (len(categories) * 3 + 1)

    




    chart += "\n"




    max_len = max(len(d["name"]) for d in data)




    for i in range(max_len):

        chart += "     "  # 5 spaces for alignment




        for d in data:

            if i < len(d["name"]):

                chart += d["name"][i] + "  "

            else:

                chart += "   "

                

        if i < max_len -1:

            chart += "\n"

    return chart

so now you need to look at the browser console and see where the spacing differences are

you can use the AssertionError of the last test for that

AssertionError: 'Perc[34 chars]     \n 90|         \n 80|         \n 70|    o[329 chars] t  '
             != 'Perc[34 chars]      \n 90|          \n 80|          \n 70|  [340 chars] t  '

the first line is your code, the second line is the expected, so you see where you have the spacing differences