Spaces:
Build error
Build error
Upload 2 files
Browse files
reports/__pycache__/progress_report.cpython-312.pyc
ADDED
|
Binary file (11.8 kB). View file
|
|
|
reports/progress_report.py
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sqlite3
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import matplotlib.pyplot as plt
|
| 4 |
+
import seaborn as sns
|
| 5 |
+
from reportlab.lib.pagesizes import A4
|
| 6 |
+
from reportlab.pdfgen import canvas
|
| 7 |
+
from reportlab.lib.units import inch
|
| 8 |
+
import os
|
| 9 |
+
import tempfile
|
| 10 |
+
import streamlit as st
|
| 11 |
+
import numpy as np
|
| 12 |
+
|
| 13 |
+
def show_progress_report(name):
|
| 14 |
+
st.title("π Weekly Progress Report")
|
| 15 |
+
|
| 16 |
+
# Connect to DB and fetch session IDs
|
| 17 |
+
conn = sqlite3.connect("data/mindmentor.db")
|
| 18 |
+
df_sess = pd.read_sql_query("SELECT * FROM user_sessions WHERE name = ?", conn, params=(name,))
|
| 19 |
+
session_ids = tuple(df_sess["id"].tolist())
|
| 20 |
+
|
| 21 |
+
if not session_ids:
|
| 22 |
+
st.warning("No session data found.")
|
| 23 |
+
return
|
| 24 |
+
|
| 25 |
+
def tuple_to_sql(tup):
|
| 26 |
+
return f"({','.join(str(x) for x in tup)})"
|
| 27 |
+
|
| 28 |
+
session_ids_sql = tuple_to_sql(session_ids)
|
| 29 |
+
|
| 30 |
+
# Fetch logs
|
| 31 |
+
df_cog = pd.read_sql_query(f"SELECT * FROM cognitive_logs WHERE session_id IN {session_ids_sql}", conn)
|
| 32 |
+
df_pers = pd.read_sql_query(f"SELECT * FROM personality_logs WHERE session_id IN {session_ids_sql}", conn)
|
| 33 |
+
df_ei = pd.read_sql_query(f"SELECT * FROM ei_logs WHERE session_id IN {session_ids_sql}", conn)
|
| 34 |
+
conn.close()
|
| 35 |
+
|
| 36 |
+
# ---------------- COGNITIVE SUMMARY ----------------
|
| 37 |
+
st.subheader("π§ Cognitive Task Summary")
|
| 38 |
+
cog_chart_path = None
|
| 39 |
+
if not df_cog.empty:
|
| 40 |
+
# Exclude unwanted tasks
|
| 41 |
+
df_cog = df_cog[~df_cog["task_name"].isin(["stroop_test", "symbol_match"])]
|
| 42 |
+
if not df_cog.empty:
|
| 43 |
+
cog_summary = df_cog.groupby("task_name").agg({
|
| 44 |
+
"score": "mean",
|
| 45 |
+
"reaction_time": "mean"
|
| 46 |
+
}).round(2)
|
| 47 |
+
st.dataframe(cog_summary)
|
| 48 |
+
|
| 49 |
+
fig1, ax1 = plt.subplots()
|
| 50 |
+
cog_summary["score"].plot(kind="bar", ax=ax1, color="lightblue")
|
| 51 |
+
ax1.set_title("Cognitive Task Scores")
|
| 52 |
+
ax1.set_ylabel("Score")
|
| 53 |
+
plt.tight_layout()
|
| 54 |
+
cog_chart_path = os.path.join(tempfile.gettempdir(), "cog_chart.png")
|
| 55 |
+
plt.savefig(cog_chart_path)
|
| 56 |
+
st.image(cog_chart_path)
|
| 57 |
+
else:
|
| 58 |
+
cog_summary = pd.DataFrame()
|
| 59 |
+
st.info("No valid cognitive task data (after filtering).")
|
| 60 |
+
else:
|
| 61 |
+
cog_summary = pd.DataFrame()
|
| 62 |
+
st.info("No cognitive data found.")
|
| 63 |
+
|
| 64 |
+
# ---------------- PERSONALITY RADAR ----------------
|
| 65 |
+
st.subheader("𧬠Personality Trait Summary")
|
| 66 |
+
radar_path = None
|
| 67 |
+
if not df_pers.empty:
|
| 68 |
+
pers_summary = df_pers.groupby("trait").agg({"score": "mean"}).round(2)
|
| 69 |
+
st.dataframe(pers_summary)
|
| 70 |
+
|
| 71 |
+
fig2 = plt.figure(figsize=(5, 5))
|
| 72 |
+
categories = list(pers_summary.index)
|
| 73 |
+
values = pers_summary["score"].tolist()
|
| 74 |
+
values += values[:1]
|
| 75 |
+
angles = [n / float(len(categories)) * 2 * np.pi for n in range(len(categories))]
|
| 76 |
+
angles += angles[:1]
|
| 77 |
+
ax2 = plt.subplot(111, polar=True)
|
| 78 |
+
ax2.plot(angles, values, linewidth=2, linestyle='solid')
|
| 79 |
+
ax2.fill(angles, values, 'skyblue', alpha=0.4)
|
| 80 |
+
ax2.set_xticks(angles[:-1])
|
| 81 |
+
ax2.set_xticklabels(categories)
|
| 82 |
+
ax2.set_title("Big Five Personality Traits")
|
| 83 |
+
radar_path = os.path.join(tempfile.gettempdir(), "radar_chart.png")
|
| 84 |
+
plt.tight_layout()
|
| 85 |
+
plt.savefig(radar_path)
|
| 86 |
+
st.image(radar_path)
|
| 87 |
+
else:
|
| 88 |
+
pers_summary = pd.DataFrame()
|
| 89 |
+
st.info("No personality data found.")
|
| 90 |
+
|
| 91 |
+
# ---------------- EI DRILL HEATMAP ----------------
|
| 92 |
+
st.subheader("π EI Drill Activity")
|
| 93 |
+
heatmap_path = None
|
| 94 |
+
if not df_ei.empty:
|
| 95 |
+
ei_counts = df_ei.groupby("drill_type").size().reset_index(name="Count")
|
| 96 |
+
heatmap_data = ei_counts.pivot_table(index="drill_type", values="Count")
|
| 97 |
+
|
| 98 |
+
fig3, ax3 = plt.subplots(figsize=(4, 3))
|
| 99 |
+
sns.heatmap(heatmap_data, annot=True, cmap="YlGnBu", ax=ax3)
|
| 100 |
+
ax3.set_title("EI Drill Frequency")
|
| 101 |
+
heatmap_path = os.path.join(tempfile.gettempdir(), "ei_heatmap.png")
|
| 102 |
+
plt.tight_layout()
|
| 103 |
+
plt.savefig(heatmap_path)
|
| 104 |
+
st.image(heatmap_path)
|
| 105 |
+
else:
|
| 106 |
+
ei_counts = pd.DataFrame()
|
| 107 |
+
st.info("No EI drill data found.")
|
| 108 |
+
|
| 109 |
+
# ---------------- RECOMMENDATIONS ----------------
|
| 110 |
+
st.subheader("π― Personalized Recommendations")
|
| 111 |
+
reco_lines = []
|
| 112 |
+
|
| 113 |
+
# Low personality traits
|
| 114 |
+
if not pers_summary.empty:
|
| 115 |
+
low_traits = pers_summary[pers_summary['score'] < 3.0]
|
| 116 |
+
if not low_traits.empty:
|
| 117 |
+
reco_lines.append("Based on your Big Five traits, you may consider the following:")
|
| 118 |
+
for trait in low_traits.index:
|
| 119 |
+
reco_lines.append(f"β’ Improve {trait} through daily habits and journaling.")
|
| 120 |
+
|
| 121 |
+
# Low EI drills
|
| 122 |
+
if not df_ei.empty:
|
| 123 |
+
drill_freq = df_ei['drill_type'].value_counts()
|
| 124 |
+
if drill_freq.min() < 3:
|
| 125 |
+
reco_lines.append("You're missing out on some EI drills. Try doing more of:")
|
| 126 |
+
underdone = drill_freq[drill_freq < 3].index.tolist()
|
| 127 |
+
reco_lines.extend([f"β’ {d}" for d in underdone])
|
| 128 |
+
|
| 129 |
+
if reco_lines:
|
| 130 |
+
for line in reco_lines:
|
| 131 |
+
st.markdown(line)
|
| 132 |
+
else:
|
| 133 |
+
st.info("You're doing great! No specific recommendations this week.")
|
| 134 |
+
|
| 135 |
+
# ---------------- PDF EXPORT ----------------
|
| 136 |
+
if st.button("π Download Weekly Report (PDF)"):
|
| 137 |
+
pdf_path = os.path.join(tempfile.gettempdir(), "weekly_report.pdf")
|
| 138 |
+
c = canvas.Canvas(pdf_path, pagesize=A4)
|
| 139 |
+
width, height = A4
|
| 140 |
+
margin = 50
|
| 141 |
+
y = height - margin
|
| 142 |
+
|
| 143 |
+
def draw_text_block(title, lines, c, y):
|
| 144 |
+
c.setFont("Helvetica-Bold", 14)
|
| 145 |
+
c.drawString(margin, y, title)
|
| 146 |
+
y -= 20
|
| 147 |
+
c.setFont("Helvetica", 12)
|
| 148 |
+
for line in lines:
|
| 149 |
+
if y < 100:
|
| 150 |
+
c.showPage()
|
| 151 |
+
y = height - margin
|
| 152 |
+
c.setFont("Helvetica", 12)
|
| 153 |
+
c.drawString(margin + 10, y, line)
|
| 154 |
+
y -= 15
|
| 155 |
+
return y - 20
|
| 156 |
+
|
| 157 |
+
def draw_image_fullpage(path, title):
|
| 158 |
+
if path and os.path.exists(path):
|
| 159 |
+
c.showPage()
|
| 160 |
+
c.setFont("Helvetica-Bold", 14)
|
| 161 |
+
c.drawString(margin, height - margin - 20, title)
|
| 162 |
+
c.drawImage(path, margin, height / 2 - 200, width=5.5 * inch, preserveAspectRatio=True)
|
| 163 |
+
|
| 164 |
+
# PAGE 1: Text Summary
|
| 165 |
+
c.setFont("Helvetica-Bold", 16)
|
| 166 |
+
c.drawString(margin, y, f"MindMentor Report for {name}")
|
| 167 |
+
y -= 30
|
| 168 |
+
|
| 169 |
+
cog_lines = [f"{task}: Score={row['score']} | RT={row['reaction_time']}s"
|
| 170 |
+
for task, row in cog_summary.iterrows()] if not cog_summary.empty else ["No cognitive data available."]
|
| 171 |
+
pers_lines = [f"{trait}: {row['score']}" for trait, row in pers_summary.iterrows()] if not pers_summary.empty else ["No personality data available."]
|
| 172 |
+
ei_lines = [f"{row['drill_type']}: {row['Count']} times" for _, row in ei_counts.iterrows()] if not ei_counts.empty else ["No EI drill data available."]
|
| 173 |
+
|
| 174 |
+
y = draw_text_block("π§ Cognitive Task Summary:", cog_lines, c, y)
|
| 175 |
+
y = draw_text_block("𧬠Personality Trait Summary:", pers_lines, c, y)
|
| 176 |
+
y = draw_text_block("π EI Drill Activity:", ei_lines, c, y)
|
| 177 |
+
|
| 178 |
+
# PAGE 2-4: Charts
|
| 179 |
+
draw_image_fullpage(cog_chart_path, "π Cognitive Task Chart")
|
| 180 |
+
draw_image_fullpage(radar_path, "π§ Personality Radar Chart")
|
| 181 |
+
draw_image_fullpage(heatmap_path, "π EI Drill Heatmap")
|
| 182 |
+
|
| 183 |
+
c.save()
|
| 184 |
+
with open(pdf_path, "rb") as f:
|
| 185 |
+
st.download_button("π₯ Download PDF", f, file_name="MindMentor_Report.pdf")
|