Build a Cash Register project, 1 test to pass!

Hi, after… um, quite a fun time trying to get my final test to pass, I am here to get some assistance. I may have intense tunnel vision at the moment, as I’ve been running this in the fCC browser, and a copy in VS Code. I’ve rummaged all the related topics I can muster at this point. ( i miss pair programming :upside_down_face: )

The only test not passing is:
When price is 3.26 , the value in the #cash element is 100 , cid is [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]] , and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: OPEN TWENTY: $60 TEN: $20 FIVE: $15 ONE: $1 QUARTER: $0.5 DIME: $0.2 PENNY: $0.04" .
My console shows test complete, but the status message displayed is:
“Status: OPEN TWENTY: $96.80” . I believe my calculations are working, I just can’t seem to to print the right status.
Very Simple HMTL:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>fCC Cash Register</title>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <main>
      <h3>freeCodeCamp Cash Register Certification Project</h3>
      <div id="change-due"></div>
      <label for="cash">Amount Tendered:</label>
      <input id="cash" type="number" val="" />
      <button id="purchase-btn">Purchase</button>
    </main>
    <script src="./script.js"></script>
  </body>
</html>

JS:

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],
];

document.getElementById("purchase-btn").addEventListener("click", () => {
  const cashProvided = document.getElementById("cash").value;

  function calculateChange(changeDue, maxChangePerDenomination) {
    const denominations = [
      ["ONE HUNDRED", 100],
      ["TWENTY", 20],
      ["TEN", 10],
      ["FIVE", 5],
      ["ONE", 1],
      ["QUARTER", 0.25],
      ["DIME", 0.1],
      ["NICKEL", 0.05],
      ["PENNY", 0.01],
    ];
    const maxChangeCopy = { ...maxChangePerDenomination };
    let change = [];
    for (let i = 0; i < denominations.length; i++) {
      const [denomination, value] = denominations[i];
      if (changeDue >= value && maxChangeCopy[denomination] > 0) {
        const amountToReturn = Math.min(
          changeDue / value,
          maxChangePerDenomination[denomination] 
        ).toFixed(2);

        // Check for available bills and adjust as needed
        const availableBills = Math.floor(maxChangeCopy[denomination]);
        const actualAmountToReturn = Math.min(amountToReturn, availableBills);
        const amountReturned = parseFloat(actualAmountToReturn) * value;
        change.push([denomination, amountReturned]);
        changeDue -= amountReturned;
        // Update maxChangeCopy with actual bills used
        maxChangeCopy[denomination] -= actualAmountToReturn;
      }
    }
    if (changeDue <= 0) {
      return change;
    }
    return [];
  }
  const totalCID = cid.reduce((acc, [, val]) => acc + val, 0);
  let changeDue = Math.round((cashProvided - price) * 100) / 100;
  if (cashProvided < price) {
    alert("Customer does not have enough money to purchase the item");
    return;
  }
  if (changeDue === 0) {
    document.getElementById("change-due").innerText =
      "No change due - customer paid with exact cash";
    return;
  }
  if (totalCID < changeDue) {
    document.getElementById("change-due").innerText =
      "Status: INSUFFICIENT_FUNDS";
    return;
  }
  if (totalCID === changeDue) {
    document.getElementById("change-due").innerText = `Status: CLOSED ${cid
      .map(([denomination, value]) => denomination + ": $" + value.toFixed(2))
      .join(" ")}`;
    return;
  }

  function calculateMaxChange(cid) {
    return cid.reduce((acc, [denomination, value]) => {
      acc[denomination] = value;
      return acc;
    }, {});
  }

  const maxChange = calculateMaxChange(cid);
  const change = calculateChange(changeDue, maxChange);
  
  if (changeDue > 0 && change.length === 0) {
    document.getElementById("change-due").innerText =
      "Status: INSUFFICIENT_FUNDS";
    return;
  }

  const statusMessage =
    "Status: OPEN " +
    change.map((item) => `${item[0]}: $${item[1].toFixed(2)}`).join(" ");
  document.getElementById("change-due").innerText = statusMessage;
});

