map fonksiyonu nedir, ne işe yarar ?

İki tür map fonksiyon vardır:

  • Değerler için map : bir değerin, 2 nokta arasındaki konumu, başka iki nokta arasına oranlar.
  • Diziler için map : bir fonksiyonu bütün dizi elemanlarına uygulayarak yeni dizi oluşturur.

map(değer,başlangıç,bitiş,yenibaşlangıç,yeniBitiş)

değerin, 2 nokta arasındaki konumu, başka iki nokta arasına oranlar

map(2,1,3,2,6) = 4

map(Math.random(),0,1,-25,75) = -25 ve 75 arası rastgele değer

Array.map(fonksiyon)

bir fonksiyonu bütün dizi elemanlarına uygulayarak yeni dizi oluşturur.

[1,2,3,4].map(Math.sqrt) = [1,4,9,16]

var array = [ 2 , 3 , 5, 6]
 
var yeniArray = array.map(function(a){ return a*a+1 });
 
// yeniArray = [5,10,26,37]

C# map fonksiyonu

    float map(float val, float iMin, float iMax, float oMin, float oMax) {
 
        return (val - iMin) * (oMax - oMin) / (iMax - iMin) + oMin;
    }

Javascript Scope İncelikleri

Bir fonksiyon veya değişken, oluşturulduğu yerin scopeuna dahildir. Kullanıldığı yerin değil.

var random = function(){
	return Math.floor(Math.random()*100);
}
var sagas = [];
var hero = "faruk"+random(); // faruk7
 
var newSaga = function(){
	var foil = "thefoil"+random();
	sagas.push(function(){
		var deed = "thedeed"+random();
		console.log(hero+deed+foil);
	});
};
 
newSaga();
sagas[0](); // faruk7 thefoil2 thedeed1
sagas[0](); // faruk7 thefoil2 thedeed4
newSaga();
sagas[0]();  // faruk7 thefoil2 thedeed5
sagas[1]();  // faruk7 thefoil9 thedeed6
sagas[0]();  // faruk7 thefoil2 thedeed7
sagas[1]();  // faruk7 thefoil9 thedeed8
 
// burdan anlaşıldığı üzere, bir fonksiyonun scopunu , oluşturulduğu yer belirliyor.
// yani sonrasında kullandıldığı scopre değil
 
// mesela burdaki foil değeri, ilk defa fonksiyonun tanımlandığı foil değeri
// newsagadan sonra, foil güncellenmiyor, yeni foil oluşuyor. 
// sagas[0] eski foil değerini döndürecektir.

Nesne Yönelimli Javascript

Javascriptte, class(sınıf) yoktur. Onun yeri objeler vardır. Bu objeler class olarakta kullanılabilir.

// Örnek sınıflar
 
// Hayvan sınıfı değişkenleri ve constructor
function Hayvan(yaş){
	this.yaş = yaş;
	console.log("Yeni hayvan");
}
 
// Hayvan sınıfı metodları
Hayvan.prototype.büyü = function(){
		this.yaş++;
}
 
// Insan sınıfı değişkenleri ve constructor
function Insan(yaş){
	Hayvan.call(this,yaş); // super classın constructorünü çağır
	console.log("Yeni Insan");
}
 
// Kalıtım - prototipleri birleştir
Insan.prototype = Object.create(Hayvan.prototype);
Insan.prototype.constructor = Insan;
 
// Insanı sınıfının kendine özgü metodları
Insan.prototype.konuş = function(){
	console.log("Ben "+this.yaş+" yaşıdayım");
}
 
// Test
var ahmet = new Insan(16);
ahmet.büyü();
ahmet.konuş();
console.log(ahmet);

Object.create fonksiyonu, bir objeyi kopyalamaz, sadece adresleme yaparak , yeni bir obje oluşturur.(delegasyon) Bunun sayesinde, kalıtım yaparken hafıza kullanımını azaltırız.

this deyimiyle javascriptte, sınıfın kendisi kastedilmez. Bir fonksiyonun hangi obje üzerinde çağrıldığı kastedilir.  obje.fonksiyon(); yani o fonksiyonun içinde this kullanıldıysa, noktanın solundaki ilk ifade olan obje ,this’e karşılık düşer. Buda javascriptin önemli farklarında biridir.

