Scientific Computing with Python Projects - Budget App

Tell us what’s happening:

can you tell me what’s wrong with my code. I test the code in vscode & the output is exactly the same

Your code so far

class Category:
    def __init__(self, categories):
        self.categories = categories
        self.ledger = []
        self.amount_to_withdraw = 0

    def deposit(self, amount, description=""):
        if self.ledger == []:
            self.ledger.append({"amount": round(float(amount), 2), "description": "Initial deposit"})
        else:
            self.ledger.append({"amount": round(float(amount), 2), "description": description})

    def withdraw(self, amount_to_withdraw, description=""):
        # print(amount_to_withdraw)
        self.amount_to_withdraw = -round(float(amount_to_withdraw), 2)
        # print(self.amount_to_withdraw)
        if self.check_funds():
            self.ledger.append({"amount": round(-float(amount_to_withdraw), 2), "description": description})

    # calculate & return the amount balance
    def get_balance(self):
        balance = 0
        for amounts in self.ledger:
            balance += amounts["amount"]
        return round(float(balance), 2)

    # transfer the amount from object a to object b 
    def transfer(self, amount_to_withdraw, object_category):
        self.amount_to_withdraw = round(-float(amount_to_withdraw), 2)
        if self.check_funds():
            self.ledger.append({"amount": self.amount_to_withdraw, "description": f"Transfer to {object_category.categories}"})
            object_category.deposit(-self.amount_to_withdraw, "deposit")
            
    # check if withdraw or transfer amount less than account balance
    def check_funds(self):
        amount_to_check = self.amount_to_withdraw
        if -amount_to_check > self.get_balance():
            return False
        return True
    
    # print the string from object
    def __str__(self):
        title = self.categories.center(30, "*")
        ledger_after_format = [f'{x["amount"]:.2f}'.format() for x in self.ledger]
        content = "\n".join([f'{str(ledger_list["description"][:23]).ljust(23)}{ledger_after_format[x].rjust(7)}' for x, ledger_list in enumerate(self.ledger)])
        return f'{title}\n{content}\nTotal: {self.get_balance():.2f}'.format()

