FCC Challenge: JS: Cash Register

This one really pushed me to my limits. I had to take a break. I solved it, I think, in nearly a week. This is a really untidy one. Doing it day after day sometimes make me forget about the code, and had to re-skim the code, had to use debug techniques, and had to make comment lines to save me some time in understanding my own code.

I can’t think of more ways of tidying up the code, because I think their positioning mattered. Maybe you can?

You can ask for clarification if the comments were’nt enough. And, I would like to know ALL of your thoughts on my ‘messy’ approach.

It was fun and frustrating, Loved it FCC!
Thank you!

Solution
function checkCashRegister(price, cash, cid) {

  // currency in the comment means penny, dime, nickel...

  // initial variables
  // cashSetChange - array of currency units that stores the change
  // totalCash - sum of cash in drawer (cid)
  cash*=1000;
  price*=1000;
  let currAmt=[10,50,100,250,1000,5000,10000,20000,100000];
  let totalCash=0;
  cid.forEach(item => totalCash+=item[1]*1000);
  let change = cash-price;
  let cashSetChange=[];
  cid.forEach(item => item[1]*=1000);

  let insufficientFunds = () => {
    return {status:"INSUFFICIENT_FUNDS", change:[]};
  }

  let closed = () =>{
    // replaces with change those currency that has 0 value in cid 
    for(let i in cashSetChange){
      for (let x in cid){
        if(cid[x][0] == cashSetChange[i][0]){
          cid[x][1] = cashSetChange[i][1];
        }
      }
    }
    return {status:"CLOSED", change:cid};
  }

  let open = () => {
    return {status:"OPEN", change:cashSetChange}
  }

  // obvious insufficient funds
  if(totalCash < change){
    return insufficientFunds();
  }

// function for calculating the change: start checking from highest currency unit using amtIndex
// amtIndex - acts as the pointer of what currency (penny, dime...) is being evaluated in the function.
  let intChange =0;
  let calcChange = (amtIndex) => { 

    // TEST CODE- uncomment the line below for debug
    // console.log("change: "+ change +"  currAmt: "+currAmt[amtIndex]+ "  cid: "+cid[amtIndex][1] +"      amtIndex: " + amtIndex);

    // the change needed is satisfied
    if(change <= 0){ return "case_sufficient"; }

    // move to lower currency only if currency is too much for change OR drawer has no cash for that specific currency
    if(change < currAmt[amtIndex] || cid[amtIndex][1]<=0){
      amtIndex--;
      intChange=0;
    }

    // this has reached the lowest currency and theres not enough money for change
    if(amtIndex < 0){ return "case_insufficient"; }

    // if specific currency is enough for change AND has cash in drawer
    if(change-currAmt[amtIndex] >= 0 && cid[amtIndex][1] > 0){ 

      // subtract value of currency from change, from drawer, and totalCash
      change -= currAmt[amtIndex];
      totalCash -= currAmt[amtIndex];
      cid[amtIndex][1] -= currAmt[amtIndex];

      // accumulate the currency
      intChange+= currAmt[amtIndex];

      // save the changes to cashSetChange before it moves to next currency
      if(change < currAmt[amtIndex] || cid[amtIndex][1]<=0){
        cashSetChange.push([cid[amtIndex][0], intChange/1000]);
      }
    }

    return calcChange(amtIndex);
  }

  let theCase = calcChange(currAmt.length-1);

  let res = theCase == "case_insufficient" ? insufficientFunds() : totalCash <= 0? closed() : open();

  // to see what is being returned
  console.log(res);

  return res;
  
}

checkCashRegister(19.5, 20, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]);