Bir fonksiyondan sonra call kullanılırak, o fonksiyonundaki this ifadesi, istediğimiz obje ile yer değiştirebiliriz.

obje1.fonksiyon(); // burda this=obje1
obje2.fonksiyon.call(obje3); // burda this=obje3

Heap Tree (Yığın Ağacı) ve JS kütüphanesi kodları

İkili bir ağaç yapısıdır. Kök hariç , her düğümün bir ebeveyni vardı. Her ebeveyninde en fazla 2 çocuğu vardı.

2 türü vardır ; Minimum heap, Maximum heap.

Amacı

En yüksek performansta, bir diziden en küçük ve en büyük değerleri teker teker sırasıyla çekebilmektir. Bu dizi, sıralı değildir. Ancak ilk elemanı(kökü) daima en büyük veya en küçük elemandır.

Kuralları

  • Eğer minimum heap ise, ebeveyn çocuklarında daima küçük olmalıdır. Maximum heapde tam tersi geçerlidir.
  • Çocuklar arası ilişki yoktur.
  • Tek indeks sahip düğüm solda, çift indekse sahip düğüm sağdadır. (yani 3>sol; 4>sağ)
  • Ebeveyninin indeksinin 2 katının 1 fazlası sol çocuğun indeksi, 2 katının 2 fazlası sağ çocuğun indeksidir. (2nin sol çocuğu 5, sağ çocuğu 6′tir)
  • Yeni eklenen düğüm, her zaman ağacın en alt sol tarafına eklenir. (Yani dizinin en sağına eklenir)
NOT : Kökün indeksi 0'dır.

p : ebeveyn indeksi
x : herhangi bir düğümün indeksi
sol : sol çocuk indeksi
sağ : sağ çocuk indeksi
---
sol = 2*p+1
sağ = 2*p+2
--
x%2 = 0 ise => sağdadır.
p = x / 2 - 1
x%2 = 1 ise => soldadır.
p = (x - 1) / 2

Ekleme

  • Değer dizinin sonuna(en sağına), eklenir.
  • Eklenen değer ebeveyni ile kıyaslanır. Ebeveyninden küçük ise, onunla yer değiştiri ve bu işlemin aynısı ebeveynlerininin ebeveynleri ilede yapılır.

Çıkarma

  • Heapda, daima kök değer çıkartılır. Yani dizinin ilk elemanı çıkartılır.
  • Çıkartılan bu değer ile yeni ağaç oluşur.
  • Bu ağaçta kökten başlayan, çocuğu olmayan düğüme kadar, en küçük değere sahip çocuk ile kıyaslanır, eğer en küçük çocuktan büyük ise yer değiştirilir. Yer değiştirilen çocuk ile aynı işlem ağacın o dalı boyunca tekrarlanır.

Bu işlemi yapan, yeni yazdığım bir Heap sınıfı.

function Heap(sortFunc){
    this.nodes = [];
    this.sortFunc= sortFunc || function(a,b){return a-b;};
 
    this.func = function(a,b){
            return this.sortFunc(a,b) < 0;
    }
}
 
 
 
Heap.prototype = {
    add : function(e){
        var x = this.nodes.length;
        this.nodes.push(e);
        var p = this.parent(x);
 
        // heapify2up
        while(this.func(this.nodes[x],this.nodes[p]) && x!=0){
            this.nodes[x]=this.nodes[p];
            this.nodes[p]=e;
 
            x=p;
            e = this.nodes[x];
            p=this.parent(x);
        }
 
        return this.nodes;
 
    },
    get : function(){
        var r = this.nodes.shift();
 
        //heapify2down
        var x = 0;
        var childs = this.childs(x);
        var min;
        while(childs.length!=0){
            min=childs[0];
            if(childs.length==2 && !this.func(this.nodes[childs[0]],this.nodes[childs[1]])){
                min = childs[1];
            }
 
            if(this.func(this.nodes[min],this.nodes[x])){
                var temp = this.nodes[x];
                this.nodes[x] = this.nodes[min];
                this.nodes[min] = temp;
                x = min;
                childs = this.childs(x);
            }
            else childs=[]
        }
        return r;
    },
    isEmpty : function(){
        return this.nodes.length==0;
    },
    parent : function(x){
        if(this.right(x)) return x/2-1;
        return (x-1)/2;
    },
    childs : function(x){
      var a = [];
      if(this.nodes[2*x+1]){
          a.push(2*x+1);
          if(this.nodes[2*x+2])
              a.push(2*x+2);
      }
      return a;
    },
    right : function(x){
        return x%2==0;
    }
};

 