If you are getting Status: OPEN TWENTY: $96.80 then that means that change.map() is returning TWENTY: $96.80. So it seems like there might be something wrong with the change array at that point. The change array is created with:

const change = calculateChange(changeDue, maxChange);

So I’d probably look at calculateChange to make sure it is producing the correct results.

1 Like

Hi! I’ve been troubleshooting your suggestion all morning to no avail as of yet.
My calculateChange function is possibly bloated :pregnant_man:.
I believe my order of operations is proper and no unnecessary global variables, as all things fired by the #purchase-btn listener are inside.
Taking a break to jog.
Thanks for your insight!

By chance anyone else have any thoughts on my issue. been plugging away at my calculateChange function, still stuck on that 1 test not passing. Same output:
“Status: OPEN TWENTY: $96.74”
when it should be
“Status: OPEN TWENTY: $60 TEN: $20 FIVE: $15 ONE: $1 QUARTER: $0.5 DIME: $0.2 PENNY: $0.04”` .
I updated my for loop to look at available bills before calculating the amount using Math.floor. but to no avail :frowning:

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],
];

document.getElementById("purchase-btn").addEventListener("click", () => {
  const cashProvided = document.getElementById("cash").value;

  function calculateChange(changeDue, maxChangePerDenomination) {
    const denominations = [
      ["ONE HUNDRED", 100],
      ["TWENTY", 20],
      ["TEN", 10],
      ["FIVE", 5],
      ["ONE", 1],
      ["QUARTER", 0.25],
      ["DIME", 0.1],
      ["NICKEL", 0.05],
      ["PENNY", 0.01],
    ];

    let change = [];
    const maxChangeCopy = { ...maxChangePerDenomination }; 

// updated for loop to look at available bills before calculating the ideal amount
    for (let i = 0; i < denominations.length; i++) {
      const [denomination, value] = denominations[i];
      if (changeDue >= value && maxChangeCopy[denomination] > 0) {
        const availableBills = Math.floor(maxChangeCopy[denomination]);
        const actualAmountToReturn = Math.min(changeDue / value, availableBills);
        const amountReturned = parseFloat(actualAmountToReturn) * value;
        change.push([denomination, amountReturned]);
        changeDue -= amountReturned;
        // then we Update maxChangeCopy with actual bills used
        maxChangeCopy[denomination] -= actualAmountToReturn;
      }
    }
    if (changeDue <= 0) {
      return change;
    }
    return [];
  }

  const totalCID = cid.reduce((acc, [, val]) => acc + val, 0);
  let changeDue = Math.round((cashProvided - price) * 100) / 100;
  if (cashProvided < price) {
    alert("Customer does not have enough money to purchase the item");
    return;
  }
  if (changeDue === 0) {
    document.getElementById("change-due").innerText =
      "No change due - customer paid with exact cash";
    return;
  }
  if (totalCID < changeDue) {
    document.getElementById("change-due").innerText =
      "Status: INSUFFICIENT_FUNDS";
    return;
  }
  if (totalCID === changeDue) {
    document.getElementById("change-due").innerText = `Status: CLOSED ${cid
      .map(([denomination, value]) => denomination + ": $" + value.toFixed(2))
      .join(" ")}`;
    return;
  }

  const maxChange = calculateMaxChange(cid);
  const change = calculateChange(changeDue, maxChange);

  function calculateMaxChange(cid) {
    return cid.reduce((acc, [denomination, value]) => {
      acc[denomination] = value;
      return acc;
    }, {});
  }

  if (changeDue > 0 && change.length === 0) {
    document.getElementById("change-due").innerText =
      "Status: INSUFFICIENT_FUNDS";
    return;
  }

  const statusMessage =
    "Status: OPEN " +
    change.map((item) => `${item[0]}: $${item[1].toFixed(2)}`).join(" ");
  document.getElementById("change-due").innerText = statusMessage;
});

this is solved. and i got the final test to pass. yippee! i was comparing flawed values and denominations in my logic.

1 Like