Döngü ile süre kontrolü...

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
brs
Üye
Mesajlar: 626
Kayıt: 04 Eki 2012 03:52

Döngü ile süre kontrolü...

Mesaj gönderen brs »

Selam; Yaklaşık 5 gündür uğraştığım kodun sanırım sonuna geldim, fakat ufak bir sıkıntım var kısaca yapmak istediğimi anlatayım.

Herhangi bir tarihte iki saat arasında süre aşımı var mı? var ise hangi saatte olmuş, burayı çözdüm;
Takıldığım nokta ise saat 00:00:00 ile 01:00:00 sorun yoksa döngü ile 01:00:00 ile 02:00:00 arası kontrol edilecek varsa uyarı yoksa sonraki saat dilime bakılacak bu şekilde yirmi dört saati kontrolü sağlanacak.

Kod: Tümünü seç

procedure TForm11.SpotClick(Sender: TObject);
var
  Sure1, Sure2: Integer;
  Total, Fazla, Saat1, Saat2: TTime;
  Tnt, Rek, Spot: String;
begin
  try
    if Form1.ListView1.Items.Count > 0 then
    begin
      Sure1 := 0;
      Sure2 := 0;
      Saat1 := StrToTime('00:00:00');
      Saat2 := StrToTime('01:00:00');
      with Form1.Ayarlar do
      begin
        Close;
        SQL.Clear;
        SQL.Add('Select * From AYARLAR');
        Open;
        if Not IsEmpty then
        begin
          Tnt := FieldByName('TANITIMMAX').Value;
          Rek := FieldByName('REKLAMMAX').Value;
          Spot := FieldByName('SPOTMAX').Value;
        end;
        for Sure1 := 1 to 24 do
        begin
          with Form1.Playlist do
          begin
            Close;
            SQL.Clear;
            SQL.Add('SELECT * FROM PLAYLIST');
            SQL.Add('Where ICERIK Like ' + QuotedStr('%' + 'Tanıtım' + '%'));
            SQL.Add('And YTARIH=:Tarih And START BETWEEN :Time1 And :Time2');
            ParamByName('Tarih').AsDate := StrToDate(Form1.Tarih.Caption);
            ParamByName('Time1').AsTime := IncMinute(Saat1, Sure1);
            ParamByName('Time2').AsTime := IncMinute(Saat2, Sure2);
            Prepared := True;
            Open;
            if Not IsEmpty then
            begin
              while Not Form1.Playlist.Eof do
              begin
                Next;
                Total := Total + StrToTime(FieldByName('YDURATION').Value);
                Fazla := (Total - StrToTime(Rek));
              end;
            end;
          end;
        end;
        if Total > StrToTime(Tnt) then
        begin
          Application.MessageBox
            (Pchar((TimeToStr(Saat1)) + ' ve ' + (TimeToStr(Saat2)) +
            ' Saatleri Arasında Tanıtım Süresini ' + (TimeToStr(Fazla)) +
            ' Aştınız!'), 'Süre Kontrol!', MB_Ok or 0);
        end;
      end;
    end;
  except
  end;
end;
İşi bilen yardım eder, az bilen akıl verir, bilmeyen eleştirir, yapamayan ise çamur atar...
Lord_Ares
Üye
Mesajlar: 1070
Kayıt: 15 Eki 2006 04:33
Konum: Çorlu

Re: Döngü ile süre kontrolü...

Mesaj gönderen Lord_Ares »

Özür dileyerek sorunu tam anlamış değilim. Belki biraz daha açık yazarsan benim gibi olan arkadaşlarda rahat anlar ve cevap veren çok olabilir düşüncesindeyim. "Herhangi bir tarihte iki saat arasında süre aşımı var mı?" kelimesinden şunu anladım. "Reklam tanıtım sürelerinin toplamı, belirtilen sabit bir zaman aralığından fazla mı" .
Örneğin : 12:00 ile 13:00 saat dilimi arasında 60 dakikalık reklam alabilirsin. Bu saat aralığına aldığın reklamların toplam süresi 70 dakika ise süre aşımı var mı demesini istiyorsun. Yanlış mı anladım.
Eğer öyle ise, iki saat aralığı 60 dakika olduğuna göre ve elinde bu saat dilimine ayrılmış reklam sürelerinin toplamıda olduğuna göre comparaTime (60,70) şeklinde karşılaştır. Eğer iki rakam birbirine eş ise 0 değerini döndürecektir.

