Add YAML-driven quest system with context-aware offering:
Core Implementation:
- Quest data models (Quest, QuestObjective, QuestReward, QuestTriggers)
- QuestService for YAML loading and caching
- QuestEligibilityService with level, location, and probability filtering
- LoreService stub (MockLoreService) ready for Phase 6 Weaviate integration
Quest Content:
- 5 example quests across difficulty tiers (2 easy, 2 medium, 1 hard)
- Quest-centric design: quests define their NPC givers
- Location-based probability weights for natural quest offering
AI Integration:
- Quest offering section in npc_dialogue.j2 template
- Response parser extracts [QUEST_OFFER:quest_id] markers
- AI naturally weaves quest offers into NPC conversations
API Endpoints:
- POST /api/v1/quests/accept - Accept quest offer
- POST /api/v1/quests/decline - Decline quest offer
- POST /api/v1/quests/progress - Update objective progress
- POST /api/v1/quests/complete - Complete quest, claim rewards
- POST /api/v1/quests/abandon - Abandon active quest
- GET /api/v1/characters/{id}/quests - List character quests
- GET /api/v1/quests/{quest_id} - Get quest details
Frontend:
- Quest tracker sidebar with HTMX integration
- Quest offer modal for accept/decline flow
- Quest detail modal for viewing progress
- Combat service integration for kill objective tracking
Testing:
- Unit tests for Quest models and serialization
- Integration tests for full quest lifecycle
- Comprehensive test coverage for eligibility service
Documentation:
- Reorganized docs into /docs/phases/ structure
- Added Phase 5-12 planning documents
- Updated ROADMAP.md with new structure
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
195 lines
5.7 KiB
Python
195 lines
5.7 KiB
Python
"""
|
|
Flask application factory for Code of Conquest.
|
|
|
|
Creates and configures the Flask application instance.
|
|
"""
|
|
|
|
import os
|
|
from flask import Flask
|
|
from flask_cors import CORS
|
|
from app.config import get_config
|
|
from app.utils.logging import setup_logging, get_logger
|
|
|
|
|
|
def create_app(environment: str = None) -> Flask:
|
|
"""
|
|
Application factory pattern for creating Flask app.
|
|
|
|
Args:
|
|
environment: Environment name (development, production, etc.)
|
|
If None, uses FLASK_ENV from environment variables.
|
|
|
|
Returns:
|
|
Flask: Configured Flask application instance
|
|
|
|
Example:
|
|
>>> app = create_app('development')
|
|
>>> app.run(debug=True)
|
|
"""
|
|
# Get the path to the project root (parent of 'app' package)
|
|
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
# Create Flask app with correct template and static folders
|
|
app = Flask(
|
|
__name__,
|
|
template_folder=os.path.join(project_root, 'templates'),
|
|
static_folder=os.path.join(project_root, 'static')
|
|
)
|
|
|
|
# Load configuration
|
|
config = get_config(environment)
|
|
|
|
# Configure Flask from config object
|
|
app.config['SECRET_KEY'] = config.secret_key
|
|
app.config['DEBUG'] = config.app.debug
|
|
|
|
# Set up logging
|
|
setup_logging(
|
|
log_level=config.logging.level,
|
|
log_format=config.logging.format,
|
|
log_file=config.logging.file_path if 'file' in config.logging.handlers else None
|
|
)
|
|
|
|
logger = get_logger(__name__)
|
|
logger.info(
|
|
"Starting Code of Conquest",
|
|
version=config.app.version,
|
|
environment=config.app.environment
|
|
)
|
|
|
|
# Configure CORS
|
|
CORS(app, origins=config.cors.origins)
|
|
|
|
# Store config in app context
|
|
app.config['COC_CONFIG'] = config
|
|
|
|
# Register error handlers
|
|
register_error_handlers(app)
|
|
|
|
# Register blueprints (when created)
|
|
register_blueprints(app)
|
|
|
|
logger.info("Application initialized successfully")
|
|
|
|
return app
|
|
|
|
|
|
def register_error_handlers(app: Flask) -> None:
|
|
"""
|
|
Register global error handlers for the application.
|
|
|
|
Args:
|
|
app: Flask application instance
|
|
"""
|
|
from app.utils.response import (
|
|
error_response,
|
|
internal_error_response,
|
|
not_found_response
|
|
)
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
@app.errorhandler(404)
|
|
def handle_404(error):
|
|
"""Handle 404 Not Found errors."""
|
|
logger.warning("404 Not Found", path=error.description)
|
|
return not_found_response()
|
|
|
|
@app.errorhandler(500)
|
|
def handle_500(error):
|
|
"""Handle 500 Internal Server errors."""
|
|
logger.error("500 Internal Server Error", error=str(error), exc_info=True)
|
|
return internal_error_response()
|
|
|
|
@app.errorhandler(Exception)
|
|
def handle_exception(error):
|
|
"""Handle uncaught exceptions."""
|
|
logger.error(
|
|
"Uncaught exception",
|
|
error=str(error),
|
|
error_type=type(error).__name__,
|
|
exc_info=True
|
|
)
|
|
return internal_error_response()
|
|
|
|
|
|
def register_blueprints(app: Flask) -> None:
|
|
"""
|
|
Register Flask blueprints (API routes and web UI views).
|
|
|
|
Args:
|
|
app: Flask application instance
|
|
"""
|
|
logger = get_logger(__name__)
|
|
|
|
# ===== API Blueprints =====
|
|
|
|
# Import and register health check API blueprint
|
|
from app.api.health import health_bp
|
|
app.register_blueprint(health_bp)
|
|
logger.info("Health API blueprint registered")
|
|
|
|
# Import and register auth API blueprint
|
|
from app.api.auth import auth_bp
|
|
app.register_blueprint(auth_bp)
|
|
logger.info("Auth API blueprint registered")
|
|
|
|
# Import and register characters API blueprint
|
|
from app.api.characters import characters_bp
|
|
app.register_blueprint(characters_bp)
|
|
logger.info("Characters API blueprint registered")
|
|
|
|
# Import and register sessions API blueprint
|
|
from app.api.sessions import sessions_bp
|
|
app.register_blueprint(sessions_bp)
|
|
logger.info("Sessions API blueprint registered")
|
|
|
|
# Import and register jobs API blueprint
|
|
from app.api.jobs import jobs_bp
|
|
app.register_blueprint(jobs_bp)
|
|
logger.info("Jobs API blueprint registered")
|
|
|
|
# Import and register game mechanics API blueprint
|
|
from app.api.game_mechanics import game_mechanics_bp
|
|
app.register_blueprint(game_mechanics_bp)
|
|
logger.info("Game Mechanics API blueprint registered")
|
|
|
|
# Import and register travel API blueprint
|
|
from app.api.travel import travel_bp
|
|
app.register_blueprint(travel_bp)
|
|
logger.info("Travel API blueprint registered")
|
|
|
|
# Import and register NPCs API blueprint
|
|
from app.api.npcs import npcs_bp
|
|
app.register_blueprint(npcs_bp)
|
|
logger.info("NPCs API blueprint registered")
|
|
|
|
# Import and register Chat API blueprint
|
|
from app.api.chat import chat_bp
|
|
app.register_blueprint(chat_bp)
|
|
logger.info("Chat API blueprint registered")
|
|
|
|
# Import and register Combat API blueprint
|
|
from app.api.combat import combat_bp
|
|
app.register_blueprint(combat_bp)
|
|
logger.info("Combat API blueprint registered")
|
|
|
|
# Import and register Inventory API blueprint
|
|
from app.api.inventory import inventory_bp
|
|
app.register_blueprint(inventory_bp)
|
|
logger.info("Inventory API blueprint registered")
|
|
|
|
# Import and register Shop API blueprint
|
|
from app.api.shop import shop_bp
|
|
app.register_blueprint(shop_bp)
|
|
logger.info("Shop API blueprint registered")
|
|
|
|
# Import and register Quests API blueprint
|
|
from app.api.quests import quests_bp
|
|
app.register_blueprint(quests_bp)
|
|
logger.info("Quests API blueprint registered")
|
|
|
|
# TODO: Register additional blueprints as they are created
|
|
# from app.api import marketplace
|
|
# app.register_blueprint(marketplace.bp, url_prefix='/api/v1/marketplace')
|