Budget App, chart representation problem

Tell us what’s happening:

Hi! I just been having trouble giving the proper format to the chart. I think it’s a spacing problem or something like that, but at this point I’m not able to see where’s the error. In many different posts I’ve seen the responses, including very graphical evaluations of the differences between the expected and actual outputs. I just can’t find that valuable resource again. I would like to do that on my own. Can anybody tell me how I can do that so I don’t have to bother in the forum each time for this reason?? Thanks!!

Your code so far

class Category:

def __init__ (self, name):
    self.name= name
    self.ledger= [] # Un diccionario que muestra los distintos movimientos en la cuenta.
    self.balance= 0
    self.add_withdraws= 0 #Suma todos los retiros para ser utilizados en la funcion externa spend_chart

def deposit (self, amount, description= ""):  #CUIDADO: description PODRIA TENER QUE SER " "
    aDict= {}
    aDict ["amount"]= amount
    aDict ["description"]= description
    self.ledger.append (aDict)

    self.balance = self.balance + amount

def withdraw (self, amount, description= ""):
    #Se crea un diccionario para que los elementos del ledger esten en el
    #formato indicado
    bDict= {}

    if self.check_funds(amount) == True: #Solo si hay fondos se hace la extraccion
    #if self.balance - amount >= 0:
        bDict ["amount"]= - amount
        bDict ["description"]= description
        self.ledger.append (bDict)
        self.balance= self.balance - amount
        self.add_withdraws= self.add_withdraws + amount
        withdrew = True
    elif self.check_funds(amount) == False :
         withdrew = False
    return withdrew

def get_balance (self): #Devuelve el balance de la cuenta
    #NOTAR: self.balance está definida como variable de clase, en el
    #metodo __init__
    return (self.balance)


def transfer (self, amount ,other): #Se transfiere desde self hacia other, hay fondos suficientes en self
    if self.check_funds(amount) == True:
        To_description= "Transfer to " + other.name
        self.withdraw(amount, To_description)
        From_description= "Transfer from " + self.name
        other.deposit(amount, From_description)

        return True
    else: return False


def check_funds (self, amount):
    if self.balance - amount >= 0:
        return True
    else:
        return False


def __str__(self): #Este metodo overrides la funcion print
    title= self.name.center(30, '*')
    Cadena= title

    for i in range (len(self.ledger)) :

        #Si la description tiene menos de 23 letras, completo con espacios y
        #la centro a la izquierda
        #Si la description tiene mas de 23 letras, corto el excedente

        description= self.ledger[i] ['description'] [0:23]
        description= description.ljust(23)

        #Tratamiento del Monto
        amount_display= str(self.ledger[i] ['amount'])
        #Agrego el punto decimal a los numeros que no lo tienen:
        if '.' not in amount_display:
            amount_display= amount_display + '.00'

        amount_display= amount_display.rjust(7)


        Cadena = Cadena + '\n' + description + amount_display

    #Formateo el monto total
    balance_display= str(self.balance)
    if '.' not in balance_display:
        balance_display = balance_display + '.00'
    Cadena = Cadena + '\n' + 'Total: ' + balance_display
    #Cadena = str(self.balance)
    return Cadena   #Si trato de devolver varios elementos, el metodo __str__ falla
                    #Esto se debe a que __str__ overrides a print () y este
                    #ultimo espera un string como argumento

def create_spend_chart(Cat_list):
import math
if len (Cat_list) > 4:
print('No se pueden analizar mas de 4 categorias ')
return

gasto_total= 0
porcentaje_gasto= []
max_len= len(Cat_list[0].name) #Longitud maxima entre los nombre de las categorias

#Sumo los retiros de todas las cuentas. Incluso las transferencias entre cuentas
#son consideradas un gasto. Esto es medio choto, pero el modulo de testeo
#no contempla esta posibilidad, so fuck it.

for category in Cat_list:
    gasto_total= gasto_total + category.add_withdraws

