Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

Can anyone have a look at this, I can’t seem to find the problem with why the tests don’t pass.
(console statements added for debugging)

My code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cash Register</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <main class="register-container">
      <!-- Header with Title -->
      <header class="register-header">
        <h1>Cash Register</h1>
      </header>

      <!-- Display screen for price and change -->
      <section class="display-screen">
        <p id="price-screen" class="price-screen">Total: $3.26</p>
        <div id="change-due" class="change-due">Change Due: $0.00</div>
      </section>

      <!-- Input area for cash entry and action button -->
      <section class="input-area">
        <input id="cash" type="number" placeholder="Enter amount" step="0.01" min="0">
      </section>

      <!-- Keypad for numerical input -->
      <section class="keypad">
        <button class="key" type="button" value="1">1</button>
        <button class="key" type="button" value="2">2</button>
        <button class="key" type="button" value="3">3</button>
        <button class="key" type="button" value="4">4</button>
        <button class="key" type="button" value="5">5</button>
        <button class="key" type="button" value="6">6</button>
        <button class="key" type="button" value="7">7</button>
        <button class="key" type="button" value="8">8</button>
        <button class="key" type="button" value="9">9</button>
        <button class="key" type="button" value="0">0</button>
        <button class="key clear" type="button">Clear</button>
        <button class="key enter" type="button" id="purchase-btn">Enter</button>
      </section>

      <!-- Cash drawer display -->
      <section class="cash-drawer">
        <h2>Cash Drawer</h2>
        <ul class="cash-list">
          <li>Pennies: <span id="penny-amount"></span></li>
          <li>Nickels: <span id="nickel-amount"></span></li>
          <li>Dimes: <span id="dime-amount"></span></li>
          <li>Quarters: <span id="quarter-amount"></span></li>
          <li>Ones: <span id="one-amount"></span></li>
          <li>Fives: <span id="five-amount"></span></li>
          <li>Tens: <span id="ten-amount"></span></li>
          <li>Twenties: <span id="twenty-amount"></span></li>
          <li>Hundreds: <span id="one hundred-amount"></span></li>
        </ul>
      </section>

      <!-- Footer -->
      <footer class="register-footer">
        <p>Developed by Belgrf</p>
      </footer>
    </main>
    <script src="script.js"></script>
  </body>
</html>
/* file: script.js */
const cashInput = document.getElementById("cash");
const changeDueElem = document.getElementById("change-due");
const purchaseBtn = document.getElementById("purchase-btn");
const priceScreen = document.getElementById("price-screen");

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

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]
].reverse();

priceScreen.textContent = `Total: $${price.toFixed(2)}`;

