Build a Cash Register test help

Hi I’m having some difficulties with the test suite for the build a cash register project. Some of the cases work some times and others work other times. Here is my HTML and JS.

HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <link rel="stylesheet" href="styles.css" />
    <title>Cash Register</title>
  </head>
  <body>
    <header>Cash Register</header>
    <main>
    <div id="price"></div>
    <input id="cash" type="number" min="0"/>
    <div id="change-due"></div>
    <button id="purchase-btn">Purchase</button>
    <div id="register"></div>
    </main>
  </body>
  <script src="script.js"></script>
</html>

JS:

const input = document.getElementById("cash");
const registerDiv = document.getElementById("register");
const output = document.getElementById("change-due");
const purchaseBtn = document.getElementById("purchase-btn");
const priceDiv = document.getElementById("price");

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

class Register {
  constructor(inp){
    this.cid = JSON.parse(JSON.stringify(inp));
    this.updateRegister();
  }

  totalCid(){
    let out = 0;
    return Math.round(this.cid.reduce((out, elem) => {return out + elem[1]}, 0) * 100) / 100;
  }

  buy(cash ,price){
    output.textContent = "";
    if (cash < price){
      alert("Customer does not have enough money to purchase the item");
      return;
    }
    if (cash == price){
      output.textContent = "No change due - customer paid with exact cash";
      return;
    }
    const change = this.calculateChange(cash, price);
    output.innerText = change;
    this.updateRegister();
  }

  calculateChange(cash, price){
    let change = Math.round((cash - price) * 100) / 100;
    if (change > this.totalCid()){
      return "Status: INSUFFICIENT_FUNDS";
    }

    let changeGiven = Array(this.cid.length).fill(0);
    const denominations = [0.01, 0.05, 0.10, 0.25, 1.00, 5.00, 10.00, 20.00, 100.00];
    const denomNames = ["PENNY", "NICKEL", "DIME", "QUARTER", "ONE", "FIVE", "TEN", "TWENTY", "ONE HUNDRED"];

    for (let i = this.cid.length - 1; i >= 0; i--){
      while (change >= denominations[i] && (this.cid[i][1] / denominations[i] > 0)){
        change -= denominations[i];
        change = Math.round(change * 100) / 100;
        this.cid[i][1] -= denominations[i];
        changeGiven[i] += denominations[i];
      }
    }
    
    if (change > 0) return "Status: INSUFFICIENT_FUNDS"; 

    const arrOutput = [];
    for (let i = changeGiven.length - 1; i >= 0; i--){
      if (changeGiven[i] != 0){
        arrOutput.push([denomNames[i], changeGiven[i]]);
      }
    }
    
    let outputStr = arrOutput.map(i => `${i[0]}: $${i[1]}`).join(" ");
    
    if (this.totalCid() === 0) {
      return "Status: CLOSED " + outputStr;
    }
    
    return "Status: OPEN " + outputStr;
  }

  updateRegister(){
    registerDiv.textContent = "";
    for (let i of this.cid){
      registerDiv.textContent += i.join(": $") + "\n";
    }
  }
}

priceDiv.textContent = "PRICE: $" + price;
const register = new Register(cid);

purchaseBtn.addEventListener("click", () => register.buy(parseFloat(input.value), price));

I’ve edited your code for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (').

Sorry about that. Thank you :slight_smile:

1 Like

don’t create this Register object in the global scope.
Create it when someone presses the purchase button because that’s how the tests run.
They only load your code once, then run the purchase event multiple times in a row.

edit:

also I notice another problem once this global scope issue is fixed which is that if you set the price and cid as below:


let price = 3.26;
let cid = [["PENNY", 1], ["NICKEL", 0], ["DIME", 1.1], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]];

and then type 5.36 into the input box you will get this incorrect output:
Status: CLOSED DIME: $1.2 PENNY: $0.9000000000000006

So you will need to deal with floating point arithmetic as well for this case. (notice the dime amount is incorrect too)

1 Like

Thank you so much! I was working on this for so long. You were a great help.

1 Like