built routes for creation of char

This commit is contained in:
2025-11-03 21:42:39 -06:00
parent 6efd3b3aa8
commit 0c83f8cb1a
6 changed files with 188 additions and 10 deletions

View File

@@ -1,8 +1,15 @@
from flask import Blueprint, g, jsonify, current_app from flask import Blueprint, g, request, jsonify, current_app
from typing import cast from typing import cast
from app.utils.typed_flask import CoCFlask from dataclasses import asdict
# from app.services.appwrite_client import AppWriteClient from app.utils.typed_flask import CoCFlask
from app.utils.session_user import SessionUser, import_g_session
from app.game.generators.entity_factory import build_char
from app.services.appwrite_db import AppwriteTables
from app.utils.logging import get_logger
logging = get_logger(__file__)
# type cast flask to my custom flask app so the app.api methods are available in the IDE / typed correctly. # type cast flask to my custom flask app so the app.api methods are available in the IDE / typed correctly.
app = cast(CoCFlask,current_app) app = cast(CoCFlask,current_app)
@@ -10,8 +17,36 @@ app = cast(CoCFlask,current_app)
# blueprint def # blueprint def
char_bp = Blueprint("char", __name__, url_prefix="/char") char_bp = Blueprint("char", __name__, url_prefix="/char")
# return CURRENT USER
# {"user":g.appwrite_user}
@char_bp.route("/", methods=["GET", "POST"]) @char_bp.route("/new", methods=["POST"])
def char(): def new():
return app.api.ok({"user":g.appwrite_user}) api_user = import_g_session(g.appwrite_user)
data = request.get_json(silent=True)
name = data.get("name")
origin_story = data.get("origin_story")
race_id = data.get("race_id")
profession_id = data.get("profession_id")
try:
player = build_char(name=name,origin_story=origin_story,race_id=race_id,profession_id=profession_id)
player_dict = asdict(player)
uuid = player.uuid
tablesdb = AppwriteTables()
tablesdb.save_character_for_user_id(api_user.id,player_dict)
logging.info(f"Created char {uuid} for {api_user.id} - {api_user.name} - {api_user.email}")
except Exception as e:
logging.error(f"Unable to create char for user: {api_user.id} due to {e}")
player_dict = {}
uuid = player_dict.get("uuid",{})
print(f"Returned {uuid}")
return app.api.ok(uuid)

View File

@@ -51,6 +51,9 @@ PATH_THEMES = _load_path_themes(themes_filename)
# ----------------- Generator ----------------- # ----------------- Generator -----------------
def generate_abilities_direct_damage(class_name: str,path: str,level: int, primary_stat:str , per_tier: int = 2,content_version: int = 1) -> List[Ability]: def generate_abilities_direct_damage(class_name: str,path: str,level: int, primary_stat:str , per_tier: int = 2,content_version: int = 1) -> List[Ability]:
if path not in PATH_THEMES:
return []
theme = PATH_THEMES[path] theme = PATH_THEMES[path]
rng = random.Random(_stable_seed(class_name, path, level, per_tier, version=content_version)) rng = random.Random(_stable_seed(class_name, path, level, per_tier, version=content_version))
spells: List[Ability] = [] spells: List[Ability] = []

View File

@@ -13,24 +13,25 @@ dice = Dice()
progression = DEFAULT_LEVEL_PROGRESSION progression = DEFAULT_LEVEL_PROGRESSION
def build_char(name:str, origin_story:str, race_id:str, profession_id:str,ability_pathway:str,level:int=1) -> Entity: def build_char(name:str, origin_story:str, race_id:str, profession_id:str,ability_pathway:str="",level:int=1) -> Entity:
races = RaceRepository() races = RaceRepository()
professions = ProfessionRepository() professions = ProfessionRepository()
race = races.get(race_id) race = races.get(race_id)
profession = professions.get(profession_id) profession = professions.get(profession_id)
profession.ability_paths
e = Entity( e = Entity(
uuid = str(uuid.uuid4()), uuid = str(uuid.uuid4()),
name = name, name = name,
origin_story = origin_story, origin_story = origin_story,
race =race, race =race,
ability_pathway=ability_pathway,
profession = profession profession = profession
) )
if ability_pathway != "":
e.ability_pathway=ability_pathway
# apply race ability scores # apply race ability scores
for stat, delta in vars(race.ability_scores).items(): for stat, delta in vars(race.ability_scores).items():

102
app/services/appwrite_db.py Normal file
View File

@@ -0,0 +1,102 @@
from __future__ import annotations
import os
from dataclasses import dataclass, asdict
from enum import StrEnum
from typing import Final, Optional
from flask import current_app
from appwrite.client import Client
from appwrite.services.tables_db import TablesDB
from appwrite.query import Query
from appwrite.id import ID
from app.game.models.entities import Entity
from app.utils.logging import get_logger
from app.utils.settings import get_settings, Environment
settings = get_settings()
logger = get_logger(__file__)
class Env(StrEnum):
PROD = "prod"
DEV = "dev"
# --- Database schemas (strongly-typed namespaces) ----------------------------
@dataclass(frozen=True)
class Database:
"""Schema for a single database: each attribute is a table name (or ID)."""
id: str
characters: str
inventory: str
# add more tables here as you grow your schema
@dataclass(frozen=True)
class Databases:
"""Top-level namespace exposing prod/dev as attributes."""
prod: Database
dev: Database
DB: Final[Databases] = Databases(
prod=Database(
id="SETME", # actual DB / ID
characters="SETME", # actual table / ID
inventory="inventory",
),
dev=Database(
id="69041f9600177b675485",
characters="69050f830024afb0d253",
inventory="inventory",
),
)
class AppwriteTables:
def __init__(self):
print()
self.client = (Client()
.set_endpoint(settings.appwrite_endpoint)
.set_project(settings.appwrite_project_id)
.set_key(settings.appwrite_api_key)
)
self.tables_db = TablesDB(self.client)
self.env = Env.DEV
if settings.env == Environment.PROD:
self.env = Env.PROD
@property
def db(self) -> Database:
# Gives autocompletion for .character, .users, etc.
return DB.prod if self.env is Env.PROD else DB.dev
def get_characters_for_user_id(self, user_id: str) -> Optional[dict]:
try:
result = self.tables_db.list_rows(
self.db.id,
self.db.characters,
[
Query.equal('player_id', [str(user_id)]),
]
)
except Exception as e:
logger.error(f"Unable to list rows for char. User id: {user_id}")
return {}
return result.get("rows",{})
def save_character_for_user_id(self, user_id:str, player_dict:dict):
result = self.tables_db.create_row(
database_id = self.db.id,
table_id = self.db.characters,
row_id = ID.unique(),
data = {
"player_id": str(user_id),
"char_data": str(player_dict),
},
)
print(result)
return result

37
app/utils/session_user.py Normal file
View File

@@ -0,0 +1,37 @@
from dataclasses import dataclass
from typing import Optional, cast
@dataclass
class SessionUser:
id: str = ""
registered_on: str = ""
name: str = ""
email: str = ""
email_verified: bool = False
phone: str = ""
phone_verified: bool = False
mfa: bool = False
@property
def is_authenticated(self) -> bool:
return True
@property
def email_verification(self) -> bool:
return self.email_verified
@property
def phone_verification(self) -> bool:
return self.phone_verification
def import_g_session(g_session:dict) -> SessionUser:
u = SessionUser(
id=g_session.get("$id"),
name=g_session.get("name"),
registered_on=g_session.get("registration"),
email=g_session.get("email"),
email_verified=g_session.get("emailVerification")
)
return u