"""Session management and progress tracking functionality""" import uuid class SessionManager: """Manages user session state and progress tracking""" def __init__(self, session_id=None, data_manager=None, achievement_system=None): self.session_id = session_id or str(uuid.uuid4()) self.data_manager = data_manager self.achievement_system = achievement_system def get_session_statistics(self): """Get statistics for the current session.""" if not self.data_manager: return self._get_empty_session_stats() all_results = self.data_manager.get_results() session_results = self.data_manager.filter_results_by_session(all_results, self.session_id) if not session_results: return self._get_empty_session_stats() scores = [r["cosine_distance"] for r in session_results] unique_prompts = set((r["prompt"], r["llm_partial_response"]) for r in session_results) return { "total_attempts": len(session_results), "best_score": max(scores), "average_score": sum(scores) / len(scores), "total_tokens_used": sum(r["num_user_tokens"] for r in session_results), "prompts_tried": len(unique_prompts), "session_results": session_results } def _get_empty_session_stats(self): """Return empty session statistics structure""" return { "total_attempts": 0, "best_score": 0.0, "average_score": 0.0, "total_tokens_used": 0, "prompts_tried": 0 } def generate_session_progress_html(self, template_renderer): """Generate HTML for session progress display.""" stats = self.get_session_statistics() if stats["total_attempts"] == 0: return template_renderer.load_template("session-progress-empty.html") # Create achievement summary for session session_achievements = set() if self.achievement_system and "session_results" in stats: for result in stats["session_results"]: achievements = self.achievement_system.determine_achievement_titles( result["cosine_distance"], result["num_user_tokens"] ) session_achievements.update(achievements) achievement_badges = "" if session_achievements: badges_html = "" for achievement in list(session_achievements)[:5]: # Show top 5 badges_html += template_renderer.load_template("achievement-badge.html", achievement=achievement) achievement_badges = template_renderer.load_template("session-achievements.html", achievement_badges=badges_html) # Recent attempts preview recent_attempts = sorted(stats["session_results"], key=lambda x: x["timestamp"], reverse=True)[:3] attempts_html = "" for i, attempt in enumerate(recent_attempts, 1): score_color = "#4CAF50" if attempt["cosine_distance"] >= 0.3 else "#FF9800" if attempt["cosine_distance"] >= 0.15 else "#9E9E9E" user_input = attempt['user_continuation'][:30] + ('...' if len(attempt['user_continuation']) > 30 else '') plural = "s" if attempt["num_user_tokens"] != 1 else "" attempt_number = len(stats["session_results"]) - i + 1 attempts_html += template_renderer.load_template("attempt-item.html", attempt_number=attempt_number, user_input=user_input, score_color=score_color, cosine_distance=attempt["cosine_distance"], num_tokens=attempt["num_user_tokens"], plural=plural ) recent_html = template_renderer.load_template("recent-attempts.html", attempts=attempts_html) return template_renderer.load_template("session-progress-main.html", total_attempts=stats['total_attempts'], best_score=stats['best_score'], average_score=stats['average_score'], prompts_tried=stats['prompts_tried'], achievement_badges=achievement_badges, recent_html=recent_html ) def generate_session_page_html(self, template_renderer, statistics_calculator=None, scorer=None): """Generate comprehensive session page HTML with ranking information.""" stats = self.get_session_statistics() if stats["total_attempts"] == 0: empty_html = template_renderer.load_template("session-page-empty.html") return empty_html, "", "" # Calculate ranking statistics ranking_stats = {} if statistics_calculator and scorer and "session_results" in stats: ranking_stats = statistics_calculator.calculate_session_ranking_stats( stats["session_results"], self.data_manager, scorer ) # Main stats overview best_attempt = max(stats["session_results"], key=lambda x: x["cosine_distance"]) recent_attempts = sorted(stats["session_results"], key=lambda x: x["timestamp"], reverse=True)[:5] # Determine trend icon and message trend_icon = {"up": "📈", "down": "📉", "stable": "📊"}.get(ranking_stats.get("ranking_trend", "stable"), "📊") trend_message = { "up": "Improving!", "down": "Room to grow", "stable": "Consistent" }.get(ranking_stats.get("ranking_trend", "stable"), "Consistent") main_stats_html = f"""
{stats['total_attempts']}
Creative Attempts
{stats['best_score']:.3f}
Personal Best
{stats['average_score']:.3f}
Average Score
""" # Add ranking stats if available if ranking_stats.get("total_ranked_attempts", 0) > 0: main_stats_html += f"""
#{ranking_stats['best_rank']}
Best Rank
{ranking_stats['average_percentile']:.0f}%
Avg vs Others
""" else: main_stats_html += f"""
{stats['prompts_tried']}
Prompts Explored
""" main_stats_html += f"""

