Build a Budget App - Test 20

Tell us what’s happening:

Test 20 doesn’t pass, and the AssertionError only says that 13 != 11. When the two extra spaces are added after the final bar, Test 24 doesn’t pass. Could anyone help me with fixing this?

Your code so far

```
import math
class Category:
    def __init__(self, name):
        self.ledger = []
        self.name = name
    def deposit(self, amount, description=''):
        self.ledger.append({'amount': amount, 'description': description})
    def withdraw(self, amount, description=''):
        if self.check_funds(amount):
            self.ledger.append({'amount': -amount, 'description': description})
            return True
        else:
            return False
    def get_balance(self):
        balance = 0
        for item in self.ledger:
            balance += float(item['amount'])
        return(balance)
    def transfer(self, amount, destination_category):
        if self.check_funds(amount):
            self.withdraw(amount, f'Transfer to {destination_category.name}')
            destination_category.deposit(amount, f'Transfer from {self.name}')
            return True
        else:
            return False
    def check_funds(self, amount):
        if amount > self.get_balance():
            return False
        else:
            return True
    def __str__(self):
        asterisks = ((30 - len(self.name)) // 2)
        lines = (('*' * asterisks) + self.name + ('*' * asterisks))
        for item in self.ledger:
            description = item['description'][:23]
            amount = '{:.2f}'.format(item['amount'])
            lines += (f"\n{description.ljust(23)}{amount.rjust(7)}")
        lines += (f'\nTotal: {self.get_balance()}')
        return (lines)
def create_spend_chart(categories):
    chart = 'Percentage spent by category'
    total_withdrawals = 0
    all_full_category_withdrawals = {}
    for cat in categories:
        category_withdrawals = []
        full_category_withdrawals = 0
        for item in cat.ledger:
            if item['amount'] < 0:
                category_withdrawals.append(item['amount'])
        full_category_withdrawals = sum(category_withdrawals)
         
        total_withdrawals += full_category_withdrawals
        all_full_category_withdrawals[cat] = full_category_withdrawals
    cat_percentages = {}   
    for cat in categories:
        cat_percentages[cat] = math.floor((all_full_category_withdrawals.get(cat) / total_withdrawals)*10) * 10
    
    blank = str(" ")    
    def olog(category, percentage):
        try:
            if cat_percentages[categories[category]] >= percentage: 
                return('o')
            else:
                return(' ')
        except IndexError:
            return ''
    cat_list = [cat.name for cat in categories]
    cats = 0
    for cat in categories:
        cats += 1    
    longest = max(cat_list, key=len)
    ll = len(longest)
    dashes = '---' * cats + '-'
    
    chart += f'\n100| {olog(0,100)}  {olog(1,100)}  {olog(2,100)}  {olog(3,100)}\n 90| {olog(0,90)}  {olog(1,90)}  {olog(2,90)}  {olog(3,90)}\n 80| {olog(0,80)}  {olog(1,80)}  {olog(2,80)}  {olog(3,80)}\n 70| {olog(0,70)}  {olog(1,70)}  {olog(2,70)}  {olog(3,70)}\n 60| {olog(0,60)}  {olog(1,60)}  {olog(2,60)}  {olog(3,60)}\n 50| {olog(0,50)}  {olog(1,50)}  {olog(2,50)}  {olog(3,50)}\n 40| {olog(0,40)}  {olog(1,40)}  {olog(2,40)}  {olog(3,40)}\n 30| {olog(0,30)}  {olog(1,30)}  {olog(2,30)}  {olog(3,30)}\n 20| {olog(0,20)}  {olog(1,20)}  {olog(2,20)}  {olog(3,20)}\n 10| {olog(0,10)}  {olog(1,10)}  {olog(2,10)}  {olog(3,10)}\n  0| {olog(0,0)}  {olog(1,0)}  {olog(2,0)}  {olog(3,0)}\n    {dashes}\n     ' 
     
    
    line_num = 0
    
    
        
    
    if cats == 1:
        for letter in longest:
            try:
                chart += f'{categories[0].name[line_num]}  \n     '
            except IndexError:
                chart += '\n     '
            line_num += 1
    if cats == 2:
        for letter in longest:
            try:
                chart += f'{categories[0].name[line_num]}  ' 
            except IndexError:
                chart += '   ' 
            
            
            try:
                chart += f'{categories[1].name[line_num]}  \n     '
            except IndexError:
                chart += '\n     '
            line_num += 1 
    if cats == 3:
        for letter in longest:
            try:
                chart += f'{categories[0].name[line_num]}  ' 
            except IndexError:
                chart += '   ' 
            try:
                chart += f'{categories[1].name[line_num]}  ' 
            except IndexError:
                chart += '   ' 
            
            try:
                chart += f'{categories[2].name[line_num]}  \n     '
            except IndexError:
                chart += '\n     '
            line_num += 1 
    if cats == 4:
        for letter in longest:
            try:
                chart += f'{categories[0].name[line_num]}  ' 
            except IndexError:
                chart += '   ' 
            try:
                chart += f'{categories[1].name[line_num]}  ' 
            except IndexError:
                chart += '   ' 
            try:
                chart += f'{categories[2].name[line_num]}  ' 
            except IndexError:
                chart += '   '
            
            #if line_num == (ll-1):
                #fletter = categories[3].name[line_num]
                #ffletter = fletter.rstrip()
                #chart += str(ffletter)
                #break
            try:
                chart += f'{categories[3].name[line_num]}  \n     '
            
            except IndexError:
                chart += '\n     '
            
            line_num += 1 
    schart = chart.rstrip() + '  '
    print(schart)
    return(schart)

food = Category('Entertainment')
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(1000, "deposit")
clothing.withdraw(100.00, "buying new clothes")

auto = Category("Auto")
auto.deposit(1000, "deposit")
auto.withdraw(200.00, "fuel")

house = Category("House")
house.deposit(1000, "deposit")
house.withdraw(200.00, "fuel")

categories = [clothing, house, auto, food]
#print(auto)
#print(clothing)
#print(food)
#print(house)
create_spend_chart(categories)
```

