Budget app - Test_create_spend_chart

Hello, campers!
I get fail at the last test and i understand that something wrong with spacing. I get more chars than in test example but there are too many in my case 348 vs 254. I can hardly find 8 odd spaces. Where are the others?

class Category:
  def __init__(self, name):
        self.name = name # instance variable unique to each instance
        self.ledger = list()

  def __str__(self):
      list_gro = ''
      for k in range(len(self.ledger)):
        list_gro += self.ledger[k]['description'][:23] + ' '*(30 - len(self.ledger[k]['description'][:23]) - len(str('{0:.2f}'.format(self.ledger[k]['amount'])))) + str('{0:.2f}'.format(self.ledger[k]['amount']))+"\n"
      total = 'Total: ' + str(self.get_balance())
      return "*"*int((30 - (len(self.name))) / 2) + self.name + "*"*int((30 - (len(self.name))) / 2)+'\n' + list_gro + total
  
  
  def deposit(self, depo, desc=''):
    self.ledger.append({'amount': depo, 'description': desc})

  
  def withdraw(self, withdr, desc=''):
    if self.check_funds(withdr):
      self.ledger.append({'amount': -withdr, 'description': desc})

      return True  
    else:
      return False         

  def get_balance(self):
    wh_mn = 0 #deposit - withdraws
    for k in range(len(self.ledger)):
      wh_mn += self.ledger[k]['amount']
    return wh_mn 

  def transfer(self, amount, categ):
    
    if(self.withdraw(amount, 'Transfer to '+categ.name)):
        categ.deposit(amount, 'Transfer from '+self.name)
        return True
    return False
  
  def check_funds(self,amount):
    wh_mn = 0 #deposit - withdraws
    for k in range(len(self.ledger)):
      wh_mn += self.ledger[k]['amount']
    if(wh_mn >= amount):
      return True
    else:
      return False
  
  

def create_spend_chart(categories):
  text_out = 'Percentage spent by category\n'

  name_0 = categories[0].name
  name_1 = categories[1].name
  name_2 = categories[2].name
  print(categories[0].ledger)
  sum_0 = 0
  for i in range(1,len(categories[0].ledger)):
    sum_0 += categories[0].ledger[i]['amount']
  sum_1 = 0
  for i in range(1,len(categories[1].ledger)):
    sum_1 += categories[1].ledger[i]['amount']
  sum_2 = 0
  for i in range(1,len(categories[2].ledger)):
    sum_2 += categories[2].ledger[i]['amount']  
  jj = abs(int(sum_0/10))
  kk = abs(int(sum_1/10))
  ll = abs(int(sum_2/10))
  for k in range(100, 0, -10):
     r = 0
     t = 0
     s = 0
     if(k/10 <= jj): r = 1
     if(k/10 <= kk): t = 1
     if(k/10 <= ll): s = 1
     text_out += ' '*(3 - len(str(k))) + str(k) + '| ' + 'o'*r + '  '*r + 'o'*t + '  '*t + 'o'*s+'\n'
  text_out += ' '*4 + '-'*10 + '\n'
  list_m = [len(name_0),len(name_1),len(name_2)]
  name_0 += ' '*((max(list_m) - len(name_0)))
  name_1 += ' '*((max(list_m) - len(name_1)))
  name_2 += ' '*((max(list_m) - len(name_2)))
  for g in range(max(list_m)):
    text_out += ' '*5 + name_0[g]+ '  ' + name_1[g]+ '  '+ name_2[g]+'\n'
  print(len(text_out))
  return text_out

You can get more output by adding

    def test_create_spend_chart(self):
        self.maxDiff = None  # add this

to your test. This generates

  Percentage spent by category
- 100| o  
-  90| o  
-  80| o  
+ 100|          
+  90|          
+  80|          
-  70| o  
+  70|    o     
?      +++   +++
-  60| o  
+  60|    o     
?      +++   +++
-  50| o  
+  50|    o     
?      +++   +++
-  40| o  
+  40|    o     
?      +++   +++
-  30| o  o
+  30|    o     
-  20| o  o
+  20|    o  o  
?      +++    ++
-  10| o  o  o
?            -
+  10|    o  o  
?      +++
+   0| o  o  o  
      ----------
-      B  F  E
+      B  F  E  
?             ++
-      u  o  n
+      u  o  n  
?             ++
-      s  o  t
+      s  o  t  
?             ++
-      i  d  e
+      i  d  e  
?             ++
-      n     r
+      n     r  
?             ++
-      e     t
+      e     t  
?             ++
-      s     a
+      s     a  
?             ++
-      s     i
+      s     i  
?             ++
-            n
+            n  
?             ++
-            m
+            m  
?             ++
-            e
+            e  
?             ++
-            n
+            n  
?             ++
-            t
?             ^
+            t  ?             ^^
 : Expected different chart representation. Check that all spacing is exact.

