stepstead-backend/db/seed_events_combat.py
jts ea049b8ccd İlk commit: Stepstead backend (FastAPI)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 11:30:24 +03:00

152 lines
8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Lokasyona özel olaylar — combat/hunting ağırlıklı 8 yeni kart (2026-07-04).
events.location_codes: seyahatin VARIŞ lokasyonu listede ise olay çıkabilir;
NULL = her yerde. Çalıştırma (idempotent):
cd /opt/stepstead && ./venv/bin/python3 db/seed_events_combat.py
"""
import asyncio
import json
import sys
sys.path.insert(0, "/opt/stepstead")
import asyncpg # noqa: E402
from config import settings # noqa: E402
EVENTS = [
{
"code": "kurt_surusu",
"name": "Kurt Sürüsü",
"text": "Alacakaranlıkta parlayan gözler... Bir kurt sürüsü yolunu kesti. Liderleri dişlerini gösteriyor.",
"locations": ["av_topraklari", "karanlik_orman"],
"choices": [
{"text": "⚔ Savaş!", "skill": "combat", "dc": 13,
"success": {"text": "Sürüyü püskürttün, lider kurdu yere serdin.",
"items": [{"code": "meat_wolf", "qty": 2}, {"code": "leather_wolf", "qty": 1}],
"xp": {"skill": "combat", "amount": 60}},
"fail": {"text": "Kurtlar seni kovaladı, kan kaybederek kaçtın.", "steps": -150}},
{"text": "🏃 Kaç", "outcome": {"text": "Uzun bir koşuyla kurtuldun ama yorgun düştün.", "steps": -80}},
],
},
{
"code": "vahsi_domuz",
"name": "Vahşi Domuz",
"text": "Çalılıklar hışırdıyor — kocaman bir yaban domuzu toprağı eşeliyor. Henüz seni fark etmedi.",
"locations": ["av_topraklari", "fisilti_ormani", "akca_koru"],
"choices": [
{"text": "🏹 Sessizce avla", "skill": "hunting", "dc": 12,
"success": {"text": "Tek atışla indirdin. Temiz bir av.",
"items": [{"code": "meat_boar", "qty": 2}, {"code": "leather_boar", "qty": 1}],
"xp": {"skill": "hunting", "amount": 50}},
"fail": {"text": "Dal kırıldı, domuz sana saldırdı! Zor kaçtın.", "steps": -100}},
{"text": "🤫 Rahat bırak", "outcome": {"text": "Domuz homurdanarak uzaklaştı.", "steps": 0}},
],
},
{
"code": "geyik_izi",
"name": "Taze Geyik İzi",
"text": "Toprakta taze geyik izleri var. İzler sık çalılığın içine gidiyor.",
"locations": ["cayirlar", "av_topraklari", "gumus_camlik"],
"choices": [
{"text": "🦌 İzi sür", "skill": "hunting", "dc": 10,
"success": {"text": "İzi sürüp genç bir geyik avladın.",
"items": [{"code": "meat_deer", "qty": 1}, {"code": "leather_deer", "qty": 1}],
"xp": {"skill": "hunting", "amount": 40}},
"fail": {"text": "İzi çalılıkta kaybettin, boşa yürüdün.", "steps": -60}},
{"text": "➡ Yoluna devam et", "outcome": {"text": "Avı başka zamana bıraktın.", "steps": 0}},
],
},
{
"code": "magara_orumcegi",
"name": "Mağara Örümceği",
"text": "Madenin karanlık bir kovuğunda dev bir örümcek ağını germiş. Ağın arkasında parlayan bir cevher damarı var.",
"locations": ["derin_maden", "ejder_dagi", "tas_ocagi"],
"choices": [
{"text": "⚔ Örümceği öldür", "skill": "combat", "dc": 14,
"success": {"text": "Örümceği alt ettin, damardaki cevheri söktün.",
"items": [{"code": "ore_silver", "qty": 2}],
"xp": {"skill": "combat", "amount": 70}},
"fail": {"text": "Ağa dolandın! Kendini zor kurtardın.", "steps": -120}},
{"text": "🕯 Geri çekil", "outcome": {"text": "O gözlerle uğraşmaya değmez. Geri döndün.", "steps": -30}},
],
},
{
"code": "korsan_yagmasi",
"name": "Korsan Artığı",
"text": "Kıyıya vurmuş kırık bir filika... İçinde kilitli küçük bir para sandığı var. Ama iki serseri de sandığı görmüş, sana doğru geliyorlar.",
"locations": ["liman", "firtina_kiyisi"],
"choices": [
{"text": "⚔ Sandık için dövüş", "skill": "combat", "dc": 15,
"success": {"text": "Serserileri kaçırttın. Sandıktan gold çıktı!",
"gold": 40, "xp": {"skill": "combat", "amount": 80}},
"fail": {"text": "İki kişiye gücün yetmedi, dayak yiyip uzaklaştın.", "steps": -180}},
{"text": "🚶 Sandığı onlara bırak", "outcome": {"text": "Belaya bulaşmadın.", "steps": 0}},
],
},
{
"code": "yasli_avci",
"name": "Yaşlı Avcı",
"text": "Kamp ateşinin başında yaşlı bir avcı oturuyor. 'Otur evlat,' diyor, 'sana av hikâyeleri anlatayım.'",
"locations": ["av_topraklari", "cayirlar"],
"choices": [
{"text": "🔥 Otur ve dinle", "outcome": {"text": "Saatlerce iz sürme ve tuzak kurma taktikleri dinledin.",
"xp": {"skill": "hunting", "amount": 45}, "steps": -40}},
{"text": "🙏 Teşekkür edip geç", "outcome": {"text": "Vaktin yoktu, yola devam ettin.", "steps": 0}},
],
},
{
"code": "balikci_aginda",
"name": "Terk Edilmiş Ağ",
"text": "Kıyıda yarısı suda bir balııı duruyor. İçinde hâlâ çırpınan balıklar var ama ağ kayalara dolanmış.",
"locations": ["aynali_gol", "firtina_kiyisi", "liman"],
"choices": [
{"text": "🎣 Ağı çöz", "skill": "fishing", "dc": 11,
"success": {"text": "ı ustaca çözdün, balıklar senin.",
"items": [{"code": "fish_mackerel", "qty": 2}, {"code": "fish_bream", "qty": 1}],
"xp": {"skill": "fishing", "amount": 40}},
"fail": {"text": "Ağ iyice dolandı, üstüne bir de sırılsıklam oldun.", "steps": -70}},
{"text": "🌊 Denize bırak", "outcome": {"text": "Balıkları özgür bıraktın, için rahat.", "steps": 0}},
],
},
{
"code": "ayi_ini",
"name": "Ayı İni",
"text": "Kadim ormanın derinliklerinde bir in... İçeriden horultu geliyor. Girişte yarım kalmış bir bal peteği duruyor.",
"locations": ["kadim_orman", "karanlik_orman"],
"choices": [
{"text": "⚔ İne gir, ayıyla yüzleş", "skill": "combat", "dc": 16,
"success": {"text": "Efsanevi bir dövüştü. Ayıyı devirdin!",
"items": [{"code": "meat_bear", "qty": 2}, {"code": "leather_bear", "qty": 1}],
"xp": {"skill": "combat", "amount": 100}},
"fail": {"text": "Ayı seni köpek gibi kovaladı. Canını zor kurtardın.", "steps": -250}},
{"text": "🍯 Sadece peteği al ve kaç", "skill": "hunting", "dc": 12,
"success": {"text": "Sessizce peteği kapıp uzaklaştın.",
"items": [{"code": "herb_chamomile", "qty": 2}],
"xp": {"skill": "hunting", "amount": 30}},
"fail": {"text": "Ayı uyandı! Peteği bırakıp kaçtın.", "steps": -100}},
{"text": "🚶 Hiç bulaşma", "outcome": {"text": "Uyuyan ayıyı rahat bıraktın.", "steps": 0}},
],
},
]
async def main() -> None:
dsn = settings.DATABASE_URL.replace("postgresql+asyncpg://", "postgresql://")
conn = await asyncpg.connect(dsn)
for ev in EVENTS:
await conn.execute("""
INSERT INTO events (code, name, text, choices, location_codes)
VALUES ($1, $2, $3, $4::jsonb, $5)
ON CONFLICT (code) DO UPDATE
SET name = EXCLUDED.name, text = EXCLUDED.text,
choices = EXCLUDED.choices, location_codes = EXCLUDED.location_codes
""", ev["code"], ev["name"], ev["text"], json.dumps(ev["choices"]), ev["locations"])
total = await conn.fetchval("SELECT count(*) FROM events")
targeted = await conn.fetchval("SELECT count(*) FROM events WHERE location_codes IS NOT NULL")
print(f"OK — toplam {total} olay ({targeted} lokasyona özel)")
await conn.close()
if __name__ == "__main__":
asyncio.run(main())