Build a Cash Register Project - Build a cash Register - Cant' pass some test

My Issues:

I’m really struggling with passing some tests. From the 6 to the last.

I’ll use that one has an example:

  1. When price is 19.5, the value in the #cash element is 20, 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 QUARTER: $0.5"

So when I change the value of my price variable to be 19.5, that my input is 20, my change-due element is change to provide the exact text demanded and yet, it doesn’t pass the test. I’ve tried many ways, like putting some “” or not, putting that in a table or not .

I’m stuck. Maybe I’m missing something obvious. I’ve been on that issue for almost a week now. My code is not cleaned now, but I don’t feel the energy left because of that specific issue.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="styles.css" rel="stylesheet">
    <title>Cash register</title>
</head>
<body>
    <header>
        <img src="https://cdn.freecodecamp.org/platform/universal/fcc_primary.svg" alt="FreeCodeCamp Logo">
        <h1>Cash Register Project</h1>
    </header>

    <div id="container">
        <div id="container-label">
            <label for="cash">Enter cash from customer:</label>
            <input type="number" id="cash" min="0" max="666">
            <button id="purchase-btn">Purchase</button>
        </div>

        <div id="caisse">
            <div id="change-due"></div>
            <div id="touchPad">
                <div class="touch-row">
                    <div class="key">1</div>
                    <div class="key">4</div>
                    <div class="key">7</div>
                </div>
                <div class="touch-row">
                    <div class="key">2</div>
                    <div class="key">5</div>
                    <div class="key">8</div>
                </div>
                <div class="touch-row">
                    <div class="key">3</div>
                    <div class="key">6</div>
                    <div class="key">9</div>
                </div>
                <div class="touch-row">
                    <div class="key">.</div>
                    <div class="key">v</div>
                    <div class="key">0</div>
                </div>
            </div>

            <table id="cid">
                <!-- Placeholder for cash register details ?-->
            </table>
        </div>

        <div id="tiroirCaisse">
<span id="buttonBlack"></span>
        </div>
    </div>
    
    <script src="script.js"></script>
</body>
</html>



body{
  background-color:#000000;
  color:#ffffff;
  margin:0;
  padding:0;
}

header {
    text-align: center;
    padding: 20px;
}

header img{
  width:666px;
  height:auto;
}

#container {
    max-width: 800px; 
    margin: 0 auto;
    padding: 20px; 
    display:flex;
    flex-direction:column;
    align-items:center;
}


#container-label {
    text-align: center;
    margin-bottom: 20px; 
    display:flex;
    flex-direction:column;
    align-items:center;
}
#container-label >*{
  margin-bottom:10px;
}


#caisse {
    text-align: center;
    margin: 20px 0;
    background-color:#1f497d;
    padding:20px;
    border-radius:8px;
}
#touchPad{
  width:150px;
  height:150px;
  background-color:#31618c;
  display:flex;
  flex-wrap:wrap;
  justify-content: space-around;
  padding:10px;
  border-radius:10px;
  margin-bottom:20px;
}

.key{
  width:30px;
  height:40px;
  background-color:#4a90e2;
  display:flex;
  justify-content: center;
  align-items:center;
  border-radius:50%;
  margin-bottom:10px;
  font-size:12px;
}

#tiroirCaisse {
    text-align: center;
    margin-top: 10px; 
    background-color:#1f497d;
    width:30%;
    padding:10px;
    border-radius:5px;
    display:flex;
    justify-content: center;
}
#buttonBlack{
  position:relative;
  width:10px;
  height:10px;
  background-color:#000000;
  border-radius:50%;
  left: calc(50% -10px);
  visibility:visible;
border: 1px solid #f0f
}

const inputMoney = document.getElementById("cash");
const purchaseButton = document.getElementById("purchase-btn");
const changeDue = document.getElementById("change-due");
const touchPad = document.getElementById("touchPad");
const cidPlace = document.getElementById("cid");

let total = 0;
let price = 19.5;
let pricePerfect = price * 100;
let money = 0;
let moneyPerfect = money *100


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 value=[
  0.01, 0.05, 0.1, 0.25, 1.00, 5.00, 10.00, 20.00, 100.00
];

