Cash Register: So close, yet so far away

Hello!

Link to challenge is here.

Before I get into my question, I know my code is ugly. I’m sorry I’m asking you to look over such a hideous beast. =) I’m very new to JS and focused on the logic. I have a long list of things I need to go back and review, particularly ES6 to clean this up and I certainly plan to. I know I shouldn’t be in global scope like I am.

My cash register passes all tests except:
“Return {status: “INSUFFICIENT_FUNDS”, change: []} if you cannot return the exact change.”

I actually get the correct answer in my console so I’m not sure why I’m getting a fail state. I’m pretty sure the issue lies within this particular block.

//calc drawer status based on if enough change is available
  if (changeDue === changeTotal) {
      result.status = "CLOSED";
      result.change = cid;
    } else if (changeDue < changeTotal) {
        calcChange(cid, changeDue);
        //check for exact change
        for (let r = 0; r < result.change.length; r++) {
          finalChange += result.change[r][1];
         } 
        finalChange = (Math.round((finalChange)*100)/100); 
        if (finalChange < changeDue) {
          result.status = "INSUFFICIENT_FUNDS";
          result.change = [];
        }
      } else {
        result.status = "INSUFFICIENT_FUNDS";
        result.change = [];
      }

What has me pulling my hair out is that this returns a pass state

else {
        result.status = "INSUFFICIENT_FUNDS";
        result.change = [];

while this returns a fail state

if (finalChange < changeDue) {
          result.status = "INSUFFICIENT_FUNDS";
          result.change = [];

Thanks for looking.
-J

Here is my full code currently:

let changeDue;
let changeTotal;
let drawerStatus;
let changeGiven = [];
let drawer = [];
let moneyPile = [];
let twentyBill;
let tenBill;
let fiveBill;
let oneBill;
let quarterBill;
let dimeBill;
let nickelBill;
let pennyBill;
let countDownQ;
let countDownTw;
let countDownTen;
let countDownF;
let countDownO;
let countDownD;
let countDownN;
let countDownP;
let num;
let finalChange = 0;

//build object
let result = {
  status: "",
  change: ["change"]
};

function checkCashRegister(price, cash, cid) {
  changeTotal = 0;
  
  //calc change due to customer
  changeDue = Math.round((cash - price)*100)/100;
  //console.log(changeDue);    

  //calc available total in drawer - may be able to remove this section later
  for (let i = 0; i < cid.length; i++) {
    changeTotal += cid[i][1];
  } 
  changeTotal = (Math.round((changeTotal)*100)/100); 
  //console.log(changeTotal);

  //calc drawer status based on if enough change is available
  if (changeDue === changeTotal) {
      result.status = "CLOSED";
      result.change = cid;
    } else if (changeDue < changeTotal) {
        calcChange(cid, changeDue);
        //check for exact change
        for (let r = 0; r < result.change.length; r++) {
          finalChange += result.change[r][1];
         } 
        finalChange = (Math.round((finalChange)*100)/100); 
        if (finalChange < changeDue) {
          result.status = "INSUFFICIENT_FUNDS";
          result.change = [];
        }
      } else {
        result.status = "INSUFFICIENT_FUNDS";
        result.change = [];
      }

  //calc change given on "OPEN" status
  function calcChange(arr, num) {
    moneyPile = arr.reverse();
    //console.log(moneyPile);
    //console.log(num)
    result.status = "OPEN";
    result.change = [];
    
    if (num > 20) {
      twentyBill = Math.floor(num/20);
      //console.log(twentyBill);
      countDownTw = 20 * twentyBill;
      if (countDownTw > arr[1][1]) {
        countDownTw = arr[1][1];
      } 
      //console.log(countDownTw);
      num = num - countDownTw;
      //console.log(num);
      result.change.push(["TWENTY", countDownTw]);
    }

    if (num > 10) {
      tenBill = Math.floor(num/10);
      //console.log(tenBill);
      countDownTen = 10 * tenBill;
      if (countDownTen > arr[2][1]) {
        countDownTen = arr[2][1];
      } 
      //console.log(countDownTen);
      num = num - countDownTen;
      //console.log(num);
      result.change.push(["TEN", countDownTen]);
    }

    if (num > 5) {
      fiveBill = Math.floor(num/5);
      //console.log(fiveBill);
      countDownF = 5 * fiveBill;
      if (countDownF > arr[3][1]) {
        countDownF = arr[3][1];
      } 
      //console.log(countDownF);
      num = num - countDownF;
      //console.log(num);
      result.change.push(["FIVE", countDownF]);
    }

    if (num > 1) {
      oneBill = Math.floor(num/1);
      //console.log(oneBill);
      countDownO = 1 * oneBill;
      if (countDownO > arr[4][1]) {
        countDownO = arr[4][1];
      } 
      //console.log(countDownO);
      num = num - countDownO;
      //console.log(num);
      result.change.push(["ONE", countDownO]);
    }

    if (num > .25) {
      quarterBill = Math.floor(num/.25);
      //console.log(quarterBill);
      countDownQ = .25 * quarterBill;
      if (countDownQ > arr[5][1]) {
        countDownQ = arr[5][1];
      } 
      //console.log(countDownQ);
      num = num - countDownQ;
      //console.log(num);
      result.change.push(["QUARTER", countDownQ]);
      }

    if (num > .1) {
      dimeBill = Math.floor(num/.1);
      //console.log(dimeBill);
      countDownD = .1 * dimeBill;
      if (countDownD > arr[6][1]) {
        countDownD = arr[6][1];
      } 
      //console.log(countDownD);
      num = num - countDownD;
      //console.log(num);
      result.change.push(["DIME", countDownD]);
      }

    if (num > .05) {
      nickelBill = Math.floor(num/.05);
      //console.log(quarterBill);
      countDownN = .05 * nickelBill;
      if (countDownN > arr[7][1]) {
        countDownN = arr[7][1];
      } 
      //console.log(countDownN);
      num = num - countDownN;
      //console.log(num);
      result.change.push(["NICKEL", countDownN]);
      }

    if (num > .01) {
      pennyBill = Math.round(num/.01);
      //console.log(pennyBill);
      countDownP = .01 * pennyBill;
      //console.log(countDownP);
      //console.log(arr[8][1]);
      if (countDownP > arr[8][1]) {
        countDownP = arr[8][1];
      } 
      num = num - countDownP;
      result.change.push(["PENNY", countDownP]);
      }
  }
  console.log(result.status, result.change);
  return result;
  }


checkCashRegister(19.5, 20, [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 1], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])

You’re very right about calling it a hideous beast. :smile:

You should never create global variables that belong to a particular function.
And the global variables are the exact problem here.

When the FCC test suite runs, it runs test one by one and global variables never get reset after each test. I mean, when the second test runs, the global variables have some existing values from the previous test already.
I’m not sure which exact variable is causing the issue as I didn’t debug the code step by step, but just cut/paste all your variables that are outside the function and paste them into the function at the very top.

This will ensure that every time the function runs in each test, it will redeclare the variables without any value that might have changed before. And the test suite should be all good then.

Thank you for that clarification! I’ll update my code now and report back.
-J

Hazzah! It was the finalChange variable. As soon as I moved that one I got a passing state. Thank you for the input!
-J

1 Like