Files
deste-hearthstone-linux-tra…/README.tr.md
T
yusufipk be88b5f65e readme: add the match history screenshot, and the icon in the title
The window shot is cropped to the window frame and saved as webp (70 KB).
assets/deste.svg is reused as a small logo next to the heading.
2026-07-28 00:21:44 +07:00

11 KiB
Raw Blame History

deste

English | Türkçe

Linux (KDE Wayland) için Hearthstone deck tracker.

Oyunun kendi log dosyalarını okur: ekran yakalama yok, görüntü tanıma yok, bellek okuma yok. Yeni set çıktığında kod değil sadece kart verisi güncellenir. Kişisel ihtiyaçtan doğdu, Arena Tracker'ın Qt5 + OpenCV mimarisi hem bakımsız hem de her yamada kırılıyordu.

maç sırasında deste

maç geçmişi ve kazanma oranı

Şu an ne yapıyor

  • Kendi destem: kalan kartlar mana sırasına göre, adetleriyle. Çekilen kart listeden düşmez, solgunlaşır: "bunu oynadım" bilgisi görünür kalır.
  • Çekme yüzdesi: her kartın bir sonraki çekişte gelme olasılığı.
  • Rakip: oynadığı ve açığa çıkan kartlar, elindeki ve destesinde kalan kart sayısı.
  • Deste seçimi kendiliğinden: deste kodu yapıştırmaya gerek yok, oyunun çevrimdışı önbelleğindeki desteler okunuyor ve maçtaki sınıfa göre eşleşen deste seçiliyor. Menüden elle de seçilebilir.
  • Maç geçmişi ve winrate: biten her maç küçük bir sqlite dosyasına yazılıyor (mod, deste, iki sınıf, sonuç, tur sayısı), menüsündeki pencere desteye ve rakip sınıfına göre galibiyet oranını gösteriyor.
  • Kart görselleri: satırın arka planında kartın sanatı, üzerine gelince kartın tam görseli (metni de görselin üstünde).
  • Ayarlanabilir saydamlık, overlay (çerçevesiz, üstte) ve normal pencere modu, sistem tepsisi ikonu, masaüstü kısayolu.
  • Türkçe ve İngilizce arayüz, menüden anında değişiyor. Varsayılan olarak sistemin diline bakılır.

Nasıl çalışıyor

Oyun her oturumda Logs/Hearthstone_YYYY_MM_DD_HH_MM_SS/ altına birkaç log dosyası yazıyor. Bunlardan Power.log maçın tamamını içeriyor: varlıkların yaratılması, bölge geçişleri (deste, el, oyun alanı, mezarlık), tag değişimleri, tur sınırları ve maç sonucu.

Akış şöyle:

Power.log satırı
  -> core/parser_power.py   satırı Event'e çevirir (regex tablosu tek yerde)
  -> core/state.py          olayı oyun durumuna işler (varlık tablosu, bölgeler)
  -> data/decks.py          durumdaki sınıf ve çekilen kartlarla desteyi eşler
  -> ui/window.py           kalan liste, yüzdeler, rakip paneli

core/logtail.py dosyayı offset tutarak takip eder, oyun yeni bir oturum dizini açtığında oraya geçer. core/watcher.py bunu Qt bilmeden çevirir, o yüzden aynı motor terminalden (tools/live.py) veya kayıtlı loglar üstünden (tools/replay.py) da çalışır.

Kart isimleri, maliyetleri ve nadirlikleri HearthstoneJSON'dan bir kere indirilip ~/.cache/deste/ altına yazılır. Kart görselleri de aynı yere, ama yalnızca ihtiyaç duyulduğunda ve arka planda. Ağ yoksa uygulama önbellekle çalışmaya devam eder. Biten maçlar ~/.local/share/deste/history.db içine yazılıyor.

Kurulum

Gereksinim: Python 3.11+, PyQt6. Geri kalan her şey stdlib.

./install.sh                # kısayol, simge, KWin kuralları
./install.sh --no-kwin      # sadece kısayol, pencere yöneticisine dokunma
./install.sh --no-hs-rule   # Hearthstone kuralı olmadan
./install.sh --uninstall    # hepsini geri al

install.sh masaüstü kısayolunu ve simgeyi kurar, wmclass=deste için "her zaman üstte" KWin kuralı yazar ve KWin'e yapılandırmayı yeniden okutur. Hepsi --uninstall ile geri alınır.