let resultatFinal=[];

cidRender();
cidValue(cid, value);
amountColumn(cid);
conversion(cid);

function format (string){
  let lowerCaseString = string.toLowerCase();
  return lowerCaseString.charAt(0).toUpperCase() + lowerCaseString.slice(1);
};

function cidRender (){
  cid.forEach((e) => {
    let coinName = e[0];
    let coinNameFormatted = format(coinName);
    let coinValue = parseFloat(e[1]);
    cidPlace.innerHTML += `<tr>
<th>${coinNameFormatted}</th>
<th>${coinValue}</th></tr>`;
    total += coinValue;
  });
  total = parseFloat(total.toFixed(2));

};

function finalRendue(){
  if(resultatFinal.length >=1){
 changeDue.innerHTML += `
    <table> 
    <tr>
    <td> Status: OPEN ${resultatFinal[0][0]}: $${parseFloat(resultatFinal[0][5])}</td>
    </tr> `;

  resultatFinal.slice(1).forEach((e)=>{
    let coinName = e[0];
    let coinValue = parseFloat(e[5]);
if (coinValue === 1){
coinValue = parseFloat(e[2])
}
    tableContent += `<tr>
    <td> ${coinName}: $${coinValue}</td>
  </tr>`
  })
  change.innerHTML += "</table>"
  } else {
    changeDue.innerHTML;
  } 
}

function cidValue(array){
  for(let i = 0 ; i < array.length; i++ ){
    array[i].push(value[i]);
  }

}

function amountColumn(array){
for (let i= 0; i <array.length; i++){
const count = Math.floor(array[i][1]/array[i][2])
array[i].push(count)
}
}

function conversion(array){

  for(let i=0; i < array.length; i++){
    const converted = array[i][2]*100;
    array[i].push(converted)
  }

}

function findLastIndex(cid, change) {
  let lastValidIndex = -1;
  for (let i = cid.length - 1; i >= 0; i--) {
    if (cid[i][2] <= change) {
      lastValidIndex = i;
      break;
    }
  }
return lastValidIndex;
}

function finalRender(){
 changeDue.innerHTML += `
    Status: CLOSED `;
    let coinName = resultatFinal[0][0];
    let coinValue = parseFloat(resultatFinal[0][5]);
if (coinValue === 1){
coinValue = parseFloat(resultatFinal[0][2])
    changeDue.innerHTML += ` ${coinName}: $${coinValue}`
  }
}

function changeRecursive(changePerfect, fLI){
  
  let lignes = [];
  lignes.push(cid[fLI][0], cid[fLI][1], cid[fLI][2], cid[fLI][3], cid[fLI][4], 0);


if (cid[fLI][1] > 0){

  while (changePerfect >= cid[fLI][4] && changePerfect > 0 && lignes[1] >0  ) {
    changePerfect -= cid[fLI][4];
    lignes[1] = parseFloat((lignes[1] - lignes[2]).toFixed(2));
    lignes[3]--;
  } 
}
  let arrondi = parseFloat((cid[fLI][1] - lignes[1]).toFixed(2));
  if (arrondi === 0) {
    arrondi = 1;
  }
  lignes[5] = arrondi;
  fLI--;
  resultatFinal.push(lignes);
  if (fLI >= 0 && changePerfect > 0) {
    changeRecursive(changePerfect, fLI);
  } else {
    console.log(resultatFinal);
    return resultatFinal;
  }
}


const fetchValue=()=>{
  money = inputMoney.value;
  if (money <=0){
    alert("You kiding me ?")
  } else {
  calculus(money)
  }
}

