Build a Cash Register Project Working, but not passing tests

I’ve been having trouble passing the " When price is less than the value in the #cash element" tests. Everything works as it’s supposed to and I’ve even console.logged the tests boolean values and they all equal what they should, but it always says I fail anyway. I had a professional programmer look at my code and she said everything is working and the tests are just bugged so I’m wondering if this is the case. It won’t let me reset the project either as I’ve tried several times. Any insight is helpful, thank you.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Cash Register</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <div id="container">
      <h1>Cash Register</h1>
      <div id="change-due"></div>
      <input id="cash">
      <button id="purchase-btn">Purchase</button>
      <div id="register">
        <p id="total"></p>
        <h4>Change in Drawer</h4>
        <p id="pennies"></p>
        <p id="nickels"></p>
        <p id="dimes"></p>
        <p id="quarters"></p>
        <p id="ones"></p>
        <p id="fives"></p>
        <p id="tens"></p>
        <p id="twenties"></p>
        <p id="hundreds"></p>
      </div>
    </div>
	  <script src="script.js"></script>
  </body>
</html>
* {
  overflow: hidden;
  margin: 0;
  padding: 0;
}
#container {
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: rgb(156, 160, 230);
}
h1 {
  margin-top: 2em;
}
#change-due {
  width: 200px;
  height: 500px;
  position: absolute;
  margin-left: 400px;
  margin-top: 300px;
}
input {
  margin-top : 1em;
  width: 35%;
  height: 30px;
  font-size: 18px;
}
button {
  margin-top: 1em;
  width: 20%;
  height: 30px;
  font-size: 18px;
}
#register {
  margin-top: 3rem;
  font-size: 20px;
}
h4 {
  margin: 20px 0px;
}
#register p {
  margin: 4px 0px;
}
const input = document.getElementById("cash");
const button = document.getElementById("purchase-btn");
const changeDueDiv = document.getElementById("change-due");
const total = document.getElementById("total");
const pennies = document.getElementById("pennies");
const nickels = document.getElementById("nickels");
const dimes = document.getElementById("dimes");
const quarters = document.getElementById("quarters");
const ones = document.getElementById("ones");
const fives = document.getElementById("fives");
const tens = document.getElementById("tens");
const twenties = document.getElementById("twenties");
const hundreds = document.getElementById("hundreds");

let price = 1.82;
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]];
let allCashInDrawer = cid.map(total => total[1]).reduce((total, arg) => total + arg, 0).toFixed(2);
let cidNumbers = [pennies, nickels, dimes, quarters, ones, fives, tens, twenties, hundreds];
let cidWords = ["Pennies: $", "Nickels: $", "Dimes: $", "Quarters: $", "Ones: $", "Fives: $", "Tens: $", "Twenties: $", "Hundreds: $"];
function updateCid() {
  total.innerText = `Total: $${price}`;
  for (let i = 0; i < cidNumbers.length; i++) {
    cidNumbers[i].innerText = `${cidWords[i]}${cid[i][1]}`;
  }
}
updateCid();
// FIXES ROUNDING ERROR
function roundCorrectly (number, n) {
  var power = Math.pow(10, n);
  return (Math.round(number * power) / power);
}
function getChange(inputValue) {
  let changeDue = inputValue - price;
  let cashValues = [100, 20, 10, 5, 1, .25, .1, .05, .01];
  let newValues = [0, 0, 0, 0, 0, 0, 0, 0, 0];
  let reverseCid = [...cid].reverse();
  // REDUCE CHANGEDUE TO 0 FROM LARGEST TO SMALLEST BILL AND STORE VALUE IN NEWVALUES[]
  for (let i = 0; i < newValues.length; i++) {
    while (changeDue >= cashValues[i] && reverseCid[i][1] >= cashValues[i]) {
    reverseCid[i][1] = roundCorrectly(reverseCid[i][1] - cashValues[i], 2);
    changeDue = roundCorrectly(changeDue - cashValues[i], 2);
    newValues[i] = roundCorrectly(newValues[i] + cashValues[i], 2);
    console.log(reverseCid[i][1]);
    } 
  }
  // ADD TEXT TO SCREEN BASED ON WHICH VALUES WERE ADDED TO NEWVALUES[]
  function addText () {
    for (let i = 0; i < newValues.length; i++) {
      if (newValues[i] > 0) {
        changeDueDiv.innerText += `${reverseCid[i][0]}: $${newValues[i]}\n`
      }
      console.log("New Values :", newValues[i]);
    }
  }
  console.log("Change Due: ", changeDue, "All Cash :", allCashInDrawer);
  if (input.value - allCashInDrawer == price) {
      changeDueDiv.innerText = "Status: CLOSED\n";
      addText();
  } else if (changeDue < allCashInDrawer && changeDue == 0) {
      changeDueDiv.innerText = "Status: OPEN\n"
      addText();
  } else {
      changeDueDiv.innerText = "Status: INSUFFICIENT_FUNDS"; 
  }
}

