Build a Budget App - Build a Budget App

Tell us what’s happening:

I see 3 issues all with the same spacing issue. I do not understand how it is occurring and there where/what the code fix should be.
line 30,
self.assertEqual(actual, expected, “Expected different category names written vertically below the bar. Check that all spacing is exact.”)
[Warning] AssertionError:
’ B F E \n u o n \n s o t [197 chars] ’ !=
’ B F E \n u o n \n s o t \n i [147 chars] t ’

Your code so far


Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/27.0 Safari/605.1.15

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

Hi @kmajor,

Your code was too long to be automatically inserted by the help button.

Please update the message, or reply to this one, to include your code, formatted as follows:

There are two ways you can format your code to make it easier to read and test:

  1. After you copy/paste your code into the editor, select it by dragging your cursor over it then click the (</>) button in the toolbar to automatically wrap your code in backticks. (You can click on the animated demo image below to enlarge it.)

  1. Manually add three backticks on a new line above your code and on a new line after your code. Note that a backtick is NOT the same as a single quote('). To find the backtick key on your keyboard, see this post.

To see changes to your post as you make them, you can click the (M+) button on the toolbar to bring up the rich text editor:


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

    def deposit(self, amount, description=''):
        self.ledger.append({'amount': amount, 'description': description})
        self.balance += amount
    
    def withdraw(self, amount, description=''):
        if self.check_funds(amount):
            self.ledger.append({'amount': -amount, 'description': description})
            self.balance -= amount
            return True
        return False
    
    def get_balance(self):
        return self.balance
    
    def transfer(self, amount, categ):
        if self.check_funds(amount):
            self.withdraw(amount, f"Transfer to {categ.category}")
            categ.deposit(amount, f"Transfer from {self.category}")
            return True
        else:
            return False
    
    def check_funds(self, amount): #check what is passed as amount against balance.
        if amount > self.balance:
            return False
        else:
            return True

    def __str__(self):
        display =''
        title = self.category.center(30, '*')
        display += title + '\n'
        for item in self.ledger:
            #description = item["description"]
            description = item["description"][:23].ljust(23)#descript. 23 chars only
            amount = "{:.2f}".format(item["amount"]).rjust(7)#amount 2 decimal places
            display += description + amount + '\n'
        display += f"Total: {self.balance:.2f}"#Display total balance 2 decimal places
        return display


def create_spend_chart(categories):
    # Calculate total spent
    total_spent = sum(-category.ledger[i]['amount'] for category in categories for i in range(len(category.ledger)) if category.ledger[i]['amount'] < 0)

   # Calculate percentage spent for each category
    percentages = [(sum(-item['amount'] for item in category.ledger if item['amount'] < 0) / total_spent) * 100 for category in categories]
    percentages = [int(p // 10) * 10 for p in percentages]  # Round down to nearest 10

    # Create chart
    chart = "Percentage spent by category\n"
    for i in range(100, -1, -10):
        chart += str(i).rjust(3) + "| "
        for p in percentages:
            if p >= i:
                chart += "o  "
            else:
                chart += "   "
        chart += "\n"
    # Print the horizontal line/dashes at the bottom of the chart
    chart += "    " + "-" * (len(categories) * 3 + 1) + "\n"

    # Find maximum category name length
    max_len = max(len(category.category) for category in categories)

    # Add category names vertically
    for i in range(max_len):
        chart += "     "  
        for j, category in enumerate(categories):
            if i < len(category.category):
                chart += category.category[i] + "  "  # Changed to consistent spacing
            else:
                chart += "   "
            if j == len(categories) - 1:  # Check if it's the last category
                chart += "  "  # Add two extra spaces
        if i != max_len - 1:  
            chart += "  \n"

    chart = chart.rstrip('\n')    
    return chart


###############################################

food = Category("Food")
clothing = Category("Clothing")
auto = Category("Auto")
food.deposit(1000, "initial deposit")
clothing.deposit(1000, "initial deposit")
auto.deposit(1000, "initial deposit")
food.withdraw(500, "groceries")
clothing.withdraw(300, "shirt")
auto.withdraw(200, "gas")

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

#food.transfer(500, clothing)
#print(food.get_balance())  # Should print 500
#print(clothing.get_balance())  # Should print 500
#print(food)

`class Category:

def \__init_\_(self,category):

self.category = category

self.ledger = []

self.balance = 0

def deposit(self, amount, description=‘’):

self.ledger.append({‘amount’: amount, ‘description’: description})

self.balance += amount

def withdraw(self, amount, description=‘’):

if self.check_funds(amount):

self.ledger.append({‘amount’: -amount, ‘description’: description})

self.balance -= amount

return True

return False

def get_balance(self):

return self.balance

def transfer(self, amount, categ):

if self.check_funds(amount):

self.withdraw(amount, f"Transfer to {categ.category}")

        categ.deposit(amount, f"Transfer from {self.category}")

return True

else:

return False

def check_funds(self, amount): #check what is passed as amount against balance.

if amount > self.balance:

return False

else:

return True

def _str_(self):

    display =''

    title = self.category.center(30, '\*')

    display += title + '\\n'

for item in self.ledger:

#description = item[“description”]

        description = item\["description"\]\[:23\].ljust(23)#descript. 23 chars only

        amount = "{:.2f}".format(item\["amount"\]).rjust(7)#amount 2 decimal places

        display += description + amount + '\\n'

    display += f"Total: {self.balance:.2f}"#Display total balance 2 decimal places

return display

def create_spend_chart(categories):

# Calculate total spent

total_spent = sum(-category.ledger\[i\]\['amount'\] for category in categories for i in range(len(category.ledger)) if category.ledger\[i\]\['amount'\] < 0)

# Calculate percentage spent for each category

percentages = \[(sum(-item\['amount'\] for item in category.ledger if item\['amount'\] < 0) / total_spent) \* 100 for category in categories\]

percentages = \[int(p // 10) \* 10 for p in percentages\]  # Round down to nearest 10

# Create chart

chart = "Percentage spent by category\\n"

for i in range(100, -1, -10):

    chart += str(i).rjust(3) + "| "

for p in percentages:

if p >= i:

            chart += "o  "

else:

            chart += "   "

    chart += "\\n"

# Print the horizontal line/dashes at the bottom of the chart

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

# Find maximum category name length

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

# Add category names vertically

for i in range(max_len):

    chart += "     "  

for j, category in enumerate(categories):

if i < len(category.category):

            chart += category.category\[i\] + "  "  # Changed to consistent spacing

else:

            chart += "   "

if j == len(categories) - 1: # Check if it’s the last category

            chart += "  "  # Add two extra spaces

if i != max_len - 1:

        chart += "  \\n"



chart = chart.rstrip('\\n')    

return chart

###############################################

food = Category(“Food”)

clothing = Category(“Clothing”)

auto = Category(“Auto”)

food.deposit(1000, “initial deposit”)

clothing.deposit(1000, “initial deposit”)

auto.deposit(1000, “initial deposit”)

food.withdraw(500, “groceries”)

clothing.withdraw(300, “shirt”)

auto.withdraw(200, “gas”)

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

#food.transfer(500, clothing)

#print(food.get_balance()) # Should print 500

#print(clothing.get_balance()) # Should print 500

#print(food)

`

thank you and my apologies. My code has been added.

Try testing like this so you can see your spacing issues:

categories = []
food = Category('Food')
categories.append(food)
food.deposit(1000,'deposit')
food.withdraw(10.15,'groceries')
food.withdraw(15.89,'restaurant and more food for dessert')
clothing = Category('Clothing')
categories.append(clothing)
food.transfer(50, clothing)
clothing.deposit(800,'deposit')
clothing.withdraw(55.20,'jacket')
auto = Category('Auto')
categories.append(auto)
auto.deposit(500,'deposit')
auto.withdraw(42.39,'fuel')
auto.withdraw(78.62,'oil change')
print(create_spend_chart(categories).replace(" ",".")) 

Happy coding

thank you. I easily resolved the final two spaces issue (for now). This is a very difficult sentence to comprehend:

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).

I’m glad you were able to work through it.

Any ideas about how the sentence could be reworded so it’s more understandable?

Happy coding

Is it expected that the ‘total spent for all categories’ is the ONLY sum to be rounded down? Utilizing the test data you provided (thank you again), I can see that my category %'s do not sum to 100.

note: 2 full days I I have not moved the needle on the final two steps (23 & 24).

No. The percentage of total spent for a single category divided by the total spent for all categories should be rounded down to the nearest 10.

For example, using the data above:

total spend is $252.25
food spend is $76.04 → 30
clothing spend is $55.20 → 20
auto spend is $121.01 → 40

Hope that helps.

Ok, I was perceiving my code as improper because the category spend %'s do not total 100%.

They wouldn’t necessarily because you are always rounding down. (e.g. auto spend percentage above would be 50 if rounded up).

Ok thank you.

These are the three errors from the browser console that I have identified but I cannot rectify in my code.

line 30, in test_create_spend_chart_names_three_categories (python-test-evaluator.js, line 2)

[Warning] self.assertEqual(actual, expected, “Expected different category names written vertically below the bar. Check that all spacing is exact.”) (python-test-evaluator.js, line 2)

[Warning] AssertionError:

’ B F E \n u o n \n s o t [199 chars] ’ !=

’ B F E \n u o n \n s o t \n i [147 chars] t ’ (python-test-evaluator.js, line 2)

line 24, in test_create_spend_chart_names_two_categories (python-test-evaluator.js, line 2)

[Warning] self.assertEqual(actual, expected, “Expected different category names written vertically below the bar. Check that all spacing is exact.”) (python-test-evaluator.js, line 2)

[Warning] AssertionError:

’ F E \n o n \n o t \n [163 chars] ’ !=

’ F E \n o n \n o t \n d e \n[111 chars] t ’

line 23, in test_create_spend_chart (python-test-evaluator.js, line 2)

[Warning] self.assertEqual(actual, expected, ‘Expected different chart representation. Check that all spacing is exact.’) (python-test-evaluator.js, line 2)

[Warning] AssertionError:

'Perc[227 chars] E \n u o n \n s o t [199 chars] ’ !=

'Perc[227 chars] E \n u o n \n s o t \n i [147 chars] t ’

These last two steps are unnecessarily difficult to teach these concepts. At this point it should be very clear why the requirements are not being met. The guidance for these steps should be as particular and detailed as the actual test steps being performed to assess the output against expectation..

I SOLVED IT!! :flexed_biceps: :smiling_face_with_sunglasses: Thank you @dhess !!!