Mimari Genel Bakış
Uygulama Sürümü: v0.1.1 (fork: DarrellThomas/en-parlant) Teknoloji Yığını: Tauri v2 (Rust) + React 19 (TypeScript) + Vite
Tauri Nedir?
Section titled “Tauri Nedir?”Tauri, masaüstü uygulamaları oluşturmak için kullanılan bir çerçevedir. Electron’un yaptığı gibi tam bir tarayıcı paketlemek yerine, Tauri kullanıcı arayüzü için işletim sisteminin yerleşik webview’ını ve arka uç için bir Rust sürecini kullanır. Sonuç olarak küçük ve hızlı bir ikili dosya elde edilir.
İki yarım, IPC (süreçler arası iletişim) üzerinden haberleşir:
+---------------------------+ IPC +---------------------------+| Rust Backend | <--------------> | React/TS Frontend || | (commands + | || - Chess engines (UCI) | events) | - Chessboard UI || - SQLite database | | - Analysis panels || - File I/O | | - Settings || - PGN parsing | | - Game tree navigation || - Position search index | | - TTS narration |+---------------------------+ +---------------------------+ src-tauri/src/ src/Rust Tarafı: src-tauri/src/
Section titled “Rust Tarafı: src-tauri/src/”Rust, hızlı olması gereken veya sistem erişimi gerektiren her şeyi yönetir.
Giriş Noktası: main.rs
Section titled “Giriş Noktası: main.rs”Ön yüzün çağırabileceği yaklaşık 50 komutu kaydeder, eklentileri (dosya sistemi, diyalog, HTTP, kabuk, günlükleme, güncelleyici) başlatır ve uygulama penceresini açar.
Komutlar bir makro ile tanımlanır:
#[tauri::command]async fn get_best_moves(id: String, engine: String, ...) -> Result<...> { // spawn UCI engine, return analysis}specta crate’i bu Rust fonksiyonlarından otomatik olarak TypeScript tür tanımlamaları üretir, böylece ön yüz hiçbir manuel çaba gerektirmeden tam tür güvenliği elde eder.
Temel Modüller
Section titled “Temel Modüller”| Modül | Ne Yapar |
|---|---|
db/mod.rs | Diesel ORM aracılığıyla SQLite veritabanı — oyun sorguları, oyuncu istatistikleri, içe aktarmalar, konum arama |
game.rs | Canlı oyun motoru — motor-insan ve motor-motor oyunlarını, zaman kontrollerini, hamle doğrulamayı yönetir |
chess.rs | Motor analizi — UCI motorlarını başlatır, en iyi hamle sonuçlarını olaylar aracılığıyla ön yüze aktarır |
engine/ | UCI protokol uygulaması — süreç başlatma, stdin/stdout kanalları, çoklu PV desteği |
pgn.rs | PGN dosyası okuma/yazma/tokenize etme |
opening.rs | FEN’den açılış adı arama (uygulamaya gömülü ikili veri) |
puzzle.rs | Lichess bulmaca veritabanı — bellek eşlemeli rastgele erişim |
fs.rs | Devam ettirilebilir dosya indirmeleri, çalıştırılabilir dosya izni ayarlama |
sound.rs | Ses akışı için yerel HTTP sunucusu (Linux ses geçici çözümü) |
tts.rs | speech-dispatcher (Linux) / yerel işletim sistemi konuşma API’leri aracılığıyla Sistem TTS’i ve KittenTTS sunucu yönetimi |
oauth.rs | Lichess/Chess.com hesap bağlama için OAuth2 akışı |
Tasarım Kalıpları
Section titled “Tasarım Kalıpları”- Her yerde asenkron: Tokio çalışma zamanı, engellemeyen G/Ç
- Eşzamanlı durum: Motor süreçleri, veritabanı bağlantıları ve önbellekler için
DashMap(eşzamanlı HashMap) - Bağlantı havuzu: r2d2, SQLite bağlantı havuzlarını yönetir
- Bellek eşlemeli arama: Anlık sonuçlar için mmap’lenmiş ikili indeks üzerinden konum arama
- Olay akışı: Rust, React’ın gerçek zamanlı olarak dinlediği olayları (en iyi hamleler, saat tikleri, oyun sonu) yayar
React/TypeScript Tarafı: src/
Section titled “React/TypeScript Tarafı: src/”Derleme Hattı: Vite
Section titled “Derleme Hattı: Vite”vite.config.ts yapılandırır:
- Babel derleyicili React eklentisi
- TanStack Router eklentisi —
routes/klasöründen otomatik olarak rota ağacı oluşturur - Vanilla Extract — sıfır çalışma zamanı CSS-in-JS
- Yol takma adı:
@,./srcile eşleştirilir - 1420 portunda geliştirme sunucusu
Derleme akışı:
pnpm dev → Vite on :1420 + Tauri opens webview pointing to itpnpm build → tsc (typecheck) → vite build (bundle to dist/) → tauri build (native binary)Giriş: App.tsx
Section titled “Giriş: App.tsx”Kök bileşen:
- Tauri eklentilerini (günlük, süreç, güncelleyici) başlatır
- Kalıcı atom’lardan kullanıcı tercihlerini yükler
- Mantine kullanıcı arayüzü temasını ayarlar
- Yönlendiriciyi kaydeder
- Uygulama güncellemelerini kontrol eder
Durum Yönetimi
Section titled “Durum Yönetimi”Jotai atom’ları (src/state/atoms.ts) — hafif reaktif durum:
| Kategori | Örnekler |
|---|---|
| Sekmeler | tabsAtom, activeTabAtom (çoklu belge arayüzü) |
| Dizinler | storedDocumentDirAtom, storedDatabasesDirAtom |
| Arayüz tercihleri | primaryColorAtom, fontSizeAtom, pieceSetAtom |
| Motor | engineMovesFamily, engineProgressFamily (atomFamily ile sekme bazlı) |
| TTS | ttsEnabledAtom, ttsProviderAtom, ttsVoiceIdAtom, ttsVolumeAtom, ttsSpeedAtom, ttsLanguageAtom |
atomWithStorage() ile tanımlanan atom’lar otomatik olarak localStorage’a kalıcı hale getirilir.
Karmaşık alan durumu için Zustand depoları:
src/state/store/tree.ts— oyun ağacı navigasyonu, hamle dallanması, notasyonlar, yorumlar. Değişmez güncellemeler için Immer kullanır.src/state/store/database.ts— veritabanı görünümü filtreleri, seçili oyun, sayfalama
Yönlendirme: TanStack Router
Section titled “Yönlendirme: TanStack Router”src/routes/ içinde dosya tabanlı yönlendirme:
routes/ __root.tsx # Root layout (AppShell, menu bar) index.tsx # Home/dashboard databases/ # Database browsing accounts.tsx # Lichess/Chess.com accounts settings.tsx # App preferences engines.tsx # Engine managementBileşenler: src/components/
Section titled “Bileşenler: src/components/”| Grup | Amaç |
|---|---|
boards/ | Satranç tahtası (chessground), hamle girişi, değerlendirme çubuğu, analiz gösterimi, terfi modalı, ok çizimi |
panels/ | Yan paneller: motor analizi (BestMoves), veritabanı konum arama, notasyon düzenleme, oyun bilgisi, pratik modu |
databases/ | Veritabanı arayüzü: oyun tablosu, oyuncu tablosu, detay kartları, filtreleme |
settings/ | Tercih formları, motor yolları, TTS ayarları |
home/ | Hesap kartları, içe aktarma arayüzü |
common/ | Paylaşılan: TreeStateContext, malzeme gösterimi, yorum hoparlör simgesi |
tabs/ | Çoklu sekme çubuğu |
Ön Yüz Rust’ı Nasıl Çağırır
Section titled “Ön Yüz Rust’ı Nasıl Çağırır”Komutlar (istek/yanıt)
Section titled “Komutlar (istek/yanıt)”Specta, src/bindings/generated.ts içinde TypeScript bağlamları oluşturur:
// Auto-generated from Rust #[tauri::command] functionsexport const commands = { async getBestMoves(id, engine, tab, goMode, options) { return await TAURI_INVOKE("get_best_moves", { id, engine, tab, goMode, options }); }, // ~50 more commands...}React bileşenleri bunları normal asenkron fonksiyonlar gibi çağırır:
import { commands } from "@/bindings";const result = await commands.getBestMoves(id, engine, tab, goMode, options);Olaylar (akış, Rust’tan React’a)
Section titled “Olaylar (akış, Rust’tan React’a)”Gerçek zamanlı veriler için (motor analizi, saat tikleri, oyun hamleleri):
Rust: app.emit("best_moves_payload", BestMovesPayload { depth: 24, ... }) ↓React: listen("best_moves_payload", (event) => updateBestMoves(event.payload))Tauri Eklentileri
Section titled “Tauri Eklentileri”Uygulama, sistem erişimi için birçok resmi eklenti kullanır:
| Eklenti | Amaç |
|---|---|
@tauri-apps/plugin-fs | Dosya okuma/yazma |
@tauri-apps/plugin-dialog | Dosya seçiciler, mesaj kutuları |
@tauri-apps/plugin-http | HTTP istemcisi (motor indirmeleri, bulut TTS) |
@tauri-apps/plugin-shell | UCI motorlarını çalıştırma |
@tauri-apps/plugin-updater | Otomatik güncelleme kontrolleri |
@tauri-apps/plugin-log | Yapılandırılmış günlükleme |
@tauri-apps/plugin-os | CPU/RAM algılama |
Metinden Konuşmaya (TTS): Bir Giriş
Section titled “Metinden Konuşmaya (TTS): Bir Giriş”En Parlant~, bir oyunun hamlelerini adım adım ilerlerken satranç hamlelerini ve yorumları sesli olarak okuyabilir. Bu bölüm, TTS sisteminin nasıl oluşturulduğunu — ön işleme hattını, sağlayıcı mimarisini ve önbellekleme stratejisini — açıklamaktadır. Kurulum talimatları için TTS menüsündeki TTS kılavuzlarına bakın.
TTS Nasıl Çalışır (Kısa Versiyon)
Section titled “TTS Nasıl Çalışır (Kısa Versiyon)”Metinden konuşmaya, yazılı metni sesli sese dönüştürür. Modern TTS sistemleri, binlerce saatlik insan konuşması üzerinde eğitilmiş derin sinir ağları üzerine kuruludur. Model, metin (harfler, kelimeler, noktalama işaretleri) ile konuşmanın akustik özellikleri (perde, zamanlama, vurgu, nefes duraklamaları) arasındaki ilişkiyi öğrenir. Çıkarım zamanında metin gönderirsiniz ve bir ses dalga formu alırsınız.
İki geniş yaklaşım vardır:
-
Bulut TTS — metin uzak bir sunucuya (Google, ElevenLabs, vb.) gönderilir; sunucu GPU donanımında büyük bir sinir ağı çalıştırır ve ses döndürür. Mükemmel kalite, ancak internet bağlantısı gerektirir ve istek başına maliyeti vardır (çoğu sağlayıcı ücretsiz katmanlar sunsa da).
-
Yerel TTS — model doğrudan makinenizde çalışır. İnternet gerekmez, istek başına maliyet yoktur ve metniniz bilgisayarınızdan asla çıkmaz. Son dönem açık kaynak modeller (Kokoro ve Piper gibi) kalite farkını önemli ölçüde kapatmıştır.
TTS modellerinin perde arkasında nasıl çalıştığını merak ediyorsanız, HuggingFace (huggingface.co) keşfedebileceğiniz, indirebileceğiniz ve yerel olarak çalıştırabileceğiniz yüzlerce açık kaynak konuşma sentezi modeli barındırmaktadır. Hafif CPU dostu seçeneklerden en son teknoloji araştırma modellerine kadar geniş bir yelpazede modeller bulmak için “text-to-speech” araması yapın.
Sağlayıcı Mimarisi
Section titled “Sağlayıcı Mimarisi”Temel TTS uygulaması src/utils/tts.ts dosyasında bulunur. Tek bir genel arayüz (speakText()) ve değiştirilebilir arka uçlar etrafında tasarlanmıştır. Uygulamanın geri kalanı hangi sağlayıcının aktif olduğunu bilmez veya umursamaz — sadece speakText() çağırır ve ses çıkar.
Beş sağlayıcı desteklenmektedir:
| Sağlayıcı | Tür | Arka Uç |
|---|---|---|
| ElevenLabs | Bulut | REST API aracılığıyla sinir ağı sesleri. MP3 döndürür. |
| Google Cloud TTS | Bulut | REST API aracılığıyla WaveNet sesleri. Base64 kodlu MP3 döndürür. |
| KittenTTS | Yerel | Rust arka ucu tarafından otomatik başlatılan paketlenmiş TTS sunucusu. Localhost üzerinden HTTP ile iletişim kurar. |
| OpenTTS | Yerel | Kendi sunucunuzda barındırılan TTS sunucusu. Birçok motoru destekler (espeak, MaryTTS, Piper, vb.). |
| System TTS | Yerel | Rust/Tauri komutları aracılığıyla işletim sistemi yerel konuşma motoru (Linux’ta speech-dispatcher, Windows’ta SAPI, macOS’ta AVSpeechSynthesizer). |
Sağlayıcı seçimi tek bir Jotai atom’unda (ttsProviderAtom) saklanır. Sağlayıcı değiştirmek anlıktır — atom’u değiştirin ve bir sonraki speakText() çağrısı yeni arka uca yönlendirilir.
Zorluk: Satranç Notasyonu İngilizce Değildir
Section titled “Zorluk: Satranç Notasyonu İngilizce Değildir”Satranç hamleleri Standart Cebirsel Notasyon (SAN) ile yazılır: Nf3, Bxe5+, O-O-O, e8=Q#. Bunu doğrudan bir TTS motoruna verirseniz anlamsız sonuçlar alırsınız — “Nf3”ü bir kelime gibi telaffuz etmeye çalışabilir veya “O-O-O”yu “oh oh oh” olarak okuyabilir.
Çözüm, satranç notasyonunu TTS motoruna ulaşmadan önce doğal dile çeviren bir ön işleme hattıdır:
SAN Input → Preprocessing → Spoken Output─────────────────────────────────────────────────────"Nf3" → sanToSpoken() → "Knight f3""Bxe5+" → sanToSpoken() → "Bishop takes e5, check""O-O-O" → sanToSpoken() → "castles queenside""e8=Q#" → sanToSpoken() → "e8 promotes to Queen, checkmate"sanToSpoken() fonksiyonu, herhangi bir SAN dizesini bileşenlerine (taş, belirsizlik giderme, alma, hedef kare, terfi, şah/mat) ayırmak için regex kalıp eşleştirmesi kullanır ve bunları bir kelime dağarcığı tablosundan doğal dil kullanarak yeniden birleştirir.
Çoklu Dil Desteği
Section titled “Çoklu Dil Desteği”Satranç kelime dağarcığı birçok dile çevrilmiştir (İngilizce, Fransızca, İspanyolca, Almanca, Japonca, Rusça, Çince, Korece ve daha fazlası). CHESS_VOCAB tablosu her terimi eşleştirir:
English: "Knight takes e5, check"French: "Cavalier prend e5, échec"German: "Springer schlägt e5, Schach"Japanese: "ナイト テイクス e5, チェック"Russian: "Конь берёт e5, шах"Dil ayarı, ön işleme için hangi kelime dağarcığı tablosunun kullanılacağını ve TTS motorunun sentez için hangi sesi/aksanı kullandığını belirler.
Yorum Temizleme
Section titled “Yorum Temizleme”Oyun notasyonları genellikle sesli okunduğunda çok kötü duyulacak PGN’e özgü işaretlemeler içerir:
Raw comment: "BLUNDER. 7.Nf3 was better [%eval -2.3] [%cal Gg1f3]"After cleaning: "7, Knight f3 was better"cleanCommentForTTS() fonksiyonu:
- PGN etiketlerini kaldırır:
[%eval ...],[%csl ...],[%cal ...],[%clk ...] - Yinelenen notasyon kelimelerini kaldırır (”??” zaten “Blunder” dediyse)
- Düzyazı içindeki satır içi SAN’ı genişletir:
"7.Nf3 controls e5"→"7, Knight f3 controls e5" - TTS motorlarının yanlış telaffuz ettiği satranç terimlerini düzeltir (ör. “en prise” → “on preez”)
- Düzyazıdaki taş kısaltmalarını genişletir:
"R vs R"→"Rook versus Rook"
Tam Anlatımın Oluşturulması
Section titled “Tam Anlatımın Oluşturulması”Yeni bir hamleye geçtiğinizde, buildNarration() üç kaynaktan tam sözlü metni bir araya getirir:
Move: "12, Knight f3, check." ← from sanToSpoken()Annotation: "Good move." ← from annotation symbol (!)Comment: "Developing with tempo." ← from cleanCommentForTTS()
Full narration: "12, Knight f3, check. Good move. Developing with tempo."Bölümler arasındaki çift boşluk, TTS motorlarına doğal bir nefes duraklaması verir.
Önbellekleme ve Oynatma
Section titled “Önbellekleme ve Oynatma”Bulut TTS çağrıları para ve zaman maliyetine sahiptir (yaklaşık 200-500ms gidiş-dönüş). Aynı sesi yeniden getirmekten kaçınmak için, üretilen her ses klibi bellekte blob URL olarak önbelleğe alınır:
Cache key: "elevenlabs:pNInz6obpgDQGcFmaJgB:en:12, Knight f3, check."Cache value: blob:http://localhost/abc123 (the MP3 audio in browser memory)Önbellek isabet ettiğinde oynatma anlıktır. Önbellek provider:voice:language:text ile anahtarlanır, bu nedenle ses veya dil değiştirmek ayrı girdiler oluşturur.
Çok sayıda notasyon içeren oyunlar için, tüm oyun ağacını arka planda önceden önbelleğe alabilirsiniz. Uygulama her düğümü gezer, anlatım metnini oluşturur ve siz gezinmeye başlamadan önce önbelleği doldurmak için sıralı API çağrıları yapar.
Eşzamanlılık ve İptal
Section titled “Eşzamanlılık ve İptal”Hızlı ok tuşu navigasyonu bir sorun yaratır: kullanıcı hızla 5 kez ileri giderse, birbirleriyle çakışan 5 ses klibi istemezsiniz. Çözüm bir nesil sayacıdır:
const thisGeneration = ++requestGeneration;// ... fetch audio ...if (thisGeneration !== requestGeneration) return; // stale — discardHer yeni speakText() çağrısı sayacı artırır ve AbortController aracılığıyla devam eden HTTP isteğini iptal eder. Ses geldiğinde, kendi neslinin hâlâ güncel olup olmadığını kontrol eder. Kullanıcı zaten ilerlemiş durumdaysa, yanıt sessizce atılır. Bu, hamleler arasında hızla tıklarken bile temiz, kesintisiz ses sağlar.
TTS’in Uygulamaya Entegrasyon Noktaları
Section titled “TTS’in Uygulamaya Entegrasyon Noktaları”Entegrasyon noktaları asgaridir:
| Dosya | Ne Olur |
|---|---|
src/state/store/tree.ts | Her navigasyon fonksiyonu (goToNext, goToPrevious, vb.) stopSpeaking() çağırır. Otomatik anlatım açık olduğunda, goToNext ayrıca speakMoveNarration() çağırır. |
src/components/common/Comment.tsx | Her yorumun yanındaki hoparlör simgesi, o yorum için TTS’i manuel olarak tetiklemenizi sağlar. |
src/components/settings/TTSSettings.tsx | Sağlayıcı, ses, dil, ses düzeyi, hız seçimi ve API anahtarı girişi için ayarlar arayüzü. |
TTS kapalı olduğunda bu kodların hiçbiri çalışmaz. Uygulama, üst akış En Croissant ile aynı şekilde davranır.
Veri Akışı Örnekleri
Section titled “Veri Akışı Örnekleri”Motor Analizi
Section titled “Motor Analizi”User clicks "Analyze" → React calls commands.getBestMoves(position, engine, settings) → Rust spawns UCI engine process, sends position via stdin → Engine writes "info depth 18 score cp 45 pv e2e4 ..." to stdout → Rust parses UCI output, emits BestMovesPayload event → React's EvalListener receives event, updates atoms → UI re-renders: eval bar moves, best move arrows appear → User clicks "Stop" → commands.stopEngine() → Rust sets AtomicBool flagVeritabanı Konum Arama
Section titled “Veritabanı Konum Arama”User reaches a position on the board → React calls commands.searchPosition(fen, gameQuery) → Rust queries memory-mapped binary search index → Returns: PositionStats (wins/losses/draws) + matching games → React renders DatabasePanel with results tableTTS Anlatımı
Section titled “TTS Anlatımı”User steps forward with arrow key → tree.ts calls stopSpeaking(), then checks isAutoNarrateEnabled() → Calls speakMoveNarration(san, comment, annotations, halfMoves) → buildNarration() assembles text: sanToSpoken("Nf3+") → "Knight f3, check" annotationsToSpoken(["!"]) → "Good move." cleanCommentForTTS(comment) → strips [%eval], expands inline SAN → speakText() checks audioCache HIT → play blob URL instantly MISS → fetch from provider API → cache as blob URL → play → HTMLAudioElement.play() with volume and playbackRate from atomsDizin Haritası
Section titled “Dizin Haritası”en-parlant/├── src-tauri/ # RUST BACKEND│ ├── src/│ │ ├── main.rs # Entry, command registration, plugins│ │ ├── chess.rs # Engine analysis│ │ ├── game.rs # Live game management│ │ ├── db/ # SQLite database (largest module)│ │ ├── engine/ # UCI protocol│ │ ├── pgn.rs # PGN parsing│ │ ├── puzzle.rs # Puzzle database│ │ ├── opening.rs # Opening lookup│ │ └── tts.rs # System TTS + KittenTTS management│ ├── Cargo.toml # Rust dependencies│ ├── tauri.conf.json # Tauri config│ └── capabilities/main.json # Security permissions│├── src/ # REACT/TS FRONTEND│ ├── App.tsx # Root component│ ├── state/│ │ ├── atoms.ts # Jotai atoms (all app state)│ │ └── store/tree.ts # Game tree (Zustand + TTS hooks)│ ├── routes/ # TanStack Router (file-based)│ ├── components/│ │ ├── boards/ # Chessboard + analysis│ │ ├── panels/ # Side panels│ │ ├── databases/ # DB browsing UI│ │ ├── common/ # Comment display (with TTS speaker icon)│ │ └── settings/ # Preferences, TTS settings│ ├── utils/│ │ ├── chess.ts # Game logic│ │ ├── tts.ts # TTS engine (SAN-to-spoken, caching, 5 providers)│ │ └── treeReducer.ts # Tree data structure│ ├── bindings/ # Auto-generated TS from Rust│ └── translation/ # i18n (13 languages)│├── docs/ # Bundled documentation (shown in Help menu)├── vite.config.ts # Build config└── package.json # Frontend depsTemel Çıkarımlar
Section titled “Temel Çıkarımlar”-
Ağır işi Rust yapar — motorlar, veritabanı, dosya G/Ç, PGN ayrıştırma. React hiçbir zaman doğrudan dosya sistemine dokunmaz veya süreç başlatmaz.
-
Sınır boyunca tür güvenliği — Specta, Rust yapılarından TypeScript türleri oluşturur, böylece bir Rust komutu imzasını değiştirirse TypeScript derlemesi anında hata verir.
-
İki durum sistemi — Basit reaktif durum için Jotai (ayarlar, arayüz tercihleri, sekme bazlı motor durumu), karmaşık alan durumu için Zustand (dallanma ve değişmez güncellemeler içeren oyun ağacı).
-
TTS bir ön işleme sorunudur — zor kısım bir konuşma API’si çağırmak değil, satranç notasyonunu ve PGN işaretlemesini birçok dilde temiz, doğal ses veren metne dönüştürmektir. Asıl iş
sanToSpoken()vecleanCommentForTTS()hatlarında gerçekleşir. -
Beş sağlayıcı, tek arayüz — ses ister ElevenLabs’tan, ister Google Cloud’dan, ister KittenTTS’ten, ister OpenTTS’ten, ister işletim sisteminizin konuşma motorundan gelsin, uygulamanın geri kalanı yalnızca
speakText()çağırır. Sağlayıcı seçimi tek bir atom değişikliğidir. -
Derleme, tek bir ikili dosya üretir —
src-tauri/target/release/en-parlantkonumunda Rust arka ucunu ve Vite ile derlenen ön yüz varlıklarını paketler.