Scientific Computing with Python - Budget App

Hey,
I’ve finished writing the app but the last test just won’t go through. My chart looks exactly like the example but it always says that a different chart representation should be printed. I’m getting desperate here. Please help me.

import math

class Category:
    instances = []

    def __init__(self, category_name):
        self.category_name = category_name
        self.ledger = []
        Category.instances.append(self)

    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(item['amount'] for item in self.ledger)
    
    def transfer(self, amount, destination_category):
        if self.check_funds(amount):
            self.withdraw(amount, f'Transfer to {destination_category.category_name}')
            destination_category.deposit(amount, f'Transfer from {self.category_name}')
            return True
        else:
            return False
    
    def check_funds(self, amount):
        return self.get_balance() >= amount

    def __str__(self):
        title = f'*{self.category_name.center(28, "*")}*'
        lines = [title]
        for item in self.ledger:
            description = item['description'][:23]
            amount = '{:.2f}'.format(item['amount']).rjust(7)
            lines.append(f'{description.ljust(23)}{amount}')
        lines.append(f'Total: {self.get_balance():.2f}')
        return '\n'.join(lines)

def create_spend_chart(categories):
    def percentage_per_category(categories):
            category_withdraw = {}
            total_withdraw = 0.00
            for category in categories:
                withdraw = -round(sum(item['amount'] for item in category.ledger if item['amount'] < 0), 2)
                category_withdraw[category.category_name] = withdraw
                total_withdraw += withdraw
            
            percentages = {}
            for category, withdraw in category_withdraw.items():
                percentages[category] = (withdraw / total_withdraw) * 100
            return percentages

    percentages = percentage_per_category(categories)

    chart = "Percentage spent by category"
    for i in range(100, -1, -10):
        line = '{:3d}{:1s}'.format(i, '|')
        for category, percent in percentages.items():
            if percent >= i:
                line += " " + "o" + " "
            else:
                line += 3 * " "
        chart += "\n" + line + 2 * " "

    chart += "\n" + 4 * " "

    for iter_dash in range(len(categories)):
        chart += 3 * "-"
    chart +=  "-"

    max_len = max(len(obj.category_name) for obj in categories)
    
    for iter_maxlen in range(max_len):
        chart += "\n" + 4 * " "
        for obj in categories:
            if len(obj.category_name) < (iter_maxlen + 1):
                chart += 2 * " " + " "
                continue
            chart += " " + obj.category_name[iter_maxlen] + " "
        chart += 2 * " "
    
    return chart

food = Category("Food")
food.deposit(1000, "deposit")
food.withdraw(10.15, "groceries")
food.withdraw(15.89, "restaurant and more food for dessert")
clothing = Category("Clothing")
food.transfer(50, clothing)

spend_chart = create_spend_chart(Category.instances)
print(spend_chart)

If you take a look at the browser’s console (not the freeCodeCamp console on page), there will be specifics why test failed. It seems there’s one space too many at the end of each line.

Thanks for the tip. I changed it so that the browser console at least displays the expected 364 chars. But it still doesn’t pass the test. As I understand the output of the browser console the test has a problem with the last character but I have too little knowledge to understand the error. Could you explain the problem to me?

import math

class Category:
    instances = []

    def __init__(self, category_name):
        self.category_name = category_name
        self.ledger = []
        Category.instances.append(self)

    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(item['amount'] for item in self.ledger)
    
    def transfer(self, amount, destination_category):
        if self.check_funds(amount):
            self.withdraw(amount, f'Transfer to {destination_category.category_name}')
            destination_category.deposit(amount, f'Transfer from {self.category_name}')
            return True
        else:
            return False
    
    def check_funds(self, amount):
        return self.get_balance() >= amount

    def __str__(self):
        title = f'*{self.category_name.center(28, "*")}*'
        lines = [title]
        for item in self.ledger:
            description = item['description'][:23]
            amount = '{:.2f}'.format(item['amount']).rjust(7)
            lines.append(f'{description.ljust(23)}{amount}')
        lines.append(f'Total: {self.get_balance():.2f}')
        return '\n'.join(lines)

def create_spend_chart(categories):
    def percentage_per_category(categories):
        category_withdraw = {}
        total_withdraw = 0.00
        for category in categories:
            withdraw = -round(sum(item['amount'] for item in category.ledger if item['amount'] < 0), 2)
            category_withdraw[category.category_name] = withdraw
            total_withdraw += withdraw
            
        percentages = {}
        for category, withdraw in category_withdraw.items():
            percentages[category] = (withdraw / total_withdraw) * 100
        return percentages

    percentages = percentage_per_category(categories)

    chart = "Percentage spent by category\n"
    for i in range(100, -1, -10):
        line = '{:3d}{:1s}'.format(i, '|')
        for category, percent in percentages.items():
            if percent >= i:
                line += " " + "o" + " "
            else:
                line += 3 * " "
        chart += line + " " + "\n"

    max_len = max(len(obj.category_name) for obj in categories)
    chart += " " * 4 + "-" * (len(categories) * 3 + 1) + "\n"

    for iter_maxlen in range(max_len):
        chart += " " * 5
        for obj in categories:
            if len(obj.category_name) > iter_maxlen:
                chart += obj.category_name[iter_maxlen] + 2 * " "
            else:
                chart += 3 * " "
        chart += "\n"

    return chart

food = Category("Food")
food.deposit(1000, "deposit")
food.withdraw(10.15, "groceries")
food.withdraw(15.89, "restaurant and more food for dessert")
clothing = Category("Clothing")
food.transfer(50, clothing)
apartment = Category("Apartment")
apartment.deposit(2000)
apartment.withdraw(500)

spend_chart = create_spend_chart(Category.instances)
print(spend_chart)

Right now the issue is the new line character - \n - on the last line.

Thank you very, very much. I was so desperate, you are a real lifesaver.