""" Worksheet Editor Models — Enums, Pydantic models, and configuration. """ import os import logging from typing import Optional, List, Dict from enum import Enum from pydantic import BaseModel, Field logger = logging.getLogger(__name__) # ============================================= # CONFIGURATION # ============================================= OLLAMA_URL = os.getenv("OLLAMA_URL", "http://host.docker.internal:11434") SD_MODEL = os.getenv("SD_MODEL", "stable-diffusion") # or specific SD model WORKSHEET_STORAGE_DIR = os.getenv("WORKSHEET_STORAGE_DIR", os.path.join(os.path.dirname(os.path.abspath(__file__)), "worksheet-storage")) # Ensure storage directory exists os.makedirs(WORKSHEET_STORAGE_DIR, exist_ok=True) # ============================================= # ENUMS & MODELS # ============================================= class AIImageStyle(str, Enum): REALISTIC = "realistic" CARTOON = "cartoon" SKETCH = "sketch" CLIPART = "clipart" EDUCATIONAL = "educational" class WorksheetStatus(str, Enum): DRAFT = "draft" PUBLISHED = "published" ARCHIVED = "archived" # Style prompt modifiers STYLE_PROMPTS = { AIImageStyle.REALISTIC: "photorealistic, high detail, professional photography", AIImageStyle.CARTOON: "cartoon style, colorful, child-friendly, simple shapes", AIImageStyle.SKETCH: "pencil sketch, hand-drawn, black and white, artistic", AIImageStyle.CLIPART: "clipart style, flat design, simple, vector-like", AIImageStyle.EDUCATIONAL: "educational illustration, clear, informative, textbook style" } # ============================================= # REQUEST/RESPONSE MODELS # ============================================= class AIImageRequest(BaseModel): prompt: str = Field(..., min_length=3, max_length=500) style: AIImageStyle = AIImageStyle.EDUCATIONAL width: int = Field(512, ge=256, le=1024) height: int = Field(512, ge=256, le=1024) class AIImageResponse(BaseModel): image_base64: str prompt_used: str error: Optional[str] = None class PageData(BaseModel): id: str index: int canvasJSON: str class PageFormat(BaseModel): width: float = 210 height: float = 297 orientation: str = "portrait" margins: Dict[str, float] = {"top": 15, "right": 15, "bottom": 15, "left": 15} class WorksheetSaveRequest(BaseModel): id: Optional[str] = None title: str description: Optional[str] = None pages: List[PageData] pageFormat: Optional[PageFormat] = None class WorksheetResponse(BaseModel): id: str title: str description: Optional[str] pages: List[PageData] pageFormat: PageFormat createdAt: str updatedAt: str class AIModifyRequest(BaseModel): prompt: str = Field(..., min_length=3, max_length=1000) canvas_json: str model: str = "qwen2.5vl:32b" class AIModifyResponse(BaseModel): modified_canvas_json: Optional[str] = None message: str error: Optional[str] = None class ReconstructRequest(BaseModel): session_id: str page_number: int = 1 include_images: bool = True regenerate_graphics: bool = False class ReconstructResponse(BaseModel): canvas_json: str page_width: int page_height: int elements_count: int vocabulary_matched: int message: str error: Optional[str] = None # ============================================= # IN-MEMORY STORAGE (Development) # ============================================= worksheets_db: Dict[str, Dict] = {} # PDF Generation availability try: from reportlab.lib import colors # noqa: F401 from reportlab.lib.pagesizes import A4 # noqa: F401 from reportlab.lib.units import mm # noqa: F401 from reportlab.pdfgen import canvas # noqa: F401 from reportlab.lib.styles import getSampleStyleSheet # noqa: F401 REPORTLAB_AVAILABLE = True except ImportError: REPORTLAB_AVAILABLE = False