Katılım
17 Aralık 2023
Mesajlar
2.966
Çözümler
8
Beğeniler
2.380
Selam. Öğretmenler odamız için zaman yönetimi uygulaması yapmak istiyorum. Belirlenen saatlerde ders, teneffüs gibi durumları ve belirlenen saate kalan zamanı gösterecek. Bunu en kolay ne ile yaparım? Örnek bir Android yazılımı var, Windows için arıyorum.

IMG_9794.webp
 
Son düzenleyen: Moderatör:
"yapay zekanın 1-2 promptta yapabileceği kadar kolay bir uygulama" cevabı forum standartları gereği "yardımcı" olarak değerlendirilmediği için eski usul gidelim.

Anladığım kadarıyla sabit saatler girilecek ve uygulama basit toplama-çıkarma işlemleriyle bu sabit saatler arasındaki zamanı hesaplayıp ekrana yazacak.

Bu uygulama için herhangi bir dili kullanabilirsin ama Windows için native uygulama yazacaksan C# en rahatı olur muhtemelen. DateTime, TimeSpan gibi kütüphanelerle kolayca kodu yazıp UI için WinForms'a MetroModernUI, MaterialSkin, vs. kütüphaneler çakıp eli yüzü düzgün arayüz yapabilirsin.

Dediğim gibi, JS ile website yazar gibi yazıp Electron'dan Windows'ta çalıştırma, Python falan hepsi kullanılabilir. Hatta website yapıp localde kaldırıp tarayıcıyı tam ekran modunda açabilirsin bile. Basit bir şey olduğu için sonsuz olasılık var.

Fikrimi soracak olursan hepsi boş iş; Cursor, Antigravity gibi bir şeyde yapay zekayı salsan çayıra en fazla 2-3 prompta çiçek gibi yapacaktır.
 
Ekte belirttiğim .zip dosyasını indirerek dilediğiniz gibi kullanabilirsiniz. Klasör içerisinde yer alan "program.js" isimli dosyayı sağ tık yapıp düzenle derseniz saatleri ve teneffüsü ayarlayabilirsiniz.

Umarım doğru anlamışımdır isteğinizi. Sevgiler.

Not: Yapay zeka kullanılarak yaptırılmıştır.




JavaScript:
// ============================================================
//  OKUL ZAMAN YÖNETİMİ - PROGRAM AYARLARI
//  Bu dosyayı bir metin editörüyle (Notepad vb.) düzenleyin.
// ============================================================

// Okul adı (üst başlık olarak görünür)
const OKUL_ADI = "Öğretmenler Odası";

// Ders programı
// Her satır bir etkinlik:
//   name  : Görünecek isim
//   start : Başlangıç saati (HH:MM formatında)
//   end   : Bitiş saati    (HH:MM formatında)
//   type  : ders / teneffus / ogle / bos
//
// Türler ve renkleri:
//   ders     → Yeşil
//   teneffus → Sarı/turuncu
//   ogle     → Pembe  (öğle arası)
//   bos      → Gri    (boş ders, hazırlık vb.)

const PROGRAM = [
  { name: "1. Ders",     start: "08:00", end: "08:40", type: "ders"     },
  { name: "Teneffüs",    start: "08:40", end: "08:50", type: "teneffus" },
  { name: "2. Ders",     start: "08:50", end: "09:30", type: "ders"     },
  { name: "Teneffüs",    start: "09:30", end: "09:40", type: "teneffus" },
  { name: "3. Ders",     start: "09:40", end: "10:20", type: "ders"     },
  { name: "Teneffüs",    start: "10:20", end: "10:35", type: "teneffus" },
  { name: "4. Ders",     start: "10:35", end: "11:15", type: "ders"     },
  { name: "Teneffüs",    start: "11:15", end: "11:25", type: "teneffus" },
  { name: "5. Ders",     start: "11:25", end: "12:05", type: "ders"     },
  { name: "Öğle Arası",  start: "12:05", end: "13:00", type: "ogle"     },
  { name: "6. Ders",     start: "13:00", end: "13:40", type: "ders"     },
  { name: "Teneffüs",    start: "13:40", end: "13:50", type: "teneffus" },
  { name: "7. Ders",     start: "13:50", end: "14:30", type: "ders"     },
  { name: "Teneffüs",    start: "14:30", end: "14:40", type: "teneffus" },
  { name: "8. Ders",     start: "14:40", end: "15:20", type: "ders"     },
];