A* Algoritması (A yıldız arama algoritması)

Amacı : Bir düğümden, diğer düğüme en az maliyetli çözümü bulmak

Türü : Arama Algoritması, Sezgisel Algoritma (Yapay zeka)

Kâşifleri : Nils Nilsson,Bertram Raphael , Peter E. Hart

Kullanım yerleri :

  • Yol bulma
  • Oyunlarda aktörün hedefe doğru izleyeceği yolların tespiti
  • Gezgin satıcı probleminin çözümü
  • Labirentten en kısa çıkışı bulma

 

f(x) : durum fonksiyonu. Az olması, o durumun daha az maliyetli olduğunu belirtir.

f(x) = g(x) + h(x)

g(x) : Başlangıç durumuna göre maliyetimiz.

h(x) : Bitiş duruma olan sezgisel maliyet.

Algoritma

OPEN -> // fCost'a göre sıralı dizi

OPEN.ekle(başlangıç_düğümü)

DÖNGÜ - OPEN dizi boyutu 0 olmadığı müddetçe
    şuanki_düğüm <- OPEN.ilk elemanı
    OPEN.sil(şuanki düğüm)
    EĞER şuanki_düğüm, hedef düğüm ise
        DÖNGÜden çık // HEDEFE ULAŞTI
    şuanki_düğüm.closed=true
    şuanki_düğüm.gCostHesapla()
    komşular = şuanki_düğüm.komşular
    DÖNGÜ komşu <- komşular
        EĞER komşu.closed ise SONRAKİ_KOMŞUYA_GEÇ
        maliyet = şuanki_düğüm.gCost + komşuya_uzaklık
        komşu.gCostHesapla()
        EĞER komşu.OPENdaDeğilse veya maliyet<komşu.gCost ise
            komşu.gCost = maliyet
            komşu.hCostHesapla()
            komşu.ebeveyn = şuanki_düğüm
            EĞER komşu.OPENdaDeğilse
                OPEN.ekle(komşu)
OPEN dizi boyutu 0 olduğu için DÖNGÜden çıkıldıysa // HEDEFE ULAŞAMADI

Javascript Kodu

FIND (Yol bulmayı başlat)
RELOAD (Gridi yeniden yükle)
ilk tık -> başlangıç karesi
2. tık -> hedef kare
sonraki tıklar -> engel oluştur

See the Pen A* Algoritması by farukcan (@farukcan) on CodePen.

3 taş oyunu için Yapay Zeka

Bu oyunda YZ, oyuncunun yaptığı hamlenin ardından, kendi yapacağı hamlelerin durum uzayını oluşturup sezgisel fonksiyon ile ileriye yönelik hamleleri bir puan vermektedir. Bunu yaparken, rakibinin bir sonraki hamlesini de göz önüne alır.

/**
 * Created by Faruk Can on 6.4.2016.
 */
 
var ç = new CanvasRender("canvas1");
 
var canvasboyut = 500;
 
var tahta = [
    [0,0,0],
    [0,0,0],
    [0,0,0]
];
// 1 : X
// diğer : O
// 0 : boş
 
 
 
// kontrol mekanizması
ç.addClickListener(function(x,y){
    console.log(x,y);
});
var hamleyapmakiçinarray = [];
for(var m=0;m<3;m++)
    for(var n=0;n<3;n++){
        hamleyapmakiçinarray.push({
            "height" : canvasboyut/3,
            "width" : canvasboyut/3,
            "top" : canvasboyut/3*m,
            "left" : canvasboyut/3*n
        });
    }