# draw a spending printed chart     
def create_spend_chart(categories):
    
    total_spending = sum(-spent["amount"] for spent in categories if spent["amount"] <= -1)
    percent_spending = {cashout["description"]:(round((-cashout["amount"]/total_spending)*100)//10)*10 for cashout in categories if cashout["amount"] <= -1}

    print("Percentage spent by category")
    percentage = 100
    while percentage > -1 :
        print(f"{str(percentage).rjust(3)}{'|'.rjust(1)}{''.rjust(1)}", end='')
        for x, y in percent_spending.items():
            if y >= percentage:
                print('o', end=('').rjust(2))
            else:
                print(' ', end=('').rjust(2))
        print("")
        percentage -= 10
    # print("")
    print(f"{''.rjust(4)}{('-'*((len(percent_spending)*3)+1)).ljust(9)}")

    try:
        max_length = max(len(word) for word in [x for x in percent_spending.keys()]) 

        for i in range(max_length):
            output_string = ("").rjust(2).join([word[i] if len(word) > i else " " for word in [x for x in percent_spending.keys()]])
            print("".rjust(4), output_string)
    
    except ValueError:
        return ''

WARNING

The challenge seed code and/or your solution exceeded the maximum length we can port over from the challenge.

You will need to take an additional step here so the code you wrote presents in an easy to read format.

Please copy/paste all the editor code showing in the challenge from where you just linked.

Replace these two sentences with your copied code.
Please leave the ``` line above and the ``` line below,
because they allow your code to properly format in the post.

Your browser information:

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

Challenge Information:

Scientific Computing with Python Projects - Budget App

create_spend_chart is not expected to print anything on it own, but to return the string with the chart representation.

this is the updated code

def create_spend_chart(categories):
    
    total_spending = sum(-spent["amount"] for spent in categories if spent["amount"] <= -1)
    percent_spending = {cashout["description"]:(round((-cashout["amount"]/total_spending)*100)//10)*10 for cashout in categories if cashout["amount"] <= -1}

    chart_title = "Percentage spent by category"

    listed_printed_chart = []
    for x in range(100, -1, -10):
        # b = ' '.join(['o'.rjust(1) if value >= x else ''.rjust(1) for key, value in words.items()])
        bar = []
        for value in percent_spending.values():
            if bar == []:
                if value >= x:
                    bar.append('o'.rjust(1))
                else:
                    bar.append(' '.rjust(1))
            else:
                if value >= x:
                    bar.append('o'.rjust(3))
                else:
                    bar.append(' '.rjust(3))
        c = '\n'.join([f"{str(x).rjust(3)}{'|'}{''.rjust(1)}"])
        listed_printed_chart.append(f'{c}{"".join(bar)}')
    printed_chart = "\n".join(listed_printed_chart)

    horizontal_bar = f"{''.ljust(4)}{('-'*((len(percent_spending)*3)+1)).ljust(9)}"

    try:
        max_length = max(len(word) for word in [x for x in percent_spending.keys()]) 
        category_name = []
        for i in range(max_length):
            output_string = ("").rjust(2).join([word[i] if len(word) > i else " " for word in [x for x in percent_spending.keys()]])
            category_name.append(f'{output_string.rjust((len(percent_spending)*3)+3)}')
        horizontal_category = '\n'.join(category_name)
    except ValueError:
        horizontal_category = ''
    return f'{chart_title}\n{printed_chart}\n{horizontal_bar}\n{horizontal_category}'

Capture why i didn’t pass?

You would need to post your full updated code. The errors are for the deposit method and you just posted the chart function.

You should look at your deposit method and see why it’s not doing what the error hints are asking for.

full code

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

    def deposit(self, amount, description=""):
        self.ledger.append({"amount": float(amount), "description": description})

    def withdraw(self, amount_to_withdraw, description=""):
        amount_to_withdraw = float(amount_to_withdraw)
        if self.check_funds(amount_to_withdraw):
            self.ledger.append({"amount": -float(amount_to_withdraw), "description": description})
            return True
        return False

    # calculate & return the amount balance
    def get_balance(self):
        balance = 0
        for amounts in self.ledger:
            balance += amounts["amount"]
        return float(balance)

    # transfer the amount from object a to object b 
    def transfer(self, amount_to_transfer, object_category):
        amount_to_transfer = float(amount_to_transfer)
        if self.check_funds(amount_to_transfer):
            self.ledger.append({"amount": -amount_to_transfer, "description": f"Transfer to {object_category.categories}"})
            object_category.deposit(-amount_to_transfer, f"deposit from {self.categories}")
            return True
        return False
            
    # check if withdraw or transfer amount less than account balance
    def check_funds(self, amount):
        if amount > self.get_balance():
            return False
        return True
    
    # print the string from object
    def __str__(self):
        title = self.categories.center(30, "*")
        ledger_after_format = [f'{x["amount"]:.2f}'.format() for x in self.ledger]
        content = "\n".join([f'{str(ledger_list["description"][:23]).ljust(23)}{ledger_after_format[x].rjust(7)}' for x, ledger_list in enumerate(self.ledger)])
        return f'{title}\n{content}\nTotal: {self.get_balance():.2f}'.format()

# draw a spending printed chart     
def create_spend_chart(categories):
    
    total_spending = sum(-spent["amount"] for spent in categories if spent["amount"] <= -1)
    percent_spending = {cashout["description"]:(round((-cashout["amount"]/total_spending)*100)//10)*10 for cashout in categories if cashout["amount"] <= -1}

    chart_title = "Percentage spent by category"

    listed_printed_chart = []
    for x in range(100, -1, -10):
        # b = ' '.join(['o'.rjust(1) if value >= x else ''.rjust(1) for key, value in words.items()])
        bar = []
        for value in percent_spending.values():
            if bar == []:
                if value >= x:
                    bar.append('o '.rjust(1))
                else:
                    bar.append('  '.rjust(1))
            else:
                if value >= x:
                    bar.append('o '.rjust(3))
                else:
                    bar.append('  '.rjust(3))
        c = '\n'.join([f"{str(x).rjust(3)}{'|'}{''.rjust(1)}"])
        listed_printed_chart.append(f'{c}{"".join(bar)}')
    printed_chart = "\n".join(listed_printed_chart)

    horizontal_bar = f"{''.ljust(4)}{('-'*((len(percent_spending)*3)+1)).ljust(9)}"

    try:
        max_length = max(len(word) for word in [x for x in percent_spending.keys()]) 
        category_name = []
        for i in range(max_length):
            output_string = ("").rjust(2).join([word[i] if len(word) > i else " " for word in [x for x in percent_spending.keys()]])
            category_name.append(f'{output_string.rjust((len(percent_spending)*3)+3)}')
        horizontal_category = '\n'.join(category_name)
    except ValueError:
        horizontal_category = ''
    return f'{chart_title}\n{printed_chart}\n{horizontal_bar}\n{horizontal_category}'

Did you already fix it? Congrats :+1:

Screenshot 2024-03-14 092526

Capture
Capture1
can u explain what’s wrong with my code.

The transfer method should increase the balance of the category object passed as its argument.

Have a look through your transfer method, here is the line you deposit to the new category.

ok., now only these two is error
Capture

Capture1

. The method should add a withdrawal with the amount and the description “Transfer to [Destination Budget Category]”.

object_category.deposit(amount_to_transfer, f"deposit from {self.categories}")

You need to carefully read the hint and check the lines of code to make sure they follow the instructions. Check the descriptions.

ok, now i have passed all the test except this one can you tell me what’s wrong with the example output.
Capture1

below is the full updated code

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

    def deposit(self, amount, description=""):
        self.ledger.append({"amount": float(amount), "description": description})

    def withdraw(self, amount_to_withdraw, description=""):
        amount_to_withdraw = float(amount_to_withdraw)
        if self.check_funds(amount_to_withdraw):
            self.ledger.append({"amount": -float(amount_to_withdraw), "description": description})
            return True
        return False

    # calculate & return the amount balance
    def get_balance(self):
        balance = 0
        for amounts in self.ledger:
            balance += amounts["amount"]
        return float(balance)

    # transfer the amount from object a to object b 
    def transfer(self, amount_to_transfer, object_category):
        amount_to_transfer = float(amount_to_transfer)
        if self.check_funds(amount_to_transfer):
            self.withdraw(amount_to_transfer, f"Transfer to {object_category.categories}")
            object_category.deposit(float(amount_to_transfer), f"Transfer from {self.categories}")
            return True
        return False
            
    # check if withdraw or transfer amount less than account balance
    def check_funds(self, amount):
        if amount > self.get_balance():
            return False
        return True
    
    # print the string from object
    def __str__(self):
        title = self.categories.center(30, "*")
        ledger_after_format = [f'{x["amount"]:.2f}'.format() for x in self.ledger]
        content = "\n".join([f'{str(ledger_list["description"][:23]).ljust(23)}{ledger_after_format[x].rjust(7)}' for x, ledger_list in enumerate(self.ledger)])
        return f'{title}\n{content}\nTotal: {self.get_balance():.2f}'.format()

# draw a spending printed chart     
def create_spend_chart(categories):
    sum_spending_list = {}
    total = 0
    total_all_spending = 0
    for x in categories:
        for y in x.ledger:
            if y["amount"] < 0:
                total_all_spending += -y["amount"]; total += y["amount"]
        sum_spending_list[x.categories] = -total
        total = 0
    percent_spending = {key:{"Percent":round(((value/total_all_spending)*100//10)*10), "Spent":value} for key, value in sum_spending_list.items()}
    
    chart_title = "Percentage spent by category"

    listed_printed_chart = []
    for x in range(100, -1, -10):
        bar = []
        for value in percent_spending.values():
            if bar == []:
                if value["Percent"] >= x:
                    bar.append('o '.rjust(1))
                else:
                    bar.append('  '.rjust(1))
            else:
                if value["Percent"] >= x:
                    bar.append('o '.rjust(3))
                else:
                    bar.append('  '.rjust(3))
        c = '\n'.join([f"{str(x).rjust(3)}{'|'}{''.rjust(1)}"])
        listed_printed_chart.append(f'{c}{"".join(bar)}')
    printed_chart = " \n".join(listed_printed_chart)

    horizontal_bar = f"{''.ljust(4)}{('-'*((len(percent_spending)*3)+1)).ljust(9)}"

    try:
        max_length = max(len(word) for word in [x for x in percent_spending.keys()]) 
        category_name = []
        for i in range(max_length):
            output_string = ("").rjust(2).join([word[i] if len(word) > i else " " for word in [x for x in percent_spending.keys()]])
            category_name.append(f'{output_string.rjust((len(percent_spending)*3)+3)}')
        horizontal_category = '  \n'.join(category_name)
    except ValueError:
        horizontal_category = ''
    return f'{chart_title}\n{printed_chart} \n{horizontal_bar}\n{horizontal_category}'

Here is the data the test uses:

food = Category("Food")
entertainment = Category("Entertainment")
business = Category("Business")    
food.deposit(900, "deposit")
entertainment.deposit(900, "deposit")
business.deposit(900, "deposit")

food.withdraw(105.55)
entertainment.withdraw(33.40)
business.withdraw(10.99)

print(repr(create_spend_chart([business, food, entertainment]))

And here is the expected output:

Percentage spent by category
100|          
 90|          
 80|          
 70|    o     
 60|    o     
 50|    o     
 40|    o     
 30|    o     
 20|    o  o  
 10|    o  o  
  0| o  o  o  
    ----------
     B  F  E  
     u  o  n  
     s  o  t  
     i  d  e  
     n     r  
     e     t  
     s     a  
     s     i  
           n  
           m  
           e  
           n  
           t  
'Percentage spent by category\n100|          \n 90|          \n 80|          \n 70|    o     \n 60|    o     \n 50|    o     \n 40|    o     \n 30|    o     \n 20|    o  o  \n 10|    o  o  \n  0| o  o  o  \n    ----------\n     B  F  E  \n     u  o  n  \n     s  o  t  \n     i  d  e  \n     n     r  \n     e     t  \n     s     a  \n     s     i  \n           n  \n           m  \n           e  \n           n  \n           t  '

Here’s the output I get with your code:

'Percentage spent by category\n100|          \n 90|          \n 80|          \n 70|    o     \n 60|    o     \n 50|    o     \n 40|    o     \n 30|    o     \n 20|    o  o  \n 10|    o  o  \n  0| o  o  o  \n    ----------\n     B  F  E  \n     u  o  n  \n     s  o  t  \n     i  d  e  \n     n     r  \n     e     t  \n     s     a  \n     s     i  \n           n  \n           m  \n           e  \n           n  \n           t'
Percentage spent by category
100|          
 90|          
 80|          
 70|    o     
 60|    o     
 50|    o     
 40|    o     
 30|    o     
 20|    o  o  
 10|    o  o  
  0| o  o  o  
    ----------
     B  F  E  
     u  o  n  
     s  o  t  
     i  d  e  
     n     r  
     e     t  
     s     a  
     s     i  
           n  
           m  
           e  
           n  
           t

It looks good :+1: You are just missing 2 spaces at the end to square off the chart

Screenshot 2024-03-15 071249

Screenshot 2024-03-15 071353

1 Like

thanks, finally i solved this project there so much details and little bit confusing btw, i need to pay more attention. :grinning:

1 Like

Yeah, in some cases you really need to pay close attention to the instructions and make sure you are implementing it exactly.

I think the tests could provide a bit more feedback. Especially the last one, I think it would be extremely tough to solve without the information I provided here.

Hopefully you learned something about working with the tests and how to troubleshoot them! Dig down to the details, use print() a lot to view variables and results and analyze exactly what is happening at each step of your program.

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.