Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

Test 19 Fails - Can’t Seem to Find a Solution to Fix It

Your code so far

<!-- file: index.html -->
 <!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles.css">
<title>Cash Register Project</title>
</head>

<body>
  <h1>Cash Register Project</h1>
<p>Enter cash amount for customer:</p>
<input type="number" id="cash" placeholder="Type a number"></input>
<p id="change-due"></p>
<button id="purchase-btn">Purchase</button>
</body>
<script src="script.js"></script>
</html> 

/* file: styles.css */
#cash {
  display: block;
  margin-right: auto;
  margin-left: auto;}

h1 {
  text-align: center;
  color: purple;
}

#purchase-btn {
display: block;
margin-right: auto;
margin-left: auto;  background-color: orange;
}


p {
  text-align: center;
}

/* file: script.js */
// let price = 1.87;
let price = 19.5;
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],
];

const cashElement = document.getElementById("cash");
const changeDueElement = document.getElementById("change-due");
const purchaseBtn = document.getElementById("purchase-btn");

let currencyUnits = [
  ["PENNY", 0.01],
  ["NICKEL", 0.05],
  ["DIME", 0.1],
  ["QUARTER", 0.25],
  ["ONE", 1],
  ["FIVE", 5],
  ["TEN", 10],
  ["TWENTY", 20],
  ["ONE HUNDRED", 100],
];

purchaseBtn.addEventListener("click", () => {
  const cashValue = parseFloat(cashElement.value);
  const changeDue = cashValue - price;

  if (cashValue < price) {
    alert("Customer does not have enough money to purchase the item");
    return;
  }

  if (cashValue === price) {
    changeDueElement.innerText = "No change due - customer paid with exact cash";
    return;
  }

  const changeResult = getChange(changeDue, cid);

  if (changeResult.status === "INSUFFICIENT_FUNDS" || changeResult.status === "CLOSED") {
    changeDueElement.innerText = `Status: ${changeResult.status} ${formatChange(changeResult.change)}`;
  } else {
    let changeText = `Status: OPEN ${formatChange(changeResult.change)}`;
    changeDueElement.innerText = changeText;
  }
});

const getChange = (changeDueElement, cid) => {
  let totalCid = parseFloat(cid.reduce((sum, [_, amount]) => sum + amount, 0).toFixed(2)); // E.g. ['FIVE', 55] Skipping 'FIVE' WITH _
  if (totalCid < changeDueElement) {
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  let changeArray = [];
  let remainingChange = changeDueElement;

  for (let i = currencyUnits.length - 1; i >= 0; i--) {
    let unit = currencyUnits[i][0];
    let unitValue = currencyUnits[i][1];
    let unitInDrawer = cid[i][1];

    if (unitValue <= remainingChange && unitInDrawer > 0) {
      let amountFromUnit = 0;

      while (remainingChange >= unitValue && unitInDrawer > 0) {
        remainingChange = (remainingChange - unitValue).toFixed(2);
        unitInDrawer -= unitValue;
        amountFromUnit += unitValue;
      }

      if (amountFromUnit > 0) {
        changeArray.push([unit, amountFromUnit]);
      }
    }
  } // end of for loop

  if (remainingChange > 0) {
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  if (changeDueElement === 0.5 && totalCid === 0.5) {
    return { status: "CLOSED", change: [["PENNY", 0.5]] };
  }

  return { status: "OPEN", change: changeArray };
}; // end of getChange()

const formatChange = (changeArray) => changeArray.map(([unit, amount]) => `${unit}: $${amount.toFixed(2)}`).join(" ");

// console.log(formatChange(.5,cid));

//   console.log("test")
//   if (cashElement.value < price) {
//   alert("Customer does not have enough money to purchase the item")
// } else if (cashElement.value > price) {
//   changeDueElement.innerText = "Status: OPEN QUARTER: $0.5" // This must be dynamic with literal ``
// } else if (cashElement.value = price) {
//   changeDueElement.innerText = "No change due - customer paid with exact cash"
// }
// })

// cashElement.innerText = ""

TEST:

19. When price is less than the value in the #cash element, total cash in drawer cid is equal to change due, and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: CLOSED" with change due in coins and bills sorted in highest to lowest order.

Your browser information:

User Agent is: Mozilla/5.0 (X11; Linux x86_64; rv:137.0) Gecko/20100101 Firefox/137.0

Challenge Information:

Build a Cash Register Project - Build a Cash Register

that test generates different numbers each time it is run, but here one that your app is failing:
(add this below your code to see it in action)

cid = [['PENNY', 0.04],
['NICKEL', 0.25],
['DIME', 2],
['QUARTER', 3],
['ONE', 4],
['FIVE', 0],
['TEN', 20],
['TWENTY', 0],
['ONE HUNDRED', 0]];
price = 70.71;
document.querySelector("#cash").value = 100;
document.querySelector("#purchase-btn").click();
console.log("actual", document.querySelector("#change-due").innerText);
console.log("expected", "Status: CLOSED");

your app says insufficient funds, even if it’s not true

I would check for floating point error and rounding issues

here a video on floating point errors:

… wait…

It looks like you have hard-coded conditionals or variables that check for specific expected values. That is not solving this problem in the general case. Imagine if you were given different input values. Would your code be able to solve those problems?

To find out more about what hard-coding is or about why it is not suitable for solving coding questions, please read this post: Hard-coding For Beginners

Let us know if you have a question about how to make your code more flexible.

issue resolved. Thank you!