const calculus =() => {
  let change = parseFloat(Math.abs(money - price).toFixed(2));
let changePerfect = change *100
 
  if (change === 0) {
    changeDue.innerHTML = "No change due - customer paid with exact cash";
  } else if (money < price) {
    alert("Customer does not have enough money to purchase the item");
  } else if(total < change){
changeDue.innerHTML += "<p>Status: INSUFFICIENT_FUNDS</p>"
  } else if(total === change){
let fLI = findLastIndex(cid, change);
changeRecursive(changePerfect, fLI)
cidPlace.innerHTML = "";
    cidRender(cid)
finalRender(resultatFinal)

for(let l = 0; l < resultatFinal.length; l ++){
    cid.forEach((element, index)=>{
      if(element[0]=== resultatFinal[l][0]){
        cid[index] = resultatFinal[l]
      }
    })
}


  } else {
    let fLI = findLastIndex(cid, change);
  changeRecursive(changePerfect, fLI)
for(let l = 0; l < resultatFinal.length; l ++){
    cid.forEach((element, index)=>{
      if(element[0]=== resultatFinal[l][0]){
        cid[index] = resultatFinal[l]
      }
    })
  
  }
cidPlace.innerHTML = "";
    cidRender(cid)
finalRendue(resultatFinal, change)
  }
}
purchaseButton.addEventListener('click', fetchValue)

If someone can help me, I’d be incredible. I just want an hint about what imma doing wrong…

Hi @A.I

It looks like you are declaring variables in the global scope.

So each time the function is run it is updating the previous values.

Happy coding

everything in the global scope is executed only once, then the tests change cid and price but all those other things are not changed, move everything but cid and price inside the functions you call from the event listener

@Teller

Is this something wrong to declare variable that way ? I really thought I had to declare them like that since I’m trying to make my first recursive function :no_mouth:

Maybe I totally misunderstood the way a recursive function works, which is frustrated cause technically, when I run manually the test one by one, it works

@ilenia Thank’s for the hint, I’m trying to do such it, but I keep tripping on issue with global variable. I have to rethink my code but it will work, I hope.

Stuck again.

With he advice of @Teller and @ilenia , i’ve change a lot of my code, cleaned it too, but I still have the same issue. When I run the test by end, it works. When i click on Run The Tests, it only passes the first 5…

My code :

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 purchaseButton = document.getElementById("purchase-btn");
var total = 0;

const cidDisplay=()=>{
console.log(" /\\_/\\");
const cidPlace = document.getElementById("cid");
cidPlace.innerHTML ="";
const value=[
  0.01, 0.05, 0.1, 0.25, 1.00, 5.00, 10.00, 20.00, 100.00
];
const coinNameFormatted = (string)=>{
  let lowerCaseString = string.toLowerCase();
  return lowerCaseString.charAt(0).toUpperCase() + lowerCaseString.slice(1);
}
  console.log("( o.o )")

for (let i = 0; i < cid.length; i++) {
  let coinName = cid[i][0];
  let formattedCoinName = coinNameFormatted(coinName);
  let coinValue = parseFloat(cid[i][1]);
   cidPlace.innerHTML += `<tr><th>${formattedCoinName}</th><th>${coinValue}</th></tr>`;
    total += coinValue;
    cid[i].push(value[i]);
const count = Math.floor(cid[i][1]/cid[i][2])
    cid[i].push(count)
const converted = cid[i][2]*100;
    cid[i].push(converted)
}
total = parseFloat(total.toFixed(2));
console.log(" > ^ <")
}
cidDisplay();



