Budget App Barchart test spacing problem

Tell us what’s happening:
I have almost done the project so far. The last thing that I can’t manage to pass the test is the barchart, and I suppose I have a spacing problem because the bar returned seems exactly like the examples. I have been looking where I have the wrong formattinc but I can’t find it and my eyes already hurt looking where I need to add (or remove) spaces.

I appreciate any help in advance!

Your code so far

class Category:
    def __init__(self, name):
        self.name = name
        self.ledger = []
    
    # returns balance of category based on deposits and withdrawals
    def get_balance(self):
        prices = []
        for i in self.ledger:
            prices.append(i["amount"])
        balance_total = sum(prices)
        return balance_total
    
    # This must be used by withdraw and transfer.
    # Accepts an amount as an argument
    # Returns False if amount less than balance of budget and True otherwise
    def check_funds(self, amount):
        if amount <= self.get_balance():
            return True
        else:
            return False
    
    # Add an amount and description to the category:
    def deposit(self, amount, description = ""):
        deposit_dict = {"amount": amount, "description": description}
        self.ledger.append(deposit_dict)
    
    # have to add a dictionary ONLY if there are enough funds
    # if no funds, return False. If funds, do the operation and return True:
    def withdraw(self, amount, description = ""):
        if self.check_funds(amount) == True:
            withdraw_dict = {"amount": -amount, "description": description}
            self.ledger.append(withdraw_dict)
            return True
        else:
            return False

    # put an amount and name of another budget.
    # add a withdrawal with amount and the description "Transfer to [Destination Budget Category]"
    # add a deposit with amount and description "Transfer from [Source Budget Category]"
    # IF no funds, cancel previous 2 steps. return True if transfer Ok, if not, returns False
    # 5
    def transfer(self, amount, destination):
        if self.check_funds(amount) == True:
            self.withdraw(amount, description = "Transfer to " + destination.name)
            destination.deposit(amount, description = "Transfer from " + self.name)
            return True
        else:
            return False
    
    # To be printed:
    def __str__(self):
        # title with 30 characters and name centered, filled with "*":
        table = self.name.center(30,"*") + "\n"
        for i in self.ledger:
            table += f"{i['description'][:23].ljust(23)}{format(i['amount'], '.2f').rjust(7)}\n"
        table += f"Total: {format(self.get_balance(),'.2f')}"
        return table

def create_spend_chart(categories):
    names = []
    spent = []
    percent_spent = []
    sum_spent = 0
    
    for i in categories:
        # Get names from each category in a list:
        names.append(i.name)
        # Get total withdraw values from each category in a list:
        spent_parcial = 0
        for j in i.ledger:
            if j["amount"] < 0:
                spent_parcial -= j["amount"]
        spent.append(round(spent_parcial,2))
        
    # Get spent in total:
    sum_spent = sum(spent)
        
    # Get percentages spent in a list, by categories:
    for i in spent:
        # Rounded to 2 decimals in percent:
        percent_spent.append(round(i / sum_spent, 2) * 100)
        
    
    # Now we can go to create the bar chart:
    bar_chart = "Percentage spent by category" + "\n"
    # Create a counter to have from 100 to 0:
    counter = 100
    # With this we have the layout of the bar:
    while counter >= 0:
        # Added align to right with width 4 to adjust the percentages:
        bar_chart += (str(counter) + "|").rjust(4)
        
        # If the percentage is greater or equal than the counter, add a bar:
        for i in percent_spent:
            if i >= counter:
                bar_chart += " o "
            # If the percentage is lesser than the counter, add only spaces:
            else:
                bar_chart += "   "    
        # Substract then 10 to the counter to keep writing the bar:
        counter -= 10
        # And start the next iteration of the loop in a new line:
        bar_chart += "\n"
            
    # Add necessary spaces in the horizontal line, and depending on the number of
    # categories, enlarge the line. Also we add a newline and the respective spaces
    # to align correctly the posterior names:
    bar_chart += "    " + "---" * len(percent_spent) + "-" + "\n" + "    "
    
    # Check the number of letters of the longest category name:
    longest_name = 0
    for i in names:
        if len(i) > longest_name:
            longest_name = len(i)
            
    # Loop through each letter of each category in one line:
    for i in range(longest_name):
        for j in names:
            if len(j) > i:
                bar_chart += " " + j[i] + " "
            else:
                bar_chart += "   "
        if i < longest_name - 1:
            bar_chart += "\n    "
    # Return the string containing the bar chart
    return bar_chart

Your browser information:

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

Challenge: Budget App

Link to the challenge:

It’s the spacing, like you suspect. Posting a live project (repl.it, etc.) is better for others as we can run your code and see your tests without copying/pasting a bunch of stuff.

I ran your code in my copy of the project and the tests said (with self.maxDiff = None as the test hints), and then I replaced all the spaces with underscores and this is the result:

-_100|_________
+_100|__________
?______________+
-__90|_________
+__90|__________
?______________+
-__80|_________
+__80|__________
?______________+
-__70|____o____
+__70|____o_____
?______________+

and so on. So it looks like you are one space short on each line (your output is the - lines, expected are the + lines). Beware some funny business with a newline at the end of the graph too.

1 Like

Thank you! I’ll check it out tomorrow morning to see if I can solve this quickly.

Okay, that little space had me more than I will recognise changing the code to fit it haha. But finally it passes the test, so thank you for pointing me out! One last question I have is how you replaced the spaces with underscores in the test, so the next time I have a spacing problem do it and prevent asking again at the forum for the same thing.
Thank you Jeremy, you made my day!

There are several ways. For this one, I ran the code in a shell in my text editor locally (emacs) and just used a search and replace to change spaces to underscores.

A slightly more portable way if you’re working on a prototyping platform like repl.it would be to alter your print() statements to use underscore instead of space, but that would only help on your generated output and not the expected output provided in the tests. Finally, I believe some IDEs have features to highlight white space so that it contrasts to the background.

Perfect! Thank you again! I am sure this will prove me useful in the future.
Have a nice day!