import re import requests API_URL = "http://127.0.0.1:8000/analyze" MAX_FILES = 5 def parse_score_value(raw_score): match = re.search(r"\d+(?:\.\d+)?", str(raw_score)) return float(match.group()) if match else None def clean_text(value, fallback="Not available yet."): text = str(value).strip() if value is not None else "" return text if text else fallback def clean_list(value): if isinstance(value, list): return [str(item).strip() for item in value if str(item).strip()] if value is None: return [] text = str(value).strip() return [text] if text else [] def count_files(uploaded_files): return len(uploaded_files) if uploaded_files else 0 def normalize_files(uploaded_files): if not uploaded_files: return [] return list(uploaded_files[:MAX_FILES]) def interest_to_percent(value): text = str(value or "").lower() mapping = { "very high": 92, "high": 82, "medium": 58, "mixed": 46, "low": 28, "very low": 14, } for key, score in mapping.items(): if key in text: return score return 50 def get_emotional_signal(score_value): if score_value is None: return ( "AI signal", "The emotional pattern is still forming." ) if score_value >= 80: return ( "Deep resonance", "The connection reads warm, mutual, and emotionally available." ) if score_value >= 60: return ( "Promising energy", "There is meaningful interest here, but clarity still matters." ) if score_value >= 40: return ( "Mixed signals", "The attraction may be real, but the emotional consistency is uneven." ) return ( "Guarded connection", "Protect your energy and look for stronger reciprocity before investing more." ) def analyze_payload( chat, feelings, uploaded_files, user_perspective="", emotional_goal="", conversation_consistency="" ): selected_files = normalize_files(uploaded_files) files_payload = [] for file in selected_files: try: file.seek(0) files_payload.append( ( "files", ( file.name, file.read(), file.type or "image/png" ) ) ) except Exception as e: print("FILE ERROR:", e) response = requests.post( API_URL, data={ "chat": chat, "feelings": feelings, "user_perspective": user_perspective, "emotional_goal": emotional_goal, "conversation_consistency": conversation_consistency, }, files=files_payload, timeout=300, ) print("STATUS CODE:", response.status_code) print("RESPONSE:", response.text) response.raise_for_status() return response.json() def detect_perspective_payload( chat, feelings, uploaded_files ): selected_files = normalize_files(uploaded_files) files_payload = [] for file in selected_files: try: file.seek(0) files_payload.append( ( "files", ( file.name, file.read(), file.type or "image/png" ) ) ) except Exception as e: print("PERSPECTIVE FILE ERROR:", e) url = "http://127.0.0.1:8000/detect_perspective" response = requests.post( url, data={ "chat": chat, "feelings": feelings, }, files=files_payload, timeout=300, ) print("PERSPECTIVE STATUS:", response.status_code) print("PERSPECTIVE RESPONSE:", response.text) response.raise_for_status() return response.json() def build_people_cards(analysis, feelings): analyst = analysis.get("analyst", {}) psychology = analysis.get("psychology", {}) interest_level = clean_text( analyst.get("interest_level"), "Unclear" ) emotional_tone = clean_text( analyst.get("emotional_tone"), "Unreadable" ) partner_intent = clean_text( psychology.get("partner_intent"), "Unclear intent" ) user_intent = clean_text( psychology.get("user_intent"), "Clarifying feelings" ) feelings_text = f"{feelings} {user_intent}".lower() partner_text = ( f"{interest_level} " f"{emotional_tone} " f"{partner_intent}" ).lower() if any(word in feelings_text for word in [ "break up", "breakup", "leave", "dont love", "don't love", "end it", "distance" ]): you = { "label": "You", "emoji": "💔", "title": "Ready to step back", "description": ( "Your side reads emotionally detached " "and focused on ending this respectfully." ), "percent": 90, "meter_label": "Clarity", } elif any(word in feelings_text for word in [ "confused", "unsure", "mixed", "idk" ]): you = { "label": "You", "emoji": "🫧", "title": "Still sorting feelings", "description": ( "You sound uncertain and are looking " "for emotional clarity before acting." ), "percent": 58, "meter_label": "Certainty", } else: you = { "label": "You", "emoji": "🩷", "title": clean_text( user_intent, "Emotionally engaged" ), "description": ( "Your side still sounds invested in " "understanding what this connection means." ), "percent": 72, "meter_label": "Investment", } if any(word in partner_text for word in [ "cold", "dry", "avoidant", "disinterest", "ignoring", "distance", "very low", "low" ]): partner = { "label": "Them", "emoji": "🧊", "title": "Emotionally cold", "description": ( "Their side reads short, guarded, " "and low-effort rather than warm or reassuring." ), "percent": 24, "meter_label": "Warmth", } elif any(word in partner_text for word in [ "mixed", "unclear" ]): partner = { "label": "Them", "emoji": "🤍", "title": "Mixed energy", "description": ( "They are giving some signal, but not enough " "consistency to feel fully safe or clear." ), "percent": 48, "meter_label": "Warmth", } else: partner = { "label": "Them", "emoji": "😍", "title": clean_text( interest_level, "Interested" ), "description": ( "Their tone and effort look more emotionally " "open and invested." ), "percent": interest_to_percent( interest_level ), "meter_label": "Warmth", } return [you, partner] def build_story_cards(analysis): analyst = analysis.get("analyst", {}) psychology = analysis.get("psychology", {}) strategy = analysis.get("strategy", {}) cards = [ { "emoji": "🔎", "title": "Truth", "body": clean_text(strategy.get("truth")), "tone": "pink", }, { "emoji": "⚠️", "title": "Risk", "body": clean_text(strategy.get("warning")), "tone": "amber", }, { "emoji": "🧭", "title": "Best next move", "body": clean_text(strategy.get("action_advice")), "tone": "violet", }, { "emoji": "🫠", "title": "Hidden meaning", "body": clean_text( analyst.get("hidden_meaning") ), "tone": "rose", }, { "emoji": "🧠", "title": "Psych dynamic", "body": clean_text( psychology.get("psychological_dynamic") ), "tone": "indigo", }, { "emoji": "⚖️", "title": "Leverage", "body": clean_text(strategy.get("leverage_assessment")), "tone": "slate", }, { "emoji": "📈", "title": "Trajectory", "body": clean_text(strategy.get("trajectory")), "tone": "amber", }, ] for reply in clean_list( strategy.get("suggested_replies") )[:3]: cards.append( { "emoji": "💬", "title": "Suggested reply", "body": reply, "tone": "slate", } ) return cards def build_key_insight_cards(analysis): analyst = analysis.get("analyst", {}) strategy = analysis.get("strategy", {}) return [ { "emoji": "⚠️", "title": "Risk", "body": clean_text(strategy.get("warning")), "tone": "amber", }, { "emoji": "🫠", "title": "Hidden meaning", "body": clean_text( analyst.get("hidden_meaning") ), "tone": "rose", }, { "emoji": "🧭", "title": "Best next step", "body": clean_text( strategy.get("action_advice") ), "tone": "violet", }, ] def default_swipe_profiles(): return [ { "name": "Aarav", "age": 26, "bio": ( "Warm texter, quick replies, " "values direct communication " "and emotional consistency." ), "compatibility": 72, "emotional_availability": "Open but cautious", "red_flags": ( "Can pull back if conversations " "become unclear." ), "communication_style": ( "Clear, affectionate, reassurance-seeking" ), "theme": "rose", "emoji": "😊", }, { "name": "Maya", "age": 24, "bio": ( "Playful energy, strong chemistry, " "but can be inconsistent when overwhelmed." ), "compatibility": 64, "emotional_availability": "Mixed signals", "red_flags": ( "Hot-cold rhythm and unclear follow-through." ), "communication_style": ( "Flirty, reactive, emotionally uneven" ), "theme": "violet", "emoji": "🥰", }, ]