""" LifeFlow AI - Core Utilities """ import plotly.graph_objects as go from config import AGENTS_INFO from datetime import datetime def create_agent_stream_output() -> str: """創建 Agent 串流輸出 HTML""" return """
Ready to analyze your tasks...
""" def create_agent_card_enhanced(agent_key: str, status: str = "idle", message: str = "") -> str: """ 創建增強的 Agent 卡片 Args: agent_key: Agent 標識符 status: 狀態 (idle/working/complete) message: 顯示訊息 """ agent = AGENTS_INFO.get(agent_key, {}) avatar = agent.get("avatar", "🤖") name = agent.get("name", "Agent") role = agent.get("role", "") color = agent.get("color", "#4A90E2") glow = agent.get("glow", "rgba(74, 144, 226, 0.3)") status_class = f"status-{status}" card_class = "agent-card active" if status == "working" else "agent-card" status_text = { "idle": "On Standby", "working": "Working...", "complete": "Complete ✓" }.get(status, "Unknown") message_html = f'
{message}
' if message else "" return f"""
{avatar}

{name}

{role}
{status_text} {message_html}
""" def create_task_card(task_num: int, task_title: str, priority: str, time_window: dict, duration: str, location: str, icon: str = "📋") -> str: """創建任務卡片""" priority_color_map = { "HIGH": "#FF6B6B", "MEDIUM": "#F5A623", "LOW": "#7ED321" } if time_window is None: time_window = "Anytime" elif isinstance(time_window, dict): start = time_window.get('earliest_time', None) end = time_window.get('latest_time', None) start = datetime.fromisoformat(start).strftime("%H:%M") if start else "Before" end = datetime.fromisoformat(end).strftime("%H:%M") if end else "After" if start == "Before" and end == "After": time_window = "Anytime" elif start == "After": time_window = f"After {end}" elif end == "Before": time_window = f"Before {start}" else: time_window = f"{start} - {end}" priority_class = f"priority-{priority.lower()}" task_color = priority_color_map.get(priority, "#999") return f"""
{icon} #{task_num}: {task_title}
{priority}
🕐 {time_window}
⏱️ {duration}
📍 {location}
""" def create_summary_card(total_tasks: int, high_priority: int, total_time: int) -> str: """創建摘要卡片""" #style="color: #FF6B6B; return f"""

📋 Task Summary

