Cash Register - I can't pass tests

Hello
My outputs seem correct but I can’t pass tests.

Cash Register CODEPEN

1 Like

Merhaba Cem foruma hoşgeldin;

Could you explain which test you can’t pass and what error you’re encountering? What have you tried so far, and what approach have you taken to solve this? Why did you opt for the OOP approach, how does your code function, and how are the calculations made? Explaining these aspects would not only facilitate understanding for others but also enhance your chances of identifying the root cause by analyzing your own code.

Also your design is looks great! :ok_hand:

Edit: If you strugling explain in English, Türkçe de yazabilirsin :wink:

1 Like
  • I can’t pass 7, 8, 9, 10 with 6 inputs.
  • I can’t pass 7, 8, 9, 10 with 7 inputs.
  • I can’t pass 6, 7, 10 with 8 inputs.
  • I can’t pass 6, 7, 10 with 9 inputs.
  • I can’t pass 6, 7, 10 with 10 inputs.
    Also I don’t understand why there are different reactions with my inputs(price, cid) because I don’t change my codes(without price and cid) and fCC tests give inherit inputs.

I fixed my faulty codes, but my codes seem correct to me in the final. I also get correct results on #change-due.

  • I learned “class” in projects before the Cash Register project and preferred class to practice with “class, constructor and this”.
  • The constructor creates an array containing the cid values, the number of coins and notes, and a variable representing the total amount of money.
  • The “inner for” refunds money from the larger to the smaller. When the change is finished, it updates the interface and ends the “inner for”.
  • The “outer for” updates the “cid” when the change is finished and ends the “outer for”.

Türkçe biliyor musunuz yoksa benim gibi Google Translate mi kullanıyorsunzuz :slight_smile: Ana dilin dışında derdini anlatmak zor cidden.

I wrote a Turkish comment, but it needs to be approved by moderators. For clarification, I wrote this to help @Ejderha, whose English is not perfect, and it can also help other Turkish people too. I hope this will not cause any problems.

1 Like

Evet Türkçe ve İngilizce biliyorum, sorun değil ama google translate kullanmanı önermem Yandex çeviri biraz daha iyi.

Türkçe devam edebiliriz, ayrıca Türkçe kaynak da olmuş olur.

Ayrıca uygulamayı OOP ile yapmış olman gayet güzel ve eşsiz olmuş. Bir kaç düzeltme ile testleri de geçebilirsin.