button.addEventListener("click", () => {
  if (Number(input.value).toFixed(2) < price) {
    alert("Customer does not have enough money to purchase the item");
    input.value = '';
  } else if (input.value == price) {
    changeDueDiv.innerHTML = "No change due - customer paid with exact cash";
  } else {
    getChange(input.value);
  }
  updateCid();
});
1 Like

:balloon:Hello @zacharysilvagrosser2 !

Welcome to the forum! Congratulations on getting through the projects and tackling this one. It is a tough one and I can hear your frustration. You are indeed getting the correct results - at least as far as I can tell with a cursory look through your code.

The main thing that sticks out in your code is that you deal with rounding errors. When a person makes change at a cash register in real life, there can never be such errors, since the operation is a matter of subtraction or addition. There can be errors of a human nature of course, but I digress…

I like you have also struggled with these challenges from time to time because what might appear to be the obvious way to approach the solution to a problem is not always the best way to solve it.

It is possible to solve this exercise without rounding, but it is necessary to think of all amounts in terms of the smallest denomination - a penny. A penny cannot be divided into fractions. Additionally, all other denominations can be represented in terms of pennies. Try that approach and you will surely succeed.

Does this help?

Keep up the good progress!

Happy Coding! :slightly_smiling_face:

Thank you so much for the reply and taking the time to try to help me.

I created the rounding function because when I would log the pennies being substracted from changeDue after a few pennies it would change suddenly. Here’s what happens:

0.49
0.48
0.47
0.45999999999999996
0.44999999999999996
0.43999999999999995
0.42999999999999994
0.41999999999999993
0.4099999999999999

and then it wouldn’t get changeDue to 0 because of the long decimal. I have no idea why this happens so I tried rounding it off to fix the issue that I assumed was a bug.

I’m really trying to understand what you mean about the pennies, but I’m not sure that I do.

Another thing to mention is that when I change cid to test out the different project tests it will pass the current test I’m checking, but will then fail another test. Then I change cid to that tests cid values and it passes, but the other one I had just tested is now failing. I’m not sure how this is possible.

I’ve completed everything in this Javascript course, but I’m still stuck on this project. Any additional insight is greatly appreciated. Thank you.

1 Like

Welcome to the forum @zacharysilvagrosser2

Try entering 170 into your app two times.

Is the correct message displaying?

Happy coding

1 Like

If you convert all amounts to pennies you don’t have to work with decimals. When one is presented with a bill to pay, the total will be written as fraction of a US dollar, GBP, etc. e.g. $1.99 or 199¢ or $1.99 x 100¢ / $ 1 = 199¢

The rounding functions are not necessary and create unnecessary complexity. Also, if the tests don’t pass, this should sound alarm bells for you to double check and possibly rethink your approach - if only because so many have gone before you on this freeCodeCamp journey - they have been successful and with persistence so will you.

As an aside, check this out: console.log((0.1 + 0.2) * 10 == 3 ); The theoretical answer is true, but javascript thinks its false. There are loads of articles about this subject a quick search will reveal them. It could be that a hidden part of this exercise is to appreciate the limitations of the underlying hardware and how best to exploit its capabilities and that of JavaScript.

I hope this helps you achieve your goal.

As far as I can tell it is. It gives the correct amount of change the first time and then insufficient funds the second time because allCashInDrawer is now less than changeDue. Maybe I’m misunderstanding how the register is supposed to work.

Okay thank you I understand what you mean. I took away the round function and converted everything into pennies by multiplying everything by 100. I went through every test multiple times and what they are asking in the tests is what I am getting on my end.

Normally I can debug a program because there are errors or I am not getting the expected result, but it’s incredibly hard for me to debug something that’s appearing to work as intended. Especially when I test something by changing the values of cid and it says it passes, but when I switch the cid values to test for another set of values, the previous test is now failing. Maybe I’m not seeing some limitation of Javascript like you mentioned and that is causing the error.

