Build a Cash Register Project

I’ve tried to follow all your recommendations and I think that I have only 2 issues for now:

  1. If change includes one or more pennies, I still lose 1 penny elsewhere (for example, if change due is 1 penny, I don’t have any result at all, if change due is 2 pennies, the result is 1 penny…

  2. I’d like to use map method to multiply the cid array instead of writing it directly, but the code doesn’t allow me to do that (when I log the modified cid array, console shows 9 “undefined” lines instead of the array values.

May I ask you to help me with this, too, please?

const button = document.getElementById("purchase-btn");
let price = 1.87;
let cid = [
  ['PENNY', 1.01],
  ['NICKEL', 2.05],
  ['DIME', 3.1],
  ['QUARTER', 4.25],
  ['ONE', 90],
  ['FIVE', 55],
  ['TEN', 20], 
  ['TWENTY', 60],
  ['ONE HUNDRED', 100]
];

function checkRegister() {
const changeDue = document.getElementById("change-due");
let change = {stat: "", changeRegex: ""};
let resultedArr = [
  [' ONE HUNDRED: $', 0],
  [' TWENTY: $', 0],
  [' TEN: $', 0],
  [' FIVE: $', 0],
  [' ONE: $', 0],
  [' QUARTER: $', 0],
  [' DIME: $', 0],
  [' NICKEL: $', 0],
  [' PENNY: $', 0],
];
const cidMult = 
[
  ['PENNY', 101],
  ['NICKEL', 205],
  ['DIME', 310],
  ['QUARTER', 425],
  ['ONE', 9000],
  ['FIVE', 5500],
  ['TEN', 2000], 
  ['TWENTY', 6000],
  ['ONE HUNDRED', 10000]
];
const currencyKeyMult = [10000, 2000, 1000, 500, 100, 25, 10, 5, 1,];
const dicMult = cidMult.reverse();
const cash = document.getElementById("cash");
let dicTotal = 0;
for (let i = 0; i < dicMult.length; i++) {
  dicTotal += dicMult[i][1];
};

  let user_input = Number(cash.value);
  let  result = ((user_input - price) * 100);
 if (user_input < price) {
       alert("Customer does not have enough money to purchase the item");
         } else if (user_input === price) {
             changeDue.textContent = "No change due - customer paid with exact cash";
    } else {
  for (let i = 0; i < dicMult.length; i++) {
    while (dicMult[i][1] > 0) {
       if(result - currencyKeyMult[i] >= 0) {
  resultedArr[i][1] += currencyKeyMult[i] / 100;
  result -= currencyKeyMult[i];
  dicMult[i][1] -= currencyKeyMult[i];
  } else {break}
    const str = String(resultedArr);
      const regex = str.replaceAll(",", "");
      
  console.log(resultedArr);
  if (result !== 0) {
    change.stat = "Status: INSUFFICIENT_FUNDS";
  } else if (result === 0 && dicTotal === (result / 100)) {
    change.stat = "CLOSED";
    change.changeRegex = regex;
  } else { 
    resultedArr = resultedArr.filter(e => e[1] !== 0);
    change.stat = "OPEN";
    change.changeRegex = regex;
    }
  }

  changeDue.textContent = change.stat;
  changeDue.textContent += change.changeRegex;
     }
  }
}

button.addEventListener("click", checkRegister);

for your first issue, this can cause floating number precision error as you are adding a floating number. you can iterate over the resultedArr array at the end and use .toFixed() method to solve this or anyway you want.


for the second, for sure you can use it. I guess there is something wrong in your code, can you post it ?

1 Like

Thank you, Mostafa, I have solved the first problem with 1 penny. Now I finally get the correct result when the change due is $0.01. I used toFixed method as you recommended.

But I have the similar problem below and I don’t know why I can’t fix it by the same way. I tried it twice, you may see my comments in the code below.

const button = document.getElementById("purchase-btn");
let price = 1.87;
let cid = [
  ['PENNY', 1.01],
  ['NICKEL', 2.05],
  ['DIME', 3.1],
  ['QUARTER', 4.25],
  ['ONE', 90],
  ['FIVE', 55],
  ['TEN', 20], 
  ['TWENTY', 60],
  ['ONE HUNDRED', 100]
];

function checkRegister() {
const changeDue = document.getElementById("change-due");
let change = {stat: "", changeRegex: ""};
let resultedArr = [
  [' ONE HUNDRED: $', 0],
  [' TWENTY: $', 0],
  [' TEN: $', 0],
  [' FIVE: $', 0],
  [' ONE: $', 0],
  [' QUARTER: $', 0],
  [' DIME: $', 0],
  [' NICKEL: $', 0],
  [' PENNY: $', 0],
];
const cidMult = 
[
  ['PENNY', 101],
  ['NICKEL', 205],
  ['DIME', 310],
  ['QUARTER', 425],
  ['ONE', 9000],
  ['FIVE', 5500],
  ['TEN', 2000], 
  ['TWENTY', 6000],
  ['ONE HUNDRED', 10000]
];
const currencyKeyMult = [10000, 2000, 1000, 500, 100, 25, 10, 5, 1,];
const dicMult = cidMult.reverse();
const cash = document.getElementById("cash");
let dicTotal = 0;
for (let i = 0; i < dicMult.length; i++) {
  dicTotal += dicMult[i][1];
};

  let user_input = Number(cash.value);
  let  result = ((user_input - price) * 100).toFixed(0);
  if (result == dicTotal) {
    change.stat = "Status: CLOSED"
  }
 if (user_input < price) {
       alert("Customer does not have enough money to purchase the item");
         } else if (user_input === price) {
             changeDue.textContent = "No change due - customer paid with exact cash";
    } else {
  for (let i = 0; i < dicMult.length; i++) {
    while (dicMult[i][1] > 0) {
       if(result - currencyKeyMult[i] >= 0) {
  resultedArr[i][1] += currencyKeyMult[i];/* I tried to use toFixed method there first, but it spoiled the whole algorithm, so I decided to do it down in the code*/
  result -= currencyKeyMult[i];
  dicMult[i][1] -= currencyKeyMult[i];
  } else {break}
  const filtered = resultedArr.filter(e => e[1] !== undefined);
const rightArr = filtered.filter(e => e[1] > 0);
const eachArr = rightArr.forEach(a => a[1] = Number(a[1]/100).toFixed(2)); /* so I tried to use for each method there*/
console.log(eachArr); /* I got a long list of undefined and warning about potential infinite loop*/
    const str = String(eachArr);
      const regex = str.replaceAll(",", "");
        change.changeRegex = regex;
          
  if (result > 0) {
    change.stat = "Status: INSUFFICIENT_FUNDS";
    change.changeRegex = "";
  } /*else if (result === 0 && dicTotal === (result / 100)) {
    change.stat = "Status: CLOSED";
    change.changeRegex = regex;
  }*/ else if (result === 0){ 
    change.stat = "Status: OPEN";
    change.changeRegex = regex;
    }
  }

  changeDue.textContent = change.stat;
  changeDue.textContent += change.changeRegex;
 }
}
}
button.addEventListener("click", checkRegister);
  

Actually, it’s not a list. It’s just the value of eachArr as undefined, you see it as a list cause this console.log() is inside your loop.

The .forEach() doesn’t return an array to store it in eachArr, it will return undefined.
Meaning it will only modify the original rightArr array.
Then, you can use rightArr directly and remove the eachArr declaration and keeping rightArr.forEach() only in this line.


These lines (and the lines after) are inside the loop which will divide the values /100 more than just one time, therefore the .filter() method will remove theses values from the result.

So you should remove all this process outside of the for loop so that it will do these calculations after the for loop finishes.


You need to use Number() to convert the string returned by .toFixed(), see previous replies for examples.

I really appreciate your explanations, thank you :pray::pray::pray:

Now my register works as expected, but I cannot pass test for OPEN and CLOSED cases, is there a reason? I have checked all the punctuation, it is correct, what’s wrong?

const button = document.getElementById("purchase-btn");
let price = 1.87;
let cid = [
  ['PENNY', 1.01],
  ['NICKEL', 2.05],
  ['DIME', 3.1],
  ['QUARTER', 4.25],
  ['ONE', 90],
  ['FIVE', 55],
  ['TEN', 20], 
  ['TWENTY', 60],
  ['ONE HUNDRED', 100]
];
cid.forEach(e => e[1] = Number((e[1] * 100).toFixed(2)));

function checkRegister() {
const changeDue = document.getElementById("change-due");
let change = {stat: "", changeRegex: ""};
let resultedArr = [
  [' ONE HUNDRED: $', 0],
  [' TWENTY: $', 0],
  [' TEN: $', 0],
  [' FIVE: $', 0],
  [' ONE: $', 0],
  [' QUARTER: $', 0],
  [' DIME: $', 0],
  [' NICKEL: $', 0],
  [' PENNY: $', 0],
];

const currencyKeyMult = [10000, 2000, 1000, 500, 100, 25, 10, 5, 1,];
const dicMult = cid.reverse();
const cash = document.getElementById("cash");
let dicTotal = 0;
for (let i = 0; i < dicMult.length; i++) {
  dicTotal += dicMult[i][1];
};

  let user_input = Number(cash.value);
  let  result = ((user_input - price) * 100).toFixed(0);
  const originalResult = result;
 if (user_input < price) {
       alert("Customer does not have enough money to purchase the item");
} 
 else  if (user_input === price) {
             change.stat = "No change due - customer paid with exact cash";
    } else {
  for (let i = 0; i < dicMult.length; i++) {
    while (dicMult[i][1] > 0) {
       if(result - currencyKeyMult[i] >= 0) {
  resultedArr[i][1] += currencyKeyMult[i] / 100;
  result -= currencyKeyMult[i];
  dicMult[i][1] -= currencyKeyMult[i];
  } else {break}}
  const filtered = resultedArr.filter(e => e[1] !== undefined);
const rightArr = filtered.filter(e => e[1] > 0);
rightArr.forEach(a => a[1] = Number((a[1]).toFixed(2)));
    const str = String(rightArr);
      const regex = str.replaceAll(",", "");
        change.changeRegex = regex;
  if (originalResult == dicTotal) {
        change.stat = "Status: CLOSED"
            change.changeRegex = regex;

  }
if (originalResult < dicTotal && result === 0) { 
  change.stat = "Status: OPEN";
  change.changeRegex = regex;
}  else if (result > 0 || originalResult < dicTotal) {
    change.stat = "Status: INSUFFICIENT_FUNDS";
    change.changeRegex = "";
  } 
  }
    }
  changeDue.textContent = change.stat;
  changeDue.textContent += change.changeRegex;
 }


button.addEventListener("click", checkRegister);
  


1 Like

This line is in the global scope, outside of the checkRegister function, it will only be executed once.

For the tests, it will change the cid array each time and click the button which means this line isn’t executed.

Since you already have a copy of this array inside your function as dicMult you can use .forEach() on this array instead and do the same.

1 Like

Omg, IT. HAS. PASSED :tada::tada::tada:
I can’t believe it :sweat_smile:
I have been struggling here for 20 days :joy:
Thank you, Mostafa and thank you @JeremyLT and @hbar1st :heart:
I was about to quit my learning, but I’m going to continue after a short break, thanks to you, guys😊

2 Likes