Your browser information:

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

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

Welcome to the forum @cubisticLion154,

It looks like you are hard coding expected values like the number of categories. What does your code do if there are five categories?

To find the spacing errors in your chart, I suggest temporarily replacing spaces with asterisks in your if cats == 4: statement.

To see what your function returns in the console, wrap your function call in print rather than using a print function inside create_spend_chart.

Happy coding

Yes, it is limited to four categories.

I made that change to the printing and adjusted the name columns after seeing the asterisks. I think it may have been returning some extra spaces on an extra line.

However, Test 20 still does not pass.

This is the updated code.

```
import math
class Category:
    def __init__(self, name):
        self.ledger = []
        self.name = name
    def deposit(self, amount, description=''):
        self.ledger.append({'amount': amount, 'description': description})
    def withdraw(self, amount, description=''):
        if self.check_funds(amount):
            self.ledger.append({'amount': -amount, 'description': description})
            return True
        else:
            return False
    def get_balance(self):
        balance = 0
        for item in self.ledger:
            balance += float(item['amount'])
        return(balance)
    def transfer(self, amount, destination_category):
        if self.check_funds(amount):
            self.withdraw(amount, f'Transfer to {destination_category.name}')
            destination_category.deposit(amount, f'Transfer from {self.name}')
            return True
        else:
            return False
    def check_funds(self, amount):
        if amount > self.get_balance():
            return False
        else:
            return True
    def __str__(self):
        asterisks = ((30 - len(self.name)) // 2)
        lines = (('*' * asterisks) + self.name + ('*' * asterisks))
        for item in self.ledger:
            description = item['description'][:23]
            amount = '{:.2f}'.format(item['amount'])
            lines += (f"\n{description.ljust(23)}{amount.rjust(7)}")
        lines += (f'\nTotal: {self.get_balance()}')
        return (lines)
def create_spend_chart(categories):
    chart = 'Percentage spent by category'
    total_withdrawals = 0
    all_full_category_withdrawals = {}
    for cat in categories:
        category_withdrawals = []
        full_category_withdrawals = 0
        for item in cat.ledger:
            if item['amount'] < 0:
                category_withdrawals.append(item['amount'])
        full_category_withdrawals = sum(category_withdrawals)
         
        total_withdrawals += full_category_withdrawals
        all_full_category_withdrawals[cat] = full_category_withdrawals
    cat_percentages = {}   
    for cat in categories:
        cat_percentages[cat] = math.floor((all_full_category_withdrawals.get(cat) / total_withdrawals)*10) * 10
    
    blank = str(" ")    
    def olog(category, percentage):
        try:
            if cat_percentages[categories[category]] >= percentage: 
                return('o')
            else:
                return(' ')
        except IndexError:
            return ''
    cat_list = [cat.name for cat in categories]
    cats = 0
    for cat in categories:
        cats += 1    
    longest = max(cat_list, key=len)
    ll = len(longest)
    dashes = '---' * cats + '-'
    
    chart += f'\n100| {olog(0,100)}  {olog(1,100)}  {olog(2,100)}  {olog(3,100)}\n 90| {olog(0,90)}  {olog(1,90)}  {olog(2,90)}  {olog(3,90)}\n 80| {olog(0,80)}  {olog(1,80)}  {olog(2,80)}  {olog(3,80)}\n 70| {olog(0,70)}  {olog(1,70)}  {olog(2,70)}  {olog(3,70)}\n 60| {olog(0,60)}  {olog(1,60)}  {olog(2,60)}  {olog(3,60)}\n 50| {olog(0,50)}  {olog(1,50)}  {olog(2,50)}  {olog(3,50)}\n 40| {olog(0,40)}  {olog(1,40)}  {olog(2,40)}  {olog(3,40)}\n 30| {olog(0,30)}  {olog(1,30)}  {olog(2,30)}  {olog(3,30)}\n 20| {olog(0,20)}  {olog(1,20)}  {olog(2,20)}  {olog(3,20)}\n 10| {olog(0,10)}  {olog(1,10)}  {olog(2,10)}  {olog(3,10)}\n  0| {olog(0,0)}  {olog(1,0)}  {olog(2,0)}  {olog(3,0)}\n    {dashes}\n     ' 
     
    
    line_num = 0
    
    
        
    
    if cats == 1:
        for letter in longest:
            try:
                if line_num <= (ll-2):
                    chart += f'{categories[0].name[line_num]}  \n     '
                else:
                    chart += f'{categories[0].name[line_num]}  '
                
            
            except IndexError:
                if line_num <= (ll-2):
                    chart += '   \n     '
                else:
                    chart += '   '
            line_num += 1
    if cats == 2:
        for letter in longest:
            try:
                chart += f'{categories[0].name[line_num]}  ' 
            except IndexError:
                chart += '   ' 
            
            
            try:
                if line_num <= (ll-2):
                    chart += f'{categories[1].name[line_num]}  \n     '
                else:
                    chart += f'{categories[1].name[line_num]}  '
                
            
            except IndexError:
                if line_num <= (ll-2):
                    chart += '   \n     '
                else:
                    chart += '   '
            line_num += 1 
    if cats == 3:
        for letter in longest:
            try:
                chart += f'{categories[0].name[line_num]}  ' 
            except IndexError:
                chart += '   ' 
            try:
                chart += f'{categories[1].name[line_num]}  ' 
            except IndexError:
                chart += '   ' 
            
            try:
                if line_num <= (ll-2):
                    chart += f'{categories[2].name[line_num]}  \n     '
                else:
                    chart += f'{categories[2].name[line_num]}  '
                
            
            except IndexError:
                if line_num <= (ll-2):
                    chart += '   \n     '
                else:
                    chart += '   '
            line_num += 1 
    if cats == 4:
        for letter in longest:
            try:
                chart += f'{categories[0].name[line_num]}  ' 
            except IndexError:
                chart += '   ' 
            try:
                chart += f'{categories[1].name[line_num]}  ' 
            except IndexError:
                chart += '   ' 
            try:
                chart += f'{categories[2].name[line_num]}  ' 
            except IndexError:
                chart += '   '
            try:
                if line_num <= (ll-2):
                    chart += f'{categories[3].name[line_num]}  \n     '
                else:
                    chart += f'{categories[3].name[line_num]}  '
                
            
            except IndexError:
                if line_num <= (ll-2):
                    chart += '   \n     '
                else:
                    chart += '   '
            
            line_num += 1 
    schart = chart.rstrip() + '  '
    return(schart)

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(1000, "deposit")
clothing.withdraw(100.00, "buying new clothes")

auto = Category("Auto")
auto.deposit(1000, "deposit")
auto.withdraw(200.00, "fuel")

house = Category("House")
house.deposit(1000, "deposit")
house.withdraw(200.00, "fuel")

categories = [clothing, house, auto, food]
#print(auto)
#print(clothing)
#print(food)
#print(house)
print(create_spend_chart(categories))
```