if compareTime(60,70)=0 then showmessage('ikisi aynı') else showmessage('reklamın toplam süresi ayırılan zamandan fazla ')

şuan akıldan ve delphi olmayan bilgisayardan yazıyorum deneme şansım olmadı, ufak hatalar olabilir.
Eğer senin istediğin farklı bişeyse , yanlış anladıysam özür dilerim.
Kullanıcı avatarı
brs
Üye
Mesajlar: 626
Kayıt: 04 Eki 2012 03:52

Re: Döngü ile süre kontrolü...

Mesaj gönderen brs »

Lord_Ares yazdı:Özür dileyerek sorunu tam anlamış değilim. Belki biraz daha açık yazarsan benim gibi olan arkadaşlarda rahat anlar ve cevap veren çok olabilir düşüncesindeyim. "Herhangi bir tarihte iki saat arasında süre aşımı var mı?" kelimesinden şunu anladım. "Reklam tanıtım sürelerinin toplamı, belirtilen sabit bir zaman aralığından fazla mı" .
Örneğin : 12:00 ile 13:00 saat dilimi arasında 60 dakikalık reklam alabilirsin. Bu saat aralığına aldığın reklamların toplam süresi 70 dakika ise süre aşımı var mı demesini istiyorsun. Yanlış mı anladım.
Eğer öyle ise, iki saat aralığı 60 dakika olduğuna göre ve elinde bu saat dilimine ayrılmış reklam sürelerinin toplamıda olduğuna göre comparaTime (60,70) şeklinde karşılaştır. Eğer iki rakam birbirine eş ise 0 değerini döndürecektir.

if compareTime(60,70)=0 then showmessage('ikisi aynı') else showmessage('reklamın toplam süresi ayırılan zamandan fazla ')

şuan akıldan ve delphi olmayan bilgisayardan yazıyorum deneme şansım olmadı, ufak hatalar olabilir.
Eğer senin istediğin farklı bişeyse , yanlış anladıysam özür dilerim.

Hocam kısmen doğru anlamışsınız;

Süre aşımı var ise bunun uyarısını veriyor burada sıkıntı yok, sorun şu 00:00:00: dan başlatıp 01:00:00'a kadar aratıyorum bu saatler arasında taşma varsa uyarıyor yok ise işlem 01:00:00 ile 02:00:00 geçmesini sağlayamadım sonrasında 02:00:00 ile 03:00:00 geçecek ve en son 23:00:00 ile 00:00:00 aradıktan sonra arama işlemi duracak... Dilimin döndüğünce anlatmaya çalıştım...

Saygılarımla...
İşi bilen yardım eder, az bilen akıl verir, bilmeyen eleştirir, yapamayan ise çamur atar...
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Döngü ile süre kontrolü...

Mesaj gönderen mrmarman »

Merhaba.

(1) TANITIMMAX, REKLAMMAX, SPOTMAX birimleri nedir ? Saat, Dakika, Saniye şeklinde saat formatında mıdır ?

(2) Olası bir yanlış uygulama rapor etmek istiyorum, "while Not Form1.Playlist.Eof do" döngü blok ilk satırını NEXT diyerek bulduğun ilk kaydı pass geçmiş, değerlendirme dışı bırakmış oluyorsun. Bunu bilerek yapmış ta olabilirsin, sadece bir tespit.

(3) Bir diğer önerim, karşılaştırmalarını en küçük zaman birimine dönüştürüp yaparsanız rahat edersiniz.

