"""Cross-card pattern analysis — distortion frequency, timing, themes.""" from __future__ import annotations from session import SessionState def analyze_patterns(state: SessionState) -> dict: """Analyze card deck for patterns. Returns dict with: - top_distortions: list of (name, count) sorted by frequency - total_cards: int - card_dates: list of dates - insight: str (generated summary) """ if not state.cards: return { "top_distortions": [], "total_cards": 0, "card_dates": [], "insight": "Complete your first thought record to start seeing patterns.", } top = sorted(state.distortion_counts.items(), key=lambda x: x[1], reverse=True) dates = [c.get("date", "") for c in state.cards] # Generate insight insight = _generate_insight(top, len(state.cards)) return { "top_distortions": top[:5], "total_cards": len(state.cards), "card_dates": dates, "insight": insight, } def _generate_insight(top_distortions: list[tuple[str, int]], total_cards: int) -> str: """Generate a human-readable insight from patterns.""" if not top_distortions: return "Keep going — patterns emerge after a few cards." top_name, top_count = top_distortions[0] if total_cards < 3: return f"Early pattern: {top_name} has come up {top_count} time(s). Let's see if it continues." pct = int((top_count / max(total_cards, 1)) * 100) return ( f"Your most common pattern is {top_name} " f"({top_count} times across {total_cards} cards — {pct}% of sessions). " f"Noticing it is the first step to changing it." ) def get_patterns_html(state: SessionState) -> str: """Render patterns as HTML for the progress panel.""" data = analyze_patterns(state) if not data["top_distortions"]: return """
Complete thought records to reveal your thinking patterns.