KabaLang örnekleri: konsol, masaüstü ve web için dokuz proje

Konsol: fraktal (paralel şeritli 24-bit Mandelbrot/Julia + yakınlaşma),
sudoku (geri izlemeli, canlı animasyon), fatura (JSON → terminal tablosu,
PDF ve Excel).
Masaüstü: hesap makinesi (işlem önceliği, canlı bağlama), odak (Pomodoro),
parola atölyesi (entropi ölçer, SHA-256).
Web: pano (Kanban REST API + SQLite), kisalt (302 yönlendirme, SVG
istatistik), anket (adres başına tek oy, sunucuda çizilen grafik).

Hepsi `kabalang calistir` ile derlenip çalışır; web uygulamaları yalnız
127.0.0.1'i dinler, SQL parametre bağlamalı, HTML çıktısı kaçırılır.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
2026-10-02 22:31:40 +03:00
co-authored by Claude Opus 5.5
commit ed201188fb
39 changed files with 2650 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
# Hesap Makinesi
İşlem önceliğini bilen, geçmişini tutan masaüstü hesap makinesi.
Hesaplama motoru dahil her satırı KabaLang.
![Hesap Makinesi](../../medya/hesap-makinesi.png)
```bash
kabalang calistir hesap-makinesi.kbl
```
## Neyi gösteriyor
| Özellik | Nerede |
|---|---|
| **İki yığınlı ifade değerlendirici**: `2+3×4` → `14` | `hesapla()` |
| `sayilabilir Islem` ile kapalı işlem kümesi | dosyanın başı |
| **Canlı bağlama**: `Ekran.metin = canli_sonuc(Ifade.metin)` | `etiket Ekran` |
| Hata yakalama: `1÷0` çökmez, ekranda `Tanımsız` yazar | `canli_sonuc()` |
| Türkçe sayı biçimi: `1.234.567,5` | `bicimle()`, `binlik()` |
| Geçmişten satır seçince sonucu yeniden kullanma | `liste Gecmis` → `secildiginde` |
| `izinler:` ile ağa çıkmadığını beyan etme (derleme anında denetlenir) | dosyanın başı |
Ekran hiçbir yerde elle güncellenmiyor. Tuşlar yalnız ifadeyi değiştiriyor,
ekran bağlı olduğu için kendini yeniliyor.
+337
View File
@@ -0,0 +1,337 @@
# ╔══════════════════════════════════════════════════════════════╗
# ║ KabaLang Hesap Makinesi ║
# ║ İşlem önceliğini bilen, geçmişini tutan bir masaüstü ║
# ║ hesap makinesi. Hesaplama motoru baştan sona KabaLang. ║
# ╚══════════════════════════════════════════════════════════════╝
#
# Çalıştır: kabalang calistir hesap-makinesi.kbl
kullan kaba.arayuz
kullan kaba.sistem
izinler:
ag_erisim = yanlis
# ── 1. HESAP MOTORU ───────────────────────────────────────────────
# İşlem türleri kapalı bir küme: derleyici yanlış üyeyi yakalar.
sayilabilir Islem:
TOPLA
CIKAR
CARP
BOL
fonksiyon oncelik(i: Islem) -> sayi:
eger i == Islem.CARP veya i == Islem.BOL:
don 2
don 1
fonksiyon uygula(a: ondalik, b: ondalik, i: Islem) -> ondalik:
eger i == Islem.TOPLA:
don a + b
degilse eger i == Islem.CIKAR:
don a - b
degilse eger i == Islem.CARP:
don a * b
don a / b
fonksiyon islem_mi(c: metin) -> mantik:
don "+−×÷".icerir(c)
fonksiyon islem_coz(c: metin) -> Islem:
eger c == "+":
don Islem.TOPLA
degilse eger c == "−":
don Islem.CIKAR
degilse eger c == "×":
don Islem.CARP
don Islem.BOL
# İki yığınlı değerlendirici: sayılar bir yığına, işlemler öbürüne.
# Yeni gelen işlemin önceliği düşükse, yığındaki güçlü işlemler önce yapılır.
fonksiyon hesapla(ifade: metin) -> ondalik:
sayilar = [0.0]
sayilar.sil(0)
islemler = [Islem.TOPLA]
islemler.sil(0)
i = 0
iken i < ifade.uzunluk():
c = ifade.parca(i, 1)
eksi_basta = c == "−" ve (i == 0 veya islem_mi(ifade.parca(i - 1, 1)))
eger islem_mi(c) ve degil eksi_basta:
yeni = islem_coz(c)
iken islemler.uzunluk() > 0 ve oncelik(islemler[islemler.uzunluk() - 1]) >= oncelik(yeni):
b = sayilar[sayilar.uzunluk() - 1]
sayilar.sil(sayilar.uzunluk() - 1)
a = sayilar[sayilar.uzunluk() - 1]
sayilar.sil(sayilar.uzunluk() - 1)
sayilar.ekle(uygula(a, b, islemler[islemler.uzunluk() - 1]))
islemler.sil(islemler.uzunluk() - 1)
islemler.ekle(yeni)
i = i + 1
devam
bas = i
i = i + 1
iken i < ifade.uzunluk() ve degil islem_mi(ifade.parca(i, 1)):
i = i + 1
sayi_metni = ifade.parca(bas, i - bas).degistir("−", "-").degistir(",", ".")
sayilar.ekle(ondalik(sayi_metni))
iken islemler.uzunluk() > 0:
b = sayilar[sayilar.uzunluk() - 1]
sayilar.sil(sayilar.uzunluk() - 1)
a = sayilar[sayilar.uzunluk() - 1]
sayilar.sil(sayilar.uzunluk() - 1)
sayilar.ekle(uygula(a, b, islemler[islemler.uzunluk() - 1]))
islemler.sil(islemler.uzunluk() - 1)
don sayilar[0]
# ── 2. SAYIYI GÜZEL YAZMAK ────────────────────────────────────────
# 1234567.5 → "1.234.567,5" (Türkçe binlik ve ondalık ayırıcı)
fonksiyon binlik(tam: metin) -> metin:
eksi = tam.ile_baslar("-")
eger eksi:
tam = tam.parca(1, tam.uzunluk() - 1)
sonuc = ""
sayac = 0
i = tam.uzunluk() - 1
iken i >= 0:
eger sayac > 0 ve sayac % 3 == 0:
sonuc = "." + sonuc
sonuc = tam.parca(i, 1) + sonuc
sayac = sayac + 1
i = i - 1
eger eksi:
don "−" + sonuc
don sonuc
fonksiyon bicimle(x: ondalik) -> metin:
ham = f"{x:.8f}"
nokta = ham.bul(".")
tam = ham.parca(0, nokta)
kesir = ham.parca(nokta + 1, ham.uzunluk() - nokta - 1)
iken kesir.ile_biter("0"):
kesir = kesir.parca(0, kesir.uzunluk() - 1)
eger tam == "-0" ve kesir == "":
tam = "0"
eger kesir == "":
don binlik(tam)
don binlik(tam) + "," + kesir
# Ekrandaki "1.234,5" biçimini motorun okuduğu "1234,5" biçimine çevirir.
fonksiyon ham_sayi(gorunen: metin) -> metin:
don gorunen.degistir(".", "")
# ── 3. TUŞ MANTIĞI ────────────────────────────────────────────────
fonksiyon son_karakter(m: metin) -> metin:
eger m.uzunluk() == 0:
don ""
don m.parca(m.uzunluk() - 1, 1)
# Arka arkaya iki işlem tuşu: sonuncusu öncekinin yerine geçer.
fonksiyon ifadeye_ekle(ifade: metin, tus: metin) -> metin:
eger islem_mi(tus):
eger ifade == "":
eger tus == "−":
don "−"
don ""
eger islem_mi(son_karakter(ifade)):
don ifade.parca(0, ifade.uzunluk() - 1) + tus
eger tus == ",":
# Aynı sayıda ikinci virgül olmaz
i = ifade.uzunluk() - 1
iken i >= 0 ve degil islem_mi(ifade.parca(i, 1)):
eger ifade.parca(i, 1) == ",":
don ifade
i = i - 1
eger ifade == "" veya islem_mi(son_karakter(ifade)):
don ifade + "0,"
don ifade + tus
# Sondaki yarım işlemi at: "12+" → "12"
fonksiyon temiz_ifade(ifade: metin) -> metin:
iken ifade != "" ve islem_mi(son_karakter(ifade)):
ifade = ifade.parca(0, ifade.uzunluk() - 1)
don ifade
# Ekranın göstereceği metin. Sıfıra bölme gibi hatalar burada yakalanır.
fonksiyon canli_sonuc(ifade: metin) -> metin:
ifade = temiz_ifade(ifade)
eger ifade == "" veya ifade == "−":
don "0"
dene:
don bicimle(hesapla(ifade))
yakala h:
don "Tanımsız"
fonksiyon yuzde(ifade: metin) -> metin:
sonuc = canli_sonuc(ifade)
eger sonuc == "Tanımsız":
don ifade
don ham_sayi(bicimle(hesapla(ham_sayi(sonuc)) / 100.0))
# ± tuşu: o anki sonucun işaretini çevirir
fonksiyon isaret(ifade: metin) -> metin:
eger canli_sonuc(ifade) == "Tanımsız" veya temiz_ifade(ifade) == "":
don ifade
don ham_sayi(bicimle(0.0 - hesapla(temiz_ifade(ifade))))
ilk_acilis = dogru
pencere HesapMakinesi:
baslik = "KabaLang Hesap Makinesi"
genislik = 840
yukseklik = 660
tema = "koyu"
yatay_kutu Govde:
dikey_kutu SolTaraf:
etiket Ifade:
metin = ""
stil = "font-size: 20px; color: #7d8aa8; padding: 8px 6px 0px 6px; min-height: 28px;"
# Ekran BAĞLIDIR: ifade her değiştiğinde sonuç kendiliğinden yenilenir.
etiket Ekran:
metin = canli_sonuc(Ifade.metin)
stil = "font-size: 60px; font-weight: 800; color: #ffffff; padding: 0px 6px 14px 6px;"
yatay_kutu Satir1:
dugme Temizle:
metin = "C"
stil = "font-size: 20px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: none; background: #1a2030; color: #22d3ee;"
tiklandiginda:
Ifade.metin = ""
dugme Sil:
metin = "⌫"
stil = "font-size: 20px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: none; background: #1a2030; color: #22d3ee;"
tiklandiginda:
eger Ifade.metin.uzunluk() > 0:
Ifade.metin = Ifade.metin.parca(0, Ifade.metin.uzunluk() - 1)
dugme Yuzde:
metin = "%"
stil = "font-size: 20px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: none; background: #1a2030; color: #22d3ee;"
tiklandiginda:
Ifade.metin = yuzde(Ifade.metin)
dugme Bol:
metin = "÷"
stil = "font-size: 26px; font-weight: 700; min-height: 68px; min-width: 92px; border-radius: 16px; border: none; background: #1d2a4d; color: #7fb0ff;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "÷")
yatay_kutu Satir2:
dugme Yedi:
metin = "7"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "7")
dugme Sekiz:
metin = "8"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "8")
dugme Dokuz:
metin = "9"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "9")
dugme Carp:
metin = "×"
stil = "font-size: 26px; font-weight: 700; min-height: 68px; min-width: 92px; border-radius: 16px; border: none; background: #1d2a4d; color: #7fb0ff;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "×")
yatay_kutu Satir3:
dugme Dort:
metin = "4"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "4")
dugme Bes:
metin = "5"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "5")
dugme Alti:
metin = "6"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "6")
dugme Cikar:
metin = "−"
stil = "font-size: 26px; font-weight: 700; min-height: 68px; min-width: 92px; border-radius: 16px; border: none; background: #1d2a4d; color: #7fb0ff;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "−")
yatay_kutu Satir4:
dugme Bir:
metin = "1"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "1")
dugme Iki:
metin = "2"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "2")
dugme Uc:
metin = "3"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "3")
dugme Topla:
metin = "+"
stil = "font-size: 26px; font-weight: 700; min-height: 68px; min-width: 92px; border-radius: 16px; border: none; background: #1d2a4d; color: #7fb0ff;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "+")
yatay_kutu Satir5:
dugme Isaret:
metin = "±"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = isaret(Ifade.metin)
dugme Sifir:
metin = "0"
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, "0")
dugme Virgul:
metin = ","
stil = "font-size: 24px; font-weight: 600; min-height: 68px; min-width: 92px; border-radius: 16px; border: 1px solid #1c2336; background: #121829; color: #e6e9f2;"
tiklandiginda:
Ifade.metin = ifadeye_ekle(Ifade.metin, ",")
dugme Esittir:
metin = "="
stil = "font-size: 26px; font-weight: 800; min-height: 68px; min-width: 92px; border-radius: 16px; border: none; background: #377ef4; color: #ffffff;"
tiklandiginda:
sonuc = canli_sonuc(Ifade.metin)
eger sonuc != "Tanımsız" ve Ifade.metin != ham_sayi(sonuc):
Gecmis.ekle(temiz_ifade(Ifade.metin) + " = " + sonuc)
Ifade.metin = ham_sayi(sonuc)
dikey_kutu SagTaraf:
etiket GecmisBasligi:
metin = "Geçmiş"
stil = "font-size: 17px; font-weight: 700; color: #22d3ee; padding: 6px 4px;"
liste Gecmis:
stil = "font-size: 18px; color: #c9d1e6; background: #0d1220; border: 1px solid #1c2336; border-radius: 12px; padding: 8px; min-width: 330px; max-width: 360px;"
secildiginde:
# Geçmişten bir satır seçince sonucu yeniden kullan
satir = Gecmis.secili_metin
eger satir.icerir(" = "):
parcalar = satir.bol(" = ")
Ifade.metin = ham_sayi(parcalar[1])
dugme GecmisiTemizle:
metin = "Geçmişi temizle"
stil = "font-size: 14px; min-height: 36px; border-radius: 10px; border: 1px solid #1c2336; background: #0d1220; color: #7d8aa8;"
tiklandiginda:
Gecmis.temizle()
# Açılışta geçmişe, işlem önceliğini gösteren örnekler düşer.
zamanlayici 50ms:
eger ilk_acilis:
ilk_acilis = yanlis
dongu ornek icinde ["2+3×4", "100−20÷4×3", "−15+40×2", "99,9×3", "22÷7", "1250×12−2500"]:
Gecmis.ekle(ornek + " = " + bicimle(hesapla(ornek)))
Ifade.metin = "1250×12−2500"
+26
View File
@@ -0,0 +1,26 @@
# Odak — Pomodoro zamanlayıcı
Odaklan, mola ver, günün oturumlarını kaydet. Oturum bitince masaüstü
bildirimi gelir.
![Odak](../../medya/odak.png)
```bash
kabalang calistir odak.kbl
ODAK_DENEME=1 kabalang calistir odak.kbl # deneme kipi: 1 dakika = 1 saniye
```
Görüntüdeki iki kayıt (25 dk odak + 5 dk mola) ve yarıya gelmiş oturum
deneme kipinde **gerçekten koşulup** kaydedilmiştir.
## Neyi gösteriyor
| Özellik | Nerede |
|---|---|
| `zamanlayici 1000ms:` ile saniyede bir güncellenen arayüz | pencerenin sonu |
| `sayilabilir Kip` (odak / mola) | dosyanın başı |
| f-string biçimi: `f"{dk:02d}:{sn:02d}"` → `07:05` | `saat_metni()` |
| **Canlı bağlama**: `"Şu an: " + GorevGirdisi.metin` | `etiket Baslik` |
| `acilir_liste` ile süre seçimi, metinden sayı ayrıştırma | `dakika_coz()` |
| `ilerleme_cubugu`, masaüstü bildirimi | zamanlayıcı bloğu |
| Ortam değişkeniyle deneme kipi | `cevre.al("ODAK_DENEME")` |
+155
View File
@@ -0,0 +1,155 @@
# ╔══════════════════════════════════════════════════════════════╗
# ║ Odak — KabaLang ile yazılmış Pomodoro zamanlayıcısı ║
# ║ Odaklan, mola ver, günün oturumlarını kaydet. ║
# ╚══════════════════════════════════════════════════════════════╝
#
# Çalıştır: kabalang calistir odak.kbl
# Deneme kipi: ODAK_DENEME=1 kabalang calistir odak.kbl
# (1 dakika 1 saniye sürer — sunum ve sınama için)
kullan kaba.arayuz
kullan kaba.sistem
izinler:
ag_erisim = yanlis
# ── Oturum türleri ────────────────────────────────────────────────
sayilabilir Kip:
ODAK
MOLA
fonksiyon dakika_coz(secim: metin) -> sayi:
# "Odak · 25 dk" → 25
parca = secim.bol(" · ")[1]
don sayi(parca.degistir(" dk", ""))
fonksiyon kip_coz(secim: metin) -> Kip:
eger secim.icerir("mola"):
don Kip.MOLA
don Kip.ODAK
# 1500 → "25:00"
fonksiyon saat_metni(saniye: sayi) -> metin:
dk = saniye // 60
sn = saniye % 60
don f"{dk:02d}:{sn:02d}"
fonksiyon durum_metni(k: Kip, calisiyor: mantik) -> metin:
eger degil calisiyor:
don "Hazır olduğunda başlat"
eger k == Kip.MOLA:
don "☕ Mola — biraz nefes al"
don "● Odaklanılıyor"
# ── Durum ─────────────────────────────────────────────────────────
saniye_carpani = 1
eger cevre.al("ODAK_DENEME") == "1":
saniye_carpani = 60
toplam = 25 * 60
kalan = toplam
kip = Kip.ODAK
calisiyor = yanlis
oturum_sayisi = 0
odak_dakikasi = 0
pencere Odak:
baslik = "Odak — Pomodoro"
genislik = 900
yukseklik = 620
tema = "koyu"
yatay_kutu Govde:
dikey_kutu Zamanlayici:
girdi GorevGirdisi:
metin = "KabaLang örnekleri"
ipucu = "Ne üzerinde çalışıyorsun?"
stil = "font-size: 17px; padding: 10px 12px; border-radius: 10px; border: 1px solid #1c2336; background: #0d1220; color: #e6e9f2;"
# Canlı bağlama: yukarıdaki girdiye yazdıkça bu satır kendiliğinden değişir.
etiket Baslik:
metin = "Şu an: " + GorevGirdisi.metin
stil = "font-size: 20px; font-weight: 700; color: #22d3ee; padding: 2px 4px 6px 4px;"
acilir_liste Secim:
secenekler = ["Odak · 25 dk", "Derin çalışma · 50 dk", "Kısa mola · 5 dk", "Uzun mola · 15 dk"]
stil = "font-size: 17px; padding: 8px 12px; border-radius: 10px; background: #121829; color: #e6e9f2;"
degistiginde:
eger degil calisiyor:
kip = kip_coz(Secim.secili_metin)
toplam = dakika_coz(Secim.secili_metin) * 60
kalan = toplam
Sayac.metin = saat_metni(kalan)
Ilerleme.deger = 0
etiket Sayac:
metin = "25:00"
stil = "font-size: 112px; font-weight: 800; color: #ffffff; padding: 10px 0px 0px 6px;"
etiket Durum:
metin = "Hazır olduğunda başlat"
stil = "font-size: 18px; color: #9ece6a; padding: 0px 8px 10px 8px;"
ilerleme_cubugu Ilerleme:
deger = 0
stil = "font-size: 14px; min-height: 22px; border-radius: 11px; background: #121829; color: #e6e9f2;"
yatay_kutu Dugmeler:
dugme Baslat:
metin = "Başlat"
stil = "font-size: 19px; font-weight: 700; min-height: 54px; border-radius: 14px; border: none; background: #377ef4; color: #ffffff;"
tiklandiginda:
calisiyor = degil calisiyor
eger calisiyor:
Baslat.metin = "Duraklat"
degilse:
Baslat.metin = "Sürdür"
Durum.metin = durum_metni(kip, calisiyor)
dugme Sifirla:
metin = "Sıfırla"
stil = "font-size: 19px; font-weight: 600; min-height: 54px; border-radius: 14px; border: 1px solid #1c2336; background: #121829; color: #c9d1e6;"
tiklandiginda:
calisiyor = yanlis
kalan = toplam
Sayac.metin = saat_metni(kalan)
Ilerleme.deger = 0
Baslat.metin = "Başlat"
Durum.metin = durum_metni(kip, calisiyor)
dikey_kutu Gunluk:
etiket GunlukBasligi:
metin = "Bugün"
stil = "font-size: 20px; font-weight: 700; color: #22d3ee; padding: 6px 4px;"
etiket Ozet:
metin = "0 oturum · 0 dk odak"
stil = "font-size: 26px; font-weight: 800; color: #ffffff; padding: 2px 4px 10px 4px;"
liste Oturumlar:
stil = "font-size: 17px; color: #c9d1e6; background: #0d1220; border: 1px solid #1c2336; border-radius: 12px; padding: 8px; min-width: 330px;"
# Saniyede bir: geri say, çubuğu ilerlet, bitince kaydet ve haber ver.
zamanlayici 1000ms:
eger calisiyor:
kalan = kalan - saniye_carpani
eger kalan < 0:
kalan = 0
Sayac.metin = saat_metni(kalan)
Ilerleme.deger = (toplam - kalan) * 100 // toplam
eger kalan == 0:
calisiyor = yanlis
dakika = toplam // 60
eger kip == Kip.ODAK:
oturum_sayisi = oturum_sayisi + 1
odak_dakikasi = odak_dakikasi + dakika
Oturumlar.ekle(f"✓ {zaman.saat().parca(0, 5)} {GorevGirdisi.metin} · {dakika} dk")
sistem.bildirim("Odak", "Oturum bitti! Kısa bir mola hak ettin.")
degilse:
Oturumlar.ekle(f"☕ {zaman.saat().parca(0, 5)} Mola · {dakika} dk")
sistem.bildirim("Odak", "Mola bitti, kaldığın yerden devam.")
Ozet.metin = f"{oturum_sayisi} oturum · {odak_dakikasi} dk odak"
kalan = toplam
Sayac.metin = saat_metni(kalan)
Baslat.metin = "Başlat"
Durum.metin = "Tamamlandı — yenisine hazır"
+32
View File
@@ -0,0 +1,32 @@
# Parola Atölyesi
Güçlü parola üret, gücünü entropiyle ölç, SHA-256 özetini çıkar. Sağdaki
ölçer siz yazdıkça canlı çalışır.
![Parola Atölyesi](../../medya/parola-atolyesi-ilk.png)
![Canlı ölçüm](../../medya/parola-atolyesi.png)
```bash
kabalang calistir parola-atolyesi.kbl
```
## Neyi gösteriyor
| Özellik | Nerede |
|---|---|
| **log₂'yi kendimiz hesaplıyoruz**: tam kısım bölmeyle, kesir kısmı kare alma yöntemiyle | `log2()` |
| Entropi = uzunluk × log₂(havuz) | `entropi()` |
| Seçilen her türden en az bir karakter (yeniden üretme yöntemi) | `parola_uret()` |
| Yaygın kalıp denetimi: `Ankara1923!` güçlü **görünür** ama değildir | `yaygin_kalip()` |
| **Canlı bağlama — fonksiyon çağrısıyla**: hem metin hem renk | `etiket DenemeSonucu` |
| Sürgüye bağlı etiket: `"Uzunluk: " + metin(Uzunluk.deger)` | `etiket UzunlukYazisi` |
| `kripto.sha256`, `tablo`, `onay_kutusu`, `kaydirici` | sol sütun |
| Geçmişte parolanın tamamı gösterilmez (`qP.~••••`) | `maskele()` |
## Dürüst notlar
- Yazılan parola için ölçülen değer bir **üst sınırdır** (`≤`): karakter
türlerinden hesaplanır, sözcük seçimini bilemez.
- Üretimde `rastgele` modülü kullanılır. Bu modül kriptografik bir rastgelelik
kaynağı değildir; örnek eğitim amaçlıdır. Gerçek parolalarınız için
kriptografik kaynak kullanan bir parola yöneticisi tercih edin.
+329
View File
@@ -0,0 +1,329 @@
# ╔══════════════════════════════════════════════════════════════╗
# ║ Parola Atölyesi ║
# ║ Güçlü parola üret, gücünü entropiyle ölç, özetini çıkar. ║
# ║ Entropi hesabı (log₂ dahil) baştan sona KabaLang. ║
# ╚══════════════════════════════════════════════════════════════╝
#
# Çalıştır: kabalang calistir parola-atolyesi.kbl
kullan kaba.arayuz
kullan kaba.sistem
kullan kaba.kripto
# Ağa çıkmaz, diske yazmaz: bu beyan derleme anında denetlenir.
izinler:
ag_erisim = yanlis
# ── 1. KARAKTER HAVUZLARI ─────────────────────────────────────────
KUCUK = "abcdefghijklmnopqrstuvwxyz"
BUYUK = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
RAKAM = "0123456789"
SEMBOL = "!@#$%^&*()-_=+[]{};:,.<>/?~"
BENZER = "0Oo1lI|"
# Metni harf listesine ayırır (Türkçe harfler tek harf sayılır).
fonksiyon harfler(m: metin) -> liste<metin>:
sonuc = [""]
sonuc.sil(0)
i = 0
iken i < m.uzunluk():
sonuc.ekle(m.parca(i, 1))
i = i + 1
don sonuc
fonksiyon benzerleri_cikar(havuz: metin) -> metin:
sonuc = ""
dongu c icinde harfler(havuz):
eger degil BENZER.icerir(c):
sonuc = sonuc + c
don sonuc
fonksiyon havuz_kur(kucuk: mantik, buyuk: mantik, rakam: mantik, sembol: mantik, sade: mantik) -> metin:
h = ""
eger kucuk:
h = h + KUCUK
eger buyuk:
h = h + BUYUK
eger rakam:
h = h + RAKAM
eger sembol:
h = h + SEMBOL
eger sade:
h = benzerleri_cikar(h)
don h
# ── 2. ENTROPİ: log₂'yi kendimiz hesaplıyoruz ─────────────────────
# Tam kısım: 2'ye bölerek sayılır. Kesir kısmı: kare alma yöntemiyle,
# her adımda bir ikili basamak (bit) bulunur.
fonksiyon log2(x: ondalik) -> ondalik:
tam = 0.0
iken x >= 2.0:
x = x / 2.0
tam = tam + 1.0
kesir = 0.0
adim = 0.5
dongu i icinde 1..24:
x = x * x
eger x >= 2.0:
x = x / 2.0
kesir = kesir + adim
adim = adim / 2.0
don tam + kesir
fonksiyon entropi(uzunluk: sayi, havuz_boyu: sayi) -> sayi:
eger havuz_boyu < 2:
don 0
don sayi(matematik.taban(ondalik(uzunluk) * log2(ondalik(havuz_boyu))))
# Kullanıcının yazdığı parolanın havuzunu, içerdiği karakter türlerinden tahmin et.
fonksiyon tahmini_havuz(p: metin) -> sayi:
var_kucuk = yanlis
var_buyuk = yanlis
var_rakam = yanlis
var_sembol = yanlis
dongu c icinde harfler(p):
eger KUCUK.icerir(c):
var_kucuk = dogru
degilse eger BUYUK.icerir(c):
var_buyuk = dogru
degilse eger RAKAM.icerir(c):
var_rakam = dogru
degilse:
var_sembol = dogru
toplam = 0
eger var_kucuk:
toplam = toplam + 26
eger var_buyuk:
toplam = toplam + 26
eger var_rakam:
toplam = toplam + 10
eger var_sembol:
toplam = toplam + 33
don toplam
sayilabilir Guc:
ZAYIF
ORTA
GUCLU
COK_GUCLU
fonksiyon guc(bit: sayi) -> Guc:
eger bit < 40:
don Guc.ZAYIF
degilse eger bit < 60:
don Guc.ORTA
degilse eger bit < 90:
don Guc.GUCLU
don Guc.COK_GUCLU
fonksiyon guc_adi(g: Guc) -> metin:
eger g == Guc.ZAYIF:
don "Zayıf"
degilse eger g == Guc.ORTA:
don "Orta"
degilse eger g == Guc.GUCLU:
don "Güçlü"
don "Çok güçlü"
fonksiyon guc_rengi(g: Guc) -> metin:
eger g == Guc.ZAYIF:
don "#f7768e"
degilse eger g == Guc.ORTA:
don "#e0af68"
degilse eger g == Guc.GUCLU:
don "#9ece6a"
don "#22d3ee"
fonksiyon guc_yuzde(bit: sayi) -> sayi:
eger bit >= 128:
don 100
don bit * 100 // 128
# Saldırganların ilk denediği kalıplar. Bunlardan biri varsa
# karakter çeşitliliği yanıltıcıdır: "Ankara1923!" güçlü GÖRÜNÜR.
YAYGIN_KALIPLAR = ["123456", "qwerty", "parola", "sifre", "password", "admin",
"ankara", "istanbul", "izmir", "1923", "1453", "galatasaray",
"fenerbahce", "besiktas", "trabzon", "asdf", "1234", "0000"]
fonksiyon yaygin_kalip(p: metin) -> metin:
kucuk = p.kucult()
dongu k icinde YAYGIN_KALIPLAR:
eger kucuk.icerir(k):
don k
don ""
fonksiyon olcum_biti(p: metin) -> sayi:
bit = entropi(p.uzunluk(), tahmini_havuz(p))
eger yaygin_kalip(p) != "":
bit = bit // 3
don bit
# Yazılan parolada ölçtüğümüz şey bir ÜST SINIRDIR: karakter türlerinden
# hesaplanır, sözcük seçimini bilemez. Bu yüzden "≤" ile gösterilir.
fonksiyon olcum_metni(p: metin) -> metin:
eger p == "":
don "Bir parola yaz, gücünü canlı ölçelim"
bit = olcum_biti(p)
kalip = yaygin_kalip(p)
eger kalip != "":
don f"{guc_adi(guc(bit))} · ≤{bit} bit · tahmin edilebilir: \"{kalip}\""
don f"{guc_adi(guc(bit))} · ≤{bit} bit · {p.uzunluk()} karakter"
fonksiyon olcum_stili(p: metin) -> metin:
don f"font-size: 17px; font-weight: 700; color: {guc_rengi(guc(olcum_biti(p)))}; padding: 4px 2px 12px 2px;"
# Geçmişte parolanın tamamı gösterilmez: "qP.~z{2x" → "qP.~••••"
fonksiyon maskele(p: metin) -> metin:
eger p.uzunluk() <= 4:
don "••••"
don p.parca(0, 4) + "••••"
# ── 3. ÜRETİM ─────────────────────────────────────────────────────
fonksiyon tur_var_mi(p: metin, havuz: metin) -> mantik:
dongu c icinde harfler(p):
eger havuz.icerir(c):
don dogru
don yanlis
# Seçilen her türden en az bir karakter gelene kadar yeniden üret.
# (Eksik karakteri sonradan yerleştirmek yerine baştan üretmek
# dağılımı bozmaz.)
fonksiyon parola_uret(uzunluk: sayi, kucuk: mantik, buyuk: mantik, rakam: mantik, sembol: mantik, sade: mantik) -> metin:
havuz = havuz_kur(kucuk, buyuk, rakam, sembol, sade)
eger havuz == "":
don ""
iken dogru:
p = rastgele.metin(uzunluk, havuz)
tamam = dogru
eger kucuk ve degil tur_var_mi(p, KUCUK):
tamam = yanlis
eger buyuk ve degil tur_var_mi(p, BUYUK):
tamam = yanlis
eger rakam ve degil tur_var_mi(p, RAKAM):
tamam = yanlis
eger sembol ve degil tur_var_mi(p, SEMBOL):
tamam = yanlis
eger tamam:
don p
don ""
ilk_acilis = dogru
pencere ParolaAtolyesi:
baslik = "Parola Atölyesi"
genislik = 980
yukseklik = 680
tema = "koyu"
yatay_kutu Govde:
# ── SOL: üretici ──────────────────────────────────────────
dikey_kutu Uretici:
etiket Baslik:
metin = "Yeni parola"
stil = "font-size: 22px; font-weight: 800; color: #ffffff; padding: 4px 2px;"
kaydirici Uzunluk:
min = 8
max = 64
deger = 20
# Canlı bağlama: sürgü hareket ettikçe yazı kendiliğinden güncellenir.
etiket UzunlukYazisi:
metin = "Uzunluk: " + metin(Uzunluk.deger) + " karakter"
stil = "font-size: 16px; color: #22d3ee; padding: 0px 2px 6px 2px;"
onay_kutusu Kucuk:
metin = "Küçük harf (a–z)"
secili = dogru
stil = "font-size: 16px; color: #c9d1e6;"
onay_kutusu Buyuk:
metin = "Büyük harf (A–Z)"
secili = dogru
stil = "font-size: 16px; color: #c9d1e6;"
onay_kutusu Rakam:
metin = "Rakam (0–9)"
secili = dogru
stil = "font-size: 16px; color: #c9d1e6;"
onay_kutusu Sembol:
metin = "Sembol (!@#$…)"
secili = dogru
stil = "font-size: 16px; color: #c9d1e6;"
onay_kutusu Sade:
metin = "Karışan karakterleri çıkar (0 O o 1 l I)"
secili = dogru
stil = "font-size: 16px; color: #c9d1e6;"
dugme Uret:
metin = "Parola üret"
stil = "font-size: 19px; font-weight: 700; min-height: 54px; border-radius: 14px; border: none; background: #377ef4; color: #ffffff;"
tiklandiginda:
p = parola_uret(Uzunluk.deger, Kucuk.secili, Buyuk.secili, Rakam.secili, Sembol.secili, Sade.secili)
eger p == "":
uyari_kutusu("Parola Atölyesi", "En az bir karakter türü seçin.")
degilse:
bit = entropi(p.uzunluk(), havuz_kur(Kucuk.secili, Buyuk.secili, Rakam.secili, Sembol.secili, Sade.secili).uzunluk())
g = guc(bit)
Parola.metin = p
GucCubugu.deger = guc_yuzde(bit)
GucYazisi.metin = f"{guc_adi(g)} · {bit} bit entropi"
GucYazisi.stil = f"font-size: 17px; font-weight: 700; color: {guc_rengi(g)}; padding: 2px;"
Ozet.metin = "SHA-256 " + kripto.sha256(p).parca(0, 32) + "…"
Gecmis.satir_ekle([zaman.saat(), maskele(p), metin(p.uzunluk()), f"{bit} bit", guc_adi(g)])
etiket Parola:
metin = "—"
stil = "font-size: 21px; font-weight: 700; font-family: monospace; color: #ffffff; background: #0d1220; border: 1px solid #1c2336; border-radius: 12px; padding: 14px;"
ilerleme_cubugu GucCubugu:
deger = 0
stil = "font-size: 13px; min-height: 18px; border-radius: 9px; background: #121829; color: #e6e9f2;"
etiket GucYazisi:
metin = ""
stil = "font-size: 17px; font-weight: 700; color: #9ece6a; padding: 2px;"
etiket Ozet:
metin = ""
stil = "font-size: 14px; font-family: monospace; color: #7d8aa8; padding: 2px;"
# ── SAĞ: ölçer ve geçmiş ──────────────────────────────────
dikey_kutu Olcer:
etiket OlcerBasligi:
metin = "Kendi parolanı ölç"
stil = "font-size: 22px; font-weight: 800; color: #ffffff; padding: 4px 2px;"
girdi Deneme:
metin = "Ankara1923!"
ipucu = "Bir parola yaz…"
stil = "font-size: 18px; font-family: monospace; padding: 10px 12px; border-radius: 10px; border: 1px solid #1c2336; background: #0d1220; color: #e6e9f2;"
# Bağlama bir FONKSİYON ÇAĞRISI da olabilir: her tuşta yeniden ölçülür.
etiket DenemeSonucu:
metin = olcum_metni(Deneme.metin)
stil = olcum_stili(Deneme.metin)
etiket GecmisBasligi:
metin = "Bu oturumda üretilenler"
stil = "font-size: 17px; font-weight: 700; color: #22d3ee; padding: 6px 2px;"
tablo Gecmis:
sutunlar = ["Saat", "Parola", "Uzunluk", "Entropi", "Güç"]
stil = "font-size: 15px;"
# Açılışta üç gerçek parola üretilir: farklı uzunluk ve türlerle.
zamanlayici 50ms:
eger ilk_acilis:
ilk_acilis = yanlis
dongu ayar icinde [12, 16, 32]:
p = parola_uret(ayar, dogru, dogru, dogru, ayar != 16, dogru)
bit = entropi(p.uzunluk(), havuz_kur(dogru, dogru, dogru, ayar != 16, dogru).uzunluk())
Gecmis.satir_ekle([zaman.saat(), maskele(p), metin(p.uzunluk()), f"{bit} bit", guc_adi(guc(bit))])
p = parola_uret(Uzunluk.deger, Kucuk.secili, Buyuk.secili, Rakam.secili, Sembol.secili, Sade.secili)
bit = entropi(p.uzunluk(), havuz_kur(Kucuk.secili, Buyuk.secili, Rakam.secili, Sembol.secili, Sade.secili).uzunluk())
g = guc(bit)
Parola.metin = p
GucCubugu.deger = guc_yuzde(bit)
GucYazisi.metin = f"{guc_adi(g)} · {bit} bit entropi"
GucYazisi.stil = f"font-size: 17px; font-weight: 700; color: {guc_rengi(g)}; padding: 2px;"
Ozet.metin = "SHA-256 " + kripto.sha256(p).parca(0, 32) + "…"
Gecmis.satir_ekle([zaman.saat(), maskele(p), metin(p.uzunluk()), f"{bit} bit", guc_adi(g)])