Örnek : YDURATION değeri 00:12:22 ise bunu saniye cinse dönüştürünce 12*60 + 22 = 742 saniye oluyor...
REKLAMAX değeri de benzeri şekilde tutuluyorsa 01:00:00 için 1 * 60 * 60 = 3600 saniye olur.
Bu süre üzerinden yapacağın işlem, döngü içerisinde eğer yayınlanan ürün bir REKLAM ise o zaman REKLAMAX değerinden YDURATION değerini basit bir çıkarma işlemine tabi tutarsın.
3600 - 742 = 2858 saniye olarak geriye kalan yayın hakkını bulursun. Döngü sonunda hala POZİTİF bir değer veya (0) kalmışsa, süre aşımı olmadığı, her şeyin normal olduğu kanaatine net olarak varmış olursun.
(4) Her saat için döngü içerisinde ard arda veritabanı erişimi yerine saate göre sıralı bir defa açılmış veritabanında baştan sona döngü daha verimli olur. Saat dilimini basit if blokları ile hükmedebilirsiniz.
Hesaplama dönüşümü de basit, bildiğin şeyler.
Resim
Resim ....Resim
Kullanıcı avatarı
brs
Üye
Mesajlar: 626
Kayıt: 04 Eki 2012 03:52

Re: Döngü ile süre kontrolü...

Mesaj gönderen brs »

Selam;

1)TANITIMMAX, REKLAMMAX, SPOTMAX alanlanları time olarak değiştirdim...

2) NEXT gözümden kaçmış ilgileneceğim...

3 ve 4) Tecrübeniz karşısında boynum kıldan incedir, lakin time hesaplama alanını integer dönüştürüp tekrar time dönüştürmek hen uzun olur diye ve açıkçası aklıma da gelmedi...

Şimdilik saatler arasını geçişi sağlayabilmek benim için yeterli bir durum, bu konuda yardımcı olursanız sevinirim...
İşi bilen yardım eder, az bilen akıl verir, bilmeyen eleştirir, yapamayan ise çamur atar...
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Döngü ile süre kontrolü...

Mesaj gönderen mrmarman »

Hayır yanlış anlaşıldı. Bu FIELD dönüştürmekten bahis değil, her kayda konumlanışta o alanı bir fonksiyon ile saniyeye dönüştürmekti önerim.

Mesela döngü içerisinde gelen Duration veya Bir limit saati saniyeye dönüştürüp kullamak için bir değişkene bunu atamanız kafi.

Örnek :
Kullanım :

Kod: Tümünü seç

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  ShowMessageFmt('%d', [ StringToSaniye('01:00:00') ]);
end;
Fonksiyon:

Kod: Tümünü seç

USES DateUtils;

Function StringToSaniye( strSure: String ): Integer;
Var
  Saat : TTime;
begin
  Saat := StrToTime( strSure );
  Result := DateUtils.SecondOf(Saat);
  Result := Result + (DateUtils.MinuteOf(Saat)*60);
  Result := Result + (DateUtils.HourOf(Saat)*60*60);
end;
Resim
Resim ....Resim
Kullanıcı avatarı
brs
Üye
Mesajlar: 626
Kayıt: 04 Eki 2012 03:52

Re: Döngü ile süre kontrolü...

Mesaj gönderen brs »

Teşekkür ederim üsdat,

Basit bir kodlama ile kendimce bir şeyler yapmaya çalışırken bazen beni korkutuyorsunuz, :lol: :lol: :lol:

Çok teferruatlı bir koda gerek yok basit bir kodlama işimi "sanırım" görecektir; Müsaadenizle konuma dönmek istiyorum :D saat dilimlerine göre nasıl çözüm üretebilirim...
İşi bilen yardım eder, az bilen akıl verir, bilmeyen eleştirir, yapamayan ise çamur atar...
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Döngü ile süre kontrolü...

Mesaj gönderen mrmarman »

Hocam gözünüzde büyütmeyin :)
(1) Bir Query kurun.. Tarih bugün olsun mesela... ORDER BY ise TARIH olsun. Bu size bugünkü tüm akışı verecektir değil mi ? Akış derken Dizi, Film, Reklam, Spot, vs. siz bunlardan sadece üç türdekiyle ilgileniyorsunuz. TANITIM, REKLAM ve SPOT

(2) LIMIT değerleri AYARLAR tablosundan aldığınızı görüyorum. Neler geliyor ?

Kod: Tümünü seç

          Tnt := FieldByName('TANITIMMAX').Value;
          Rek := FieldByName('REKLAMMAX').Value;
          Spot := FieldByName('SPOTMAX').Value;