Tiling betiği (Krohnkite gibi) kullanıyorsan paneli o betiğin yüzen pencere listesine eklemen gerekir, kurulum betiği başkasının ayarlarına dokunmuyor.

Oyunun logları yazması için iki dosya gerekiyor, ikisi de zaten kuruluysa dokunulmaz:

  • <prefix>/users/<kullanıcı>/AppData/Local/Blizzard/Hearthstone/log.config içinde [Power] Verbose=1, [Zone], [LoadingScreen], [Arena]
  • <oyun dizini>/client.config içinde [Log] FileSizeLimit.Int=-1

Uygulama bunları kendi başına değiştirmez, eksikse uyarır.

Kullanım

./run.sh                  # arayüz (masaüstü kısayolu da bunu çağırır)
python main.py --full     # mevcut oturum logunu baştan okuyup başlat

python -m tools.live      # terminalde canlı takip
python -m tools.replay <log_dizini> --deck   # kayıtlı oturumu baştan oynat
python -m tools.import_history               # eski oturum loglarını geçmişe aktar
python -m tests.test_replay <log_dizini>     # tutarlılık testleri
python -m tests.test_history                 # maç geçmişi testleri

Pencere kapatıldığında uygulama tepsiye iner, tepsi ikonuna tıklayınca geri gelir. Saydamlık, mod değişimi, dil ve deste seçimi menüsünde.

Wayland notları

Oyunun üstünde durmak. KWin'de tam ekran pencereler "aktif katman"a çıkar ve bu katman "her zaman üstte" katmanının da üstündedir. Yani oyun tam ekrandayken hiçbir overlay üstünde duramaz, kural ne olursa olsun. Çözüm oyunun tam ekrana geçmesini engellemek: install.sh Hearthstone için fullscreen=false ve noborder=true kuralı yazar, oyun kenarlıksız pencere olarak ekranı kaplamaya devam eder, görüntü aynıdır, overlay üstte kalabilir. Oyun umu/Proton ile açıldığı için pencere sınıfı steam_app_default, bu sınıf başka oyunlarla ortak olabileceğinden kural başlığa da bakar (Hearthstone).

Konum. Wayland'da uygulama kendi penceresinin ekranda nerede olduğunu bilmez ve kendini taşıyamaz. Panel sürüklenirken startSystemMove() ile taşımayı pencere yöneticisine bırakıyoruz; move() çağırmak pencereyi kıpırdatmadığı gibi Qt'nin konum bilgisini de bozuyor, sonra menüler ve kart önizlemesi ekranın dibine düşüyor. Aynı sebeple ayarlarda yalnızca boyut saklanıyor, konum saklanmıyor. Menü ve önizleme konumları ekran kenarına göre değil pencerenin kendi koordinatlarına göre hesaplanıyor, böylece bilinmeyen kayma sadeleşiyor.

Pencere boyutu. Yerleşimin minimum boyutu pencereye dayatılmıyor (SetNoConstraint), başlık metni kısaltılarak çiziliyor ve tur etiketi sabit genişlikte. Yoksa maç sonucu yazısı geldiğinde panel kendiliğinden genişliyor, kullanıcı her maçtan sonra boyutu düzeltmek zorunda kalıyor.

İkon. Tepsi ikonu bilerek QIcon.fromTheme ile kurulmuyor. Öyle kurulursa Qt sisteme ikonun kendisini değil adını gönderiyor ve Plasma yeni kurulmuş bir ikonu önbelleğinde bulamayınca tepside boş kare çıkıyor. ui/icon.py ikonu her zaman dosyadan ve hazır PNG'lerle kuruyor.

Mimari

