D&D temel kural kitaplarını kaynak ve sayfa numarasıyla yanıtlayan Streamlit RAG uygulaması. LlamaIndex, Qdrant, Ollama ve isteğe bağlı Gemini kullanır.
- Oyuncu ve DM kitaplarında tekli veya çoklu kitap retrieval
- Qdrant dense retrieval ve seçilebilir BM25 hybrid search
- Kitap ve sayfa aralığı metadata filtreleri
- Yanıtta kullanılan kitap ve PDF sayfalarının gösterimi
- Canlı kaynak seçimi, okuma, reranking ve yanıt hazırlama durumları
- Seçilebilir Ollama tabanlı LLM reranking
- 40 soruluk router/retrieval evaluation seti
- PDF hash ve indeks sürümü tabanlı yeniden ingestion
Soru -> kitap router -> bir veya iki Qdrant koleksiyonu
-> dense/hybrid retrieval -> opsiyonel rerank
-> kaynak odaklı RAG promptu -> birleşik yanıt
İki mevcut kitap için router deterministiktir: monster/stat-block terimleri DM kitabına, karşılaştırma soruları iki kitaba, diğer kurallar oyuncu kitabına gider. Farklı kitap kataloglarında LLM selector fallback'i kullanılır.
Temel multiplayer API ve web uygulaması için Python 3.10+, uv ve Node.js/npm yeterlidir. Ollama ve yerel modeller zorunlu değildir; yalnızca yerel RAG, Kurala Sor veya evaluation özellikleri kullanılacaksa gerekir.
uv sync
cd web
npm install
npm run build
cd ..
uv run python run_api.pyYerel RAG özelliklerini kullanmak isteyenler ayrıca Docker ve Ollama kurabilir.
LLM modeli sabit değildir: Kullanıcı istediği Ollama sohbet modelini indirip .env
içindeki OLLAMA_LLM_MODEL alanına aynı model adını yazar. Uncensored ve anlatım
ağırlıklı RPG oturumları için opsiyonel başlangıç önerisi
dolphin-llama3:8b'dir; bu yalnızca
öneridir ve otomatik indirilmez.
docker compose up -d
# Örnek öneri; bunun yerine istediğiniz Ollama modelini kullanabilirsiniz.
ollama pull dolphin-llama3:8b
ollama pull nomic-embed-text
uv run python ingestion.py
uv run streamlit run main.pyOLLAMA_LLM_MODEL=dolphin-llama3:8bİlk Aşama 2 ingestion çalıştırması koleksiyonları dense + BM25 sparse vektör şemasında yeniden oluşturur. Sonraki çalıştırmalarda PDF hash'i, embedding modeli, sparse model ve indeks sürümü değişmediyse kitap atlanır.
Gemini kullanmak için .env.example dosyasını temel alan bir .env oluşturup
GEMINI_API_KEY değerini tanımlayın. Retrieval ve reranking varsayılanları da aynı
dosyadan değiştirilebilir.
uv run streamlit run main.pySidebar üzerinden kitap kapsamı, Dense/Hybrid modu, reranking ve PDF sayfa aralığı seçilebilir. Dense retrieval varsayılandır. Hybrid ve reranking ölçülmüş ancak bu küçük lokal model/veri setinde varsayılan açık tutulmamıştır.
Sohbetler ve oyun state'i runtime/sessions.db SQLite dosyasında kalıcıdır. Her
oturum kendi konuşma hafızasını, karakterini, HP/envanterini, encounter initiative
durumunu ve notlarını tutar. Sohbette /roll 2d6+3, avantaj için
/roll 2d20kh1+5, dezavantaj için /roll 2d20kl1+5 kullanılabilir.
Kural modu kaynaklı cevabı doğrudan verir. Anlatım modu önce aynı kaynaklı
kural cevabını üretir, sonra ikinci LLM çağrısıyla mevcut karakter/encounter state'ine
uygun sahne anlatımına dönüştürür. İkinci aşama kaynakları ve kural temelini korur.
Set 20 oyuncu, 15 DM ve 5 multi-book olmak üzere 40 Türkçe/İngilizce sorudan
oluşur. Beklenen kitap ve PDF sayfaları evaluation/questions.yaml içindedir.
# Router + varsayılan hybrid retrieval
uv run python evaluate.py
# Ayrı deneyler
uv run python evaluate.py --mode router
uv run python evaluate.py --mode retrieval --retrieval dense
uv run python evaluate.py --mode retrieval --retrieval hybridMevcut raporlar evaluation/results/ dizinindedir:
| Ölçüm | Sonuç |
|---|---|
| Router exact accuracy | 100% |
| Multi-book exact accuracy | 100% |
| Dense page hit@10 | 95.56% |
| Dense MRR | 0.7506 |
| Hybrid page hit@10 | 93.33% |
| Hybrid MRR | 0.7654 |
| Kaynak metadata bütünlüğü | 100% |
Hybrid daha iyi ortalama sıra üretse de page-hit oranını düşürdüğü için dense varsayılan bırakıldı. Ollama LLM reranking doğru kaynağı korudu fakat tek sorguya yaklaşık 2.5 dakika ekledi; daha güçlü/hızlı bir modelle tekrar ölçülmelidir.
Gerçek oyun istemcisi React, ortak oyun otoritesi FastAPI'dir. Her oyuncu davet koduyla kendi cihazından bağlanır. DM ve Player tamamen ayrı çalışma yüzeyleri alır; Streamlit yalnızca RAG/evaluation laboratuvarı olarak tutulur.
+# Frontend bağımlılıkları ve production build
+cd web
+npm install
+npm run build
+cd ..
+
+# API + build edilmiş React, tek adres
+uv run python run_api.py
+```
Uygulama `http://localhost:8000` adresindedir. Aynı ağdaki oyuncular sunucunun LAN
IP adresini ve DM'nin ekranda gördüğü davet kodunu kullanır. Frontend geliştirirken
ayrı terminalde `cd web && npm run dev` ile `http://localhost:5173` açılabilir.
### Roller ve Yetki
- **Player:** Kendi karakter detayları, görünür encounter bilgisi, zar, HP değişiklik
talebi ve dar Kurala Sor paneli.
- **Human DM:** Tüm state, gizli canavarlar/HP, initiative, sahne, onay kuyruğu.
- **Assisted DM:** Human DM yetkili kalır; AI yapılandırılmış plan üretir, DM uygular.
- **AI DM:** AI planındaki doğrulanabilir komutlar backend tarafından uygulanır.
Oyuncu HP'yi doğrudan değiştiremez. Talep DM kuyruğuna gider; onaydan sonra backend
transaction'ı state'i değiştirir ve WebSocket tüm istemcileri günceller. Event
visibility değerleri `public`, `party`, `dm_only` veya `player:<id>` olabilir.
### Multiplayer Mimarisi
```text
React Player/DM clients
↕ REST + WebSocket
FastAPI authoritative server
├─ bearer token ve rol doğrulama
├─ command/game engine
├─ visibility/redaction
├─ Redis shared runtime (opsiyonel; multi-worker için zorunlu)
├─ AI DM structured plan
├─ RAG rule service
└─ SQLite event/state storeYerel MVP runtime/multiplayer.db kullanır. GameStore sınırı PostgreSQL'e geçiş
için veri erişimini API ve game engine'den ayırır. Token ve davetler HMAC hash ile
saklanır; süreli, döndürülebilir ve iptal edilebilirdir. WebSocket bağlantısı bearer
token yerine 60 saniyelik tek kullanımlık ticket kullanır.
REDIS_URL ayarlandığında presence kayıtları bağlantı başına TTL ile Redis'te tutulur;
event/snapshot invalidation ve uzak token iptali pub/sub ile bütün worker'lara taşınır.
DM grace deadline'ları recoverable sorted-set scheduler ve lease lock ile yalnız bir
worker tarafından işlenir. HTTP/WebSocket rate limit pencereleri Redis TIME kullanan
atomik Lua script'iyle ortak kota uygular. Redis başlangıçta erişilemiyorsa servis fail
fast olur; subscriber ve durable grace tarayıcısı uygulama lifespan başlangıcında,
ilk WebSocket beklenmeden hazır edilir. Kısa failover sırasında pub/sub worker'ı tekrar
bağlanmayı dener; canlı socket heartbeat'i kaybolmuş presence lease'ini geri kurar.
Async endpoint'lerde senkron Redis sürücüsü worker thread'e aktarılır. /api/health,
Redis yapılandırılmışken subscriber veya Redis erişimi sağlıklı değilse 503 döndürür.
Pub/sub yeniden bağlandığında, kesinti sırasında kaçmış ephemeral mesajlar için worker
üzerindeki açık oyunlara authoritative snapshot resync gönderilir.
REDIS_URL boşken sıfır ayarlı local/LAN davranışı korunur: presence, broadcast, grace
timer ve rate limit process-local çalışır. Birden fazla worker başlatılacaksa
WEB_CONCURRENCY gerçek worker sayısına ayarlanmalı ve REDIS_URL verilmelidir;
uygulama WEB_CONCURRENCY>1 olup Redis yoksa başlamaz. Docker Compose içindeki Redis
servisi docker compose up -d redis ile açılabilir. Canlı entegrasyon testi
TEST_REDIS_URL=redis://localhost:6379/0 verilerek çalıştırılır.
Authoritative store tek-host dağıtımda SQLite kullanır. Veritabanı WAL,
busy_timeout=10000, foreign key enforcement ve kayıp riskini performansa tercih eden
synchronous=FULL ile açılır. Sentetik concurrent probe:
python -m api.sqlite_scale_probe \
--concurrency 1,2,4,8 --operations 250 --write-ratio 0.2Probe ayrı connection kullanan thread'leri ve gerçek minimal metadata write'larını ölçer; multi-process kapasite iddiası değildir ve mevcut bir DB yolunu değiştirmeyi reddeder. Sekiz-thread örnek profilinde write p99 guardrail'ı aşıldığı için bu profil SQLite production onayı sayılmaz.
Online backup, doğrulama ve overwrite etmeyen restore:
python -m api.db_admin backup --source runtime/multiplayer.db --target backups/game.db
python -m api.db_admin verify --source backups/game.db
python -m api.db_admin restore --source backups/game.db --target runtime/restored.dbBackup doğrulama ve kopyalamayı aynı WAL read snapshot'ında yapar; atomik yayın başka
bir process'in oluşturduğu hedefi overwrite etmez. Restore var olan hedefi değiştirmez;
API durdurulduktan sonra doğrulanmış yeni dosya GAME_DB olarak seçilir. Ölçüm
sonuçları, PostgreSQL geçiş eşikleri, normalized
aggregate ve transactional outbox kararı
docs/sqlite-postgresql-evaluation.md
dosyasındadır. Redis multi-worker coordination aynı hosttaki SQLite writer sınırını
kaldırmaz; multi-host production PostgreSQL geçiş kapısıdır.
run_api.py geliştirme/reload runner'ıdır ve tek worker içindir. Çok-worker çalıştırma
gerçek worker sayısı environment ile aynı olacak şekilde, örneğin
WEB_CONCURRENCY=2 uvicorn api.app:app --workers 2 ile yapılmalıdır. Compose Redis
portu varsayılan olarak yalnız 127.0.0.1 üzerinde yayınlanır.
VTT haritaları SQLite içine binary olarak yazılmaz. API doğrulanmış PNG/JPEG
dosyalarını SHA-256 içerik anahtarıyla MAP_OBJECT_ROOT altında saklar; SQLite
yalnız metadata, campaign sahipliği ve scene/grid/viewport revision bilgisini tutar.
Varsayılan tek dosya sınırı 10 MiB (MAX_MAP_UPLOAD_BYTES), boyut sınırı
64–8192 px ve campaign başına mantıksal metadata kotası 100 MiB'dir.
Harita yükleme ve scene değiştirme yalnız aktif DM tarafından yapılır. Oyuncu, asset içeriğine ancak kendi oyununun scene'i yayınlandığında erişebilir; yayınlanmamış scene adı, grid ve viewport bilgileri de oyuncu projection'ından çıkarılır. Görseller Bearer token ile alınır ve frontend'de kısa ömürlü Blob URL olarak gösterilir; token URL query parametresine yazılmaz.
Yerel object store üretimde tek process/tek disk varsayımı taşır. Çok worker veya yatay ölçek için VTT asset katmanı S3 uyumlu object storage'a taşınmalı; metadata transaction'ı ile binary write arasında oluşabilecek erişilemeyen content-addressed orphan dosyalar periyodik garbage collection ile temizlenmelidir.
Encounter tokenları map_tokens tablosunda yalnız konum, boyut, sahiplik ve
optimistic-lock revision'ı saklar. Ad, initiative, HP ve gizlilik canlı
state.combatants kaydından türetilir; liste ile harita için ikinci bir encounter
state'i oluşturulmaz. Aktif DM canlı encounter listesini scene'e senkronize eder ve
tüm tokenları taşıyabilir. Oyuncu yalnız kendi character_id kaydına bağlı tokenı
taşıyabilir. Gizli combatant tokenları ve hareket event'leri player projection'ına
girmez. Hareket ve silme işlemleri token revision CAS; tüm token komutları global
game revision/idempotency receipt ile korunur. Grid veya map boyutu değiştikten sonra
senkronizasyon mevcut token boyutlarını günceller ve merkezlerini yeni asset sınırları
içine taşır.
Migration v27, yeni bir veritabanında data/rulesets/srd-5.2.1 altındaki immutable
bootstrap seed'ini bir kez rulesets ve ruleset_entries tablolarına aktarır.
Uygulamanın sonraki tüm katalog okumaları SQLite üzerinden yapılır. Seed class,
species, background, spell, feature, item ve condition için başlangıç kayıtları
sağlar; tam SRD değildir ve foundation durumundadır.
Her kayıt resmî SRD belge sürümünü ve SHA-256 özetini, sayfa/section provenance'ını,
CC BY 4.0 lisansını ve gerekli attribution bilgisini taşır. Bootstrap doğrulaması
resmî URL/hash/attribution, entity şeması, referanslar veya onaylı seed hash'leri
uyuşmazsa migration'ı geri alır.
Yayınlanmış ruleset'ler immutable'dır. Developer akışı published bir sürümü yeni bir draft ID'sine klonlar; entry ekleme/güncelleme/silme revision CAS ile korunur. Publish tüm katalog referanslarını yeniden doğrular. Default yapılan yeni sürümü yalnız bundan sonra oluşturulan campaign'ler kullanır; mevcut campaign'ler pinli sürümlerinde kalır.
Kimliği doğrulanmış istemciler sürümleri GET /api/rulesets, filtreli kayıtları
GET /api/rulesets/{version}/entries ve tek kaydı
GET /api/rulesets/{version}/entries/{entry_id} üzerinden okuyabilir. Liste endpoint'i
type, q, offset ve en fazla 100 olan limit parametrelerini kabul eder. Bunlar
statik katalog sorgularıdır; Ollama, Qdrant veya model indirmesi gerektirmez.
Gizli development ekranı /__developer/catalog adresindedir ve navigasyonda
gösterilmez. Backend erişimi varsayılan olarak kapalıdır. En az 32 karakterlik
rastgele DEVELOPER_ADMIN_TOKEN ayarlanmalıdır; token yalnız X-Developer-Token
header'ında kullanılır ve ekran tarafından browser storage'a yazılmaz. Public
deployment'ta bu yüzey yalnız HTTPS arkasında kullanılmalıdır.
Schema-v1 ile kayıpsız temsil edilebilen 21 ek SRD kaydını inceleme draft'ına almak için:
uv run python -m api.catalog_curation \
--database runtime/multiplayer.db \
--pack data/catalog-curation/srd-5.2.1-foundation-expansion-1.jsonBu paket idempotent ve bilinçli olarak draft-only'dir; otomatik publish/default
reddedilir. Silah, genel damage spell, background ekipman paketi ve typed feat
semantikleri için önce docs/catalog-schema-v2-prerequisites.md uygulanmalıdır.
Katalog ekranı veri tanımlarını yönetir; yeni bir feature kaydı tek başına yeni bir oynanış mekaniği çalıştırmaz. Second Wind gibi action/resource/encounter etkileri için ilgili authoritative engine komutu ve testleri ayrıca uygulanmalıdır.
Character Builder'da spell slot maksimumları oyuncu girdisi değildir. Class kaydındaki spellcasting ability, class spell listesi, known/prepared limitleri ve level tablosundan türetilir. Fighter gibi 1. seviyede spellcasting kazanmayan class'lar boş spell state ile devam eder; eski taslaklardaki elle girilmiş slotlar açılışta temizlenir.
Yeni campaign davet kodları kopyalaması kolay XXXXXXXX-XXXXXXXX biçimindedir. Kodlar
case-insensitive çalışır; süre sonu, kullanım limiti, rotate/revoke ve IP rate limit
korumaları devam eder. Veritabanında yalnız amaç-ayrımlı HMAC özeti saklanır.
DM ve co-DM oturumları bu cihazda en fazla 12 campaign için saklanabilir ve giriş
ekranından yeniden açılabilir. Bu kolaylık tokenları browser localStorage içinde
tutar; public kurulumlarda sıkı CSP/TLS zorunludur. “Bu cihazdan kaldır” yalnız yerel
kaydı siler. Sunucudan kalıcı silme sadece campaign sahibine açıktır ve güncel snapshot
sonrası tam game_id:name onayı ister.
Multiplayer karakterleri schema v2 kullanır. Oyuncu seçimleri ve ham değerler inputs,
sunucunun deterministik sonuçları derived altında tutulur. Motor ability modifier,
proficiency, saving throw, 18 skill, expertise, AC, initiative, maksimum HP, speed ve
passive perception değerlerini hesaplar. Eski ac, max_hp ve class_name alanları
mevcut UI uyumluluğu için sunulur ancak her hesaplamada backend tarafından yeniden
üretilir ve istemciden yazılamaz.
Genel karakter güncellemesi ability score ve skill seçimlerini kabul eder; AC, HP ve speed politikaları ilerideki typed equipment/level-up işlemlerine ayrılmıştır. Migration v9 eski karakterlerin mevcut HP/AC, condition, inventory ve özel class adlarını korur. HTTP JSON gövdeleri FastAPI doğrulamasından önce varsayılan 256 KiB ile sınırlandırılır; internet deployment'ında reverse proxy aynı veya daha düşük limit kullanmalıdır.
Karakter resource schema v2; Hit Point Dice, sınıf kaynakları ve death save durumunu
resource_state, concentration ile typed/süreli condition kayıtlarını effects
altında tutar. ResourceEngine level veya class değiştiğinde harcanmış kullanımları
koruyarak maximum değerleri katalogdan yeniden uzlaştırır. Fighter Second Wind typed
bir komuttur; 1d10 + Fighter level iyileştirir ve katalogdaki level tier kullanımlarını
harcar. Generic resource komutu bu özelliği atlayamaz.
Short ve long rest yalnızca pozitif HP ile ve aktif encounter dışında yapılabilir.
Death save yalnızca karakterin aktif turunda bir kez yapılır; tur kimliği round
numarası yerine monotonik turn_serial ile izlenir. Encounter içindeki Second Wind
yalnızca karakterin sırasında ve o turun tek Bonus Action hakkıyla kullanılabilir;
turn_actions ledger'ı her tur geçişinde atomik olarak sıfırlanır. Ölü durumundaki karakter normal
healing komutuyla geri döndürülemez. Hasar concentration için authoritative
Constitution save üretir; incapacitated, bilinçsizlik ve başarısız save concentration'ı
bitirir. Migration v10-v12 eski karakterleri geri doldurur, eski death-save alanını
dönüştürür ve daha yeni ya da bozuk resource şemasını sessizce ezmeden fail-fast olur.
Karakter inventory schema v1, her eşyayı kalıcı bir id ile tutar; eski string
inventory alanı yalnız uyumluluk projeksiyonudur. Kayıtlar quantity, katalog kimliği,
ağırlık/değer, equipment slot, parent container, attunement ve equip durumunu taşır.
Container hareketleri kayıp parent, cycle ve kapasite aşımını; silme işlemi dolu container,
equipped veya attuned item'ı reddeder. Migration v13 legacy isimleri korur, eşleşen Shield
kaydını pinned SRD kataloğuna bağlar ve current/future/corrupt state'i fail-closed doğrular.
Para kesesi CP/SP/EP/GP/PP sayılarını tam sayı tutar; her 50 coin 1 lb olarak toplam
ağırlığa katılır. Standard encumbrance Small/Medium karakter için Strength×15 lb taşıma
kapasitesini hesaplar; ignore politikası yalnız aktif DM tarafından seçilebilir ve
ağırlığı gizlemeden uyarıyı kapatır. Fighter'ın katalogdaki Shield training'i ve equipped
Shield'ın +2 AC katkısı her hesaplamada backend tarafından yeniden üretilir. Encounter
içinde equip/unequip yalnız karakterin turunda bir Action tüketir.
Attunement en fazla üç item ile sınırlıdır; aynı katalog item'ının iki kopyasına attune olunamaz. Manuel attune/unattune, encounter dışında 0 Hit Dice harcanan Short Rest ile atomik yürür; ölüm bütün attunement bağlarını bitirir. Oyuncu kendi tam inventory state'ini görür; başka karakterlerin detayları ve hidden monster verisi snapshot ve command cevaplarında aynı role-aware projeksiyonla redacted edilir.
ActionEngine, karakter başına versioned known/prepared spell, spell slot ve attack
repertuvarı tutar. Repertuvarı yalnız aktif DM yapılandırır; oyuncu yalnızca kayıtlı
kimlikleri çalıştırabilir. Ability/skill/save, attack, Cure Wounds, concentration,
death save ve Second Wind akışları actor/source/action-cost/mode/roll bilgisi taşıyan
typed intent üretir. Attack bonusu, save/skill modifier'ı, hedef AC ve healing sunucuda
hesaplanır; istemci damage dice veya modifier enjekte edemez. Slot ve sonuç aynı revision
transaction'ında yazılır, duplicate client_action_id aynı authoritative sonucu replay
eder. Long Rest tüm spell slotlarını yeniler. Migration v14 eski karakterlere boş ve
geçerli action state ekler; future/corrupt state'te fail closed davranır.
Migration v15, karakter taslaklarını canlı game aggregate'inden ayrı
character_drafts tablosunda tutar. POST/GET/PATCH /api/characters/{character_id}/draft private taslağı başlatır, okur ve optimistic
expected_revision ile autosave eder; stale sekme 409 alır. /draft/navigate,
basics → abilities → class → species → background → proficiencies → equipment → spells → review sırasında ileri giderken mevcut adımı doğrular, geri dönüşe izin verir.
publish_character_draft komutu bütün adımları yeniden doğrular ve karakteri catalog,
derived stats, resource, inventory ve action motorlarından fresh üretir. Draft status,
character state, game revision, event ve idempotency receipt tek SQLite transaction'ında
yazılır; validation veya revision çatışmasında hiçbir parça commit olmaz. Oyuncu yalnız
kendi draft'ını, aktif DM ise kampanyadaki draft'ları yönetebilir.
Migration v26 yeni katılan oyuncuyu character_ready=0 olarak kaydeder ve private
oluşturma taslağını üyelikle aynı transaction içinde açar. Snapshot bu durumu
character_creation_required olarak taşır; oyuncu geçerli karakterini yayınlayana kadar
normal player workspace, Campaign/Session ekranları ve zar FAB'ı yerine zorunlu builder
görür. Migration, mevcut oyunculardan yalnız published draft'ı bulunanları hazır kabul
eder; draft'ı hiç olmayan veya hâlâ active olan oyuncular da oluşturma akışına alınır.
Draft schema v2, ability score'ları pinned SRD kurallarıyla doğrular: Standard Array
tam olarak 15, 14, 13, 12, 10, 8 çoklu kümesini; Point Cost ise 8–15 aralığı ve tam
27 puan bütçesini gerektirir. Background ability artışları katalogdaki izinli
ability'lerle sınırlıdır ve +2/+1 ya da +1/+1/+1 dağılımıyla uygulanır. Rastgele ability üretimi
henüz authoritative roll provenance taşımadığı için builder seçeneği değildir.
Oyuncu zorunlu akış dışında üst bardaki Karakter oluştur eylemiyle dokuz adımlı builder workspace'ini açar. Değişiklikler kısa bir debounce sonrasında sırayla autosave edilir; ekrandaki cloud durumu saved, pending, saving, error ve conflict hallerini ayırır. Başka sekme draft revision'ını ilerletirse yerel form sessizce ezilmez, kullanıcıya sunucudaki taslağı açıkça yeniden yükleme seçeneği verilir. İleri geçiş backend adım doğrulamasını, geri geçiş non-destructive navigasyonu kullanır; review ekranı publish komutunu çalıştırır.
Oyuncu ekranı Overview, Actions, Spells, Inventory, Features ve Notes sekmelerine ayrılmıştır. Overview authoritative derived stat'ları, save ve skill modifier'larını; Actions attack repertuvarını; Spells known/prepared ve slot durumunu; Features rest, Hit Dice, class resource, condition ve concentration bilgisini birlikte gösterir. Ability, skill, save ve attack eylemleri global zar dialogunu doğru derived modifier ile açar; dialog modifier'ı read-only tutar ve sonucu raw client toplamı yerine ilgili typed backend komutundan alır. Advantage/dezavantaj seçimi typed payload'a taşınır.
Notes alanı bu aşamada 20.000 karakter sınırıyla yalnız tarayıcı cihazında saklanır ve arayüz bunu açıkça belirtir. Campaign senkronizasyonu/backup ayrı bir persistence task'ı olarak ele alınmalıdır; private notlar snapshot veya event stream'e gönderilmez.
Global zar FAB'ı serbest expression göndermek yerine roll_intent komutunu kullanır.
İstemci actor character, custom_roll action, party/private görünürlük,
global_fab context ve sınırlandırılmış count/sides/modifier/mode alanlarını taşır;
expression, encounter bağlamı, intent kimliği ve RNG sonucu sunucuda üretilir.
Oyuncu başka bir karakteri actor gösteremez. Private sonuç yalnız atan oyuncu ile
DM/co-DM rollerine görünür.
Migration v20, event satırlarına typed intent kimliği ve schema version metadata'sı
ekler; game başına benzersiz intent index'i ile INSERT/UPDATE validation trigger'ları
bozuk metadata'yı reddeder ve mevcut typed action eventlerini backfill eder.
client_action_id receipt'i aynı komutun eşzamanlı, tekrarlı veya response kaybı sonrası
yeniden tesliminde tek typed_roll_resolved Game Log olayı ve aynı authoritative
sonucu üretir. Player-visible intent context internal encounter ID/turn index taşımaz.
FAB'daki görünürlük seçimi ile mevcut d4–d100, adet,
advantage/disadvantage ve sonuç animasyonu bu sözleşmeye bağlıdır.
Authoritative zar sonucu geldikten sonra lazy-loaded Dice3DTray, Three.js ile d4,
d6, d8, d10, d12, d20 ve tam 100 triangle yüzlü d100 meshini üretir. cannon-es world;
gravity, friction, restitution ve görünmeyen fizik sınırlarıyla çarpışma/sekme
koreografisini çalıştırır. Görsel masa çizilmez; canvas yüksek z-index'li, şeffaf bir
ekran katmanıdır. Görsel fizik RNG değildir: sonuç, kept/discarded ayrımı ve toplam
backend payload'ından gelir. Her mesh settle olduğunda authoritative sonuç kameraya,
yani kullanıcıya en çok bakan gerçek zar yüzüne yerleşir. d4–d20'nin diğer yüz sayıları
geometrinin yüz merkezine ve yüz normaline bağlı, ışık alan kazıma decal'larıdır; d100
mobil GPU yükünü sınırlamak için görünür yüzlerde bounded etiket kullanır. Sonuç ayrı
bir rozet/yuvarlak içinde tekrarlanmaz.
İlk 12 zar 3B çizilir, kalanı bounded overflow sayacıyla belirtilir.
Migration v21 üye kapsamlı crimson, arcane, ivory tema ve ses tercihini saklar.
GET/PATCH /api/me/dice-preferences strict payload, member/game scope trigger'ı ve
rate limit ile çalışır; UI hızlı değişiklikleri sıraya alır. Web Audio yalnız kullanıcı
etkileşimiyle prime edilir ve collision sesleri throttle edilir.
Three ve cannon ana uygulamadan ayrı lazy vendor chunk'larıdır; masa ilk açılışta 3B
motoru indirmez. Renderer 3.3 saniye sonra animation frame, geometry, material, body ve
WebGL kaynaklarını dispose eder; context açıkça kaybedilir ve audio node/context yaşam
döngüsü kapanır. prefers-reduced-motion istemcide 3B vendor chunk'ları hiç yüklenmez.
WebGL init/context-loss veya lazy chunk hatasında error boundary authoritative değerleri
statik fallback olarak gösterir. Performans trade-off'u
olarak d6 box, diğer zarlar bounded sphere physics collider kullanır; gerçek polyhedral
görsel mesh korunurken mobil collision solver maliyeti sınırlanır.
Migration v16 campaign settings'i house rules, safety tools ve Session Zero agenda taşıyan
schema v1'e yükseltir; üyeliklere optimistic readiness version, consent ve private safety
preferences ekler. Oyuncu ready olmadan önce consent'i kabul etmelidir. Lines, veils ve
özel not yalnız ilgili üye ile DM/co-DM rollerine döner; party event'i sadece readiness ve
consent durumunu taşır.
Üst bardaki Campaign Hub, mevcut kampanyayı, lobi readiness özetini, planlanan preparing
session'ı ve davet yaşam döngüsünü gösterir. Aktif DM house rules, safety tools, agenda ve
oturum tarihini düzenler; her üye kendi consent/readiness ve safety tercihlerini yönetir.
Settings/member/game revision çatışmaları 409 ile fail closed olur.
Migration v17, aktif oturuma bağlı rol filtreli notları, loot havuzunu ve quest listesini
kalıcılaştırır. Üst bardaki Session ekranı aktif DM'e
preparing → live → paused/completed yaşam döngüsü kontrollerini; bütün üyelere cursor
tabanlı Game Log, oturum notları ve loot claim akışını sunar. Aktif DM loot ve quest
oluşturur, quest durumunu değiştirir ve oturum özetini taslak veya yayınlanmış olarak
kaydeder.
Not görünürlüğü sunucuda uygulanır: party notları tüm masaya, DM-only notlar DM ekibine, private notlar yalnızca yazarı ile DM/co-DM rollerine görünür. Loot claim işlemi koşullu tek update ile yarışa dayanıklıdır; command receipt, state revision ve olay kaydı aynı transaction içinde tamamlanır. Tamamlanan oturuma yeni not, loot veya quest eklenemez; aktif DM kapanış özetini daha sonra düzenleyip yayınlayabilir. Yayınlanmamış özet içeriği oyuncu workspace'ine veya party event stream'ine girmez.
Migration v18 kampanya kapsamlı, revision'lı encounter draft'larını kalıcılaştırır.
DM üst bardaki Encounters workspace'inde manuel monster/NPC ekleyebilir, kampanyadaki
character sheet'lerini kaynak olarak bağlayabilir, roster'ı kaydedebilir ve encounter'ı
duplicate edebilir. Draft güncellemeleri hem game aggregate revision hem draft revision
ile korunur; stale builder sekmesi 409 alır.
Kaydedilmiş encounter başlatıldığında manuel combatant kaynakları doğrulanmış HP, max HP, AC ve initiative değerlerini taşır; character kaynakları ise o andaki authoritative sheet name/HP/AC/initiative değerlerinden yeniden hydrate edilir. Aynı doğrulanmış roster canlı encounter state'ine geçer ve kaynak encounter kimliği/revision'ı korunur. Pause/resume round, turn ve combatant durumunu sıfırlamaz; paused durumda gameplay, inventory, resource ve builder publish mutasyonları kapalıdır. Hidden combatant'lar oyuncudan tamamen, görünür monster HP/max HP bilgisi ise player projection'ından redacted edilir.
Migration v19 canlı roster'a açık initiative tie-break metadata'sı ve kampanya başına 20 adımlık atomik encounter undo geçmişi ekler. Eşit initiative sırası önce DM'in verdiği tie-break değerine, sonra isim ve stable ID'ye göre deterministik çözülür. Aktif aktörün kimliği tie düzenlemesi veya lair/environment turn entry eklenmesi sırasında korunur. Lair/environment entry'leri sıra alır ancak HP veya character resource'u taşımaz.
DM canlı encounter panelinden combatant HP'sini, tie sırasını, round/permanent/rest süreli condition'ları ve concentration'ı yönetebilir. Character'a bağlı combatant HP, max HP, AC ve ad bilgisi her command sonunda authoritative character aggregate'inden aynı transaction içinde yeniden projekte edilir; sheet ile initiative board ayrı HP kaynaklarına dönüşmez. End-turn condition tick'i, concentration damage save'i, state, event, revision ve idempotency receipt birlikte commit olur.
Son işlemi geri al yalnız state-only encounter mutasyonlarını geri alır. Önceki state
snapshot'ı, undo stack pop'u, restore, event ve yeni revision tek BEGIN IMMEDIATE
transaction'ındadır; event yazımı veya state save başarısızsa undo kaydı tüketilmez.
Corrupt undo JSON'u fail closed davranır.
Migration v24, oyun kapsamlı fog revision'ını, açılmış grid hücrelerini ve kısa ömürlü ping/çizim sinyallerini saklar. Fog açma-kapama ve boyama yalnız aktif DM tarafından, fog revision CAS kontrolüyle yapılır. Oyuncu snapshot'ı açılmış hücre koordinatlarını almaz; yalnız yetkili raster mask URL'sini ve tüm geometrisi açılmış hücrelerde kalan, süresi dolmamış masa sinyallerini görür. Kalıcı event payload'ları fog hücrelerini veya çizim geometrisini taşımaz; kalıcı transient payload'ları her okumada fail-closed yeniden doğrulanır.
Fog etkin olduğunda oyuncuya özgün harita dosyası verilmez. Yetkili content endpoint'i,
sunucuda açılmış hücreleri kaynak görselle birleştirip siyahlanmış PNG projection üretir.
Cache anahtarı oyun, asset, fog ve scene revision ile grid boyutunu kapsar; eşzamanlı
aynı-target üretimleri atomik tekilleştirilir. Bu türetilmiş dosyalar
MAP_FOG_CACHE_ROOT altında tutulur, kaynak asset değildir ve servis kapalıyken güvenle
temizlenebilir. DM görünümünde fog editörü tokenların altında;
oyuncu görünümünde fog katmanı token ve sinyallerin üstündedir, böylece gizli bölgedeki
authoritative nesneler CSS katman sırasıyla sızmaz.
Masa araç çubuğu yerel ölçüm cetveli, altı saniyelik oyuncu/DM ping'i ve yalnız DM'e açık
otuz saniyelik çizim katmanı sunar. Cetvel sonucu haritanın grid_size_px,
distance_per_cell ve distance_unit değerlerinden istemcide hesaplanır; oyun state'ini
değiştirmez. Ping/çizim payload'ları strict koordinat ve boyut sınırlarından geçer.
İnternet yayını için PUBLIC_MODE=true, yalnızca HTTPS adreslerden oluşan
WEB_ORIGIN ve en az 32 karakterlik rastgele AUTH_PEPPER zorunludur. TLS reverse
proxy zorunludur; çok-worker yayınında Redis shared runtime etkinleştirilmelidir.
Yerel/LAN kullanımında PUBLIC_MODE=false ile sıfır ayar davranışı korunur.
Pepper ilk credential oluşturulmadan belirlenmeli ve değiştirilmemelidir. Mevcut v5/v6
veritabanını aynı pepper ile ilk kez v7'ye bağlarken bir defaya mahsus
AUTH_PEPPER_BIND_EXISTING=true onayı gerekir; farklı pepper credential reissue ister.
Catalog developer yüzeyi gerekiyorsa ayrıca en az 32 karakterlik rastgele
DEVELOPER_ADMIN_TOKEN ayarlanır; boş bırakıldığında ilgili API'ler 404 döner.
- Kaynak kitap ve sayfa numarası
- RAG sistem promptu ve servis hata yönetimi
- PDF hash tabanlı ingestion
- Ortam ve Docker yapılandırması
- 40 soruluk evaluation seti
- Router doğruluk ölçümü
- Multi-book retrieval
- Metadata ve sayfa filtreleri
- BM25 hybrid search
- Deneysel LLM reranking
- Konuşma ve session memory
- Dice roller tool (
/roll 2d20kh1+5) - Character ve encounter state machine
- Inventory, HP ve session yönetimi
- Kural yanıtı ile yaratıcı anlatımı ayıran iki aşamalı pipeline
Production TLS, export/delete, retention, JSON log/metrics/trace correlation, ClamAV upload taraması, bounded load probe ve zorunlu release kapıları production operations runbook içinde tanımlıdır. Ollama ve herhangi bir yerel model opsiyoneldir; kullanıcı istediği modeli seçer ve çekirdek multiplayer API model indirmeden çalışır.