for i in range (len(Cat_list)):
    #print(i, Cat_list[i].add_withdraws)
    porcentaje_gasto= porcentaje_gasto + [int((Cat_list[i].add_withdraws / gasto_total * 100)//10 * 10)]
    print(Cat_list[i].name,porcentaje_gasto)

    #Determino la longitud para los nombres de las categorias debajo de todo:
    #NO SE SI ES DEL TODO NECESARIO...
    if max_len < len(Cat_list[i].name):
        max_len = len(Cat_list[i].name)
#print('max_len: ', max_len)


first_line= 'Percentage spent by category'
print(first_line) #,'\n', porcentaje_gasto, '\n', gasto_total)
#print(porcentaje_gasto[0],porcentaje_gasto[1],porcentaje_gasto[2])
for i in reversed (range (11)):
    line= (str(i*10).rjust(3) + '|' + ' ')

    for j in range(len(Cat_list)):
        #print(porcentaje_gasto[j])
        if i*10 <= porcentaje_gasto[j]:
            line= line + 'o' + 2* ' '
        elif i*10 > porcentaje_gasto[j]:
            line= line + 3 * ' '
            #print(porcentaje_gasto[j])
    line= line + 2 * ' '


    print (line)
#Linea divisoria con '----':
print ('    ' + (3*len(Cat_list)+1) * '-')

#Escribo los nombres de las categorias de manera vertical
for i in range(max_len):
    #if i>3: return
    line = 5* ' '
    for j in range(len(Cat_list)):
        if i > len(Cat_list[j].name) - 1:   #Recordar que len es el numero de elementos, pero los indices van
                                            #desde 0 hasta (len-1)
            line= line + ' ' + 2* ' '
        else:
            line= line + Cat_list[j].name[i] + 2* ' '

    #Agrego dos espacios al final de cada Linea
    line= line + 2 * ' '

    print (line)

Your browser information:

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

Challenge: Budget App

Link to the challenge:

Please include a link to your code so we can look at the error.
As it is a Traceback error, it will show in which file and which line the error occured.
Reading it in the Replit console is a bit hard because of formatting there.

What I do is take this comment-window, paste the error-message, make sure “expected” and “actual” results are on a seperate line and use the “</>” button to format it as code. This way it’s easier to spot differences.

https://replit.com/ @AdrianParodi/boilerplate-budget-app-5#budget.py

I don’t know why I cannot share it. I added a space between / and “@” and now is visible

When I do what you suggested I get the following:

Expected (from line 101 of the test module)

"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  "

Actual ouput (copied from the console after running the code):

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    

I used the “</>” button, but for the expected result but I got a horrible representation. I’ve also tried to put all that into as argument for print, but it still looks terrible

Thanks for the link, although there is a wrong space in there.
Anyway I said “copy the error message” - which is this:

FAIL: test_create_spend_chart (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/A963tjngA-i/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.

----------------------------------------------------------------------

Now you gotta look at the assertion-error and usually align them properly to see differences. Although here you simply didn’t return the spend-chart at all. You printed something to the console, which wasn’t the task.

Okay Jagaya, I see now what you mean by that. I’ve been fixing some errors using this tip, as you suggested (now the function returns the chart). Nevertheless, There’s still a tiny mistake and I share the link again, just in case:

boilerplate-budget-app-5 - Replit

The only problem is at the end… I suppose that I shouldn’t add a new line after the last character has been appended to the string. I tried fixing that in my code and I couldn’t surpass the error. Can you please take a look to it and give me some advice? Below I pasted the evaluation of the code. Thanks for your help!

FAIL: test_create_spend_chart (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/boilerplate-budget-app-5/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: 'Perc[364 chars]         m  \n           e  \n           n  \n           t  \n' != 'Perc[364 chars]         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  
?               -
+            t   : Expected different chart representation. Check that all spacing is exact.

Firstup, there is indeed a newline to much

AssertionError:
'Perc[364 chars]         m  \n           e  \n           n  \n           t  \n' != 
'Perc[364 chars]         m  \n           e  \n           n  \n           t  '

Now you could try to alter the logic so it doesn’t add the newline at the end.
Or take the lazy approach and just return the string without the last two characters :wink:

Hey man, how are you? I could finally solve it! I was not taking into account that ‘\n’ actually has a length of 1. But I did it at last! Thank you so muc for your guidance, I truly appreciate it! :smiley: