| 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": "π₯°", |
| }, |
| ] |