Jump to page: 1 2 3
Thread overview
Tuş Önbellekleme Algoritması
May 04, 2013
Salih Dinçer
May 04, 2013
Salih Dinçer
May 05, 2013
Salih Dinçer
May 05, 2013
Salih Dinçer
May 06, 2013
Salih Dinçer
May 07, 2013
Salih Dinçer
May 08, 2013
Salih Dinçer
May 08, 2013
Salih Dinçer
May 09, 2013
Salih Dinçer
May 09, 2013
Salih Dinçer
May 10, 2013
huseyin
May 10, 2013
Salih Dinçer
May 11, 2013
huseyin
May 11, 2013
Salih Dinçer
May 11, 2013
huseyin
May 04, 2013

Merhaba,

"Textbox" niteliğinde bir nesne düşünün, örneğin:

class MetinKutusu { ... }

Buna öyle nitelikli üyeler verelim ki ekranda etkin olduğu zaman (üzerine tıklanıp fare imleçi yanıp söndüğünde), klavyenin basılan her tuşunu ''wchar''[] metin;'' dizisinde depolasın. Tabi basılan tuşları yakalama, kodunu varsayılan klavye düzenine göre UTF harfle eşleştirme, imleçin yanıp sönmesi ve harflerin sırayla metin kutusu sınırları içerisinde görünmesi, alt satıra kayması gibi görsel nitelikli işlemlerin halihazırda olduğunu varsayıyoruz...

İşimiz kolay görünüyor...:)

Peki standart, olması gereken üye değişkenleri aşağıdaki gibiyse, sizce başka nelere ihtiyaç var? Örneğin bir kaç kB. geçmişi tutan ve baştaki elemandan eksilerek azalan bir önbellekleme yığınına (buffer stack) duyabiliriz sanki...

size_t kimlik_id;
static kilitlenen_lockId;  // etkin olan
uint soldan_x, yukardan_y;
uint en_w, boy_h;
wchar[] metin;

Sanırım bu kadar basit değil!

Çünkü klavyemiz, bilgisayarımızın fare tuşları gibi basılıp bırakılana kadar (herhangi bir süre) tekrar yapmadan beklemez. O yüzden akıllıca çalışan bir zamanlayıcı ve önbellek yığınına ihtiyaç var. Belli bir sürede (type rate and delay) karakter tekrarı olduğu için, yığının başından (FIFO) ve zamanlayıcının denetiminde klavye karakterleri nesneye yazılmalı.