işte bu aşamada bu string ifadeleri bir INTEGER değere alın.
Tnt string ifadesini SANİYE cinsine dönüştürüp bir değişkende tutun.

Kod: Tümünü seç

TNTsn := StringToSaniye(Tnt );
Rek string ifadesini SANİYE cinsinde dönüştürüp başka bir değişkende tutun.

Kod: Tümünü seç

REKsn := StringToSaniye(Rek );
Spot string ifadesini SANİYE cinsinde dönüştürüp başka bir değişkende tutun.

Kod: Tümünü seç

SPOTsn := StringToSaniye(Spot );
şimdi elinizde saniye cinsinden maksimum değerleriniz var değil mi ?
Girin döngüye ve olanları birlikte izleyelim...

Aşağıdaki kodu deneme şansım yok, veritabanı içerik ve yapısı size ait. Ben sadece gözle takip ederek verdiğiniz örnek üzerinden tahmini kod yazdım. Delphi IDE kullandığımdan syntax hataları konusunda sıkıntı yok. Sadece mantık konusunda birşeyler anlatmasını umuyorum

EDIT: Şimdi gördüm tek eksik, en son saat diliminde değişim olmayacağı için değerlendirmeye almayacağından, döngünü sonunda sona kalan saat dilimi için yeniden IF'leri koymak gerekecek. Hani limitler 0'ın altındaysa uyarı veriyor ya onlar. Bunları zaten düzeltirsiniz.

Kod: Tümünü seç

procedure TForm1.SpotClick(Sender: TObject);
  Function StringToSaniye( strSure: String ): Integer;
  Var
    Saat : TTime;
  begin
    Saat := StrToTime( strSure );
    Result := DateUtils.SecondOf(Saat);
    Result := Result + (DateUtils.MinuteOf(Saat)*60);
    Result := Result + (DateUtils.HourOf(Saat)*60*60);
  end;
var
  SaatDilimi : Integer;
  Tnt, Rek, Spot: String;
  TNTsn, REKsn, SPOTsn : Integer;
begin
  TNTsn  := 0;
  REKsn  := 0;
  SPOTsn := 0;
  with Form1.Ayarlar do
  begin
    Close;
    SQL.Clear;
    SQL.Add('Select * From AYARLAR');
    Open;
    if Not IsEmpty then
    begin
      Tnt  := FieldByName('TANITIMMAX').Value;
      Rek  := FieldByName('REKLAMMAX').Value;
      Spot := FieldByName('SPOTMAX').Value;
    end;
    Close; // işi bitti... Açık kalmasın...
  end; // With Form1.Ayarlar

  SaatDilimi := -1; // Başlangıç değeri için...
  with Form1.Playlist do
  begin
    Close;
    SQL.Clear;
    SQL.Add('SELECT * FROM PLAYLIST');
    SQL.Add('WHERE YTARIH = :Tarih');
    ParamByName('Tarih').AsDate := StrToDate(Form1.Tarih.Caption);
    Prepared := True;
    Open;
    if Not IsEmpty then
    begin
      while Not Form1.Playlist.Eof do
      begin
        // saatdilimi -1 olduğundan ilk kayıt ile gelen ilk saat
        // yeni atama için direkt bu sorguda bloğa girecek ve limitler RESET edilecek.
        if SaatDilimi <> DateUtils.HourOf( StrToTime(FieldByName('START').AsString) ) then
        begin
          if SaatDilimi >= 0 then
          begin // -1 ise pass geçilir...

            if TNTsn < 0 then
            begin // Negatif değerler limit aşımı demektir.
                Application.MessageBox ( PCHar( Format('%.2d:00:00 saat diliminde TANITIM süresini (%d) saniye aştınız...!', [ SaatDilimi, -1*TNTsn ]) )
                , 'Süre Kontrol!'
                , MB_Ok or 0);
            end;
            if REKsn < 0 then
            begin // Negatif değerler limit aşımı demektir.
                Application.MessageBox ( PCHar( Format('%.2d:00:00 saat diliminde REKLAM süresini (%d) saniye aştınız...!', [ SaatDilimi, -1*REKsn ]) )
                , 'Süre Kontrol!'
                , MB_Ok or 0);
            end;
            if SPOTsn < 0 then
            begin // Negatif değerler limit aşımı demektir.
                Application.MessageBox ( PCHar( Format('%.2d:00:00 saat diliminde SPOT süresini (%d) saniye aştınız...!', [ SaatDilimi, -1*SPOTsn ]) )
                , 'Süre Kontrol!'
                , MB_Ok or 0);
            end;
          end;

          // Yeni saat dilimine geçildi. 01 ise 02, 02 ise 03 gibi
          // kayıtlardaki saatler dikkate alındığından boş saatler için geresiz döngü de kurmamış olduk...
          SaatDilimi := DateUtils.HourOf( StrToTime(FieldByName('START').AsString) );
          // Limitleri Resetliyoruz..
          TNTsn  := StringToSaniye(Tnt );
          REKsn  := StringToSaniye(Rek );
          SPOTsn := StringToSaniye(Spot );
        end;
        if FieldByName('ICERIK').AsString = 'Tanıtım'
          then TNTsn  := TNTsn  - StringToSaniye(FieldByName('YDURATION').AsString);
        if FieldByName('ICERIK').AsString = 'Reklam'
          then REKsn  := REKsn  - StringToSaniye(FieldByName('YDURATION').AsString);
        if FieldByName('ICERIK').AsString = 'Spot'
          then SPOTsn := SPOTsn - StringToSaniye(FieldByName('YDURATION').AsString);
        Next;
      end;
    end;
  end; // With
