I have tried everything I can think of to do this on my own, to be honest. I have pulled in the “Expected Ouput” and counted out the spaces, replaced the spaces with numbers to double check that my output matched, made my output iterate numbers intead of spaces to check; nothing. So, here I am asking for help =)
I’ll attach my code (excuse the notes, I make a lot of them), and hope you guys can help to point me where in the direction I went wrong. Here’s the one and only error 'm getting:
Traceback (most recent call last):
File “/home/runner/boilerplate-budget-app-11/test_module.py”, line 94, 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.
Here’s my code:
import math
from math import floor
class Category:
def __str__(self):
# ALL OF THIS HAS TO BE RETURNED IN A SINGLE STRING =(
# The same way as the "Percentage spent by category"
i = 0
tempLedger = self.ledger
printLedger = ""
while i < len(tempLedger):
if len(tempLedger[i]["description"]) > 23:
printLedger = printLedger + "{:<23}{:>7.2f}".format(tempLedger[i]["description"][0:23], float(tempLedger[i]["amount"])) + "\n"
i = i+1
else:
printLedger = printLedger + "{:<23}{:>7.2f}".format(tempLedger[i]["description"], float(tempLedger[i]["amount"])) + "\n"
i = i+1
return("{:*^30}".format(str(self.name), str(self.ledger)) + "\n" + printLedger + "Total: {:.2f}".format(self.total))
def __init__(self, name):
self.name = name
self.ledger = list()
self.total = float()
self.totalWithdrawn = float()
self.totalDeposited = float()
# Method that accepts an amount and description.
# If no description is given, it should default to an empty string.
# The method should append an object to the ledger list in the
# form of:
# {"amount": amount, "description": description}
def deposit(self,amount_value, description_value=''):
if amount_value < 0:
return(False)
else:
dict_1 = {"amount": amount_value, "description": description_value}
self.ledger.append(dict_1)
self.total = self.total + amount_value
self.totalDeposited = self.totalDeposited + amount_value
return(True)
# Method that is similar to the deposit method, but the amount
# stored is a negative number.
# If there are not enough funds, nothing should be added to the ledger.
# This method should return TRUE if the withdrawal took place, and
# FALSE otherwise.
def withdraw(self,amount_value, description_value=''):
if amount_value < 0:
return(False)
elif self.check_funds(amount_value) == False:
return(False)
else:
amount_value = amount_value * -1
dict_1 = {"amount": amount_value, "description": description_value}
self.ledger.append(dict_1)
self.total = self.total + amount_value
self.totalWithdrawn = self.totalWithdrawn + abs(amount_value)
return(True)
# Method returns the current balance of the budget category based
# on the deposits and withdrawals that have occurred.
def get_balance(self):
return(self.total)
def return_balance(self):
return(self.total)
# Method that accepts an amount and another budget category as arguments.
# The method should add a withdrawal with the amount and the description
# "Transfer from [SOURCE BUDGET CATEGORY]"
# If there are not enough funds, nothing should be added to either ledger.
# This method should return TRUE if the transfer took place, and FALSE
# otherwise
def transfer(self, amount, budgetCategory):
if self.check_funds(amount) == False:
#print("CHECK!")
return(False)
else:
self.withdraw(abs(amount), "Transfer to " + str(budgetCategory.name))
budgetCategory.deposit(abs(amount), "Transfer from " + str(self.name))
return(True)
# Method that accepts an amount as an argument.
# It returns FALSE if the amount is greater than the balance of the budget
# and returns TRUE otherwise
# This method should be used in both the WITHDRAW and the TRANSFER methods.
def check_funds(self, amount):
if abs(amount) > self.total:
return(False)
else:
return(True)
# Besides the Category class, create a function (ouside of the class)
# called create_spend_chart that takes a list of categories as an argument.
# It should return a string that is a bar chart.
# The chart should show the percentage spent in each category passed into the
# function. The percentage spent should be calculated only with withdrawals
# and not with deposits. Down the left side of the chart should be labels 0 - 100.
# The "bars" in the bar chart should be made out of the "o" character. The height of
# each bar should be rounded down to the nearest 10. The horizontal line below the bars
# should go two spaces past the final bar. Each category name should be vertacally
# below the bar. There should be a title at the top that says "Percentage spent by category".
# This function will be tested with up to four categories.
# MAKE IT A SINGLE STRING!!!!!
def create_spend_chart(categories):
absoluteTotal = 0
for i in categories:
absoluteTotal = absoluteTotal + i.totalWithdrawn
#print("absoluteTotal = ", end="")
#print(absoluteTotal)
oneHundred = ""
ninety = ""
eighty = ""
seventy = ""
sixty = ""
fifty = ""
forty = ""
thirty = ""
twenty = ""
teen = ""
zeros = ""
nameSpace = ""
topTitle = ("Percentage spent by category")
oneHundredTitle = "100|"
oneHundred = ""
for i in categories:
#print(i.name + " = ", end="")
#print((i.totalWithdrawn/absoluteTotal)*100)
#print(absoluteTotal)
if (i.totalWithdrawn/absoluteTotal) * 100 >= 100:
oneHundred = oneHundred + " o "
else:
oneHundred = oneHundred + " "
ninetyTitle = " 90|"
ninety = ""
for i in categories:
if (i.totalWithdrawn/absoluteTotal) * 100 >= 90:
ninety = ninety + " o "
else:
ninety = ninety + " "
eightyTitle = " 80|"
eighty = ""
for i in categories:
if (i.totalWithdrawn/absoluteTotal) * 100 >= 80:
eighty = eighty + " o "
else:
eighty = eighty + " "
seventyTitle = " 70|"
seventy = ""
for i in categories:
if (i.totalWithdrawn/absoluteTotal) * 100 >= 70:
seventy = seventy + " o "
else:
seventy = seventy + " "
sixtyTitle = " 60|"
sixty = ""
for i in categories:
if (i.totalWithdrawn/absoluteTotal) * 100 >= 60:
sixty = sixty + " o "
else:
sixty = sixty + " "
fiftyTitle = " 50|"
fifty = ""
for i in categories:
if (i.totalWithdrawn/absoluteTotal) * 100 >= 50:
fifty = fifty + " o "
else:
fifty = fifty + " "
fortyTitle = " 40|"
forty = ""
for i in categories:
if (i.totalWithdrawn/absoluteTotal) * 100 >= 40:
forty = forty + " o "
else:
forty = forty + " "
thirtyTitle = " 30|"
thirty = ""
for i in categories:
if (i.totalWithdrawn/absoluteTotal) * 100 >= 30:
thirty = thirty + " o "
else:
thirty = thirty + " "
twentyTitle = " 20|"
twenty = ""
for i in categories:
if (i.totalWithdrawn/absoluteTotal) * 100 >= 20:
twenty = twenty + " o "
else:
twenty = twenty + " "
teenTitle = " 10|"
teen = ""
for i in categories:
if (i.totalWithdrawn/absoluteTotal) * 100 >= 10:
teen = teen + " o "
else:
teen = teen + " "
zeroTitle = " 0|"
zeros = ""
for i in categories:
if (i.totalWithdrawn/absoluteTotal) * 100 >= 0:
zeros = zeros + " o "
else:
zeros = zeros + " "
fourSpace = " "
# THIS IS THE LOGIC TO USE TO GET YOU THERE!!!
dashLine = ""
for i in categories:
dashLine = dashLine + "---"
dashLine = dashLine + "-"
# ^^^^^^^^^^^^^^^^^^^^^ APPLY THIS TO THE NINETY THROUGH TEEN WITH " o "
# using => for i in categories:
# then ninety = ninety + " o " logic
# plus an IF statement
# OR, do I need to apply the following logic to the NINETY through TEEN statement?
longLength = 0
for i in categories:
if len(i.name) >= longLength:
longLength = len(i.name)
x = 0
nameSpace = ""
while x < longLength:
# add fourSpace
nameSpace = nameSpace + fourSpace
for i in categories:
if x >= len(i.name):
nameSpace = nameSpace + " "
else:
nameSpace = nameSpace + " " + i.name[x] + " "
x = x+1
nameSpace = nameSpace + " \n"
# Overly long and convoluted PRINT statement, but that's how the API requires it
print(topTitle + "\n" + oneHundredTitle + oneHundred + " \n" + ninetyTitle + ninety + " \n" + eightyTitle + eighty + " \n" + seventyTitle + seventy + " \n" + sixtyTitle + sixty + " \n" + fiftyTitle + fifty + " \n" + fortyTitle + forty + " \n" + thirtyTitle + thirty + " \n" + twentyTitle + twenty + " \n" + teenTitle + teen + " \n" + zeroTitle + zeros + " \n" + fourSpace + dashLine + "\n" + nameSpace, end="")