hamleyapmakiçinarray[0].func = function (){hamleyap(0,0)};
hamleyapmakiçinarray[1].func = function (){hamleyap(0,1)};
hamleyapmakiçinarray[2].func = function (){hamleyap(0,2)};
hamleyapmakiçinarray[3].func = function (){hamleyap(1,0)};
hamleyapmakiçinarray[4].func = function (){hamleyap(1,1)};
hamleyapmakiçinarray[5].func = function (){hamleyap(1,2)};
hamleyapmakiçinarray[6].func = function (){hamleyap(2,0)};
hamleyapmakiçinarray[7].func = function (){hamleyap(2,1)};
hamleyapmakiçinarray[8].func = function (){hamleyap(2,2)};
ç.clickElement = hamleyapmakiçinarray;
 
 
 
// ilk durum
var oyunKimde = "X";
var sıra = 0;
tahtayıÇiz();
hamleleriÇiz(true);
 
 
 
 
 
function hamleyap(m,n){
    if(oyunKimde == "X" && tahta[m][n]==0){
        tahta[m][n] = 1;
        oyunKimde = "O";
        ç.clear();
        tahtayıÇiz();
        hamleleriÇiz();
        sıra++;
        if(!oyunsonu())
            setTimeout(YZhamleyap,500);
    }
}
 
function oyunsonu(){
    if(sıra>8) return beraber();
    var taraf = 1;
    kontrolEdilecekYerler.forEach(function(yerler){
        var kactane1var = 0;
        yerler.every(function(y){
            var n= (y-1)%3;
            var m= Math.floor((y-1)/3);
            if(tahta[m][n]*taraf==-1) {
                kactane1var=0;
                return false;
            }
            if(tahta[m][n]*taraf==1) kactane1var++;
            return true;
        });
        if(kactane1var==3) {
            Xkazandı();
        }
    });
    var taraf = -1;
    kontrolEdilecekYerler.forEach(function(yerler){
        var kactane1var = 0;
        yerler.every(function(y){
            var n= (y-1)%3;
            var m= Math.floor((y-1)/3);
            if(tahta[m][n]*taraf==-1) {
                kactane1var=0;
                return false;
            }
            if(tahta[m][n]*taraf==1) kactane1var++;
            return true;
        });
        if(kactane1var==3) {
            Okazandı();
        }
    });
 
}
 
function Xkazandı(){
    alert("X kazandı");
    reload();
}
function Okazandı(){
    alert("O kazandı");
    reload();
}
function beraber(){
    alert("Berabere");
    reload();
}
 
function reload(){
    setTimeout(function(){location.reload();},2000);
}
 
 
var kontrolEdilecekYerler = [
    [1,2,3],
    [4,5,6],
    [7,8,9],
    [1,4,7],
    [2,5,8],
    [3,6,9],
    [1,5,9],
    [3,5,7]
];
 
// # tek taraf sezgisel fonksiyon h2
// -- her satır, sutun ve 2çarpraz için
// --- Eğer -1 varsa : 0 puan
// --- Eğer 1 tane 1 varsa : 1 puan
// --- Eğer 2 tane 1 varsa : 3 puan
// --- Eğer 3 tane 1 varsa : 99 puan
function h2(taraf,durum){
    var puan=0;
    kontrolEdilecekYerler.forEach(function(yerler){
        var kactane1var = 0;
        yerler.every(function(y){
            var n= (y-1)%3;
            var m= Math.floor((y-1)/3);
            if(durum[m][n]*taraf==-1) {
                kactane1var=0;
                return false;
            }
            if(durum[m][n]*taraf==1) kactane1var++;
            return true;
        });
        if(kactane1var==3) puan+=999;
        else if(kactane1var==2)  puan+=3;
        else puan+=kactane1var;
    });
    return puan;
}
 
