Build a Budget App - Build a Budget App - function create_spend_chart

Tell us what’s happening:

in create_spend_chart function my output show [object Object] and i dont know if is because a internal error or my code is with something wrong.

Your code so far

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

    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):
        return sum(map(lambda x: x['amount'], self.ledger))

    def transfer(self, amount, category):
        if self.check_funds(amount):
            self.withdraw(amount, f'Transfer to {category.name}')
            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):
        text = self.name.center(30,'*')
        for entry in self.ledger:
            float_amount = f"{entry['amount']:.2f}"
            text += f"\n{entry['description'][:23].ljust(23)}"
            text += f"{float_amount[:7].rjust(7)}"
        text += f"\nTotal: {self.get_balance()}"
        return text
        
def create_spend_chart(categories):
    def sum_withdraw(categorie):
        total_withdraw = 0
        for entry in categorie.ledger:
            if entry["amount"] < 0:
                total_withdraw += entry["amount"]
        return total_withdraw

    def round_down(number):
        return math.floor(number) - (math.floor(number)%-10)

    def max_len_name(categories):
        max_len = 0
        for categorie in categories:
            if len(categorie.name) > max_len:
                max_len = len(categorie.name)
        return max_len

    
    categories_total_withdraw = sum([sum_withdraw(categorie) for categorie in categories])
    categories_data = []
    for categorie in categories:
        categories_data.append({
            "name": categorie.name,
            "percentage": round(abs(sum_withdraw(categorie))/abs(categories_total_withdraw),1)*100,
        })

    title = 'Percentage spent by category'
    print(title)

    # y axis labels inverted
    graph = []
    for percentage in range(0,110,10):
        text_percentage = str(percentage)
        graph.append(f"{text_percentage.rjust(3)}| ")

    # add chart bars
    for i in range(0,11):
        for data in categories_data:
            if (i*10) <= data['percentage']:
                graph[i] += "o  "
    print("\n".join(graph[::-1]))
    print(4*" " + 10 * "-")

    # add legend to x axis
    for i in range(max_len_name(categories)):
        print(3*" ", end="")
        for categorie in categories:
            if len(categorie.name) > i:
                print("  " + categorie.name[i], end="")
            else:
                print(3*" ", end="")
        print("")
        
    


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(35.40, "jeans pants")
create_spend_chart([food, clothing])

My console output:

Percentage spent by category
100| 
 90| 
 80| 
 70| o  
 60| o  
 50| o  
 40| o  
 30| o  o  
 20| o  o  
 10| o  o  
  0| o  o  
    ----------
    [object Object]
  F [object Object]
  C [object Object]

    [object Object]
  o [object Object]
  l [object Object]

    [object Object]
  o [object Object]
  o [object Object]

    [object Object]
  d [object Object]
  t [object Object]

    [object Object]
    [object Object]
  h [object Object]

    [object Object]
    [object Object]
  i [object Object]

    [object Object]
    [object Object]
  n [object Object]

    [object Object]
    [object Object]
  g [object Object]


Your browser information:

User Agent is: Mozilla/5.0 (X11; Linux x86_64; rv:153.0) Gecko/20100101 Firefox/153.0

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 @acordado,

Does your function return anything?

Happy coding

if i try in vs code, code output is normal

Percentage spent by category
100| 
 90| 
 80| 
 70| o  
 60| o  
 50| o  
 40| o  
 30| o  o  
 20| o  o  
 10| o  o  
  0| o  o  
    ----------
     F  C
     o  l
     o  o
     d  t
        h
        i
        n
        g

I’m not asking about the output; I’m asking if your function is returning anything because it looks like your function is just printing. That is not what is asked.

thanks i try modify my function

now problem is: The height of each bar on the create_spend_chart chart should be rounded down to the nearest 10.

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

    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):
        return sum(map(lambda x: x['amount'], self.ledger))

    def transfer(self, amount, category):
        if self.check_funds(amount):
            self.withdraw(amount, f'Transfer to {category.name}')
            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):
        text = self.name.center(30,'*')
        for entry in self.ledger:
            float_amount = f"{entry['amount']:.2f}"
            text += f"\n{entry['description'][:23].ljust(23)}"
            text += f"{float_amount[:7].rjust(7)}"
        text += f"\nTotal: {self.get_balance()}"
        return text
        