The ‘-’ lines are your output and the ‘+’ lines are the expected output. You can see that the bars are different than expected and that each expected lines have the same number of spaces for each line. For the bars, remember that you are calculating the percent spent in a category of the total, rounded down. So for the business category, you would tally the business expenses and divide that by the total spent in all three categories (rounded down).

Good luck.

1 Like

Right now with this technique i don’t see any difference in outputs though still has 15 char difference in second part after horizontal line

class Category:
  def __init__(self, name):
        self.name = name # instance variable unique to each instance
        self.ledger = list()

  def __str__(self):
      list_gro = ''
      for k in range(len(self.ledger)):
        list_gro += self.ledger[k]['description'][:23] + ' '*(30 - len(self.ledger[k]['description'][:23]) - len(str('{0:.2f}'.format(self.ledger[k]['amount'])))) + str('{0:.2f}'.format(self.ledger[k]['amount']))+"\n"
      total = 'Total: ' + str(self.get_balance())
      return "*"*int((30 - (len(self.name))) / 2) + self.name + "*"*int((30 - (len(self.name))) / 2)+'\n' + list_gro + total
  
  
  def deposit(self, depo, desc=''):
    self.ledger.append({'amount': depo, 'description': desc})

  
  def withdraw(self, withdr, desc=''):
    if self.check_funds(withdr):
      self.ledger.append({'amount': -withdr, 'description': desc})

      return True  
    else:
      return False         

  def get_balance(self):
    wh_mn = 0 #deposit - withdraws
    for k in range(len(self.ledger)):
      wh_mn += self.ledger[k]['amount']
    return wh_mn 

  def transfer(self, amount, categ):
    
    if(self.withdraw(amount, 'Transfer to '+categ.name)):
        categ.deposit(amount, 'Transfer from '+self.name)
        return True
    return False
  
  def check_funds(self,amount):
    wh_mn = 0 #deposit - withdraws
    for k in range(len(self.ledger)):
      wh_mn += self.ledger[k]['amount']
    if(wh_mn >= amount):
      return True
    else:
      return False
  
  

def create_spend_chart(categories):
  text_out = 'Percentage spent by category\n'

  name_0 = categories[0].name
  name_1 = categories[1].name
  name_2 = categories[2].name

  sum_0 = 0
  for i in range(1,len(categories[0].ledger)):
    sum_0 += categories[0].ledger[i]['amount']
  sum_1 = 0
  for i in range(1,len(categories[1].ledger)):
    sum_1 += categories[1].ledger[i]['amount']
  sum_2 = 0
  for i in range(1,len(categories[2].ledger)):
    sum_2 += categories[2].ledger[i]['amount'] 
  sum_all = sum_0 + sum_1 + sum_2

  jj = abs(int(sum_0/(sum_all/100)))
  kk = abs(int(sum_1/(sum_all/100)))
  ll = abs(int(sum_2/(sum_all/100)))

  for k in range(100, 0, -10):
     if(k <= ll):
       s = 1
       sx=0
     else:
       s = 0
       sx=1
     if(k <= kk):
       t = 1
       tx=0
     else:
       t = 0
       tx=1
     if(k <= jj): 
       r = 1
       rx=0
     else:
       r = 0
       rx=1
     
     text_out += ' '*(3 - len(str(k))) + str(k) + '| ' + 'o'*r + '  '+' '*rx + 'o'*t + '  '+' '*tx + 'o'*s+'  '+' '*sx+'\n'
  text_out += ' '*4 + '-'*10 + '\n'
  list_m = [len(name_0),len(name_1),len(name_2)]
  name_0 += ' '*((max(list_m) - len(name_0)))
  name_1 += ' '*((max(list_m) - len(name_1)))
  name_2 += ' '*((max(list_m) - len(name_2)))
  for g in range(max(list_m)):
    text_out += ' '*5 + name_0[g]+ '  ' + name_1[g]+ '  '+ name_2[g]+'  ''\n'

  return text_out[:-1]

Testing indicates that the zero row of the chart is not printing

   10|    o  o  
+   0| o  o  o  
      ----------
       B  F  E  

The problem is in the for loop you are using to write the output. Put a prink(k) in at the top and you will see the problem immediately.

Fixing this did pass all the tests, so you’re almost there.

1 Like

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