HTML:
<!DOCTYPE html>
<html lang="tr">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Okul Zaman Yönetimi</title>
  <script src="program.js"></script>
  <style>
    @import url('https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=DM+Sans:wght@300;400;500;600&display=swap');

    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    :root {
      --bg:        #0f1117;
      --bg2:       #181b24;
      --bg3:       #1e2130;
      --border:    rgba(255,255,255,0.07);
      --text:      #e8eaf0;
      --muted:     #7a7e8e;
      --ders:      #1fba8a;
      --ders-dim:  rgba(31,186,138,0.12);
      --teneffus:  #f0a030;
      --teneffus-dim: rgba(240,160,48,0.12);
      --ogle:      #c96090;
      --ogle-dim:  rgba(201,96,144,0.12);
      --bos:       #6a7080;
      --bos-dim:   rgba(106,112,128,0.12);
      --radius:    14px;
      --radius-sm: 8px;
    }

    html, body {
      height: 100%;
      background: var(--bg);
      color: var(--text);
      font-family: 'DM Sans', sans-serif;
      font-size: 15px;
    }

    body {
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 28px 20px 40px;
      min-height: 100vh;
    }

    /* ── HEADER ── */
    header {
      width: 100%;
      max-width: 680px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 28px;
    }
    .school-name {
      font-size: 13px;
      font-weight: 500;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--muted);
    }
    .header-date {
      font-size: 13px;
      color: var(--muted);
    }

    /* ── CLOCK ── */
    .clock-wrap {
      width: 100%;
      max-width: 680px;
      text-align: center;
      margin-bottom: 28px;
    }
    .clock {
      font-family: 'DM Mono', monospace;
      font-size: clamp(56px, 14vw, 96px);
      font-weight: 400;
      letter-spacing: 0.04em;
      color: var(--text);
      line-height: 1;
    }
    .clock-sep { opacity: 0.3; animation: blink 1s step-end infinite; }
    @keyframes blink { 0%,100%{opacity:0.3} 50%{opacity:0.08} }

    /* ── STATUS CARD ── */
    .status-card {
      width: 100%;
      max-width: 680px;
      border-radius: var(--radius);
      border: 1px solid var(--border);
      background: var(--bg2);
      padding: 20px 24px;
      margin-bottom: 16px;
      transition: border-color 0.4s, background 0.4s;
    }
    .status-card.active-ders     { border-color: rgba(31,186,138,0.35); background: linear-gradient(135deg, var(--bg2) 60%, rgba(31,186,138,0.06)); }
    .status-card.active-teneffus { border-color: rgba(240,160,48,0.35);  background: linear-gradient(135deg, var(--bg2) 60%, rgba(240,160,48,0.06)); }
    .status-card.active-ogle     { border-color: rgba(201,96,144,0.35);  background: linear-gradient(135deg, var(--bg2) 60%, rgba(201,96,144,0.06)); }
    .status-card.active-bos      { border-color: rgba(106,112,128,0.35); background: linear-gradient(135deg, var(--bg2) 60%, rgba(106,112,128,0.06)); }

    .status-top {
      display: flex;
      justify-content: space-between;
      align-items: flex-start;
      margin-bottom: 14px;
    }
    .status-type-badge {
      font-size: 11px;
      font-weight: 600;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      padding: 4px 10px;
      border-radius: 20px;
    }
    .badge-ders     { background: var(--ders-dim);     color: var(--ders);     }
    .badge-teneffus { background: var(--teneffus-dim); color: var(--teneffus); }
    .badge-ogle     { background: var(--ogle-dim);     color: var(--ogle);     }
    .badge-bos      { background: var(--bos-dim);      color: var(--bos);      }

    .status-range { font-size: 13px; color: var(--muted); font-family: 'DM Mono', monospace; }

    .status-name {
      font-size: 30px;
      font-weight: 500;
      color: var(--text);
      margin-bottom: 14px;
    }

    .progress-track {
      width: 100%;
      height: 5px;
      background: rgba(255,255,255,0.07);
      border-radius: 3px;
      overflow: hidden;
      margin-bottom: 10px;
    }
    .progress-bar {
      height: 100%;
      border-radius: 3px;
      transition: width 1s linear;
    }
    .bar-ders     { background: var(--ders); }
    .bar-teneffus { background: var(--teneffus); }
    .bar-ogle     { background: var(--ogle); }
    .bar-bos      { background: var(--bos); }

    .status-bottom {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    .time-left {
      font-family: 'DM Mono', monospace;
      font-size: 22px;
      font-weight: 500;
    }
    .color-ders     { color: var(--ders); }
    .color-teneffus { color: var(--teneffus); }
    .color-ogle     { color: var(--ogle); }
    .color-bos      { color: var(--bos); }

    .next-info { font-size: 13px; color: var(--muted); text-align: right; }
    .next-info span { color: var(--text); font-weight: 500; }

    /* ── SCHEDULE LIST ── */
    .schedule-wrap {
      width: 100%;
      max-width: 680px;
      background: var(--bg2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      overflow: hidden;
    }
    .schedule-header {
      padding: 14px 20px;
      font-size: 11px;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      color: var(--muted);
      font-weight: 600;
      border-bottom: 1px solid var(--border);
      display: flex;
      gap: 16px;
    }
    .schedule-header .col-time { min-width: 105px; }

    .sched-item {
      display: flex;
      align-items: center;
      gap: 16px;
      padding: 12px 20px;
      border-bottom: 1px solid var(--border);
      transition: background 0.2s;
    }
    .sched-item:last-child { border-bottom: none; }
    .sched-item.is-past { opacity: 0.3; }
    .sched-item.is-current {
      background: var(--bg3);
    }
    .sched-dot {
      width: 8px; height: 8px;
      border-radius: 50%;
      flex-shrink: 0;
    }
    .dot-ders     { background: var(--ders); }
    .dot-teneffus { background: var(--teneffus); }
    .dot-ogle     { background: var(--ogle); }
    .dot-bos      { background: var(--bos); }

    .sched-time {
      font-family: 'DM Mono', monospace;
      font-size: 13px;
      color: var(--muted);
      min-width: 105px;
    }
    .sched-name {
      font-size: 14px;
      color: var(--text);
      flex: 1;
    }
    .sched-item.is-current .sched-name { font-weight: 600; }
    .now-tag {
      font-size: 10px;
      font-weight: 600;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      padding: 3px 8px;
      border-radius: 20px;
      background: rgba(255,255,255,0.07);
      color: var(--muted);
    }
  </style>
</head>
<body>

<header>
  <div class="school-name" id="schoolName">—</div>
  <div class="header-date" id="headerDate">—</div>
</header>

<div class="clock-wrap">
  <div class="clock">
    <span id="ch">00</span><span class="clock-sep">:</span><span id="cm">00</span><span class="clock-sep">:</span><span id="cs">00</span>
  </div>
</div>

<div class="status-card" id="statusCard">
  <div class="status-top">
    <span class="status-type-badge" id="statusBadge">—</span>
    <span class="status-range" id="statusRange">—</span>
  </div>
  <div class="status-name" id="statusName">—</div>
  <div class="progress-track"><div class="progress-bar" id="progressBar" style="width:0%"></div></div>
  <div class="status-bottom">
    <div class="time-left" id="timeLeft">—</div>
    <div class="next-info" id="nextInfo">—</div>
  </div>
</div>

<div class="schedule-wrap">
  <div class="schedule-header">
    <div class="col-time">Saat</div>
    <div>Etkinlik</div>
  </div>
  <div id="scheduleList"></div>
</div>

<script>
  // program.js'den gelenler: OKUL_ADI, PROGRAM

  function toMin(s) {
    const [h, m] = s.split(":").map(Number);
    return h * 60 + m;
  }
  function pad(n) { return String(n).padStart(2, "0"); }

  function formatLeft(secs) {
    const m = Math.floor(secs / 60), s = secs % 60;
    if (m === 0) return s + " sn";
    if (s === 0) return m + " dk";
    return m + " dk " + s + " sn";
  }

  const DAYS = ["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"];
  const MONTHS = ["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"];

  const TYPE_LABEL = { ders: "Ders", teneffus: "Teneffüs", ogle: "Öğle Arası", bos: "Boş" };

  document.getElementById("schoolName").textContent = typeof OKUL_ADI !== "undefined" ? OKUL_ADI : "Okul";

  function buildList(currentIdx) {
    const list = document.getElementById("scheduleList");
    list.innerHTML = "";
    const nowMin = (new Date().getHours()) * 60 + new Date().getMinutes();
    PROGRAM.forEach((item, i) => {
      const div = document.createElement("div");
      const isCurrent = i === currentIdx;
      const isPast = toMin(item.end) <= nowMin && !isCurrent;
      div.className = "sched-item" + (isCurrent ? " is-current" : "") + (isPast ? " is-past" : "");

      const dot = document.createElement("div");
      dot.className = "sched-dot dot-" + item.type;

      const time = document.createElement("div");
      time.className = "sched-time";
      time.textContent = item.start + " – " + item.end;

      const name = document.createElement("div");
      name.className = "sched-name";
      name.textContent = item.name;

      div.appendChild(dot);
      div.appendChild(time);
      div.appendChild(name);

      if (isCurrent) {
        const tag = document.createElement("div");
        tag.className = "now-tag";
        tag.textContent = "Şimdi";
        div.appendChild(tag);
      }

      list.appendChild(div);
    });
  }

  function tick() {
    const now = new Date();
    const h = now.getHours(), m = now.getMinutes(), s = now.getSeconds();
    document.getElementById("ch").textContent = pad(h);
    document.getElementById("cm").textContent = pad(m);
    document.getElementById("cs").textContent = pad(s);

    document.getElementById("headerDate").textContent =
      DAYS[now.getDay()] + ", " + now.getDate() + " " + MONTHS[now.getMonth()] + " " + now.getFullYear();

    const nowMin = h * 60 + m;
    const nowSec = nowMin * 60 + s;

    let current = null, nextItem = null, currentIdx = -1;
    for (let i = 0; i < PROGRAM.length; i++) {
      const st = toMin(PROGRAM[i].start), en = toMin(PROGRAM[i].end);
      if (nowMin >= st && nowMin < en) { current = PROGRAM[i]; currentIdx = i; }
      if (nowMin < st && !nextItem) nextItem = PROGRAM[i];
    }

    const card = document.getElementById("statusCard");
    card.className = "status-card" + (current ? " active-" + current.type : " active-bos");

    if (current) {
      const badge = document.getElementById("statusBadge");
      badge.className = "status-type-badge badge-" + current.type;
      badge.textContent = TYPE_LABEL[current.type] || current.type;

      document.getElementById("statusRange").textContent = current.start + " – " + current.end;
      document.getElementById("statusName").textContent = current.name;

      const startSec = toMin(current.start) * 60;
      const endSec   = toMin(current.end) * 60;
      const total    = endSec - startSec;
      const elapsed  = nowSec - startSec;
      const rem      = endSec - nowSec;
      const pct      = Math.min(100, Math.round(elapsed / total * 100));

      const pb = document.getElementById("progressBar");
      pb.style.width = pct + "%";
      pb.className = "progress-bar bar-" + current.type;

      const tl = document.getElementById("timeLeft");
      tl.textContent = formatLeft(rem);
      tl.className = "time-left color-" + current.type;

      document.getElementById("nextInfo").innerHTML = nextItem
        ? "Sonraki: <span>" + nextItem.name + "</span> " + nextItem.start
        : "<span>Program sona erdi</span>";

    } else {
      const badge = document.getElementById("statusBadge");
      badge.className = "status-type-badge badge-bos";
      badge.textContent = "Boş";
      document.getElementById("statusRange").textContent = "";
      const afterLast = nowMin >= toMin(PROGRAM[PROGRAM.length - 1].end);
      const beforeFirst = nowMin < toMin(PROGRAM[0].start);
      document.getElementById("statusName").textContent =
        beforeFirst ? "Okul henüz başlamadı" : afterLast ? "Okul bitti" : "Boş zaman";

      const pb = document.getElementById("progressBar");
      pb.style.width = "0%";
      pb.className = "progress-bar bar-bos";

      const tl = document.getElementById("timeLeft");
      tl.className = "time-left color-bos";
      if (nextItem) {
        const rem = toMin(nextItem.start) * 60 - nowSec;
        tl.textContent = formatLeft(rem);
        document.getElementById("nextInfo").innerHTML = "Sonraki: <span>" + nextItem.name + "</span> " + nextItem.start;
      } else {
        tl.textContent = "—";
        document.getElementById("nextInfo").textContent = "—";
      }
    }

    buildList(currentIdx);
  }

  tick();
  setInterval(tick, 1000);
</script>
</body>
</html>
 

Dosya Ekleri

Son düzenleme:
Python + Tkinter kullanabilirsin. Kodu Python ile, arayüzü Tkinter ile yapabilirsin. Python tarafında datetime ile sistem saatini alıp ders/teneffüs saatlerini tanımlarsın, ardından mevcut zamana göre kalan süre (remaining time) hesaplayarak ekrana yazdırırsın. Tkinter’da ise Label ve Frame gibi bileşenlerle basit bir arayüz kurup, after() fonksiyonunu kullanarak arayüzü belirli milisaniyelerde sürekli güncellersin. Böylece uygulama gerçek zamanlı olarak geri sayım yapar, belirlenen saat geldiğinde durum değiştirip ders ve teneffüs gibi modlar arasında geçiş yapabilir.

Daha teknik açıdan bakarsak bu sistem aslında bir tür event-driven loop mantığıyla çalışır, yani sürekli çalışan bir döngü yerine, belirli aralıklarla tetiklenen callback fonksiyonları üzerinden UI güncellenir. Zaman hesaplama kısmında epoch time, timedelta gibi yapılar kullanılarak precision korunur.
 
Selamlar. Claude mükemmel bir şeymiş. Gerçekten işten güçten dolayı böyle nimetlerden uzak kalmışız. Arkadaşlar Claude'a yaptırıp siteme entegre ettim. Dersolay.com.tr sitesinde Öğretmenler Odası sekmesinde mevcut.