stepstead-backend/db/seed_craftables.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

244 lines
12 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.

"""
250 örnek craftable üretir: item + tarif. Idempotent (code üzerinden ON CONFLICT DO NOTHING).
Gruplar: Kerestecilik, Marangozluk, Okçuluk, Metalurji, Demircilik, Kuyumculuk,
Simya, Aşçılık, Dericilik, Balıılık.
Çalıştırma: cd /opt/stepstead && ./venv/bin/python3 db/seed_craftables.py
"""
import asyncio
import json
import sys
import asyncpg
sys.path.insert(0, "/opt/stepstead")
from config import settings
DSN = settings.DATABASE_URL.replace("postgresql+asyncpg://", "postgresql://")
# (kod, Türkçe ad, tier)
WOODS = [
("oak", "Meşe", 1), ("pine", "Çam", 2), ("birch", "Huş", 3), ("beech", "Kayın", 4),
("maple", "Akçaağaç", 5), ("willow", "Söğüt", 6), ("ash", "Dişbudak", 7), ("cedar", "Sedir", 8),
("walnut", "Ceviz", 9), ("cherry", "Kiraz", 10), ("yew", "Porsuk", 11),
("mahogany", "Maun", 12), ("ebony", "Abanoz", 13),
]
METALS = [
("copper", "Bakır", 1), ("bronze", "Bronz", 2), ("iron", "Demir", 3),
("steel", "Çelik", 4), ("silver", "Gümüş", 5), ("gold", "Altın", 6),
]
HERBS = [
("mint", "Nane", 1), ("sage", "Adaçayı", 2), ("thyme", "Kekik", 3), ("chamomile", "Papatya", 4),
("rosemary", "Biberiye", 5), ("basil", "Fesleğen", 6), ("nettle", "Isırgan", 7),
("lemonbalm", "Melisa", 8), ("fennel", "Rezene", 9), ("lavender", "Lavanta", 10),
("ginseng", "Ginseng", 11), ("saffron", "Safran", 12),
]
FISH = [
("carp", "Sazan", 1), ("perch", "Levrek", 2), ("anchovy", "Hamsi", 3), ("mullet", "Kefal", 4),
("mackerel", "Uskumru", 5), ("bonito", "Palamut", 6), ("bluefish", "Lüfer", 7),
("bream", "Çipura", 8), ("trout", "Alabalık", 9), ("pike", "Turna", 10),
("catfish", "Yayın", 11), ("salmon", "Somon", 12), ("turbot", "Kalkan", 13),
("tuna", "Ton Balığı", 14), ("sturgeon", "Mersin", 15),
]
ANIMALS = [
("rabbit", "Tavşan", 1), ("deer", "Geyik", 2), ("boar", "Yaban Domuzu", 3),
("wolf", "Kurt", 4), ("bear", "Ayı", 5),
]
FURNITURE = [("chair", "Sandalye", 3), ("table", "Masa", 4), ("bed", "Yatak", 6),
("cabinet", "Dolap", 5), ("door", "Kapı", 4), ("chest", "Sandık", 5)] # (kod, ad, kereste)
WEAPONS = [("axe", "Balta"), ("pickaxe", "Kazma"), ("sword", "Kılıç"),
("dagger", "Hançer"), ("shield", "Kalkan"), ("armor", "Zırh")]
JEWELRY = [("ring", "Yüzük"), ("necklace", "Kolye"), ("bracelet", "Bilezik")]
LEATHERGOODS = [("bag", "Çanta"), ("belt", "Kemer"), ("boots", "Bot"), ("gloves", "Eldiven")]
def rarity_for(tier: int, max_tier: int) -> str:
r = tier / max_tier
if r <= 0.25:
return "common"
if r <= 0.5:
return "uncommon"
if r <= 0.75:
return "rare"
if r < 1.0:
return "epic"
return "legendary"
items: list[dict] = [] # {code,name,type,rarity,stack_max,description,effect}
recipes: list[dict] = [] # {code,name,out,out_qty,skill,level,xp,steps,ings}
def add_item(code, name, typ, rarity="common", stack=99, desc=None, effect=None):
items.append({"code": code, "name": name, "type": typ, "rarity": rarity,
"stack": stack, "desc": desc, "effect": effect})
def add_recipe(code, name, out, skill, level, xp, steps, ings, out_qty=1):
recipes.append({"code": code, "name": name, "out": out, "out_qty": out_qty,
"skill": skill, "level": min(level, 50), "xp": xp, "steps": steps,
"ings": [{"item_code": c, "qty": q} for c, q in ings]})
def build():
# --- Ham maddeler ---
for w, tr, t in WOODS:
add_item(f"log_{w}", f"{tr} Odunu", "material", rarity_for(t, 13))
for m, tr, t in METALS:
if m in ("bronze", "steel"):
pass # cevheri yok, alaşım
else:
add_item(f"ore_{m}", f"{tr} Cevheri", "material", rarity_for(t, 6))
add_item(f"ingot_{m}", f"{tr} Külçe", "material", rarity_for(t, 6))
add_item("ore_tin", "Kalay Cevheri", "material", "common")
add_item("coal", "Kömür", "material", "common")
for h, tr, t in HERBS:
add_item(f"herb_{h}", f"{tr}", "material", rarity_for(t, 12))
for f, tr, t in FISH:
add_item(f"fish_{f}", f"{tr}", "material", rarity_for(t, 15))
for a, tr, t in ANIMALS:
add_item(f"leather_{a}", f"{tr} Derisi", "material", rarity_for(t, 5))
add_item(f"meat_{a}", f"{tr} Eti", "material", rarity_for(t, 5))
# --- 1) Kerestecilik: 13 kereste ---
for w, tr, t in WOODS:
add_item(f"plank_{w}", f"{tr} Kereste", "material", rarity_for(t, 13))
add_recipe(f"saw_{w}", f"{tr} Kereste", f"plank_{w}", "woodcutting",
max(1, t * 3 - 2), 4 + 2 * t, 2 + t, [(f"log_{w}", 2)], out_qty=2)
# --- 2) Marangozluk: 13 odun × 6 mobilya = 78 ---
for w, wtr, t in WOODS:
for fc, ftr, planks in FURNITURE:
add_item(f"{fc}_{w}", f"{wtr} {ftr}", "furniture", rarity_for(t, 13), stack=10)
add_recipe(f"build_{fc}_{w}", f"{wtr} {ftr}", f"{fc}_{w}", "construction",
max(1, t * 3 - 2), 8 + 3 * t, 4 + t + planks, [(f"plank_{w}", planks)])
# --- 3) Okçuluk: 13 yay + 13 ok = 26 ---
for w, wtr, t in WOODS:
add_item(f"bow_{w}", f"{wtr} Yay", "tool", rarity_for(t, 13), stack=1)
add_recipe(f"craft_bow_{w}", f"{wtr} Yay", f"bow_{w}", "combat",
max(1, t * 3 - 2), 10 + 3 * t, 6 + t, [(f"plank_{w}", 2), ("vine", 1)])
add_item(f"arrow_{w}", f"{wtr} Ok", "material", rarity_for(t, 13))
add_recipe(f"craft_arrow_{w}", f"{wtr} Ok (10)", f"arrow_{w}", "combat",
max(1, t * 3 - 2), 5 + 2 * t, 3 + t, [(f"plank_{w}", 1), ("stone_small", 1)], out_qty=10)
# --- 4) Metalurji: 4 yeni külçe (bakır+demir eritme zaten var) ---
add_recipe("smelt_bronze", "Bronz Külçe", "ingot_bronze", "smithing", 4, 12, 5,
[("ore_copper", 1), ("ore_tin", 1)])
add_recipe("smelt_steel", "Çelik Külçe", "ingot_steel", "smithing", 10, 18, 6,
[("ore_iron", 2), ("coal", 1)])
add_recipe("smelt_silver", "Gümüş Külçe", "ingot_silver", "smithing", 15, 22, 7, [("ore_silver", 2)])
add_recipe("smelt_gold", "Altın Külçe", "ingot_gold", "smithing", 20, 28, 8, [("ore_gold", 2)])
# --- 5) Demircilik: 6 metal × 6 = 36, bakır balta+kazma mevcut → 34 ---
for m, mtr, t in METALS:
for wc, wtr in WEAPONS:
if m == "copper" and wc in ("axe", "pickaxe"):
continue # craft_axe_cu / craft_pick_cu zaten var
code = f"{wc}_{m}"
typ = "tool" if wc in ("axe", "pickaxe") else "gear"
add_item(code, f"{mtr} {wtr}", typ, rarity_for(t, 6), stack=1)
n_ingot = 3 if wc in ("shield", "armor") else 2
add_recipe(f"forge_{wc}_{m}", f"{mtr} {wtr}", code, "smithing",
max(1, t * 5 - 3), 10 + 5 * t, 6 + 2 * t,
[(f"ingot_{m}", n_ingot), ("log_oak", 1)])
# --- 6) Kuyumculuk: gümüş+altın × 3 takı = 6 ---
for m, mtr, t in [("silver", "Gümüş", 5), ("gold", "Altın", 6)]:
for jc, jtr in JEWELRY:
add_item(f"{jc}_{m}", f"{mtr} {jtr}", "gear", rarity_for(t, 6), stack=1)
add_recipe(f"jewel_{jc}_{m}", f"{mtr} {jtr}", f"{jc}_{m}", "smithing",
t * 5, 15 + 4 * t, 8, [(f"ingot_{m}", 1)])
# --- 7) Simya: 12 ot × 3 = 36, nane çayı mevcut → 35 ---
for h, htr, t in HERBS:
if h != "mint": # brew_tea_mint zaten var
add_item(f"tea_{h}", f"{htr} Çayı", "consumable", rarity_for(t, 12),
desc=f"Adım bakiyesini +{40 + 5 * t} yeniler.",
effect={"type": "steps", "amount": 40 + 5 * t})
add_recipe(f"brew_tea_{h}", f"{htr} Çayı", f"tea_{h}", "alchemy",
max(1, t * 4 - 3), 6 + 2 * t, 4, [(f"herb_{h}", 2)])
add_item(f"potion_{h}", f"{htr} İksiri", "consumable", rarity_for(t, 12),
desc=f"Adım bakiyesini +{80 + 10 * t} yeniler.",
effect={"type": "steps", "amount": 80 + 10 * t})
add_recipe(f"brew_potion_{h}", f"{htr} İksiri", f"potion_{h}", "alchemy",
min(50, t * 4), 12 + 3 * t, 6, [(f"herb_{h}", 3), ("vine", 1)])
add_item(f"salve_{h}", f"{htr} Merhemi", "consumable", rarity_for(t, 12),
desc="İyileştirici merhem (gelecek özellik).")
add_recipe(f"brew_salve_{h}", f"{htr} Merhemi", f"salve_{h}", "alchemy",
min(50, t * 4 + 1), 10 + 3 * t, 5, [(f"herb_{h}", 2), ("stone_small", 1)])
# --- 8) Aşçılık: 14 balık (sazan mevcut) + 5 et × 3 = 29 ---
for f, ftr, t in FISH:
if f == "carp":
continue # cook_carp zaten var
add_item(f"cooked_{f}", f"Izgara {ftr}", "consumable", rarity_for(t, 15),
desc=f"Adım bakiyesini +{25 + 3 * t} yeniler.",
effect={"type": "steps", "amount": 25 + 3 * t})
add_recipe(f"cook_{f}", f"Izgara {ftr}", f"cooked_{f}", "cooking",
max(1, t * 3 - 2), 6 + 2 * t, 4, [(f"fish_{f}", 1)])
for a, atr, t in ANIMALS:
for mc, mtr, bonus in [("grilled", "Izgara", 30), ("stew", "Güveç", 50), ("dried", "Kurutulmuş", 40)]:
add_item(f"{mc}_{a}", f"{mtr} {atr} Eti", "consumable", rarity_for(t, 5),
desc=f"Adım bakiyesini +{bonus + 8 * t} yeniler.",
effect={"type": "steps", "amount": bonus + 8 * t})
ings = [(f"meat_{a}", 1)] if mc != "stew" else [(f"meat_{a}", 1), ("herb_mint", 1)]
add_recipe(f"cook_{mc}_{a}", f"{mtr} {atr} Eti", f"{mc}_{a}", "cooking",
min(50, t * 6), 8 + 4 * t, 5, ings)
# --- 9) Dericilik: 5 deri × 4 = 20 ---
for a, atr, t in ANIMALS:
for lc, ltr in LEATHERGOODS:
add_item(f"{lc}_{a}", f"{atr} Derisi {ltr}", "gear", rarity_for(t, 5), stack=1)
add_recipe(f"tailor_{lc}_{a}", f"{atr} Derisi {ltr}", f"{lc}_{a}", "hunting",
min(50, t * 7 - 4), 10 + 5 * t, 6 + t, [(f"leather_{a}", 2), ("vine", 1)])
# --- 10) Balıılık: 2 gelişmiş olta ---
add_item("fishing_rod_fine", "Usta Oltası", "tool", "rare", stack=1)
add_recipe("craft_rod_fine", "Usta Oltası", "fishing_rod_fine", "fishing", 10, 25, 8,
[("plank_willow", 2), ("vine", 2)])
add_item("fishing_rod_master", "Efsane Olta", "tool", "epic", stack=1)
add_recipe("craft_rod_master", "Efsane Olta", "fishing_rod_master", "fishing", 25, 50, 12,
[("plank_yew", 2), ("vine", 3), ("ingot_silver", 1)])
# --- 11) İnşaat ekstra: 3 ---
add_item("campfire", "Kamp Ateşi", "furniture", "common", stack=10)
add_recipe("build_campfire", "Kamp Ateşi", "campfire", "construction", 1, 8, 5,
[("stick", 3), ("stone_small", 2)])
add_item("fence", "Çit", "furniture", "common", stack=50)
add_recipe("build_fence", "Çit", "fence", "construction", 2, 6, 4, [("plank_pine", 1), ("vine", 1)])
add_item("sign", "Tabela", "furniture", "common", stack=20)
add_recipe("build_sign", "Tabela", "sign", "construction", 1, 5, 3, [("plank_oak", 1), ("stick", 1)])
async def main():
build()
print(f"Üretilen: {len(recipes)} tarif, {len(items)} item tanımı")
assert len(recipes) == 250, f"250 bekleniyor, {len(recipes)} üretildi"
conn = await asyncpg.connect(DSN)
ins_i = 0
for it in items:
r = await conn.execute("""
INSERT INTO items (code, name, type, rarity, stack_max, description, effect)
VALUES ($1,$2,$3,$4,$5,$6,$7) ON CONFLICT (code) DO NOTHING
""", it["code"], it["name"], it["type"], it["rarity"], it["stack"],
it["desc"], json.dumps(it["effect"]) if it["effect"] else None)
ins_i += int(r.endswith("1"))
ins_r = 0
for rc in recipes:
r = await conn.execute("""
INSERT INTO recipes (code, name, output_item_id, output_qty, skill, required_level,
xp_reward, step_cost, ingredients)
SELECT $1,$2,i.id,$3,$4,$5,$6,$7,$8::jsonb FROM items i WHERE i.code=$9
ON CONFLICT (code) DO NOTHING
""", rc["code"], rc["name"], rc["out_qty"], rc["skill"], rc["level"],
rc["xp"], rc["steps"], json.dumps(rc["ings"]), rc["out"])
ins_r += int(r.endswith("1"))
ti = await conn.fetchval("SELECT count(*) FROM items")
tr = await conn.fetchval("SELECT count(*) FROM recipes")
await conn.close()
print(f"DB'ye eklendi: {ins_i} item, {ins_r} tarif. Toplam: {ti} item, {tr} tarif.")
asyncio.run(main())