end;
Resim
Resim ....Resim
Kullanıcı avatarı
brs
Üye
Mesajlar: 626
Kayıt: 04 Eki 2012 03:52

Re: Döngü ile süre kontrolü...

Mesaj gönderen brs »

Üsdat ne olur kusuruma bakmayın neredeyse bir haftadır kafa bi dünya oldu;

Saat 09:00 da playliste tanıtım süresi yaklaşık 16 dakika iken ve maksimum tanıtım süresini 00:01:00 dakika yapmama rağmen
22 saniye aşma var, ve MessageBox birden fazla ekrana yansıyor...

Resim ile olayı anlatmak daha iyi olabilir diye artı olarak görsel ekledim, boyut konusunda adminler kusura bakmasınlar...

Resim
İşi bilen yardım eder, az bilen akıl verir, bilmeyen eleştirir, yapamayan ise çamur atar...
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Döngü ile süre kontrolü...

Mesaj gönderen mrmarman »

Şunları bir kontrol eder misin ?

(1) Her saat dilimi değişimi var ya, orada SaatDilimi hangi değeri alıyor. ShowMessage ile gösterttir, sana sırasıyla birer defa 6,7,9,11,12,13 göstermesi lazım.

(2) Tanıtımı için 00:01:00 olarak aldığına göre StringToSaniye sonucu TNTsn 60 değeri alıyor mu ? Yoksa en son veritabanında daha büyük bir değer mi vardı da onu aldı. Çünkü 22 saniye demesi için

(3) Döngü içerisinde DURATION değerlerini StringToSaniye doğru hesap yapıyor mu ? Anlamak için showmessage içinde önce duration'u yanına da StringToSaniye sonucunu yazdırarak kontrol et.

(4)

Kod: Tümünü seç

SaatDilimi := DateUtils.HourOf( StrToTime(FieldByName('START').AsString) );
satırının hemen üzerinde bu iki değeri showmessage ile göstermeyi sağla ve karşılaştırmada neden hemen bloğa giriş yaptığını tespit edelim.

Kod: Tümünü seç

ShowmessageFmt('%d - %d', [SaatDilimi, DateUtils.HourOf( StrToTime(FieldByName('START').AsString) ] );
şeklinde denersin.

SON olarak uyguladığın kodu tam olarak buraya yaz ki anlayayım. Dönüşüm sırasında değişiklik yapıldı mı bilemem. Motomod zaten çalışmasını beklemiyorum, amaç metodolojiyi sana aktarabilmek. :idea:
Resim
Resim ....Resim
Cevapla