Spaces:
Sleeping
Sleeping
| import logging | |
| from fastapi import APIRouter, Depends, HTTPException, status | |
| from supabase import Client | |
| from app.schemas.cards import LearningDeckRequest, LearningDeckResponse | |
| from app.services.graph_service import get_existing_skills_for_strand | |
| from app.services.llm_service import generate_learning_deck | |
| from app.core.security import get_user_db_client | |
| logger = logging.getLogger(__name__) | |
| router = APIRouter() | |
| async def create_learning_deck( | |
| request: LearningDeckRequest, | |
| db_data: tuple[Client, str] = Depends(get_user_db_client), | |
| ): | |
| db_client, user_id = db_data | |
| try: | |
| # --- 1. MEMORY CHECK (ANTI-CHEAT) --- | |
| # Did the user already scan this exact object under this exact lens? | |
| past_scan = ( | |
| db_client.table("scans") | |
| .select("learning_deck") | |
| .eq("user_id", user_id) | |
| .eq("object_name", request.object_name) | |
| .eq("chosen_lens", request.chosen_lens) | |
| .execute() | |
| ) | |
| if past_scan.data: | |
| # DUPLICATE FOUND: Return the old deck, bypass Gemini, save API costs! | |
| saved_deck = past_scan.data[0]["learning_deck"] | |
| return LearningDeckResponse( | |
| concept_card=saved_deck.get("concept_card", {}), | |
| real_world_card=saved_deck.get("real_world_card", {}), | |
| challenge_card=saved_deck.get("challenge_card", {}), | |
| is_memory=True, # ๐ Flag for the mobile UI | |
| ) | |
| # --- 2. NEW DISCOVERY (Proceed normally) --- | |
| existing_skills = await get_existing_skills_for_strand(request.chosen_lens) | |
| deck = await generate_learning_deck( | |
| object_name=request.object_name, | |
| strand=request.chosen_lens, | |
| grade_level=request.grade_level, | |
| teaser_context=request.teaser_context, | |
| existing_skills=existing_skills, | |
| ) | |
| # Ensure the flag is false for new generations | |
| deck.is_memory = False | |
| return deck | |
| except HTTPException: | |
| raise | |
| except RuntimeError as e: | |
| logger.error(f"Deck Generation Error: {e}") | |
| raise HTTPException( | |
| status_code=status.HTTP_502_BAD_GATEWAY, | |
| detail="Failed to generate the learning deck. The AI might be overloaded.", | |
| ) | |
| except Exception as e: | |
| logger.error(f"Unexpected error in /generate-deck: {e}") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="An internal server error occurred.", | |
| ) | |