// rahibin sonraki el en iyi hamlesinin puanını belirle
var h3iterasyon=0;
function h3(taraf,durum){
 
    if(++h3iterasyon==100) return 0;
 
    var olasıHamleler = [];
    /*
     {
     m: (x)
     n: (y)
     h:(sayı) // hamlenin sezgisel fonksiyon değeri
     }
     */
    for(var m=0;m<3;m++)
        for(var n=0;n<3;n++){
            if(durum[m][n]==0){
                // boş olan yerlere hamle yapılabilir
                var d = JSON.parse(JSON.stringify(durum)) // dunyayı klonla
                d[m][n] = taraf; //hamleyi duruma dahil et
                olasıHamleler.push(
                    {
                        "m" : m,
                        "n" : n,
                        "h" : h(taraf,d)
                    }
                );
            }
        }
 
    // en iyi hamleleri sırala
    olasıHamleler.sort(function(a,b){
        return b.h - a.h;
    });
    if(typeof olasıHamleler[0] == "undefined") return 0;
    return olasıHamleler[0].h;
}
 
// # çift taraf sezgisel fonksiyon h
// -- h = h2 - h3
function h(taraf,durum){
    return h2(taraf,durum) - h3(-taraf,durum);
}
 
function YZhamleyap(){
 
    h3iterasyon=0;
    sıra++;
 
    var olasıHamleler = [];
    /*
    {
        m: (x)
        n: (y)
        h:(sayı) // hamlenin sezgisel fonksiyon değeri
    }
     */
    for(var m=0;m<3;m++)
        for(var n=0;n<3;n++){
            if(tahta[m][n]==0){
                // boş olan yerlere hamle yapılabilir
                var durum = JSON.parse(JSON.stringify(tahta)) // dunyayı klonla
                durum[m][n] = -1; //hamleyi duruma dahil et
                olasıHamleler.push(
                    {
                        "m" : m,
                        "n" : n,
                        "h" : h(-1,durum)
                    }
                );
            }
        }
 
    // en iyi hamleleri sırala
    olasıHamleler.sort(function(a,b){
       return b.h - a.h;
    });
 
    tahta[olasıHamleler[0].m][olasıHamleler[0].n] = -1;
    console.log(olasıHamleler);
    oyunKimde = "X";
    ç.clear();
    tahtayıÇiz();
    hamleleriÇiz(true);
    oyunsonu();
}
 
 
function tahtayıÇiz(){
    // tik tak to tahtası
    for(var i=1;i<3;i++){
        ç.line(canvasboyut/3*i,20,canvasboyut/3*i,canvasboyut-20);
        ç.line(20,canvasboyut/3*i,canvasboyut-20,canvasboyut/3*i);
    }
 
}
 
function hamleleriÇiz(num){
    // tahta üzerinde yazan meretler
    var sira = 0;
    for(var m=0;m<3;m++)
        for(var n=0;n<3;n++){
            sira++;
            if(tahta[m][n]==0){
                if(num){
                    ç.font(ç.standartFont);
                    ç.text(sira,canvasboyut/6+canvasboyut/3*n,canvasboyut/6+canvasboyut/3*m);
                }
            }
            else if(tahta[m][n]==1){
                ç.font("233px Arial");
                ç.text("X",canvasboyut/3*n,canvasboyut/3+canvasboyut/3*m);
            }else{
                ç.font("213px Arial");
                ç.text("O",canvasboyut/3*n,canvasboyut/3+canvasboyut/3*m-5);
            }
        }
 
 
    ç.font(ç.standartFont);
}