const calculateChange = changeDue => {
  console.log(`Calculating change for: $${changeDue.toFixed(2)}`);

  const totalCID = cid.reduce((acc, el) => el[1] + acc, 0);
  console.log(`Total CID: $${totalCID.toFixed(2)}`);

  if (totalCID < changeDue) {
    console.log("Insufficient funds");
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  if (totalCID === changeDue) {
    console.log("Closed");
    return { status: "CLOSED", change: cid };
  }

  let change = [];
  changeDue = parseFloat(changeDue.toFixed(2));

  for (let i = 0; i < currencyUnits.length && changeDue > 0; i++) {
    let amount = 0;
    while (changeDue >= currencyUnits[i][1] && cid[i][1] >= currencyUnits[i][1]) {
      amount += currencyUnits[i][1];
      cid[i][1] -= currencyUnits[i][1];
      changeDue = parseFloat(changeDue - currencyUnits[i][1]).toFixed(2);
      console.log(`Change due now: $${changeDue}`);
    }
    if (amount > 0) change.push([currencyUnits[i][0], amount]);
    console.log(`Amount for ${currencyUnits[i][0]}: $${amount.toFixed(2)}`);
  }

  if (changeDue > 0) {
    console.log("Insufficient funds after processing");
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  console.log("Open");
  console.log(`Change returned: ${JSON.stringify(change)}`);
  return { status: "OPEN", change: change };
};

const handlePurchase = () => {
  console.log("Handling purchase");

  const cash = parseFloat(cashInput.value);
  console.log(`Cash entered: $${cash.toFixed(2)}`);

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

  if (cash === price) {
    changeDueElem.textContent = "No change due - customer paid with exact cash";
    console.log("No change due");
    return;
  }

  const { status, change } = calculateChange(cash - price);
  console.log(`Purchase status: ${status}`);
  
  changeDueElem.textContent = status === "INSUFFICIENT_FUNDS"
    ? "Status: INSUFFICIENT_FUNDS"
    : `Status: ${status} ${change
        .map(([unit, amount]) => `${unit}: $${amount}`)
        .join(" ")}`;

  console.log(`Change due displayed: ${changeDueElem.textContent}`);
};

const updateCashDrawerDisplay = () => {
  console.log("Updating cash drawer display");
  cid.forEach(([unit, amount]) => {
    const element = document.getElementById(`${unit.toLowerCase()}-amount`);
    if (element) {
      element.textContent = `$${amount.toFixed(2)}`;
    }
    console.log(`${unit}: $${amount.toFixed(2)}`);
  });
};

updateCashDrawerDisplay();

document.querySelectorAll('.key').forEach(button => {
  button.addEventListener('click', function() {
    if (this.classList.contains('enter')) {
      handlePurchase();
      updateCashDrawerDisplay();
    } else if (this.classList.contains('clear')) {
      cashInput.value = '';
    } else {
      cashInput.value += this.textContent;
    }
  });
});

Console output and test results:

// running tests
12. 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".
13. When price is less than the value in the #cash element, total cash in drawer cid is greater than the change due, individual denomination amounts allows for returning change due, and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: OPEN" with required change due in coins and bills sorted in highest to lowest order.
17. When price is less than the value in the #cash element, total cash in drawer cid is greater than change due, but the individual denomination amounts make it impossible to return needed change, when the #purchase-btn element is clicked, the value in the #change-due element should be "Status: INSUFFICIENT_FUNDS"
18. When price is 19.5, the value in the #cash element is 20, cid is [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]], and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: CLOSED PENNY: $0.5".
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.
// tests completed
// console output
Updating cash drawer display
ONE HUNDRED: $100.00
TWENTY: $60.00
TEN: $20.00
FIVE: $55.00
ONE: $90.00
QUARTER: $4.25
DIME: $3.10
NICKEL: $2.05
PENNY: $1.01
Handling purchase
Cash entered: $10.00
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $90.00
FIVE: $55.00
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $10.51
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $90.00
FIVE: $55.00
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $11.95
No change due
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $90.00
FIVE: $55.00
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $31.95
No change due
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $90.00
FIVE: $55.00
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $20.00
Calculating change for: $0.50
Total CID: $335.41
Amount for ONE HUNDRED: $0.00
Amount for TWENTY: $0.00
Amount for TEN: $0.00
Amount for FIVE: $0.00
Amount for ONE: $0.00
Change due now: $0.25
Change due now: $0.00
Amount for QUARTER: $0.50
Open
Change returned: [["QUARTER",0.5]]
Purchase status: OPEN
Change due displayed: Status: OPEN QUARTER: $0.5
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $90.00
FIVE: $54.50
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $100.00
Calculating change for: $96.74
Total CID: $335.41
Amount for ONE HUNDRED: $0.00
Amount for TWENTY: $0.00
Amount for TEN: $0.00
Amount for FIVE: $0.00
Change due now: $95.74
Change due now: $94.74
Change due now: $93.74
Change due now: $92.74
Change due now: $91.74
Change due now: $90.74
Change due now: $89.74
Change due now: $88.74
Change due now: $87.74
Change due now: $86.74
Change due now: $85.74
Change due now: $84.74
Change due now: $83.74
Change due now: $82.74
Change due now: $81.74
Change due now: $80.74
Change due now: $79.74
Change due now: $78.74
Change due now: $77.74
Change due now: $76.74
Change due now: $75.74
Change due now: $74.74
Change due now: $73.74
Change due now: $72.74
Change due now: $71.74
Change due now: $70.74
Change due now: $69.74
Change due now: $68.74
Change due now: $67.74
Change due now: $66.74
Change due now: $65.74
Change due now: $64.74
Change due now: $63.74
Change due now: $62.74
Change due now: $61.74
Change due now: $60.74
Change due now: $59.74
Change due now: $58.74
Change due now: $57.74
Change due now: $56.74
Change due now: $55.74
Change due now: $54.74
Change due now: $53.74
Change due now: $52.74
Change due now: $51.74
Change due now: $50.74
Change due now: $49.74
Change due now: $48.74
Change due now: $47.74
Change due now: $46.74
Change due now: $45.74
Change due now: $44.74
Change due now: $43.74
Change due now: $42.74
Change due now: $41.74
Change due now: $40.74
Change due now: $39.74
Change due now: $38.74
Change due now: $37.74
Change due now: $36.74
Change due now: $35.74
Change due now: $34.74
Change due now: $33.74
Change due now: $32.74
Change due now: $31.74
Change due now: $30.74
Change due now: $29.74
Change due now: $28.74
Change due now: $27.74
Change due now: $26.74
Change due now: $25.74
Change due now: $24.74
Change due now: $23.74
Change due now: $22.74
Change due now: $21.74
Change due now: $20.74
Change due now: $19.74
Change due now: $18.74
Change due now: $17.74
Change due now: $16.74
Change due now: $15.74
Change due now: $14.74
Change due now: $13.74
Change due now: $12.74
Change due now: $11.74
Change due now: $10.74
Change due now: $9.74
Change due now: $8.74
Change due now: $7.74
Change due now: $6.74
Amount for ONE: $90.00
Change due now: $6.49
Change due now: $6.24
Change due now: $5.99
Change due now: $5.74
Change due now: $5.49
Change due now: $5.24
Change due now: $4.99
Change due now: $4.74
Change due now: $4.49
Change due now: $4.24
Change due now: $3.99
Change due now: $3.74
Change due now: $3.49
Change due now: $3.24
Change due now: $2.99
Change due now: $2.74
Change due now: $2.49
Change due now: $2.24
Change due now: $1.99
Change due now: $1.74
Change due now: $1.49
Change due now: $1.24
Change due now: $0.99
Change due now: $0.74
Change due now: $0.49
Change due now: $0.24
Amount for QUARTER: $6.50
Change due now: $0.14
Change due now: $0.04
Amount for DIME: $0.20
Amount for NICKEL: $0.00
Change due now: $0.03
Change due now: $0.02
Change due now: $0.01
Change due now: $0.00
Amount for PENNY: $0.04
Open
Change returned: [["ONE",90],["QUARTER",6.5],["DIME",0.2],["PENNY",0.04]]
Purchase status: OPEN
Change due displayed: Status: OPEN ONE: $90 QUARTER: $6.5 DIME: $0.2 PENNY: $0.04
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $0.00
FIVE: $48.50
TEN: $19.80
TWENTY: $60.00
ONE HUNDRED: $99.96
Handling purchase
Cash entered: $80.00
Calculating change for: $13.77
Total CID: $771.51
Amount for ONE HUNDRED: $0.00
Amount for TWENTY: $0.00
Amount for TEN: $0.00
Amount for FIVE: $0.00
Change due now: $12.77
Change due now: $11.77
Change due now: $10.77
Amount for ONE: $3.00
Change due now: $10.52
Change due now: $10.27
Change due now: $10.02
Change due now: $9.77
Change due now: $9.52
Change due now: $9.27
Change due now: $9.02
Change due now: $8.77
Change due now: $8.52
Change due now: $8.27
Change due now: $8.02
Change due now: $7.77
Change due now: $7.52
Change due now: $7.27
Change due now: $7.02
Change due now: $6.77
Change due now: $6.52
Change due now: $6.27
Change due now: $6.02
Change due now: $5.77
Amount for QUARTER: $5.00
Change due now: $5.67
Change due now: $5.57
Change due now: $5.47
Change due now: $5.37
Change due now: $5.27
Change due now: $5.17
Change due now: $5.07
Change due now: $4.97
Change due now: $4.87
Change due now: $4.77
Change due now: $4.67
Change due now: $4.57
Change due now: $4.47
Change due now: $4.37
Change due now: $4.27
Change due now: $4.17
Change due now: $4.07
Change due now: $3.97
Change due now: $3.87
Change due now: $3.77
Change due now: $3.67
Change due now: $3.57
Change due now: $3.47
Change due now: $3.37
Change due now: $3.27
Change due now: $3.17
Change due now: $3.07
Change due now: $2.97
Change due now: $2.87
Change due now: $2.77
Change due now: $2.67
Change due now: $2.57
Change due now: $2.47
Change due now: $2.37
Change due now: $2.27
Change due now: $2.17
Change due now: $2.07
Change due now: $1.97
Change due now: $1.87
Change due now: $1.77
Change due now: $1.67
Change due now: $1.57
Change due now: $1.47
Change due now: $1.37
Change due now: $1.27
Change due now: $1.17
Change due now: $1.07
Change due now: $0.97
Change due now: $0.87
Change due now: $0.77
Change due now: $0.67
Change due now: $0.57
Change due now: $0.47
Change due now: $0.37
Change due now: $0.27
Change due now: $0.17
Change due now: $0.07
Amount for DIME: $5.70
Change due now: $0.02
Amount for NICKEL: $0.05
Change due now: $0.01
Change due now: $0.00
Amount for PENNY: $0.02
Open
Change returned: [["ONE",3],["QUARTER",5],["DIME",5.699999999999996],["NICKEL",0.05],["PENNY",0.02]]
Purchase status: OPEN
Change due displayed: Status: OPEN ONE: $3 QUARTER: $5 DIME: $5.699999999999996 NICKEL: $0.05 PENNY: $0.02
Updating cash drawer display
PENNY: $0.21
NICKEL: $0.65
DIME: $0.90
QUARTER: $1.75
ONE: $0.00
FIVE: $0.00
TEN: $114.30
TWENTY: $39.95
ONE HUNDRED: $599.98
Handling purchase
Cash entered: $20.00
Calculating change for: $0.50
Total CID: $0.01
Insufficient funds
Purchase status: INSUFFICIENT_FUNDS
Change due displayed: Status: INSUFFICIENT_FUNDS
Updating cash drawer display
PENNY: $0.01
NICKEL: $0.00
DIME: $0.00
QUARTER: $0.00
ONE: $0.00
FIVE: $0.00
TEN: $0.00
TWENTY: $0.00
ONE HUNDRED: $0.00
Handling purchase
Cash entered: $50.00
Calculating change for: $28.91
Total CID: $11.28
Insufficient funds
Purchase status: INSUFFICIENT_FUNDS
Change due displayed: Status: INSUFFICIENT_FUNDS
Updating cash drawer display
PENNY: $0.13
NICKEL: $0.50
DIME: $0.40
QUARTER: $3.25
ONE: $2.00
FIVE: $5.00
TEN: $0.00
TWENTY: $0.00
ONE HUNDRED: $0.00
Handling purchase
Cash entered: $20.00
Calculating change for: $0.50
Total CID: $1.01
Amount for ONE HUNDRED: $0.00
Amount for TWENTY: $0.00
Amount for TEN: $0.00
Amount for FIVE: $0.00
Amount for ONE: $0.00
Amount for QUARTER: $0.00
Amount for DIME: $0.00
Amount for NICKEL: $0.00
Amount for PENNY: $0.00
Insufficient funds after processing
Purchase status: INSUFFICIENT_FUNDS
Change due displayed: Status: INSUFFICIENT_FUNDS
Updating cash drawer display
PENNY: $0.01
NICKEL: $0.00
DIME: $0.00
QUARTER: $0.00
ONE: $1.00
FIVE: $0.00
TEN: $0.00
TWENTY: $0.00
ONE HUNDRED: $0.00
Handling purchase
Cash entered: $60.00
Calculating change for: $16.43
Total CID: $1008.76
Amount for ONE HUNDRED: $0.00
Amount for TWENTY: $0.00
Amount for TEN: $0.00
Amount for FIVE: $0.00
Change due now: $15.43
Change due now: $14.43
Change due now: $13.43
Change due now: $12.43
Change due now: $11.43
Change due now: $10.43
Change due now: $9.43
Change due now: $8.43
Change due now: $7.43
Change due now: $6.43
Change due now: $5.43
Change due now: $4.43
Amount for ONE: $12.00
Change due now: $4.18
Change due now: $3.93
Change due now: $3.68
Change due now: $3.43
Change due now: $3.18
Change due now: $2.93
Change due now: $2.68
Change due now: $2.43
Change due now: $2.18
Change due now: $1.93
Change due now: $1.68
Change due now: $1.43
Change due now: $1.18
Change due now: $0.93
Change due now: $0.68
Change due now: $0.43
Change due now: $0.18
Amount for QUARTER: $4.25
Change due now: $0.08
Amount for DIME: $0.10
Change due now: $0.03
Amount for NICKEL: $0.05
Change due now: $0.02
Change due now: $0.01
Change due now: $0.00
Amount for PENNY: $0.03
Open
Change returned: [["ONE",12],["QUARTER",4.25],["DIME",0.1],["NICKEL",0.05],["PENNY",0.03]]
Purchase status: OPEN
Change due displayed: Status: OPEN ONE: $12 QUARTER: $4.25 DIME: $0.1 NICKEL: $0.05 PENNY: $0.03
Updating cash drawer display
PENNY: $0.01
NICKEL: $0.05
DIME: $0.70
QUARTER: $1.00
ONE: $0.00
FIVE: $60.75
TEN: $49.90
TWENTY: $279.95
ONE HUNDRED: $599.97
Handling purchase
Cash entered: $20.00
Calculating change for: $0.50
Total CID: $0.50
Closed
Purchase status: CLOSED
Change due displayed: Status: CLOSED PENNY: $0.5 NICKEL: $0 DIME: $0 QUARTER: $0 ONE: $0 FIVE: $0 TEN: $0 TWENTY: $0 ONE HUNDRED: $0
Updating cash drawer display
PENNY: $0.50
NICKEL: $0.00
DIME: $0.00
QUARTER: $0.00
ONE: $0.00
FIVE: $0.00
TEN: $0.00
TWENTY: $0.00
ONE HUNDRED: $0.00
Handling purchase
Cash entered: $50.00
Calculating change for: $29.86
Total CID: $29.86
Closed
Purchase status: CLOSED
Change due displayed: Status: CLOSED PENNY: $1.26 NICKEL: $2.5 DIME: $0.6 QUARTER: $9.5 ONE: $11 FIVE: $5 TEN: $0 TWENTY: $0 ONE HUNDRED: $0
Updating cash drawer display
PENNY: $1.26
NICKEL: $2.50
DIME: $0.60
QUARTER: $9.50
ONE: $11.00
FIVE: $5.00
TEN: $0.00
TWENTY: $0.00
ONE HUNDRED: $0.00

Challenge Information:

Build a Cash Register Project - Build a Cash Register

the reverse here is one problem
the cid is set by the testcase and will not run this reverse command each time a test runs.

If you need to reverse the cid, do it in the code that runs when the purchase button is clicked.

1 Like

Thanks for the quick response, I have implemented this, unfortunately I am still making no progress in finding out why it is not working.

let isCIDReversed = false;
const calculateChange = changeDue => {
  if (!isCIDReversed) {
    cid.reverse();
    isCIDReversed = true;
  }
  console.log(`Calculating change for: $${changeDue.toFixed(2)}`);

  const totalCID = cid.reduce((acc, el) => el[1] + acc, 0);
  console.log(`Total CID: $${totalCID.toFixed(2)}`);

  if (totalCID < changeDue) {
    console.log("Insufficient funds");
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  if (totalCID === changeDue) {
    console.log("Closed");
    return { status: "CLOSED", change: cid };
  }

  let change = [];
  changeDue = parseFloat(changeDue.toFixed(2));

  for (let i = 0; i < currencyUnits.length && changeDue > 0; i++) {
    let amount = 0;
    while (changeDue >= currencyUnits[i][1] && cid[i][1] >= currencyUnits[i][1]) {
      amount += currencyUnits[i][1];
      cid[i][1] -= currencyUnits[i][1];
      changeDue = parseFloat(changeDue - currencyUnits[i][1]).toFixed(2);
      console.log(`Change due now: $${changeDue}`);
    }
    if (amount > 0) change.push([currencyUnits[i][0], amount]);
    console.log(`Amount for ${currencyUnits[i][0]}: $${amount.toFixed(2)}`);
  }

  if (changeDue > 0) {
    console.log("Insufficient funds after processing");
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  console.log("Open");
  console.log(`Change returned: ${JSON.stringify(change)}`);
  return { status: "OPEN", change: change };
};

global variables are still not a good idea, why are you adding this here?

button is clicked, calculateChange is executed, and the tests evaluate things, then price and cid are changed, the button is clicked again, but at this point isCIDReversed is true, the new cid is not reversed, and your function doesn’t work as expected

1 Like

ah okay i did that because the problem is if you call calculateChange once everything is fine but if you call calculateChange another time and cid stays the same cid will be reversed another time and i want to avoid that

Just reverse a copy of it when the button is clicked for purchase. The original should not be changed.

calculateChange is called when you press the button so still the same problem even if I work with a copy or did I misunderstand you?
sorry for the inconvenience

const calculateChange = changeDue => {
  cidReversed = cid.slice().reverse();

  console.log(`Calculating change for: $${changeDue.toFixed(2)}`);

  const totalCID = cid.reduce((acc, el) => el[1] + acc, 0);
  console.log(`Total CID: $${totalCID.toFixed(2)}`);

  if (totalCID < changeDue) {
    console.log("Insufficient funds");
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  if (totalCID === changeDue) {
    console.log("Closed");
    return { status: "CLOSED", change: cid };
  }

  let change = [];
  changeDue = parseFloat(changeDue.toFixed(2));

  for (let i = 0; i < currencyUnits.length && changeDue > 0; i++) {
    let amount = 0;
    while (changeDue >= currencyUnits[i][1] && cidReversed[i][1] >= currencyUnits[i][1]) {
      amount += currencyUnits[i][1];
      cidReversed[i][1] -= currencyUnits[i][1];
      changeDue = parseFloat(changeDue - currencyUnits[i][1]).toFixed(2);
      console.log(`Change due now: $${changeDue}`);
    }
    if (amount > 0) change.push([currencyUnits[i][0], amount]);
    console.log(`Amount for ${currencyUnits[i][0]}: $${amount.toFixed(2)}`);
  }

  if (changeDue > 0) {
    console.log("Insufficient funds after processing");
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  console.log("Open");
  console.log(`Change returned: ${JSON.stringify(change)}`);
  return { status: "OPEN", change: change };
};

When you make a new copy each time the button is clicked and reverse it, then that means you will always be working with the reversed version. What issue are you having with your current code?

Edit: you should not be declaring the reversed copy outside the function.

1 Like

you are absolutely right no idea what i was thinking it works now i only have the two tests that fail

18. When price is 19.5, the value in the #cash element is 20, cid is [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]], and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: CLOSED PENNY: $0.5".
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.

what’s your output for those two tests?

here is the console output

// console output
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $90.00
FIVE: $55.00
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $10.00
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $90.00
FIVE: $55.00
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $3.37
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $90.00
FIVE: $55.00
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $11.95
No change due
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $90.00
FIVE: $55.00
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $34.87
No change due
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $4.25
ONE: $90.00
FIVE: $55.00
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $20.00
Calculating change for: $0.50
Total CID: $335.41
Amount for ONE HUNDRED: $0.00
Amount for TWENTY: $0.00
Amount for TEN: $0.00
Amount for FIVE: $0.00
Amount for ONE: $0.00
Change due now: $0.25
Change due now: $0.00
Amount for QUARTER: $0.50
Open
Change returned: [["QUARTER",0.5]]
Purchase status: OPEN
Change due displayed: Status: OPEN QUARTER: $0.5
Updating cash drawer display
PENNY: $1.01
NICKEL: $2.05
DIME: $3.10
QUARTER: $3.75
ONE: $90.00
FIVE: $55.00
TEN: $20.00
TWENTY: $60.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $100.00
Calculating change for: $96.74
Total CID: $335.41
Amount for ONE HUNDRED: $0.00
Change due now: $76.74
Change due now: $56.74
Change due now: $36.74
Amount for TWENTY: $60.00
Change due now: $26.74
Change due now: $16.74
Amount for TEN: $20.00
Change due now: $11.74
Change due now: $6.74
Change due now: $1.74
Amount for FIVE: $15.00
Change due now: $0.74
Amount for ONE: $1.00
Change due now: $0.49
Change due now: $0.24
Amount for QUARTER: $0.50
Change due now: $0.14
Change due now: $0.04
Amount for DIME: $0.20
Amount for NICKEL: $0.00
Change due now: $0.03
Change due now: $0.02
Change due now: $0.01
Change due now: $0.00
Amount for PENNY: $0.04
Open
Change returned: [["TWENTY",60],["TEN",20],["FIVE",15],["ONE",1],["QUARTER",0.5],["DIME",0.2],["PENNY",0.04]]
Purchase status: OPEN
Change due displayed: Status: OPEN TWENTY: $60 TEN: $20 FIVE: $15 ONE: $1 QUARTER: $0.5 DIME: $0.2 PENNY: $0.04
Updating cash drawer display
PENNY: $0.97
NICKEL: $2.05
DIME: $2.90
QUARTER: $3.75
ONE: $89.00
FIVE: $40.00
TEN: $0.00
TWENTY: $0.00
ONE HUNDRED: $100.00
Handling purchase
Cash entered: $80.00
Calculating change for: $12.00
Total CID: $1082.62
Amount for ONE HUNDRED: $0.00
Amount for TWENTY: $0.00
Change due now: $2.00
Amount for TEN: $10.00
Amount for FIVE: $0.00
Change due now: $1.00
Change due now: $0.00
Amount for ONE: $2.00
Open
Change returned: [["TEN",10],["ONE",2]]
Purchase status: OPEN
Change due displayed: Status: OPEN TEN: $10 ONE: $2
Updating cash drawer display
PENNY: $0.72
NICKEL: $0.50
DIME: $1.40
QUARTER: $2.00
ONE: $1.00
FIVE: $55.00
TEN: $30.00
TWENTY: $80.00
ONE HUNDRED: $900.00
Handling purchase
Cash entered: $20.00
Calculating change for: $0.50
Total CID: $0.01
Insufficient funds
Purchase status: INSUFFICIENT_FUNDS
Change due displayed: Status: INSUFFICIENT_FUNDS
Updating cash drawer display
PENNY: $0.01
NICKEL: $0.00
DIME: $0.00
QUARTER: $0.00
ONE: $0.00
FIVE: $0.00
TEN: $0.00
TWENTY: $0.00
ONE HUNDRED: $0.00
Handling purchase
Cash entered: $80.00
Calculating change for: $10.47
Total CID: $8.05
Insufficient funds
Purchase status: INSUFFICIENT_FUNDS
Change due displayed: Status: INSUFFICIENT_FUNDS
Updating cash drawer display
PENNY: $0.05
NICKEL: $0.40
DIME: $1.10
QUARTER: $2.50
ONE: $4.00
FIVE: $0.00
TEN: $0.00
TWENTY: $0.00
ONE HUNDRED: $0.00
Handling purchase
Cash entered: $20.00
Calculating change for: $0.50
Total CID: $1.01
Amount for ONE HUNDRED: $0.00
Amount for TWENTY: $0.00
Amount for TEN: $0.00
Amount for FIVE: $0.00
Amount for ONE: $0.00
Amount for QUARTER: $0.00
Amount for DIME: $0.00
Amount for NICKEL: $0.00
Change due now: $0.49
Amount for PENNY: $0.01
Insufficient funds after processing
Purchase status: INSUFFICIENT_FUNDS
Change due displayed: Status: INSUFFICIENT_FUNDS
Updating cash drawer display
PENNY: $0.00
NICKEL: $0.00
DIME: $0.00
QUARTER: $0.00
ONE: $1.00
FIVE: $0.00
TEN: $0.00
TWENTY: $0.00
ONE HUNDRED: $0.00
Handling purchase
Cash entered: $70.00
Calculating change for: $29.77
Total CID: $714.60
Amount for ONE HUNDRED: $0.00
Change due now: $9.77
Amount for TWENTY: $20.00
Amount for TEN: $0.00
Change due now: $4.77
Amount for FIVE: $5.00
Change due now: $3.77
Change due now: $2.77
Change due now: $1.77
Change due now: $0.77
Amount for ONE: $4.00
Change due now: $0.52
Change due now: $0.27
Change due now: $0.02
Amount for QUARTER: $0.75
Amount for DIME: $0.00
Amount for NICKEL: $0.00
Amount for PENNY: $0.00
Insufficient funds after processing
Purchase status: INSUFFICIENT_FUNDS
Change due displayed: Status: INSUFFICIENT_FUNDS
Updating cash drawer display
PENNY: $0.00
NICKEL: $0.55
DIME: $0.30
QUARTER: $1.00
ONE: $3.00
FIVE: $20.00
TEN: $100.00
TWENTY: $260.00
ONE HUNDRED: $300.00
Handling purchase
Cash entered: $20.00
Calculating change for: $0.50
Total CID: $0.50
Closed
Purchase status: CLOSED
Change due displayed: Status: CLOSED PENNY: $0.5 NICKEL: $0 DIME: $0 QUARTER: $0 ONE: $0 FIVE: $0 TEN: $0 TWENTY: $0 ONE HUNDRED: $0
Updating cash drawer display
PENNY: $0.50
NICKEL: $0.00
DIME: $0.00
QUARTER: $0.00
ONE: $0.00
FIVE: $0.00
TEN: $0.00
TWENTY: $0.00
ONE HUNDRED: $0.00
Handling purchase
Cash entered: $100.00
Calculating change for: $25.89
Total CID: $25.89
Closed
Purchase status: CLOSED
Change due displayed: Status: CLOSED PENNY: $0.24 NICKEL: $0.3 DIME: $0.1 QUARTER: $0.25 ONE: $0 FIVE: $15 TEN: $10 TWENTY: $0 ONE HUNDRED: $0
Updating cash drawer display
PENNY: $0.24
NICKEL: $0.30
DIME: $0.10
QUARTER: $0.25
ONE: $0.00
FIVE: $15.00
TEN: $10.00
TWENTY: $0.00
ONE HUNDRED: $0.00

is that for that specific test? there is so much stuff in what you posted that is useless to determine what’s wrong with the specific test that is failing

ah i’m sorry i didn’t read your question properly here is the output for the two tests i don’t know if you can do anything with it

[DEBUG] Enter key pressed 
[DEBUG] Handling purchase 
[DEBUG] Cash entered: $20.00 
[DEBUG] Change due: $0.50 
[DEBUG] Transaction #7 
[DEBUG] Initial CID: [ [ 'PENNY', 0.5 ],
  [ 'NICKEL', 0 ],
  [ 'DIME', 0 ],
  [ 'QUARTER', 0 ],
  [ 'ONE', 0 ],
  [ 'FIVE', 0 ],
  [ 'TEN', 0 ],
  [ 'TWENTY', 0 ],
  [ 'ONE HUNDRED', 0 ] ]
[DEBUG] Calculating change for: $0.50 
[DEBUG] Total CID: $0.50 
[DEBUG] Closed - Exact change 
[DEBUG] Purchase status: CLOSED 
[DEBUG] Change due displayed: Status: CLOSED PENNY: $0.50 NICKEL: $0.00 DIME: $0.00 QUARTER: $0.00 ONE: $0.00 FIVE: $0.00 TEN: $0.00 TWENTY: $0.00 ONE HUNDRED: $0.00 
[DEBUG] Updating cash drawer display 
[DEBUG] Updated PENNY display: $0.50 
[DEBUG] Updated NICKEL display: $0.00 
[DEBUG] Updated DIME display: $0.00 
[DEBUG] Updated QUARTER display: $0.00 
[DEBUG] Updated ONE display: $0.00 
[DEBUG] Updated FIVE display: $0.00 
[DEBUG] Updated TEN display: $0.00 
[DEBUG] Updated TWENTY display: $0.00 
[DEBUG] Updated ONE HUNDRED display: $0.00 
[DEBUG] Enter key pressed 
[DEBUG] Handling purchase 
[DEBUG] Cash entered: $60.00 
[DEBUG] Change due: $26.03 
[DEBUG] Transaction #8 
[DEBUG] Initial CID: [ [ 'PENNY', 0.03 ],
  [ 'NICKEL', 0 ],
  [ 'DIME', 0 ],
  [ 'QUARTER', 3 ],
  [ 'ONE', 3 ],
  [ 'FIVE', 20 ],
  [ 'TEN', 0 ],
  [ 'TWENTY', 0 ],
  [ 'ONE HUNDRED', 0 ] ]
[DEBUG] Calculating change for: $26.03 
[DEBUG] Total CID: $26.03 
[DEBUG] Closed - Exact change 
[DEBUG] Purchase status: CLOSED 
[DEBUG] Change due displayed: Status: CLOSED PENNY: $0.03 NICKEL: $0.00 DIME: $0.00 QUARTER: $3.00 ONE: $3.00 FIVE: $20.00 TEN: $0.00 TWENTY: $0.00 ONE HUNDRED: $0.00 
[DEBUG] Updating cash drawer display 
[DEBUG] Updated PENNY display: $0.03 
[DEBUG] Updated NICKEL display: $0.00 
[DEBUG] Updated DIME display: $0.00 
[DEBUG] Updated QUARTER display: $3.00 
[DEBUG] Updated ONE display: $3.00 
[DEBUG] Updated FIVE display: $20.00 
[DEBUG] Updated TEN display: $0.00 
[DEBUG] Updated TWENTY display: $0.00 
[DEBUG] Updated ONE HUNDRED display: $0.00

this looks like a problem?

None of those zero values should be shown.

1 Like

Thanks, I overlooked it. :person_facepalming: Here is the fix, unfortunately I still do not know why test 19 does not pass.

const cashInput = document.getElementById("cash");
const changeDueElem = document.getElementById("change-due");
const purchaseBtn = document.getElementById("purchase-btn");
const priceScreen = document.getElementById("price-screen");

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

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

priceScreen.textContent = `Total: $${price.toFixed(2)}`;

const calculateChange = (changeDue) => {
  const reversedCid = cid.slice().reverse();

  const totalCID = cid.reduce((acc, el) => el[1] + acc, 0);

  let status = 'OPEN';
  let change = [];

  if (totalCID < changeDue) {
    return { status: "INSUFFICIENT_FUNDS", change: [] };
  }

  if (totalCID === changeDue) {
    status = 'CLOSED';
  }

  for (let i = 0; i < currencyUnits.length && changeDue > 0; i++) {
    let amount = 0;
    let coinValue = currencyUnits[i][1];

    while (changeDue >= coinValue && reversedCid[i][1] > 0) {
      amount += coinValue;
      reversedCid[i][1] = parseFloat((reversedCid[i][1] - coinValue).toFixed(2))
      changeDue = parseFloat((changeDue - coinValue).toFixed(2));
    }
    if (amount > 0) {
      change.push([currencyUnits[i][0], parseFloat(amount.toFixed(2))]);
    }
  }

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

  return { status, change };
};

const handlePurchase = () => {
  const cash = parseFloat(cashInput.value);
  if (isNaN(cash) || cash < price) {
    alert("Customer does not have enough money to purchase the item");
    return;
  }

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

  const { status, change } = calculateChange(parseFloat(cash - price));

  changeDueElem.textContent = status === "INSUFFICIENT_FUNDS"
    ? "Status: INSUFFICIENT_FUNDS"
    : `Status: ${status} ${change.map(([unit, amount]) => `${unit}: $${amount}`).join(" ")}`;

    updateCashDrawerDisplay();
};

const updateCashDrawerDisplay = () => {
  cid.forEach(([unit, amount]) => {
    const element = document.getElementById(`${unit.toLowerCase()}-amount`);
    if (element) {
      element.textContent = `$${amount}`;
    }
  });
};

document.querySelectorAll('.key').forEach(button => {
  button.addEventListener('click', function() {
    if (this.classList.contains('enter')) {
      handlePurchase();
    } else if (this.classList.contains('clear')) {
      cashInput.value = '';
    } else {
      cashInput.value += this.textContent;
    }
  });
});

updateCashDrawerDisplay();
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.

Edit: I was wrong, the code seems to pass the test, but strangely only sometimes… if I don’t have a logic error, the code should pass the test :thinking:

A floating point error can do that. Check all the lines that do anything with floating point numbers.

1 Like

Thanks! I’ve reviewed the code again and found another way to handle the floating-point calculations. Based on the tests, everything now works as it should. I appreciate your patience and hard work, guys.

1 Like

Well done. Some people don’t bother trying this hard.

1 Like