Meğer çatı yazmak ne zormuş! O yüzden hala mütevazi bir aşamadayım (sdlMİNİ) ve belki bir gün eksiksiz GUI çatısı meydana getirebiliriz. Henüz bu konuda bir çözüm bulamadım...:(

Küçük bir deneme yaptım da başlangıç fena değil ama yardıma ihtiyacım var...
Alıntı:

>
> import sdlmini2, std.stdio;
>
> struct BoşKutu {
>   size_t kimlik;
>   bool etkin_Mi;
>   int x, y, boy;
>   static int en = 170;
>   clr renk;
>
>   this(int solAlttanX, int solAlttanY) {
>     this.x = solAlttanX;
>     this.y = solAlttanY;
>     this.renk = clr.red;
>     this.boy = 140;
>   }
>
>   void durumuEvir() {
>     if(etkin_Mi) {
>       etkin_Mi = false;
>       renk = clr.red;
>     } else {
>       etkin_Mi = true;
>       renk = clr.gray;
>     }
>   }
>
>   bool üstünde_Mi(int mouseX, int mouseY) {
>     int en = this.x + this.en;
>     int boy = this.y - this.boy;
>
>     return (this.x < mouseX && this.y > mouseY &&
>                 en > mouseX &&    boy < mouseY);
>   }
> }
>
> void main() {
>     BoşKutu[3] kutular;
>
>     with( new scene(600, 200, "Etkin Kutu Denemesi", clr.white) ) {
>
>       // 3 ayrı kutumuz yan yana kurulur...
>
>       foreach(int i, ref kutu; kutular) {
>         int ötele = (25 + kutu.en) * i;
>         kutu = BoşKutu(20 + ötele, h - 20);
>         kutu.kimlik = 100 + i;
>       }
>
>       do {
>
>         SDL_Clear();
>
>         foreach(i, ref kutu; kutular) {
>
>           /* sırayla tüm kutular, fare imleç ile
>            * etkileşip etkileşmediği denetlenir:
>            */
>
>           if(sonBasılanDüğme == SDL_BUTTON_LEFT
>              && kutu.üstünde_Mi(xMouse, yMouse)
>              && !birNesneyeKilitlendi) {
>
>             birNesneyeKilitlendi = true;  // sdl2mini.scene üyesi
>
>           /* etkin olan kutular ekrana yazılır...
>            * DİKKAT: Bu yöntemde birden fazla kutu etkin!
>            */
>
>             kutu.durumuEvir();
>             kutu.kimlik.write(". kutu etkin");
>             if(!kutu.etkin_Mi) writeln(" değil!");
>             else writeln("...");
>           }
>
>           /* Henüz kutular ekrana yansıtılmadan evvel
>            * GPU belleğine son durumları yazılır...
>            */
>
>           rectangle(kutu.x, kutu.y,
>                     kutu.x + kutu.en,
>                     kutu.y - kutu.boy, kutu.renk);
>         }
>
>         SDL_Flip(scr);
>
>       } while( checkEvents() );
>     }
>     SDL_Quit();
> } /* sdlmini2.scene'deki yardımcı işlevler:
>   void rectangle(int x0, int y0,
>                  int x1, int y1, clr c=clr.white) {
>     line(x0, y0, x1, y0, c);
>     line(x1, y0, x1, y1, c);
>     line(x1, y1, x0, y1, c);
>     line(x0, y1, x0, y0, c);
>   }
>
>   bool checkEvents() {
>     bool continueLoop = true;
>     SDL_PollEvent(&event);
>
>     if(!keyEventControl() ||
>        !mouseEventControl())
>     {
>       continueLoop = false;
>     }
>
>     return continueLoop;
>   }
> //*/
>
> ```

>

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
May 04, 2013

Evet, tıpkı "mouse" gibi "keyboard" da UP ve DOWN olayları tanımlanmış:

 enum : ubyte {
   SDL_KEYDOWN = 2,            /* Keys pressed */
   SDL_KEYUP,                  /* Keys released */
   SDL_MOUSEMOTION,			/* Mouse moved */
   SDL_MOUSEBUTTONDOWN,		/* Mouse button pressed */
   SDL_MOUSEBUTTONUP		   /* Mouse button released */
 }

Ancak yenilenme (repeat) olayı ve sıklığı (type rate) olayı bozuyor. Ben şu an, bu cümleyi yazarken, kısa aralıklar ile tuşu basıp çekiyorum ya; ammaaaaaaaaaaa <--burada olduğu gibi uzun basarsak sanki otomatik bas bırak olmuş gibi oluyor. SDL'de ise sanırım bunu algılamıyor daha doğrusu algılama işini geliştiriciye bırakıyor; örn. karakterleri sayabilir...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

May 05, 2013

Merhaba,

Sabah kalktığımda aklımda şöyle bir fikir vardı...:)
Alıntı ("sdl2mini.d içinde"):

>
>   auto blinkingTicks(uint bits) {
>     // it's recommended to bits > 7
>     auto now = SDL_GetTicks();
>          now &= 1 << bits;
>     return cast(bool)now;
>   }
> ```

>

// sahne döngüsü >>
do {

   SDL_Clear();
   // Yaklaşık saniyede 1 yanıp söner (sahneye gelir/gider)
   if(blinkingTicks(9)) circle(30, 20, 10, clr.red);

: : :


Burada mantık şu:

SDL'nin basit bir sayaçtan öte ve uint türünde (yeni sürümde ulong oldu) bir işlevi var. Bu sayısal değerin herhangi bir bit'ini true/false olarak öğrenirsem farklı ölçülerde frameRate elde edebilirim. Sonra bunu, klavyeden basılan herhangi bir tuşu, yığına örneklemede (rate pushing) kullanabilirim.

Nasıl fikir?

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
May 04, 2013

Alıntı (Salih Dinçer):

>

Çünkü klavyemiz, bilgisayarımızın fare tuşları gibi basılıp bırakılana kadar (herhangi bir süre) tekrar yapmadan beklemez.

Klavyenin basılıp bırakıldığını farede olduğu gibi anlayamıyor muyuz? Ön belleğe yalnızca tuş bırakıldığında yazsa?

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

May 05, 2013

Hocam çok düşündüm, olmuyor ama denemedim! Çünkü n'olcağını tahmin edebiliyorum...:)

Hassaslık o kadar önemlli değil, daha ziyade sahnedeki grafik işlemlerini etkileyecek CPU kaynağını ziyan etmemeli. O yüzden olabildiğince basit şekilde ve harici sayaçı (SDL_GetTicks)'i kullandım. Olmamasına gelince; aşağıdaki kare dalgadan hemen tahmin edebilirsiniz:

'http://www.tamsat.org.tr/tr/wp-content/uploads/2010/04/KareDalgaOrnegi.jpg'

Kısaca maksadımız, numune (örnekleme) almak. Tıpkı deprem dayanıklılık testi yapanların binanın bütün bir katı yerine bir duvarından küçük bir numune alması gibi. Yukarıdaki bana ait olmayan fotoğraftaki gibi katlar (periods) bizim blinkingTicks() işlevinin görüntüsüdür...

Eğe aşağıdaki gibi bir durumu değişen yığın yapmazsak işler karışır gibime geliyor:

struct Stack {
 wchar[] data;
 int index;
 bool status; // true => push to stack

 this() {
   this.data.length = 64;
   this.status = true;
 }

 void push() {
   auto period = blinkingTicks(8);

   if(period && status) {            // 1 AND 1 =>

     data[++i] = cast(wchar)event.key.keysym.sym; // UtfConvert() use may be needed...
     status = false;

   } else if(!period && !status) {   // 0 AND 0 =>

      status = true;

   }

 }
 :  :  :
}

Kodu denemedim ama çalışır gibi duruyor. Çünü T0 anında preiod ve status'ün 1 olduğunu varsayarsak 1 adet harf alınır. Sonra status, false'a çekildiği artık push yapmaz; ta ki periyot bitip tekrar true dönene kadar. Zaten o zamana kadar status tekrar true yapılmış (else if) yapılmış oluyor.

Denemek lazım, sürprizlere açık...:)

Sevgiler, saygılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

May 05, 2013

Olur ama tam hassas olmaz herhalde. Onun yerine, şuKadarZamanGeçti_mi(1234) gibi bir çağrı da olabilir.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

May 06, 2013

Hasta hasta halimle ancak 12 saatte yapabildim... :'(

Oldu galiba, bir test eder misiniz?

module bufferstack;

import std.format;
import std.stdio;
import std.string;

class BufferStack(T) {
 struct Index {
   int pop, push;
 }

 Index index;
 T[] data;

 this(size_t length) {
   this.data.length = length;
 }

 bool empty() const @property
 {
   // Başlangıçra 0. eleman kullanılmıyor!
   return index.pop == index.push;
 }

 auto size() @property {
   return cast(int)data.length - 1;
 }

 void popFront() @property {
   if( index.pop < this.size() ) index.pop++;
   else index.pop = 0;
 }

 T pop() @property
 {
   popFront();

   return data[index.pop];
 }

 T front() @property
 {
   return data[index.pop];
 }

 void push(T value) @property
 {
   if( index.push < this.size() ) index.push++;
   else index.push = 0;

   data[index.push] = value;
 }

 override
 string toString() @property
 {
   string result = "\tPOP\tPUSH\n";
   result ~= format("INDEX:\t%s\t%s\n", index.pop, index.push);
   result ~= format("STACK: %s\n", data);
   result ~= format("SIZE OF %s / ", index.push > 0 ?
                  data.length - index.push :
                  data.length);
   result ~= format("%s", data.length);
   return result;
 }

}

void main() {
 enum {
   TEKRAR_SAYISI = 10,
   POP1 = 3,
   POP2 = 5,

 }
 auto stack = new BufferStack!dchar(64);
 string key;

 foreach(tekrar; 1..TEKRAR_SAYISI + 1) {
   stack.writeln;

   key = readln().chomp();
   foreach(dchar k; key) {
     stack.push(k);
   }

   if(tekrar == POP1 || tekrar == POP2) {
     "POP STACK:".write;
     foreach(s; stack) s.write;
     writeln;
   }
 }
}

Alıntı:

>

C:\DMD>bufferstack
POP PUSH
INDEX: 0 0
STACK: ￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿
SIZE OF 64 / 64
111111111111111111
POP PUSH
INDEX: 0 18
STACK: ￿111111111111111111￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿
SIZE OF 46 / 64
22222222222222222222222222222
POP PUSH
INDEX: 0 47
STACK: ￿11111111111111111122222222222222222222222222222￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿￿
SIZE OF 17 / 64
3333333
POP STACK:￿11111111111111111122222222222222222222222222222333333
POP PUSH
INDEX: 54 54
STACK: ￿11111111111111111122222222222222222222222222222333333'3'￿￿￿￿￿￿￿￿￿
SIZE OF 10 / 64
444444444444
POP PUSH
INDEX: 54 2
STACK: 4441111111111111111222222222222222222222222222223333333444444444
SIZE OF 62 / 64
55555555555555
POP STACK:'3'4444444444445555555555555
POP PUSH
INDEX: 16 16
STACK: 444555555555555551122222222222222222222222222222333333**'3'444444444**
SIZE OF 48 / 64

Kırımızı ile işaretlediğim bölüme bakılırsa olmamış galiba. Zaten sorunu empty() içinde dile getirmiştim. Ama sonrada işler rayına girip düzeleceğini zannettim. Ama öyle, düzeliyor; en azından kafamda...:)