core/     saf stdlib, UI ve ağ bilmez, headless test edilebilir
  logdir.py       kurulumu ve log dizinini bul, log.config doğrula
  logtail.py      offset tabanlı dosya takibi
  parser_power.py Power.log satırı -> olay
  state.py        olay -> oyun durumu (varlıklar, bölgeler, deste)
  watcher.py      canlı takip döngüsü (Qt'ye bağımlı değil)
  deckstring.py   deste kodu çöz/kodla
  history.py      maç geçmişi ve winrate (sqlite)
  config.py       kullanıcı ayarları
data/     ağ ve disk önbelleği
  cards.py        HearthstoneJSON kart verisi
  localdecks.py   oyunun çevrimdışı önbelleğinden desteler
  decks.py        deste kütüphanesi ve maça deste eşleştirme
  images.py       kart görselleri (tile ve tam render), arka planda indirir
ui/       PyQt6 arayüz
  window.py       panel, tepsi ikonu, saydamlık, mod yönetimi
  history_window.py  maç geçmişi, desteye ve sınıfa göre winrate
  widgets.py      kart satırı (sanat şeridi) ve hover önizlemesi
  i18n.py         arayüz metinleri, Türkçe ve İngilizce
  theme.py        renkler ve stil
  icon.py         uygulama simgesi
tools/    replay ve terminal canlı takip
tests/    gerçek log korpusu üstünde tutarlılık testleri

Tasarım kararları

Power.log tek doğruluk kaynağı. Zone.log daha okunaklı ama iki dosyayı zaman damgasına göre birleştirmek gereksiz karmaşıklık. Power.log maç sınırlarını, metadatayı ve tüm bölge geçişlerini zaten içeriyor. Zone.log yalnızca testlerde bağımsız doğrulama kaynağı olarak kullanılıyor.

Yalnızca GameState.* satırları işlenir. PowerTaskList.* satırları aynı içeriğin istemci kopyası, ikisi de işlenirse her olay iki kere sayılır.

Olay değil durum sayılır. Log satırları tekrar edebildiği için "her DECK -> HAND satırında sayacı azalt" yaklaşımı yanlış sonuç verir. Her varlığın bölgesi saklanır, sadece gerçek değişimler işlenir.

Deste takibi deste seçiminden bağımsız. Tracker sadece "destemden ne çıktı, desteme ne karıştı" kaydını tutar. Kalan liste istenen an bir deste listesine göre hesaplanır, böylece deste maç ortasında da seçilebilir.

Üretilen kartlar destemden düşmez. Discover, kopyalama veya rastgele üretilen kartlar deste sayacına dokunmaz. Tersine, oyun içinde desteye karıştırılan kartlar listeye eklenir.

Log dosyaları asla silinmez. Sadece okunur.

Maç, sonucu belli olduğu anda geçmişe yazılır, maç nesnesi kapandığında değil: kapanma ancak bir sonraki maç başlayınca oluyor. Benzersiz anahtar oturum dizini ile maçın başlangıç saati, bu yüzden eski loglar aynı veritabanına istendiği kadar tekrar aktarılabilir, kopya oluşmaz.

Doğrulama

tests/test_replay.py uydurma veri kullanmaz, makinedeki gerçek oturum loglarını okur. En kıymetli iki kontrol:

  1. Bağımsız kaynakla çapraz doğrulama: Power.log'dan çıkarılan "çektiğim kartlar" kümesi, Zone.log'daki FRIENDLY DECK -> FRIENDLY HAND geçişleriyle varlık kimliği düzeyinde birebir eşleşmeli.
  2. Kalan liste oyunun sayacıyla tutmalı: hesaplanan kalan deste listesinin boyutu, oyunun kendi DECK bölgesindeki kart sayısına eşit olmalı. Bir çekiş kaçarsa ya da karıştırılan kart sayılmazsa bu test anında kırılır.

6 oturum, 33 maç üstünde çalıştırıldı, hepsi geçiyor.

Pencere yönetimiyle ilgili davranışlar (menü ve önizleme konumu, tiling'e girmemesi) sanal bir KWin oturumunda deneniyor: kwin_wayland --virtual --width 1800 --height 1125. Böylece test ekranda pencere açmıyor.

Yol haritası

Sırada:

  • Rakip arketip tahmini: HSReplay imza kartlarıyla eşleştirip "Zee Shaman, 4/8 imza kartı" gibi bir tahmin. Eşleşme zayıfsa panel gizlenir, tahmin uydurulmaz.
  • Rakip secret takibi: oynanan secret'ın adayları oyun olaylarıyla elenir. Eleme kuralları rules/secrets.json içinde veri olarak durur, yeni set gelince kod değil o dosya güncellenir.

Sonraya bıraktıklarım:

  • Arena draft asistanı. Ekran yakalama gerektiren tek özellik: kart sanatının algısal hash'i (pHash) ile tanıma, skorlar için hazır arena istatistikleri.
  • Battlegrounds paneli
  • Mulligan istatistikleri, deste bazlı detaylı analiz
  • Tur/rope zamanlayıcısı, Twitch overlay, HSReplay yükleme

Notlar

Kart verisi HearthstoneJSON, kart görselleri Blizzard'a ait. Bu depo Blizzard ile ilişkili değil. Uygulama yalnızca oyunun kendi yazdığı log dosyalarını okur, oyunun belleğine veya ağ trafiğine dokunmaz.