Zamanlanmış Olay Kurgulama (ÇÖZÜLDÜ)

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
cengaver
Üye
Mesajlar: 111
Kayıt: 01 Nis 2014 04:02
Konum: İstanbul

Zamanlanmış Olay Kurgulama (ÇÖZÜLDÜ)

Mesaj gönderen cengaver » 29 Eyl 2014 03:44

Merhaba Arkadaşlar,

(Mantığını kuramadığım ve doyurucu örnekler bulamadığım için sorma ihtiyacı duydum.)

Şöyle bir derdim var fakat öncesinde tasarladığım yapıyı anlatayım;

1) Bir olay tablom var. Bu tablonun (Pasif(bit), Baslangic(DateTime), Bitis(DateTime), Tetiklenme(DateTime), PeriyotTipi(Str), PeriyotGun(Int), PeriyotHafta(Int), H1, H2, H3, H4, H5 ve H7(Boolean), OlayAdi(Str), SQL(Str)) diye alanları var.

2) Bir Timer'im var. Bu Timer Tetiklenme zamanı gelen kaydın SQL kodunu execute ediyor.

3) Periyot Tipi şimdilik 3 değer alıyor {Tek, Günlük, Haftalık}. Şimdi ben bu Tek ve Günlük kipte bir sonraki Tetiklenme zamanını hesaplatabiliyorum.
a) Tek'te sonraki tetiklenme olmuyor.
b) Günlükte ise Tetiklenme zamanını şu formüle göre hesaplatıyorum;

Kod: Tümünü seç

var
  QRY: TADODataSet;
Begin
...
  if (PeriyotTipi = 'Günlük') then begin
      PeriyotGun := QRY.AsInteger('PeriyotGun');
      aTarih := IncDay(Baslangic, PeriyotGun);
      while (aTarih < aBugun) do begin
             aTarih := IncDay(aTarih, PeriyotGun);
      end;
      Result := aTarih;
  end else
...
SIKINTI ŞU;

Şimdi mesela 2 hafta sonrası için salı ve cuma günleri işaretli bir olay için "bir sonraki" Tetiklenme tarihini nasıl hesaplayabilirim?


Sorunlar şuralarda da ortaya çıkıyor. Mesela diyelim ki bugünden itibaren 2 hafta sonrasına salı ve cuma günlerine bir olay tanımı olsun;

1) Bunun birinci adımında olayın çalıştırıldığı en son tetiklenme tarihinden itibaren üzerine 2 hafta ekleyelim diyelim. En son cuma günü çalıştırıldığı için üzerine iki hafta eklediğimizde iki hafta sonraki cuma gününe geçiyor, halbuki 2 hafta sonraki cuma gününe değil, 2 hafta sonraki salı gününe geçiş yapması gerekir.
2) Yine aynı örnek üzerinden gidersek; Bir şekilde "salı" problemini çözdüğümüzü varsayım, son tetiklenme tarihine göre üzerine yine 2 hafta ekleneceği için 3 gün sonraki cuma gününe tetiklenmesi gerekirken 2 hafta sonraki salı gününe geçiş yapıyor.

Bunun çözümü nedir? Ben hakikaten bu noktada tıkandım sizce nasıl bir kurgu yapmalıyım?
En son cengaver tarafından 01 Eki 2014 10:13 tarihinde düzenlendi, toplamda 1 kere düzenlendi.

Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1315
Kayıt: 07 May 2009 09:42
Konum: İstanbul
İletişim:

Re: Zamanlanmış Olay Kurgulama

Mesaj gönderen SimaWB » 29 Eyl 2014 04:25

Sorunuzu yanlış anlamadıysam şöyle bir mantıkla çözülebilir:
2 hafta sonra Salı günü için açıklayayım, Cuma için de uyarlarsınız.
DayOfTheWeek ile bugün haftanın kaçıncı günü olduğunu tespit edersiniz. DayOfTheWeek'te Salı haftanın 2. günüdür.
Dolayısıyla siz

Kod: Tümünü seç

Fark := 2 - DayOfTheWeek(Tarih);
ile Salı günü ile aramızdaki farkı bulursunuz.

Kod: Tümünü seç

IncDay(Tarih, Fark)
ile Salı gününü bulursunuz.
2 hafta sonrasını da IncWeek ile tespit edersiniz.
There's no place like 127.0.0.1


uparlayan
Üye
Mesajlar: 28
Kayıt: 09 Oca 2009 05:48

Re: Zamanlanmış Olay Kurgulama

Mesaj gönderen uparlayan » 01 Eki 2014 09:32

Merhaba,

Bence bahsettiğin yöntem sol elinle sağ kulağını tutmak gibi. Yani salı ve perşembe günleri için yazacağın kodları o mantığa göre haftanın diğer günleri için de yazman gerekecek, veya her gün için bulunduğun güne göre ayrı bir formül bulman gerekecek... Uzun ve kısır bir iş bence çünkü anladığım karadıyla sen haftalık periyotla da duracak gibi gözükmüyorsun zira "hafta"yı ele alıyorsan "ay"ı da ele alacaksın gibime geliyor doğru mu?

Ben olsam bunun periyodik olarak kendi kendini tekrar eden bir durum olduğunu düşünürdüm. Aslında aşağıdaki gibi bir fonksiyon kullanarak verdiğin bir tarihin önerdiğim mantığa göre bir periyoda denk gelip gelmediğini de doğrulayabilirsin;

Kod: Tümünü seç

...
Uses
   System.DateUtils;