def create_spend_chart(categories):
    def sum_withdraw(categorie):
        total_withdraw = 0
        for entry in categorie.ledger:
            if entry["amount"] < 0:
                total_withdraw += entry["amount"]
        return total_withdraw

    def round_down(number):
        return math.floor(number) - (math.floor(number)%-10)

    def max_len_name(categories):
        max_len = 0
        for categorie in categories:
            if len(categorie.name) > max_len:
                max_len = len(categorie.name)
        return max_len

    
    categories_total_withdraw = sum([sum_withdraw(categorie) for categorie in categories])
    categories_data = []
    for categorie in categories:
        categories_data.append({
            "name": categorie.name,
            "percentage": round(abs(sum_withdraw(categorie))/abs(categories_total_withdraw),1)*100,
        })
    print(categories_data)
    full_chart = ""

    title = 'Percentage spent by category'
    full_chart += f"{title}\n"
    # y axis labels inverted
    graph = []
    for percentage in range(0,110,10):
        text_percentage = str(percentage)
        graph.append(f"{text_percentage.rjust(3)}| ")

    # add chart bars
    for i in range(0,11):
        for data in categories_data:
            if (i*10) <= data['percentage']:
                graph[i] += "o  "
    full_chart += "\n".join(graph[::-1]) + "\n"
    full_chart += 4*" " + 10 * "-" + "\n"
    
    # add legend to x axis
    for i in range(max_len_name(categories)):
        full_chart += 3*" "
        for categorie in categories:
            if len(categorie.name) > i:
                full_chart += "  " + categorie.name[i]
            else:
                full_chart += 3*" "
        full_chart += "\n"
    return full_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(35.40, "jeans pants")
print(create_spend_chart([food, clothing]))

Tell us what’s happening:

Failed: 19. The height of each bar on the create_spend_chart chart should be rounded down to the nearest 10.

Your code so far

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

    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):
        return sum(map(lambda x: x['amount'], self.ledger))

    def transfer(self, amount, category):
        if self.check_funds(amount):
            self.withdraw(amount, f'Transfer to {category.name}')
            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):
        text = self.name.center(30,'*')
        for entry in self.ledger:
            float_amount = f"{entry['amount']:.2f}"
            text += f"\n{entry['description'][:23].ljust(23)}"
            text += f"{float_amount[:7].rjust(7)}"
        text += f"\nTotal: {self.get_balance()}"
        return text
        
def create_spend_chart(categories):
    def sum_withdraw(categorie):
        total_withdraw = 0
        for entry in categorie.ledger:
            if entry["amount"] < 0:
                total_withdraw += entry["amount"]
        return total_withdraw

    def max_len_name(categories):
        max_len = 0
        for categorie in categories:
            if len(categorie.name) > max_len:
                max_len = len(categorie.name)
        return max_len

    
    categories_total_withdraw = sum([sum_withdraw(categorie) for categorie in categories])
    categories_data = []
    for categorie in categories:
        categories_data.append({
            "name": categorie.name,
            "percentage": round(abs(sum_withdraw(categorie))/abs(categories_total_withdraw),1)*100,
        })
    full_chart = ""

    title = 'Percentage spent by category'
    full_chart += f"{title}\n"
    # y axis labels inverted
    graph = []
    for percentage in range(0,110,10):
        text_percentage = str(percentage)
        graph.append(f"{text_percentage.rjust(3)}| ")

    # add chart bars
    for i in range(0,11):
        for data in categories_data:
            if (i*10) <= data['percentage']:
                graph[i] += "o  "
            else:
                graph[i] += 3*" "
    full_chart += "\n".join(graph[::-1]) + "\n"
    full_chart += 4*" " + len(categories) * "---" + "--" + "\n"
    
    # add legend to x axis
    for i in range(max_len_name(categories)):
        full_chart += 3*" "
        for categorie in categories:
            if len(categorie.name) > i:
                full_chart += "  " + categorie.name[i]
            else:
                full_chart += 3*" "
        full_chart += "\n"
    return full_chart.strip()
        
    


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(35.40, "jeans pants")
print(create_spend_chart([food, clothing]))

Your browser information:

User Agent is: Mozilla/5.0 (X11; Linux x86_64; rv:153.0) Gecko/20100101 Firefox/153.0

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

I went ahead and combined your posts for you. In the future, just reply to the original thread to add further updates.

in test 19 i cant found error in logic

What are you doing to test your code?

using js developer console:

?            --- python-test-evaluator.js:2:104264
+  10|    o  o  python-test-evaluator.js:2:104264
?      +++ python-test-evaluator.js:2:104264
    0| o  o  o  python-test-evaluator.js:2:104264