Öncelikle toFixed(2) ile virgülden sonra iki basamak olacak şekilde sayıyı düzeltiyorsun, ancak

 for (let i = 8; i > -1; i--) {
        for (let j = this.items[i][1]; j > -1; j--) {
          let item = Number(parseFloat(this.items[i][0] / this.items[i][1]).toFixed(2));
          if (remainder >= item) {
            this.items[i][0] = Number(parseFloat(this.items[i][0] - item).toFixed(2));
            this.items[i][1]--;
            this.totalTillCash = Number(parseFloat(this.totalTillCash - item).toFixed(2));
            remainder = Number(parseFloat(remainder - item).toFixed(2));
          }
          if (remainder === 0) {
            changeDue.innerHTML = "<p>Status: OPEN</p>";
            for (let k = 8; k > -1; k--) {
              if (cid[k][1] - this.items[k][0] > 0) {
                changeDue.innerHTML += `<p>${cid[k][0]}: $${Number(parseFloat(cid[k][1] - this.items[k][0]).toFixed(2))}</p>`;
                cidDisplay[k].textContent = `${this.items[k][0]}`;
              }
            }

örneğin parseFloat(this.items[i][0] / this.items[i][1]) kısmını parseFloat yapıyorsun sonra toFixed ile stringe dönüşüyor sonra yeniden Number. Yani

let item = Number(parseFloat(this.items[i][0] / this.items[i][1]).toFixed(2));

ifadesini,

let item = parseFloat((this.items[i][0] / this.items[i][1]).toFixed(2));

yapman yeterli. Bu hem decimal kısmı iki basamağa düşürecek hem de string dönüşümünü engelleyecektir.

Sonrasında ödenecek bozukluğu nasıl hesapladığına bakalım:

 let remainder =parseFloat((payment - price).toFixed(2));
      for (let i = 8; i > -1; i--) {
        for (let j = this.items[i][1]; j > -1; j--) {
          let item = Number(parseFloat(this.items[i][0] / this.items[i][1]).toFixed(2));
          if (remainder >= item) {
            this.items[i][0] = parseFloat((this.items[i][0] - item).toFixed(2));
            this.items[i][1]--;
            this.totalTillCash = parseFloat((this.totalTillCash - item).toFixed(2));
            remainder = parseFloat((remainder - item).toFixed(2));
          }
          if (remainder === 0) {
            changeDue.innerHTML = "<p>Status: OPEN</p>";
            for (let k = 8; k > -1; k--) {
              if (cid[k][1] - this.items[k][0] > 0) {
                changeDue.innerHTML += `<p>${cid[k][0]}: $${parseFloat((cid[k][1] - this.items[k][0]).toFixed(2))}</p>`;
                cidDisplay[k].textContent = `${this.items[k][0]}`;
              }
            }
            if (this.totalTillCash === 0) {
              changeDue.innerHTML = changeDue.innerHTML.replace("OPEN", "CLOSED");
            }
            break;
          }
        }

Önce for döngüsünde i’e 8 verip bir azaltarak son elemandan tersine döngü yapıyorsun. Mantık çok güzel ama kodu şöyle daha şık yapabiliriz: (let i= this.items.length-1; i=> 0; i--). Sonra ikinci for döngüsüne kasadaki bozukluğun adedini j’e atayarak sıfır olana kadar döndürüyorsun. Eğer reminder ilk döngüdeki para biriminin değerinden (100’lük mü 1 centlik mi ne ise) daha büyüke o bozukluktan ödeme yapılabilinir kurgusu ile ödeme safhasına geçiliyor. Sonra kasadaki bakiye sıfır olana kadar teker teker bozukluktan/para biriminden düşülüyor ve ödeme yapılıyor.

Ayrıca her döngü aşamasında item deklarasyonu esnasında mevcut bozukluğun para birimini yeniden hesaplıyorsun, bunu ayrı bir changeValue gibi array’da tutsan ve ihtiyacın olanı oradan alarak kullansan daha hoş olmaz mı?

Buradaki ödeme işlemi için daha basit bir şekilde döngüyle birer birere azaltmaktansa, ilk i döngüsündeki para biriminden mevcut remiander’ı ödemek için ne kadarlık bir tutuar gerektiğini hesaplayıp, sonra mevcut bakiye ile kıyaslayarak hangisi daha küçükse (mesela Math.min) onu kasadaki ilgili bozukluk bakiyesinden ve reminder dan düşsen ve kasanında sıfırın altına düşmeyecek şekilde düzeltmesini yapsan daha kısa ve kolay olmaz mı? reminder sıfır olana kadar i for döngüsünü kullanman yeterli olur. İkinci bir döngüye de ihtiyacın olmaz.

Örnek kod:

const gerekliTutar = Math.floor(remiander / currencyValue) * currencyValue;
const ödenecekTutar= Math.min(gerekliTutar , mevcutBakiye);

  cid[i][1] -= ödenecekTutar;
  reminder -= ödenecekTutar;

  if (cid[i][1] <= 0) {
    cid[i][1] = 0;
  }

Ayrıca cid bakiyesini güncelledikten sonra ihtiyacın olan yere sadece buradaki değeri toFixed yaparak yerleştirsen daha okunabilir olmaz mı? dom elementlerinde güncellediğin textler konusunda.

Testlere dönersek, testlerin sorun olmasının bir kısmı ara işlemlerde toFixed ve parseFloat yapman, bu küçük tutarlı bozukluklarda hataya sebep oluyor çünkü kasa doğru güncellenmiyor, yani aşağıdki kısmı

 if (remainder >= item) {
            this.items[i][0] = parseFloat((this.items[i][0] - item).toFixed(2));
            this.items[i][1]--;
            this.totalTillCash = parseFloat((this.totalTillCash - item).toFixed(2));
            remainder = parseFloat((remainder - item).toFixed(2));
          }

parseFloat ve toFixed(2) olmadan yazarsan ve input ile hesaplanan remiander’ı ve ekrana verdiğin sayıları toFixed yapman yeterli.

Ayrıca Bakiye yetersiz döndürdüğün zaman önce yine bütün ödeme işlemlerini yapıyor ve eğer remainder sıfır olmamışsa döndürüyorsun. Bunun yerine en başta yaptığın kıyaslama yetmez mi?

Bir diğer sorun sınıf sistemiyle kurduğun kod yapınsında cid’i güncel olarak dışarıdan alması ve böyle çalışması gerekiyor. Yani aşağıdaki gibi:

constructor(cid) {
    this.cid = cid;

Bu güncellemeleri yaptıktan sonra tekrardan gözden geçirdiğinde ufak hataları sen de fark edebilirsin. Eğer sorun devam ederse yeni kod yapısıyla incelemeye devam edebiliriz. Ama şuana kadar neredeyse hiç kullanmadığım OOP class ve karışık kod yapısı beni baya yordu dostum. Daha sade ve daha basit tutmak her zaman daha iyi. Özellikle değişken isimleri benzer olmaması daha anlaşılır yapardı, item ve items’in her yerde olması, ayrıca iç içe döngüler ve kontroller oldukça ortalığı karıştırıyor. Bunun için alt fonksiyonları da ayırman daha anlaşılır yapabilir örneğin tutarın düşüldüğü kısım ayrı küçük bir fonksiyon olabilir, ekran güncellemesi ayrı bir fonksiyon olabilir. Ekran güncellemesi ve kasa bakiyesi aynı değişken üzerinden güncellenebilir yani çıkarma işlemini birden fazla kez yapmaya gerek yok…

Umarım bu bilgiler sana yardımcı olur, söz ettiğim değişiklikleri yaparak bir test hariç hepsinden geçirmeyi başardım, bakalım son testi de bulabilecek miyiz :sweat_smile:

1 Like

Hızlıca okudum. Tavsiyelerinizi tek tek değerlendireceğim. Çok zaman ayırmışsınnız, çok mahcup hissettim.

Ne demek dostum, bilgi paylaştıkça güzel. Ayrıca başkalarının yazdığı kodu anlamaya çalışmak, sorunları çözme eğlenceli ve faydalı oluyor. Takıldığın yerlerde tekrardan sor lütfen :wink:… Ben de ortalığı ekstra karıştırmış olabilirim…

1 Like
let remainder = Number(parseFloat(payment - price).toFixed(2));

parseFloat’ın parantezlerini yanlış koymuşum, sonuç string geliyordu. Diyordum

this.totalTillCash = parseFloat(cid.map(item => item[1]).reduce((acc, cur) => acc + cur).toFixed(2));

burada sonuç number gelirken yukarıdakinde niçin string geliyor. Sonra tekrar Number kullanıyordum :slight_smile: Bunu fark etmem iyi oldu. Teşekkür ederim.

          if (remainder >= item) {
            this.items[i][0] = this.items[i][0] - item;
            this.items[i][1]--;
            this.totalTillCash = parseFloat((this.totalTillCash - item).toFixed(2));
            remainder = parseFloat((remainder - item).toFixed(2));
          }

Burada yalnızca " this.items[i][0] = this.items[i][0] - item; " satırının parseFloat ve toFixed’ını kaldırabildim. Diğerlerini kaldırınca sayılar bozuluyor. parseFloat ve toFixed’ı ne zaman kullanmam gerektiğine dair aklımda net bir şey belirmedi açıkçası. Ayrıca DOM’a verceğim kodda tavsiyeniz üzere yalnızca toFixed kullandım, teşekkür ederim.

Son bir testte takıldığınızı söylemiştiniz.

for (let j = this.items[i][1]; j > -1; j--) {

satırında " j > -1 " yerine " j > 0 " koyup dener misiniz? " j > -1 " haliyle banknot veya bozukluk sıfırlanınca NaN dönmesine sebep oluyordu.

constructor(cid) {
    this.cid = cid;

Son olarak bu kısmı açıklamanız mümkün mü? Eğer takılmaya devam edersem class’ta ısrarcı olmayacağım.

Class kullanman çok güzel dostum, farklı ve etkili, bunda bir sorun yok. Sadece cid’i constructor’a dışarıdan bir parametre olarak alıp kullanman daha doğru olur. Ayrıca cid’deki para birimlerinin değerlerini ayrı bir object’de ya da array’da sabit şekilde tutup kullanabilirsin, ayrıca constructur ile oluşturduğun items field’de *100, *20 gibi işlemleri yapmana da gerek yok. İkinci döngü için adetleri ilgili cid elemanının (bozuklukların) para birimine bölerek bulabilirsin.

const paraBirimleri = [0.01, 0.05, 0.10, 0.25 ...] //bunu obje olarak para birimi ismiyle eşleştirerek yapıp sonra ilgili para birimini ismine göre de çağırabilirsin, index'e göre çağırmak biraz güvensiz bir yöntem

let remainder =parseFloat((payment - price).toFixed(2));
      for (let i = 8; i > -1; i--) {
        const bozukAdedi = this.cid[i][0]/paraBirimleri[i]
        for (let j = bozukAdedi; j > -1; j--) {
          let item = paraBirimleri[i]
          if (remainder >= item) {
            this.cid[i][0] -= item;
            remainder -= item;
          }
        ...

Ayrıca ödenecek tutarı ikinci bir döngüyle tek tek düşerek yapmak istiyorsan sorun değil. Sadece ilgili cid elemanından tutarı düştükten sonra bu güncellenen değere göre ihtiyacın olduğunda total’ı yeniden hesaplaman daha doğru olur. Hem ilgili tutar hem de total değişkeninden tutarı (item’i) düşmene gerek kalmaz.

Ama ikinci döngüsüz yöntem hala çok şık, bir daha incelemeni istiyorum bu sefer değişken isimlerini daha anlaşılır yapalım:

const ödenmesiGerekenTutar = Math.floor(remiander / paraBirimleri[i]) * paraBirimi[i]; 
/*örneğin remainder 234 ve kasada bir yüzlük var, önce ne kadar yüzlük lazım onu ödenmesiGerekenTutar'da bakıyoruz: 234/100 = 2,34; Math.floor => 2; 2*paraBirimleri[i]= 200;*/

const ödenecekTutar= Math.min(ödenmesiGerekenTutar , mevcutBakiye);
/*Sonra ödenecekTutar'dan ne kadar hangisi daha küçükse alıyoruz, mevcutBakiye 100, ödenmesiGerekenTutar = 200; 100 sadece ödeyebiliriz;*/

  cid[i][1] -= ödenecekTutar;
  remiander -= ödenecekTutar;
//100'ü ilgili yerlerden düşüyoruz.

  if (cid[i][1] <= 0) {
    cid[i][1] = 0;
  }


/*Sonra 134 ödenmesi gereken tutar kaldı, ilk döngü ile bir sonraki para birimi yani 20'likler ile yenidenn ödemeye çalışıyoruz, onu da yapalım*/

const ödenmesiGerekenTutar = Math.floor(remiander / paraBirimleri[i]) * paraBirimleri[i];
/*134/20= 6,7; Math.floor=> 6; 6*20=120;*/

const ödenecekTutar= Math.min(ödenmesiGerekenTutar , mevcutBakiye);
/* kasada 60 dolarlık 20'lik var, o zaman 60 doların hepsini ödüyoruz, eğer ödenmesiGerekenTutar daha az olsaydı sadece o kadarını kasadan ve remiander'dan düşerdik. */

  cid[i][1] -= ödenecekTutar;
  remiander -= ödenecekTutar;

Yani sonuç olarak kod yazarken bir işlemin tek bir çözümü yok ama her zaman daha iyi bir çözümü var. Muhtemelen benim öneriminde daha iyisi var ama çözüm olarak olaylara farklı açılardan yaklaşmak önemli. Bu yüzden ikinci döngüsüz olanı tekrardan incelemeni istedim. Güncellenmiş kodları codePen’de ya da burada paylaşırsn yine inceleyebilriiz. Kolay gelsin :wink::ok_hand:

1 Like

Bir önceki mesajınızdaki tüm tavsiyelerinizi dikkatlice okuyup değerlendirmiştim ve çoğu benim çözümümden daha iyiydi. Daha uzun yoldan da olsa kurduğum mantıktaki eksiği görüp tadilat yapmayı denemiştim. Mesela palindrom projesinde kendi çözümümle testleri geçtikten sonra fCC’nin çözümünü de inceliyorum. fCC’nin algoritması benimkinden daha güzeldi ama farklı bir yoldan gitmiş olmak hoşuma gitmişti. O çözümü sonraki projelerimde gerektiğinde kullanırım ama palindrome projemi olduğu halde bıraktım. Siz o kadar zaman ayırdıktan sonra tavsiyeleri değerlendirmeseydim büyük saygısızlık olurdu zaten.

Her adıma console.log() ekledim, her şey doğru görünüyor ama yine testleri geçemedim.

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

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


const cidDisplay = [...document.getElementById("cash-drawer-display").getElementsByTagName("span")];
cidDisplay.forEach((element, i) => {
  element.textContent = `$${cid[i][1]}`;
});

const total = document.getElementById("total");
total.innerHTML = `Total: $<span>${price}</span>`;

class CashRegister {

  constructor(price, cid) {

    this.price = price;
    console.log("this.price ", this.price);
    this.cid = cid;
    console.log("this.cid ", this.cid);

    this.totalTillCash = parseFloat(this.cid.map(money => money[1]).reduce((acc, cur) => acc + cur).toFixed(2));
    console.log("this.totalTillCash: ", this.totalTillCash);

  }

  change() {

    let payment = Number(cash.value);
    console.log("payment ", payment);
    if (payment < this.price) {
      alert("Customer does not have enough money to purchase the item");
    } else if (this.totalTillCash + this.price - payment < 0) {
      changeDue.innerHTML = "<p>Status: INSUFFICIENT_FUNDS</p>";
    } else if (payment === this.price) {
      changeDue.innerHTML = "<p>No change due - customer paid with exact cash</p>";
    } else {
      let inhCid = [...this.cid.map(mon => mon[1])];
      console.log("inhCid ", inhCid);
      let money = [...this.cid.map(mon => mon[1])];
      console.log("money ", money);
      let values = [0.01, 0.05, 0.1, 0.25, 1, 5, 10, 20, 100]
      console.log("values ", values);
      let remainder = parseFloat((payment - this.price).toFixed(2));
      console.log("remainder ", remainder);
      for (let i = 8; i > -1; i--) {
        let items = parseFloat((money[i] / values[i]).toFixed(2));
        console.log("items ", items);
        for (let j = items; j > 0; j--) {
          if (remainder >= values[i]) {
            money[i] = parseFloat((money[i] - values[i]).toFixed(2));
            console.log("money[i] ", money[i]);
            remainder = parseFloat((remainder - values[i]).toFixed(2));
            console.log("remainder ", remainder);
            this.cid[i][1] = parseFloat((this.cid[i][1] - values[i]).toFixed(2));
            console.log("this.cid[i][1] ", this.cid[i][1]);
            this.totalTillCash = parseFloat((this.totalTillCash - values[i]).toFixed(2));
            console.log("this.totalTillCash ", this.totalTillCash);
          }
          if (remainder === 0) {
            changeDue.innerHTML = "<p>Status: OPEN</p>";
            for (let k = 8; k > -1; k--) {
              if (inhCid[k] - money[k] > 0) {
                changeDue.innerHTML += `<p>${this.cid[k][0]}: $${parseFloat((inhCid[k] - money[k]).toFixed(2))}</p>`;
                cidDisplay[k].textContent = `${money[k]}`;
              }
            }
            if (this.totalTillCash === 0) {
              changeDue.innerHTML = changeDue.innerHTML.replace("OPEN", "CLOSED");
            }
            break;
          }
        }
        if (remainder === 0) {
          break;
        }
      }
      if (remainder !== 0) {
        for (let l = 8; l > -1; l--) {
          this.cid[l][1] = inhCid[l];
          console.log("this.cid[l][1] ", this.cid[l][1]);
        }
        changeDue.innerHTML = "<p>Status: INSUFFICIENT_FUNDS</p>";
      }
    }
    console.log(this.cid);
    console.log(this.price);

  }

  purchase() {
    this.change();
    cash.value = "";
  }

Yok dostum saygısızlıkla alakası yok. Tartışabilirsin, kendi çözümünü ya da yaklaşımını kullanabilirsin. Bunlarda yanlış bir şey yok. Ben senin proje yöneticin değilim sonuçta :sweat_smile:. Ayrıca tartışmaya açık şekilde öneride bulunuyorum, senin fikir yürütüp çözüm bulman daha doğru ve öğretici olur.

Aldığın hata ya da geçemediğin adımlar neler? Bir de gözüme çarpan, totalTillCash’i constructor kısmında almışsın. Aslında bu bir variable değil ya da field, bu mevcut cid’lerin toplamı. Bunu bir method olarak oluşturup kullansan daha doğru olmaz mıydı?

Edit: Ayrıca gereksiz değişkenler var, money, inhCid bunlar nedir? Ne işe yarıyorlar? Bunların hiç bir gereği yok. Yapman gereken şey this.cid deki ilgili eleman üzerinden değerleri güncellemek ve bu değerleri ekrana yansıtacak şekilde kullanmak. Toplam için ayrı metod ve kullanımının örneğini de gönderiyorum:

 totalCidFunk (cid) {
   this.totalTillCash = parseFloat(cid.map(money => money[1]).reduce((acc, cur) => acc + cur).toFixed(2));
 }
kullanacagınFonk () {
    let totalCid =this.totalCidFunk(this.cid);
...
};

Ayrıca çok fazla console.log var bunları da temizler misin?
Gereksiz değişkenler ve işlemi uzatmayı bırakarak sade kod yazman lazım;

Burada neden money ayrı güncelleniyor? Neden hâlâ ara işlemlerde toFixed ve parseFloat kullanılıyor. Neden hâlâ total’den değer ayrıca düşüyor? İlgili cid elementinden değer düştükten sonra hesaplanan total’de değer güncellenmiyor mu? Neden döngünün içinde toplama ihtiyaç duyuyorsun? Toplamı kullandığın yer bir ama her yerde adı geçiyor hesaplaması yapılıyor.

Total’i bozukluk düşme işlemi bittikten sonra bir kez hesapla, mesela ekrana output’u verdiğin zaman, bunu en başta da bir kez yapman lazım. Bunun için ayrı bir screenUpdater fonksiyonu yapabilirsin ve tuşa basılmasa da çalıştırabilirsin, ekrandaki cid tutarlarını veren kısımdan bahsediyorum. Bunu sınıf nesnesi oluşturduktan sonra click eventListener’dan bağımsız çalıştırabilirsin. Bir sonraki hesaplamada bu total’den kontrolü yap kasada yeterli para var mı yok mu kontrolünü oradan yaparsın.

Neyse ki söylediklerimi uygulamışsın, uygulamamış olsaydın ne yaprdık kim bilir :sweat_smile:… Kodu düzeltip, güncel versiyonunu codePende de yazarsan tekrardan bakarız. Bu şekidle hata ayıklamak çok zor.

1 Like

Bir de gözüme çarpan, totalTillCash’i constructor kısmında almışsın. Aslında bu bir variable değil ya da field, bu mevcut cid’lerin toplamı. Bunu bir method olarak oluşturup kullansan daha doğru olmaz mıydı?

Bunu biraz açar mısınız?

Çok vakit kaybettim, class’tan vazgeçip normal fonksiyonlar ile yapacağım ama Reach projeleriyle uğraşırken class bilgim daha da artar ve bu projeyi class ile tekrar denerim belki.

totalTillCash dışarıdan gelen bir parametre değil ya da ayrı bir değişken olarak sınıfda bir field olmasına gerek yok, constructor içerisinde tanımlayıp sonra toplama işlemini burada yapıp, sonra her işlem esnasında tekrardan güncellemek hem performans açısından maliyetli hem de kolay bir çözüm değil. OOP’nin temel prensiplerini bildiğin zaman hiç mantıklı değil. Çünkü her yeni fiyata göre hesaplama esnasında, oluşturduğun örnek nesne üzerinden constructor değişkenleri memory de oluşturuyor, hesaplama yapıyor, sonra;

bozukluk hesaplama fonksiyonunun her aşamasında teker teker hem cid hem de toplam değerden düşüyor. Örneğin 10 cent ile 10 dolar ödeyeceksin diyelim; 1000 kez hem money’den hem remainder’dan hem this.cid’den hem de this.totalTillCash’den çıkarma işlemi yapıyorsun.

Sorun class yapısında değil, aynı şekilde normal fonksiyon ile yaptığın zamanda aynı sorunları yaşayacaksın. Bozuklukları sırayla düşme ve buna göre kontrolleri yapma konusunda sorun var. Dışarıdan gelen parametreleri doğru yönetmediğin için sorun var. Örneklemini oluşturduğun sınıfın metodlarını doğru kullanmadığın için sorun var. Bir ya da iki metodu olan bir sınıf tanımlaman lazım hepsi bu kadar. Inheritance yok, polymorphism yok, interface yok, abstraction yok, normal fonksiyonel yaklaşımdan çok bir farkı yok yani…

1 Like

Haklısınız, henüz OPP hakkında o kadar bilgim yok.
Ben son olarak şunu merak ediyorum. Uzun yoldan gidip gereksiz işlemci, bellek vs. kullansam bile testin verdiği price ve cid’i yerlerine koyduğum zaman fonksiyonlar #change-due’ya testten istenen sonucu veriyor. Testleri başlattığımda sistem price ve cid’i her test için ayrı ayrı tanımlamıyor mu? Ben niçin kodumdaki price ve cid’i değiştirdiğimde sistemin farklı testlerinden geçip farklı testlerinden kalıyorum?

let price = 1.87;
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 cash = document.getElementById("cash");
const changeDue = document.getElementById("change-due");
const purchaseBtn = document.getElementById("purchase-btn");


const cidDisplay = [...document.getElementById("cash-drawer-display").getElementsByTagName("span")];
cidDisplay.forEach((element, i) => {
  element.textContent = `$${cid[i][1]}`;
});

let variableCid = cid.map(money => money[1]);
const totalCidAmount = (iCid) => parseFloat(iCid.reduce((acc, cur) => acc + cur).toFixed(2));

const total = document.getElementById("total");
total.innerHTML = `Total: $<span>${price}</span>`;

const change = () => {
  let payment = Number(cash.value);
  let initialCid = [...variableCid];
  let cidAmount = totalCidAmount(variableCid);
  if (payment < price) {
    alert("Customer does not have enough money to purchase the item");
  } else if (cidAmount + price - payment < 0) {
    changeDue.innerHTML = "<p>Status: INSUFFICIENT_FUNDS</p>";
  } else if (payment === price) {
    changeDue.innerHTML = "<p>No change due - customer paid with exact cash</p>";
  } else {
    let moneyValues = [0.01, 0.05, 0.1, 0.25, 1, 5, 10, 20, 100]
    let remainder = parseFloat((payment - price).toFixed(2));
    for (let i = 8; i > -1; i--) {
      let items = parseFloat((variableCid[i] / moneyValues[i]).toFixed(2));
      for (let j = items; j > 0; j--) {
        if (remainder >= moneyValues[i]) {
          variableCid[i] = parseFloat((variableCid[i] - moneyValues[i]).toFixed(2));
          remainder = parseFloat((remainder - moneyValues[i]).toFixed(2));
        }
        if (remainder === 0) {
          changeDue.innerHTML = "<p>Status: OPEN</p>";
          for (let k = 8; k > -1; k--) {
            if (initialCid[k] - variableCid[k] > 0) {
              changeDue.innerHTML += `<p>${cid[k][0]}: $${parseFloat((initialCid[k] - variableCid[k]).toFixed(2))}</p>`;
              cidDisplay[k].textContent = `${variableCid[k]}`;
            }
          }
          if (totalCidAmount(variableCid) === 0) {
            changeDue.innerHTML = changeDue.innerHTML.replace("OPEN", "CLOSED");
          }
          break;
        }
      }
      if (remainder === 0) {
        break;
      }
    }
    if (remainder !== 0) {
      variableCid = [...initialCid];
      changeDue.innerHTML = "<p>Status: INSUFFICIENT_FUNDS</p>";
    }
  }
}
const purchase = () => {
  change();
  cash.value = "";
}

purchaseBtn.addEventListener("click", purchase);
cash.addEventListener("keyup", event => {
  if (event.key === "Enter") {
    purchase();
  }
});

En baştaki cid ve price değişkenlerini değiştirmeden olduğu gibi bırakmalısın. Test gerekli değişiklikleri yaparak farklı durumlarda testi yapıyor. Eğer değiştirmeden bıraktığında testleri geçiyorsan sorun yoktur.

Edit: Ama şuan bu kodları test ettiğim zaman son üç testi geçemiyor gibi görünüyor…

1 Like