...
///	<summary>
///	  Zamanlanmış görevler oluştururken bir sonraki tetiklenme tarihini haftalık bazda bulunması için verilen bir
///	  tarihin parametreler bağlamında bir periyoda denk gelip gelmediğini hesaplar.
///	</summary>
///	<param name="aTarih">
///	  Bu tarihin bir periyoda denk gelip gelmediği kıyaslanacaktır.
///	</param>
///	<param name="aHaftalikPeriyot">
///	  Doğrulama periyodunun kaç haftada bir yapılacağı kastedilmektedir.
///	</param>
///	<param name="H1">
///	  Pazartesi
///	</param>
///	<param name="H2">
///	  Salı
///	</param>
///	<param name="H3">
///	  Çarşamba
///	</param>
///	<param name="H4">
///	  Perşembe
///	</param>
///	<param name="H5">
///	  Cuma
///	</param>
///	<param name="H6">
///	  Cumartesi
///	</param>
///	<param name="H7">
///	  Pazar
///	</param>
///	<remarks>
///	  Eğer bir periyoda denk geliyorsa sonuç TRUE değilse FALSE'dir...
///	</remarks>
function SonrakiPeriyodikTarih(aTarih: TDateTime; aHaftalikPeriyot: Integer; H1, H2, H3, H4, H5, H6, H7: Boolean): Boolean; overload;
var
  TarihinGunu, KontrolIndex, PeriyodikDesen, DesendekiGunNo: Integer;
  function DayOfMiladi(aTarih: TDateTime): Integer;
  var
    Y, M, D   : WORD;
    Y1, M1, D1: Integer;
  begin
    DecodeDate(aTarih, Y, M, D);
    M1 := M; Y1 := Y; D1 := D;
    M1 := (M1 + 9) mod 12;
    Y1 := Y1 - (M1 div 10);
    Result := (365 * Y1 + Y1 div 4 - Y1 div 100 + Y1 div 400 + (M1 * 306 + 5) div 10 + ( D1 - 1 ));
  end;
begin
  TarihinGunu    := DayOfMiladi(aTarih);            // = 1.. sonsuz... Gregoryen 1 Ocak 0001 Pazartesiden bu yana verilen tarihin gününün sıra numarasını verir.
  KontrolIndex   := DayOfTheWeek(aTarih);           // = 1..7 Haftanın kaçıncı günü olduğu... Uses'e System.DateUtils ekleyin...
  PeriyodikDesen := aHaftalikPeriyot * 7;           // = Haftalık periyot 3 ise sonuç 21 şeklinde düşünün...
  DesendekiGunNo := TarihinGunu MOD PeriyodikDesen; // = 0..20 gibi (hafta periyodu 3 ise 3 x 7 = 21 -> 0..20 gibi...)

  if (DesendekiGunNo < 7) then begin // Bize ilk 7 günlük kısım lazım...
      case KontrolIndex of
        1: Result := (H1 = TRUE);
        2: Result := (H2 = TRUE);
        3: Result := (H3 = TRUE);
        4: Result := (H4 = TRUE);
        5: Result := (H5 = TRUE);
        6: Result := (H6 = TRUE);
        7: Result := (H7 = TRUE);
      end;
  end else Result := FALSE;
end;

Kullanıcı avatarı
cengaver
Üye
Mesajlar: 111
Kayıt: 01 Nis 2014 04:02
Konum: İstanbul

Re: Zamanlanmış Olay Kurgulama

Mesaj gönderen cengaver » 01 Eki 2014 10:11

Teşekkürler arkadaşlar,
uparlayan yazdı: Bence bahsettiğin yöntem sol elinle sağ kulağını tutmak gibi. Yani salı ve perşembe günleri için yazacağın kodları o mantığa göre haftanın diğer günleri için de yazman gerekecek, veya her gün için bulunduğun güne göre ayrı bir formül bulman gerekecek... Uzun ve kısır bir iş bence çünkü anladığım karadıyla sen haftalık periyotla da duracak gibi gözükmüyorsun zira "hafta"yı ele alıyorsan "ay"ı da ele alacaksın gibime geliyor doğru mu?
Verdiğin fonksiyonu denedim ve gayet iyi çalışıyor, bir sürü kontrolden beni kurtardı diyebilirim. Şu şekilde kullandım ve sorun çözüldü;

Kod: Tümünü seç

...
  if (PeriyotTipi = 'Haftalık') then begin
      h1 := QRY.AsBit('H1');
      h2 := QRY.AsBit('H2');
      h3 := QRY.AsBit('H3');
      h4 := QRY.AsBit('H4');
      h5 := QRY.AsBit('H5');
      h6 := QRY.AsBit('H6');
      h7 := QRY.AsBit('H7');
      PeriyotHafta := QRY.AsInteger('PeriyotHafta');
      aTarih := Baslangic;
      repeat
            if  (SonrakiPeriyodikTarih(aTarih, PeriyotHafta, H1, H2, H3, H4, H5, H6, H7) = FALSE)
            then aTarih := IncDay(aTarih, 1)
            else Break;
      until 1 <> 1;
      Result := aTarih;
  end else
...
Ve Evet, doğru, ay konusunda da haklısın. Haftalık periyottan sonra aylık periyodu da ele almayı planlıyordum ama haftalık periyodu çözmeden cesaret edememiştim. Bu fonksiyonu aylık periyot için uyarlamak sanırım zor olmayacak zira H1...H7 yerine günleri temsilen G1..G31 gelecek, periyodik desen için de çarpanı 30 yaparsak sanırım aya da uyarlanmış olur...

Cevapla