Scientific Computing with Python Projects - Budget App

I have an issue with the bar chart part of the project. It functions well when it comes to printing the bar out in a well formatted way but I have issues with calculating the percentage which fails the tests. The instructions in the project aren’t clear on what I would have to calculate exactly. It just says to use the withdrawals and not the deposits, but I still need a “full” value to calculate the percentage the withdrawals make up from them. For example: (total_withdrawals / initial_deposit) * 100.

Your browser information:

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

Challenge: Scientific Computing with Python Projects - Budget App

Link to the challenge:

You’re calculating the percentage of the total spending spent in each category. So, your denominator is the total spent over all categories.

But then what’s the numerator if it’s not the initial deposit?

I found the solution, the percentage in question was the percentage of the individual category spending from the total spending.

NEW QUESTION:

Hi, I submitted my Budget.py app on Replit and I have 2 errors I just can’t seem to solve. Can you help, please?

My output seems to be spot on, except, when the test module runs the 2nd (hidden) test, the test module manages to add an errant (.) period just before the spend_chart. Why?

Here’s the error descriptions (there are 2):

973.96
Food
initial deposit 1000.00
groceries -10.15
restaurant and more foo -15.89
Transfer to Clothing -50.00
Total: 923.96
Clothing
Transfer from Food 50.00
-25.55
Total: 24.45
Percentage spent by category
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

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

F…F…

FAIL: test_create_spend_chart (test_module.UnitTests)

Traceback (most recent call last):
File “/home/runner/boilerplate-budget-app-1/test_module.py”, line 102, in test_create_spend_chart
self.assertEqual(actual, expected, ‘Expected different chart representation. Check that all spacing is exact.’)
AssertionError: None != 'Percentage spent by category\n100| [384 chars] t ’ : Expected different chart representation. Check that all spacing is exact.

======================================================================
FAIL: test_to_string (test_module.UnitTests)

Traceback (most recent call last):
File “/home/runner/boilerplate-budget-app-1/test_module.py”, line 91, in test_to_string
self.assertEqual(actual, expected, ‘Expected different string representation of object.’)
AssertionError: ‘[92 chars]Transfer to Entertainme -20.00\nTotal: 834.33 ’ != '[92 chars]Transfer to Entertainme -20.00\nTotal: 834.33’
Food
deposit 900.00
milk, cereal, eggs, bac -45.67
Transfer to Entertainme -20.00

  • Total: 834.33 + Total: 834.33 : Expected different string representation of object.

Ran 11 tests in 0.009s

FAILED (failures=2)

KeyboardInterrupt


And here’s the code I submitted:

# Budget App

class Category:

    def __init__(self, name):
        self.name = name
        self.balance = 0
        self.ledger = []

    def __str__(self):
        s = f"{self.name:*^30}\n"
        # Here’s the grammar of a format specifier: [[fill]align][sign][#][0][width][grouping_option][.precision][type]

        for n in self.ledger:
            descriptions = (n['description'])[0:23]  # each character of the string up until the 23rd.
            amounts = str(n['amount'])  # entire amount as a string.
            d = (f"{descriptions: <23}")
            a = (f"{float(amounts): >#7.2f}\n")
            s += d
            s += (a)[0:7] + "\n"
        s += (f"Total: {self.balance:<#23.2f}\n")[0:30]
        #s += "\n"

        return s

    # DEFINE METHODS = FUNCTIONS (with self-contained variables)
    def get_balance(self):
        return self.balance

    def check_funds(self, amount):  # per category
        self.amount = amount

        if self.amount <= self.balance:
            return True
        else:
            return False

    def deposit(self, amount, description=""):
        self.balance += amount
        self.ledger.append({"amount": amount, "description": description})  # can take ONE argument
        return True

    def withdraw(self, amount, description=""):

        if self.check_funds(amount):
            self.balance -= amount
            self.ledger.append({"amount": -abs(amount), "description": description})
            return True
        else:
            amount = 0
            return False

    def transfer(self, amount, instance):

        if self.check_funds(amount):
            description_transfer = f"Transfer ${amount} from {self.name} to {instance.name}."
            self.withdraw(amount, f"Transfer to {instance.name}")
            instance.deposit(amount, f"Transfer from {self.name}")
            return True
        else:
            return False

    def print_ledger(self):
        print(self.__str__())

    def get_withdrawls(self):
        global cat_total
        cat_total = 0

        for item in self.ledger[0:]:
            if int(item['amount']) < 0:
                cat_total += item['amount']

        return cat_total

# -------------------OUTSIDE OF CLASS------------------- #
def get_totals(names):
    total = 0
    totals = []
    for each in names:
        total += Category.get_withdrawls(self=each)
        totals.append(Category.get_withdrawls(self=each))
    rounded = list(map(lambda x: math_reduce(x / total), totals))  # x is each in totals list, x/grand total for each.
    return rounded

def math_reduce(n):
    multiplier = 10
    return int(n * multiplier) / multiplier

# ***********************************^^^WORKS^^^*********************************** #

def create_spend_chart(categories):

    p = "Percentage spent by category\n"
    percentages = []
    names_list = []
    nums_list = []
    padded = []

    for cat in categories:  # use.method
        names_list.append(cat.name)
        nums_list.append(cat.get_withdrawls())
        height = (len(max(names_list, key=len)))
        padded = [name.ljust(height) for name in names_list]

    percentages.append(get_totals(categories))

    # PERCENTAGES FOR CHART
    percentages_big = []
    for i in percentages[0]:
        multiplied = i * 100
        percentages_big.append(multiplied)

    # THE CHART
    for n in range(100, -1, -10):
        p += f"{n:>3}" + "| "
        for percent in percentages_big:
            if percent >= n:
                p += "o  "
            else:
                p += "   "
        p += "\n"
    p += f"{'    ' + '-' + (('-' * 3) * len(categories))}\n"

    for name in zip(*padded):
        p += ('     ' + ('  '.join(name))) + '  \n'
    print(p)