Sanırım foreach() aralıkta(range) gezinirken önce empty()'e uğruyor ve onay alırsa devam ediyor. Sonra front()'a uğrayıp güncel index'deki veriyi çekiyor. En son popFront() ile index arttırılıyor. Oysa popFront() daha önce sonra front() olması gerekiyor. Sanırım aralıklarda çalıştıramayacağım...:(

Yatmalıyım, başım çatlıyor ve her dakika hapşırıyorum...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

May 07, 2013

Başlangıçta index'ler 0'dan başladığı için ve dizilerin 0. elemanı olduğundan hiç bir zaman düzelmeyen (aynı zamanda artmayan) bir kayma meydana geliyor. Bunu 2. döngünün toString() çıktısında görebiliyoruz.

Bunu düzeltmenin bir yolu var; o da index'leri -1'den başlatmak. Ama foreach() içinde aralık özelliklerini kullandığımız zaman döngü şu sırayla çalıştığından Range Overflow hatası alıyoruz:

  • empty() => false ise döngüye devam...
  • front() => index değerine göre veriyi döndür
  • popFront() ile index değerini güncelle

Bu sorunu aşmanın bir yolu da aralık kullanmamak. Yani bir while döngüsü içinde, pekala pop() vasıtasıyla veri istenilen şekilde çekilebiliyor. Ama yine index'ler -1'den başlamak zorunda çünkü pop()'un ilk hamlesi index.pop'u arttırmak olacak. Fakat hem aralık hem de geleneksel yöntemler ile erişmek istersek ne yapabiliriz?