-     ----------- python-test-evaluator.js:2:104264
?     - python-test-evaluator.js:2:104264
+     ---------- python-test-evaluator.js:2:104264
-      B  F  E python-test-evaluator.js:2:104264
+      B  F  E  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-      u  o  n python-test-evaluator.js:2:104264
+      u  o  n  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-      s  o  t python-test-evaluator.js:2:104264
+      s  o  t  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-      i  d  e python-test-evaluator.js:2:104264
+      i  d  e  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-      n     r python-test-evaluator.js:2:104264
+      n     r  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-      e     t python-test-evaluator.js:2:104264
+      e     t  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-      s     a python-test-evaluator.js:2:104264
+      s     a  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-      s     i python-test-evaluator.js:2:104264
+      s     i  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-            n python-test-evaluator.js:2:104264
+            n  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-            m python-test-evaluator.js:2:104264
+            m  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-            e python-test-evaluator.js:2:104264
+            e  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-            n python-test-evaluator.js:2:104264
+            n  python-test-evaluator.js:2:104264
?             ++ python-test-evaluator.js:2:104264
-            t+            t  ?             ++ python-test-evaluator.js:2:104264
 : Expected different chart representation. Check that all spacing is exact. python-test-evaluator.js:2:104264

That looks like a different error than what is mentioned in Test #19.

To check your spacing, try testing like this:
print(create_spend_chart(categories).replace(" ","."))

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

    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):
        return sum(map(lambda x: x['amount'], self.ledger))

    def transfer(self, amount, category):
        if self.check_funds(amount):
            self.withdraw(amount, f'Transfer to {category.name}')
            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):
        text = self.name.center(30,'*')
        for entry in self.ledger:
            float_amount = f"{entry['amount']:.2f}"
            text += f"\n{entry['description'][:23].ljust(23)}"
            text += f"{float_amount[:7].rjust(7)}"
        text += f"\nTotal: {self.get_balance()}"
        return text
        
def create_spend_chart(categories):
    def sum_withdraw(categorie):
        total = 0
        for entry in categorie.ledger:
            if entry["amount"] < 0:
                total += entry['amount']
        return total

    def sum_all_withdraw(categories):
        total = 0
        for categorie in categories:
            total += sum_withdraw(categorie)
        return total

    def max_name_len(categories):
        max = 0
        for categorie in categories:
            if len(categorie.name) > max:
                max = len(categorie.name)
        return max

    total_withdraw = abs(sum_all_withdraw(categories))
    categories_percentage = {}
    for categorie in categories:
        categories_percentage[categorie.name] = round(abs(sum_withdraw(categorie)/total_withdraw),1)*100

    print(categories_percentage)
    fullgraph = []
    # title
    title = 'Percentage spent by category'
    fullgraph.append(title)

    # label y-axis
    for label in range(100,-10,-10):
        fullgraph.append(f"{str(label).rjust(3)}| ")
        for categorie_name in categories_percentage.keys():
            if categories_percentage[categorie_name] >= label:
                fullgraph[-1] = fullgraph[-1] + "o" + 2 *" "
            else:
                fullgraph[-1] = fullgraph[-1] + 3 * " "

    fullgraph.append(3*" "+ len(categories) * "---" + 2*"-")

    
    # x axis labels
    labels = []
    for index in range(max_name_len(categories)):
        label = ""
        label = label + 3 * " "
        for name in categories_percentage.keys():
            if index < len(name):
                label += 2 * " " + name[index]
            else:
                label +=  3 * " "
        labels.append(label+ 2 * " ")

    for i,line in enumerate(fullgraph):
        print(i, len(line))
    for i,line in enumerate(labels):
        print(i, len(line))
    fullgraph.extend(labels)
    return "\n".join(fullgraph)
        
    


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(35.40, "jeans pants")
auto = Category('Auto')
food.transfer(50, auto)
auto.withdraw(35.40, "gas")
print(create_spend_chart([food, clothing, auto]))

i dont know what is wrong in my function to round percentage. i am testing all my lines have 14 chars length

Hey acordado!

I think the issue is with how you’re rounding the percentage. The test says it needs to be rounded down to the nearest 10, rather than using round(..., 1). For example, 35% should become 30%, not 40%.

Hope this helps!

i solved with math.floor, in example:

100|          
 90|          
 80|          
 70|          
 60| o        
 50| o        
 40| o        
 30| o        
 20| o  o     
 10| o  o  o  
  0| o  o  o  
    ----------
     F  C  A  
     o  l  u  
     o  o  t  
     d  t  o  
        h     
        i     
        n     
        g     

use three bars each category , more two in the end, but in example has only one bar after nine bars.

create_spend_chart should correctly show horizontal line below the bars. Using three - characters for each category, and in total going two characters past the final bar.

i solved