🎯 Your Best Response

"{best_attempt['user_continuation']}"
Score: {best_attempt['cosine_distance']:.3f}""" # Add ranking info for best attempt if available if ranking_stats.get("total_ranked_attempts", 0) > 0 and "recent_percentiles" in ranking_stats: best_ranking = next((r for r in ranking_stats["recent_percentiles"] if abs(float(r["timestamp"].replace('-', '').replace(':', '').replace('T', '').replace('.', '')[:14]) - float(best_attempt["timestamp"].replace('-', '').replace(':', '').replace('T', '').replace('.', '')[:14])) < 1000), None) if best_ranking: main_stats_html += f""" #{best_ranking['rank']} of {best_ranking['total']}""" main_stats_html += f"""
""" # Add trend information if sufficient data if ranking_stats.get("total_ranked_attempts", 0) >= 2: main_stats_html += f"""
{trend_icon} Ranking Trend: {trend_message} ({ranking_stats['total_ranked_attempts']} ranked attempts)
""" main_stats_html += f"""
""" # Enhanced detailed history with ranking history_html = """
""" for i, attempt in enumerate(recent_attempts, 1): score_color = "#4CAF50" if attempt["cosine_distance"] >= 0.3 else "#FF9800" if attempt["cosine_distance"] >= 0.15 else "#9E9E9E" # Truncate long inputs for display display_input = attempt['user_continuation'][:50] + ('...' if len(attempt['user_continuation']) > 50 else '') # Find ranking info for this attempt ranking_info = None if "recent_percentiles" in ranking_stats: ranking_info = next((r for r in ranking_stats["recent_percentiles"] if r["timestamp"] == attempt["timestamp"]), None) history_html += f"""
#{len(stats["session_results"]) - i + 1}
"{display_input}"
{attempt['timestamp'][:10]} {attempt['timestamp'][11:16]}""" if ranking_info: # Add percentile indicator percentile = ranking_info["percentile"] percentile_color = "#4CAF50" if percentile >= 75 else "#FF9800" if percentile >= 50 else "#9E9E9E" percentile_icon = "🏆" if percentile >= 90 else "⭐" if percentile >= 75 else "📈" if percentile >= 50 else "🎯" history_html += f""" {percentile_icon} #{ranking_info['rank']} of {ranking_info['total']} ({percentile:.0f}%) """ else: history_html += f""" 🌱 First attempt at this prompt+token combo """ history_html += f"""
{attempt["cosine_distance"]:.3f} {attempt["num_user_tokens"]} tokens
""" if len(recent_attempts) < len(stats["session_results"]): remaining = len(stats["session_results"]) - len(recent_attempts) history_html += f"""
...
And {remaining} more creative attempts!
📊 View all attempts for complete ranking history
📈
""" history_html += """
""" # Achievements all_achievements = set() if self.achievement_system and "session_results" in stats: for result in stats["session_results"]: achievements = self.achievement_system.determine_achievement_titles( result["cosine_distance"], result["num_user_tokens"] ) all_achievements.update(achievements) achievements_html = """
""" if all_achievements: achievements_html += """
""" for achievement in sorted(all_achievements): achievements_html += f'
{achievement}
' achievements_html += """
""" else: achievements_html += """
🏆 Keep being creative to unlock achievements! Try different token counts and creative approaches.
""" achievements_html += """
""" return main_stats_html, history_html, achievements_html