{total_tasks} Tasks
{high_priority} High Priority
{total_time} min total
""" def create_animated_map(): """創建動畫地圖(模擬)""" fig = go.Figure() # 模擬路線點 lats = [25.033, 25.045, 25.055, 25.040] lons = [121.565, 121.575, 121.585, 121.570] fig.add_trace(go.Scattermapbox( lat=lats, lon=lons, mode='markers+lines', marker=dict(size=12, color='#4A90E2'), line=dict(width=3, color='#50C878'), text=['Start', 'Task 1', 'Task 2', 'End'], hoverinfo='text' )) fig.update_layout( mapbox=dict( style='open-street-map', center=dict(lat=25.043, lon=121.575), zoom=12 ), margin=dict(l=0, r=0, t=0, b=0), height=500 ) return fig def get_reasoning_html_reversed(reasoning_messages: list = None) -> str: """獲取推理過程 HTML(反向排序,最新在上)""" if not reasoning_messages: return '

No reasoning messages yet...

' items_html = "" for msg in reversed(reasoning_messages[-20:]): # 只顯示最近20條,反向 agent_info = AGENTS_INFO.get(msg.get('agent', 'planner'), {}) color = agent_info.get('color', '#4A90E2') avatar = agent_info.get('avatar', '🤖') items_html += f"""
{avatar} {msg.get('agent', 'Agent')} {msg.get('time', '')}
{msg.get('message', '')}
""" return f'
{items_html}
' def create_celebration_animation() -> str: """創建慶祝動畫(純 CSS 撒花效果)- Gradio 兼容版本""" import random # 生成 100 個隨機位置和動畫的撒花元素 confetti_html = "" colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E2'] for i in range(100): left = random.randint(0, 100) delay = random.uniform(0, 2) duration = random.uniform(3, 6) rotation = random.randint(0, 360) color = random.choice(colors) size = random.randint(8, 15) confetti_html += f"""
""" return f"""
{confetti_html}
""" def decode_polyline(polyline_str): """ 解碼 Google Maps Polyline 字符串為 (lat, lng) 列表 純 Python 實現,無需額外依賴 """ index, lat, lng = 0, 0, 0 coordinates = [] changes = {'latitude': 0, 'longitude': 0} while index < len(polyline_str): for unit in ['latitude', 'longitude']: shift, result = 0, 0 while True: byte = ord(polyline_str[index]) - 63 index += 1 result |= (byte & 0x1f) << shift shift += 5 if not byte >= 0x20: break if (result & 1): changes[unit] = ~(result >> 1) else: changes[unit] = (result >> 1) lat += changes['latitude'] lng += changes['longitude'] coordinates.append((lat / 100000.0, lng / 100000.0)) return coordinates def create_result_visualization(task_list: list, structured_data: dict) -> str: """ 創建詳細的結果視覺化卡片 (綁定真實數據) """ # 提取數據 metrics = structured_data.get("metrics", {}) traffic = structured_data.get("traffic_summary", {}) timeline = structured_data.get("timeline", []) # 1. 計算摘要數據 completed_tasks = metrics.get("completed_tasks", 0) total_tasks = metrics.get("total_tasks", 0) total_dist_km = traffic.get("total_distance_km", 0) total_dur_min = traffic.get("total_duration_min", 0) # 格式化時間 (例如 85 min -> 1h 25min) hours = int(total_dur_min // 60) mins = int(total_dur_min % 60) time_str = f"{hours}h {mins}m" if hours > 0 else f"{mins}min" # 2. 優化指標 efficiency = metrics.get("route_efficiency_pct", 90) time_saved_pct = metrics.get("time_improvement_pct", 0) dist_saved_pct = metrics.get("distance_improvement_pct", 0) time_saved_val = metrics.get("time_saved_min", 0) dist_saved_val_km = metrics.get("distance_saved_m", 0) / 1000 html = f"""

🎉 Planning Complete!

Optimized based on real-time traffic & weather

📊 Quick Summary

🎯
{completed_tasks} / {total_tasks}
Tasks Completed
⏱️
{time_str}
Total Duration
🚗
{total_dist_km:.1f} km
Total Distance
{efficiency}%
Efficiency Score

🗓️ Timeline Preview

""" # 綁定時間線數據 # 跳過 start point (index 0) 如果不需要顯示,或者全部顯示 for i, stop in enumerate(timeline): time = stop.get("time", "") loc_name = stop.get("location", "") weather = stop.get("weather", "") travel_time = stop.get("travel_time_from_prev", "") # 簡單的圖標邏輯 icon = "🏁" if i == 0 else ("🔚" if i == len(timeline) - 1 else "📍") html += f"""
{time}
━━
{icon}
{loc_name} {weather}
""" # 添加交通時間 (如果不是最後一個) if i < len(timeline) - 1: next_travel = timeline[i + 1].get("travel_time_from_prev", "0 mins") html += f"""
Drive: {next_travel}
""" html += """

📈 Optimization Metrics

""" # 綁定指標數據 viz_metrics = [ ("Route Efficiency", efficiency, "#50C878"), ("Time Saved", time_saved_pct, "#4A90E2"), ("Distance Reduced", dist_saved_pct, "#F5A623") ] for label, value, color in viz_metrics: # 限制 value 在 0-100 之間顯示 display_val = min(max(value, 0), 100) html += f"""
{label} {value:.1f}%
""" html += f"""
⏱️ Saved: {time_saved_val} min
📏 Reduced: {dist_saved_val_km:.1f} km
""" return html