RDT ve TCP Protokolü Similatörü

    var checksum=false;
    var seqnumenabled = false;
    var onlyack = false;
    var seqnum = 0;
    var rtd30 = false;
    var seqnumold = seqnum;
    var tcp = false;
 
    function send(){
 
        delay();
 
        checksum = $("#checksum").is(":checked");
        seqnumenabled = $("#seqnum").is(":checked");
        onlyack = $("#onlyack").is(":checked");
        rtd30 = $("#rtd30").is(":checked");;
        tcp = $("#tcp").is(":checked");;
 
        if(!checksum)
            return tabloyaekle($("#datawillsend").val(),"==>",recieve());
        else{
            if(seqnumenabled){
                if(onlyack){
                    if(rtd30){
 
                        if(tcp){
                            var recieved = recieve();
                            var crecieved = checksummed(recieved);
                            var sended =  $("#datawillsend").val();
                            var csended = checksummed(sended);
                            if(kayboldumu()){
 
                                tabloyaekle("["+seqnum+"] "+sended+"("+csended+")","=[KAYIP]>","");
 
                                setTimeout(send,$("#time").val());
 
                            }else{
 
                                tabloyaekle("["+seqnum+"] "+sended+"("+csended+")","==> ","["+seqnum+"] "+recieved+"("+csended+"/"+crecieved+")");
 
                                seqnumold = seqnum;
 
                                sendACKforTCP(csended==crecieved)
 
 
                                setTimeout(function () {
                                    if(seqnumold == seqnum)
                                        send();
                                },$("#time").val());
 
 
                            }
 
                        }
                        else{
 
                            var recieved = recieve();
                            var crecieved = checksummed(recieved);
                            var sended =  $("#datawillsend").val();
                            var csended = checksummed(sended);
 
                            if(kayboldumu()){
 
                                tabloyaekle("["+seqnum+"] "+sended+"("+csended+")","=[KAYIP]>","");
 
                                setTimeout(send,$("#time").val());
 
                            }else{
 
                                tabloyaekle("["+seqnum+"] "+sended+"("+csended+")","==> ","["+seqnum+"] "+recieved+"("+csended+"/"+crecieved+")");
 
                                seqnumold = seqnum;
 
                                sendACKwithCS2withLoss(csended==crecieved)
 
 
                                setTimeout(function () {
                                    if(seqnumold == seqnum)
                                        send();
                                },$("#time").val());
 
 
                            }
 
                        }
 
 
 
                    }else{
 
                        var recieved = recieve();
                        var crecieved = checksummed(recieved);
                        var sended =  $("#datawillsend").val();
                        var csended = checksummed(sended);
 
                        tabloyaekle("["+seqnum+"] "+sended+"("+csended+")","==> ","["+seqnum+"] "+recieved+"("+csended+"/"+crecieved+")");
 
                        seqnumold = seqnum;
 
                        sendACKwithCS2(csended==crecieved);
 
                        setTimeout(function () {
                            if(seqnumold == seqnum)
                                send();
                        },$("#time").val());
 
                    }
 
 
                }else{
                    var recieved = recieve();
                    var crecieved = checksummed(recieved);
                    var sended =  $("#datawillsend").val();
                    var csended = checksummed(sended);
 
                    tabloyaekle("["+seqnum+"] "+sended+"("+csended+")","==> ","["+seqnum+"] "+recieved+"("+csended+"/"+crecieved+")");
 
                    if(csended==crecieved){
                        sendACKwithCS();
                    }else{
                        sendNACKwithCS();
                    }
                }
 
 
 
 
            }else{
                var recieved = recieve();
                var crecieved = checksummed(recieved);
                var sended =  $("#datawillsend").val();
                var csended = checksummed(sended);
 
                tabloyaekle(sended+"("+csended+")" , " ==>" , recieved+"("+csended+"/"+crecieved+")");
 
 
                if(csended==crecieved){
                    sendACK();
                }else{
                    sendNACK();
                }
 
            }
 
        }
    }
 
    function sendACK(){
        delay();
 
        if(bozuldumu()){
            tabloyaekle("?NACK?"," <==  ","ACK");
            send();
            return tabloyaekle("","","! HATA : duplikasyon tespit edildi ?");
        }
        else
            return tabloyaekle("ACK"," <==  ","ACK") + tabloyaekle("","BiTTi","");
    }
    function sendNACK(){
        delay();
 
        if(bozuldumu()){
            tabloyaekle("?ACK?"," <==  ","NACK");
            return tabloyaekle("","","! HATA : istenen veri alınamadı ?");
        }
        else
            return tabloyaekle("NACK"," <==  ","NACK");
        return send();
    }
 
    function sendACKwithCS(){
        delay();
 
        if(bozuldumu()){
            if(checksumdogrumu()){
                tabloyaekle("NACK (A)"," <==  ","ACK (A)");
                tabloyaekle("checksum eşleşmedi","   ","");
                tabloyaekle("","","! DÜZELTİLDİ : duplikasyon tespit edildi?");
                send();
            }else{
                tabloyaekle("NACK (N)"," <==  ","ACK (A)");
                send();
            }
        }else{
            tabloyaekle("ACK (A)"," <==  ","ACK (A)");
            seqnum++;
            tabloyaekle("","BiTTi","");
        }
    }
 
    function sendNACKwithCS(){
        if(bozuldumu()){
            if(checksumdogrumu()){
                tabloyaekle("ACK (N)"," <==  ","NACK (N)");
                tabloyaekle("checksum eşleşmedi","   ","");
                send();
            }else{
                tabloyaekle("ACK (A)"," <==  ","NACK (N)");
                seqnum++;
                return tabloyaekle("","","! HATA : istenen veri alınamadı ?");
            }
        }else{
            tabloyaekle("NACK (N)"," <==  ","NACK (N)");
            send();
        }
    }
 
    function sendACKwithCS2(checksum){
        delay();
 
        if(bozuldumu()){
            {
                tabloyaekle("["+seqnum+"] ACK (N)"," <==  ","["+seqnum+"] ACK (A)");
                tabloyaekle("checksum eşleşmedi","   ","");
                send();
                tabloyaekle("","","! DÜZELTİLDİ : duplikasyon tespit edildi ?");
            }
        }else{
            if(checksum){
                tabloyaekle("["+seqnum+"] ACK (A)"," <==  ","["+seqnum+"] ACK (A)");
                seqnum++;
                tabloyaekle("","BiTTi","");
            }
        }
 
 
    }
 
    function sendACKwithCS2withLoss(checksum){
        delay();
 
        if(kayboldumu()){
            tabloyaekle(""," <[KAYIP]=  ","["+seqnum+"] ACK");
        }else{
            sendACKwithCS2(checksum);
        }
 
    }
 
    function sendACKforTCP(checksum){
        delay();
        if(kayboldumu()){
            tabloyaekle(""," <[KAYIP]=  ","["+seqnum+"] ACK");
        }else{
            if(bozuldumu()){
                {
                    if(checksum) {
                        tabloyaekle("[" + seqnum + "] ACK (N)", " <==  ", "[" + seqnum + "] ACK (A)");
                        tabloyaekle("checksum eşleşmedi", "   ", "");
                        send();
                    }
                }
            }else{
                if(checksum){
                    tabloyaekle("["+seqnum+"] ACK (A)"," <==  ","["+seqnum+"] ACK (A)");
                    seqnum+=$("#datawillsend").val().length;
                    tabloyaekle("","BiTTi","");
                }
            }
        }
    }
 
    function checksummed(t){
        var csum = 0;
        for(var i= 0;i<t.length;i++){
                if(t[i]=="1") csum++;
        }
        return csum;
    }
    function recieve(){
        var t = $("#datawillsend").val();
        for(var i= 0;i<t.length;i++){
            if(bozuldumu()){
                if(t[i]=="0") t = t.replaceAt(i, "1");
                else  t = t.replaceAt(i, "0");;
            }
        }
        return t;
    }
 
 
    function bozuldumu(){
        return Math.random()*100<parseInt($("#bozulma").val());
    }
    function kayboldumu(){
        return Math.random()*100<parseInt($("#kayip").val());
    }
    function checksumdogrumu(){
        return Math.random()*100<50;
    }
    function tabloyaekle(a,b,c){
        $("#tablo").append("<tr><td>"+Date.now().toTime()+"</td></td><td>"+a+"</td><td>"+b+"</td><td>"+c+"</td></tr>");
    }
 
    function temizle(){
        $("#tablo").html("<tr><th>GÖNDEREN</th><th>ARA</th><th>ALAN</th></tr>");
        seqnum = 0;
    }
    String.prototype.replaceAt=function(index, character) {
        return this.substr(0, index) + character + this.substr(index+character.length);
    }
 
    Number.prototype.toTime = function(){
        return Math.floor(this%3600000/60000)+":"+ Math.floor(this%60000/1000) + ':' + this%1000
    };
 
    function delay(){
        sleep(parseInt($("#thr").val()));
    }
    function sleep(milliseconds) {
        var start = new Date().getTime();
        for (var i = 0; i < 1e7; i++) {
            if ((new Date().getTime() - start) > milliseconds){
                break;
            }
        }
    }