Cevabı şu düzeltmede buldum:

 void popFront(){}        // foreach() içinde, aralıklarda
 T front(){return pop();} // kullanabilmek içindir...

 T pop() @property
 {
   if( index.pop < this.size() ) index.pop++;
   else index.pop = 0;

   return data[index.pop];
 }

Burada tek yaptığım popFront() aralık olanağını foreach() içinde hata vermeyecek şekilde @disable yapmak. Tabi dil olanakları etkinsizleştirince hata aldığımız için boş şekilde tanımlamaktan başka yol bulamadım. Zaten çok önemli değil çünkü çalışıyor...:)

Özetle, özelleştirilmiş bu yığın uygulamasında 2 dizin (index) değeri olduğu için farklı muamele gerekiyor.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

May 07, 2013

Alıntı (Salih Dinçer):

>

Kırımızı ile işaretlediğim bölüme bakılırsa olmamış galiba.

Ben bu programı denedim ve aynı seninkine benzer sonuçlar aldım. Kırmızılarda ne sorun var?

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

May 07, 2013

front() her çağrıldığında eleman kaybedilmesi yanlış olmuş. front() her zaman için en baştaki elemanı vermeli ve istediğimiz kadar çağrılabilmeli. Eleman yalnızca popFront() çağrıldığında kaybedilmeli.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

« First   ‹ Prev
1 2 3