What if there are 5 categories?

  1. Each line in create_spend_chart chart should have the same length. Bars for different categories should be separated by two spaces, with additional two spaces after the final bar.

I tested like this:

print(create_spend_chart(categories).replace(" ","."))

You can see that every line is not the same length.

.10|.o..o..o...
..0|.o..o..o..o
....-------------
.....C..H..A..F..
.....l..o..u..o..
.....o..u..t..o..
.....t..s..o..d..
.....h..e........
.....i...........
.....n...........
.....g..

I fixed the part that was making the final line cut off early. The test still does not pass.

Also I could add capabilities for a fifth category, I just haven’t because the tests didn’t require it.

Did you try the test I suggested above? What did the result look like? Are all the lines the same length? (its not just the last line…)

That’s ok but it’s good to write more flexible code and not to hardcode it for 4 categories.

I’ve replaced spaces with asterisks, that helped me with that issue in the final line. I know that the lines with the bars need two spaces after the final bar, but I haven’t been able to add those spaces without failing Test 24.

Ok, so fix that and then you can work on test 24?

You will need to fix Test 20 in any case.

Post your updated code if you need help after that.

EDIT: Did you try this?

Open your browser console with F12 for more details.

NOTE: open the browser console with F12 to see a more verbose output of the tests.

This function will be tested with up to four categories.

There will not be

I got it to pass! There were some extra spaces that stayed behind when there were fewer categories. Using .rstrip I was able to remove those. Thank you all so much for your help!