I have all of the tests passing except the last two. When I switch cid to the values of the last test it is now passing and another test is now failing. This is the main problem I have and why I am struggling so much to find the solution since the tests pass when I pass in the correct cid values to test my code. I’ll post my updated js here. Thank you again for the continued help with this problem.

const input = document.getElementById("cash");
const button = document.getElementById("purchase-btn");
const changeDueDiv = document.getElementById("change-due");
const total = document.getElementById("total");
const pennies = document.getElementById("pennies");
const nickels = document.getElementById("nickels");
const dimes = document.getElementById("dimes");
const quarters = document.getElementById("quarters");
const ones = document.getElementById("ones");
const fives = document.getElementById("fives");
const tens = document.getElementById("tens");
const twenties = document.getElementById("twenties");
const hundreds = document.getElementById("hundreds");

let price = 3.26;
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]];
let allCashInDrawer = cid.map(total => total[1]).reduce((total, arg) => total + arg, 0).toFixed(2) * 100;
let cidNumbers = [pennies, nickels, dimes, quarters, ones, fives, tens, twenties, hundreds];
let cidWords = ["Pennies: $", "Nickels: $", "Dimes: $", "Quarters: $", "Ones: $", "Fives: $", "Tens: $", "Twenties: $", "Hundreds: $"];
function updateCid() {
  total.innerText = `Total: $${price}`;
  for (let i = 0; i < cidNumbers.length; i++) {
    cidNumbers[i].innerText = `${cidWords[i]}${cid[i][1]}`;
  }
}
updateCid();
function getChange(inputValue) {
  inputValue = Number(inputValue) * 100;
  price *= 100;
  let changeDue = Number(inputValue) - price;
  if (changeDue < allCashInDrawer) {
      changeDueDiv.innerText = "Status: OPEN\n"
  }
  if (changeDue === allCashInDrawer) {
      changeDueDiv.innerText = "Status: CLOSED\n";
  }
  if (allCashInDrawer < changeDue) {
      changeDueDiv.innerText = "Status: INSUFFICIENT_FUNDS";
  }
  let cashValues = [10000, 2000, 1000, 500, 100, 25, 10, 5, 1];
  let newValues = [0, 0, 0, 0, 0, 0, 0, 0, 0];
  let reverseCid = [...cid].reverse();
  for (let i = 0; i < reverseCid.length; i++) {
    reverseCid[i][1] *= 100;
  }
  // REDUCE CHANGEDUE TO 0 FROM LARGEST TO SMALLEST BILL AND STORE VALUE IN NEWVALUES[]
  for (let i = 0; i < newValues.length; i++) {
    while (changeDue >= cashValues[i] && reverseCid[i][1] >= cashValues[i]) {
    reverseCid[i][1] = reverseCid[i][1] - cashValues[i];
    changeDue = changeDue - cashValues[i];
    newValues[i] = newValues[i] + cashValues[i];
    //console.log(reverseCid[i][1]);
    } 
  }
  if (changeDue > 0) {
      changeDueDiv.innerText = "Status: INSUFFICIENT_FUNDS";
  }
  // ADD TEXT TO SCREEN BASED ON WHICH VALUES WERE ADDED TO NEWVALUES[]
  function addText () {
    console.log(changeDue);
    if ((Number(inputValue) - price < allCashInDrawer || Number(inputValue) - price === allCashInDrawer) && !changeDue > 0) {
      for (let i = 0; i < newValues.length; i++) {
        if (newValues[i] > 0) {
          newValues[i] *= .01;
          changeDueDiv.innerText += `${reverseCid[i][0]}: $${newValues[i]}\n`
        }
      }
    }
  }
  addText();
  for (let i = 0; i < reverseCid.length; i++) {
    reverseCid[i][1] *= .01;
  }
  if (allCashInDrawer > Number(inputValue) - price) {
    allCashInDrawer -= Number(inputValue) - price;
  }
  console.log("Change Due: ", changeDue, "All Cash :", allCashInDrawer);
  inputValue = "";
}

button.addEventListener("click", () => {
  if (Number(input.value).toFixed(2) < price) {
    alert("Customer does not have enough money to purchase the item");
    input.value = '';
  } else if (input.value == price) {
    changeDueDiv.innerHTML = "No change due - customer paid with exact cash";
  } else {
    getChange(input.value);
  }
  updateCid();
});