const processTransaction=()=>{

const inputMoney = document.getElementById("cash").value;

const changeDue = document.getElementById("change-due");

  if(!inputMoney){
    alert("Please, provide an amount")
  }

let change = parseFloat(Math.abs(price - inputMoney ).toFixed(2));

let adjustedChange = change *100

if(change ===0 ){
changeDue.innerHTML += "<p>No change due - customer paid with exact cash</p>"
} else if (inputMoney < price) {
  alert("Customer does not have enough money to purchase the item")
} else if( total < inputMoney){
changeDue.innerHTML += "<p>Status: INSUFFICIENT_FUNDS</p>"
}else if( total === change){
 console.log("debut de la fin !")
 const findLastIndex= ()=>{
let lastValidIndex = -1;
    for (let i = cid.length - 1; i >= 0; i--) {
      if (cid[i][2] <= change) {
        lastValidIndex = i;
          break;
          }
        }
      return lastValidIndex
  }
    var lastIndex = findLastIndex();
  let indexLignes = 0;
  let lignes = [];

const changeRecursive=()=>{
   lignes.push([cid[lastIndex][0], cid[lastIndex][1], cid[lastIndex][2], cid[lastIndex][3], cid[lastIndex][4], 0]);
if (cid[lastIndex][1] > 0){
  while (adjustedChange >= cid[lastIndex][4] && adjustedChange >= 0 && lignes[indexLignes][1] >0 ) {
    adjustedChange -= cid[lastIndex][4];
    lignes[indexLignes][1] = parseFloat((lignes[indexLignes][1] - lignes[indexLignes][2]).toFixed(2));
    lignes[indexLignes][3]--;
    lignes[indexLignes][5] += cid[lastIndex][2]
  } 
}
  lastIndex--;
  indexLignes ++;
  if (lastIndex > 0 && adjustedChange > 0) {
    changeRecursive(adjustedChange, lastIndex);
  }
}
changeRecursive();

 changeDue.innerHTML += `
    <table> 
    <tr>
    <td> Status: OPEN ${lignes[0][0]}: $${parseFloat(lignes[0][5])}</td>
    </tr> </table>`;
} else {

  const findLastIndex= ()=>{
let lastValidIndex = -1;
    for (let i = cid.length - 1; i >= 0; i--) {
      if (cid[i][2] <= change) {
        lastValidIndex = i;
          break;
          }
        }
      return lastValidIndex
  }
  
    var lastIndex = findLastIndex();
  
  let indexLignes = 0;
  let lignes = [];

const changeRecursive=()=>{
lignes.push([cid[lastIndex][0], cid[lastIndex][1], cid[lastIndex][2], cid[lastIndex][3], cid[lastIndex][4], 0]);
if (cid[lastIndex][1] > 0){
  while (adjustedChange >= cid[lastIndex][4] && adjustedChange >= 0 && lignes[indexLignes][1] >0 ) {
    adjustedChange -= cid[lastIndex][4];
    lignes[indexLignes][1] = parseFloat((lignes[indexLignes][1] - lignes[indexLignes][2]).toFixed(2));
    cid[lastIndex][1] -= cid[lastIndex][2]
    lignes[indexLignes][3]--;
    cid[lastIndex][3]--
    lignes[indexLignes][5] += cid[lastIndex][2]
  } 
}
  lastIndex--;
  indexLignes ++;
  if (lastIndex > 0 && adjustedChange > 0) {
    changeRecursive(adjustedChange, lastIndex);
  }
}
 changeRecursive();
cidDisplay();
let tableContent= "";
 changeDue.innerHTML += `
    <table> 
    <tr>
    <td> Status: OPEN ${lignes[0][0]}: $${parseFloat(lignes[0][5])}</td>
    </tr> `;

  lignes.slice(1).forEach((e)=>{
    console.log("chat")
    let coinName = e[0];
    console.log("pristi", coinName)
    let coinValue = parseFloat(e[5]);
    console.log("pardeur", coinValue);

    tableContent += `<tr>
    <td> ${coinName}: $${coinValue}</td>
  </tr>\n`
  console.log("coin", tableContent)
  })
  changeDue.innerHTML += tableContent + "</table>"
  
}

}

purchaseButton.addEventListener('click', processTransaction)

And a little screenshot of the result. I know it’s ugly, I just want to have a functionnal algorythm for now, I’ll make something prettier later

image

None of the tests checking the output pass, one reason is that you append an output every time you click the button. Every time you click the button you should have a new output that overwrites the precedent

I have a new output that overwrites the precedent, every time the button is clicked every value restart, isn’t what it must do ?? Or shall I still keep all the status but have a new output ???

If you put in a number and click the purchase button a couple of times, what do you see?

The test checks the change-due elements innerText so I would assume you can’t add the output to child elements (the table).

The total variable is still a top-level variable.

1 Like

Thank you so much @lasjorg, the way you asked me those questions really helped me to figure out my issues !!!

I’m sorry @ilenia, you put me on the right way to solve my issue, but I couldn’t see it !

I finally find a way to move total where it shall be, and not anymore on top. Furthermore, I also find a simple way to “clean” my changeDue each time.

Thank you again everyone for your help, now I only have two errors left !