2020# ========================================
2121# CARICAMENTO DATI
2222# ========================================
23- # Carica i 3 CSV
2423df_domande = pl .read_csv ("domande.csv" )
2524df_risposte = pl .read_csv ("risposte.csv" )
2625df_studenti = pl .read_csv ("risposte_tutti.csv" )
2726
2827# ========================================
29- # SEZIONE 1: STATISTICHE GENERALI
28+ # JOIN E CALCOLO CORRETTEZZA
3029# ========================================
31- st .header ("📊 Statistiche Generali" )
32-
33- # Calcola metriche base
34- num_studenti = df_studenti .select ("nome_utente" ).unique ().height
35- num_domande = df_domande .height
36- totale_risposte = df_studenti .height
37-
38- # Mostra le metriche in colonne
39- col1 , col2 , col3 = st .columns (3 )
40- with col1 :
41- st .metric ("👥 Studenti partecipanti" , num_studenti )
42- with col2 :
43- st .metric ("❓ Domande totali" , num_domande )
44- with col3 :
45- st .metric ("✍️ Risposte date" , totale_risposte )
46-
47- # ========================================
48- # SEZIONE 2: ANALISI CORRETTEZZA
49- # ========================================
50- st .header ("✅ Analisi Correttezza Risposte" )
51-
52- # Join per verificare le risposte corrette
5330df_con_corrette = df_studenti .join (
5431 df_risposte ,
5532 on = "id_domanda" ,
5633 how = "left"
57- )
58-
59- # Aggiungi colonna che indica se la risposta è corretta
60- df_con_corrette = df_con_corrette .with_columns (
34+ ).with_columns (
6135 (pl .col ("numero_risposta_fornita" ) == pl .col ("numero_risposta_corretta" ))
6236 .alias ("corretta" )
6337)
6438
65- # Calcola percentuale risposte corrette
66- risposte_corrette = df_con_corrette .filter (pl .col ("corretta" ) == True ).height
67- percentuale_corrette = (risposte_corrette / totale_risposte * 100 ) if totale_risposte > 0 else 0
68-
69- st .metric (
70- "Percentuale risposte corrette" ,
71- f"{ percentuale_corrette :.1f} %"
72- )
73-
74- # ========================================
75- # SEZIONE 3: CLASSIFICA STUDENTI
76- # ========================================
77- st .header ("🏆 Classifica Studenti" )
78-
79- # Calcola punteggio per studente
39+ # Classifica studenti
8040classifica = (
8141 df_con_corrette
8242 .group_by ("nome_utente" )
8545 pl .col ("id_domanda" ).count ().alias ("domande_risposte" ),
8646 pl .col ("tempo_risposta" ).mean ().alias ("tempo_medio" )
8747 ])
88- .sort ("risposte_corrette" , descending = True )
89- )
90-
91- # Mostra la classifica
92- st .dataframe (
93- classifica ,
94- width = 'stretch' ,
95- hide_index = True
48+ .with_columns (
49+ (pl .col ("risposte_corrette" ) / pl .col ("domande_risposte" ) * 100 )
50+ .round (1 )
51+ .alias ("percentuale_corrette" )
52+ )
53+ .sort (["risposte_corrette" , "tempo_medio" ], descending = [True , False ])
9654)
9755
9856# ========================================
99- # SEZIONE 4: DIFFICOLTÀ DOMANDE
57+ # SEZIONE 1: STATISTICHE GENERALI
10058# ========================================
101- st .header ("📈 Difficoltà Domande " )
59+ st .header ("📊 Statistiche Generali " )
10260
103- # Calcola percentuale di successo per domanda
61+ num_studenti = df_studenti .select ("nome_utente" ).unique ().height
62+ num_domande = df_domande .height
63+ totale_risposte = df_studenti .height
64+ risposte_corrette = df_con_corrette .filter (pl .col ("corretta" ) == True ).height
65+ percentuale_corrette = (risposte_corrette / totale_risposte * 100 ) if totale_risposte > 0 else 0
66+ tempo_medio_globale = df_studenti .select (pl .col ("tempo_risposta" ).mean ())[0 , 0 ]
67+
68+ # Studente migliore e peggiore
69+ migliore = classifica .row (0 , named = True )
70+ peggiore = classifica .row (- 1 , named = True )
71+
72+ # Domanda più difficile (minor percentuale di successo)
10473difficolta = (
10574 df_con_corrette
10675 .group_by ("id_domanda" )
11079 ])
11180 .with_columns (
11281 (pl .col ("risposte_corrette" ) / pl .col ("totale_risposte" ) * 100 )
82+ .round (1 )
11383 .alias ("percentuale_corrette" )
11484 )
11585 .sort ("percentuale_corrette" )
11686)
87+ id_domanda_difficile = difficolta .row (0 , named = True )["id_domanda" ]
11788
118- # Join con il testo delle domande
119- difficolta = difficolta .join (
120- df_domande .select (["id_domanda" , "domanda" ]),
121- on = "id_domanda" ,
122- how = "left"
123- )
89+ col1 , col2 , col3 = st .columns (3 )
90+ with col1 :
91+ st .metric ("👥 Studenti partecipanti" , num_studenti )
92+ with col2 :
93+ st .metric ("❓ Domande totali" , num_domande )
94+ with col3 :
95+ st .metric ("✍️ Risposte date" , totale_risposte )
12496
125- # Mostra tabella difficoltà
126- st .dataframe (
127- difficolta .select (["id_domanda" , "domanda" , "percentuale_corrette" ]),
128- width = 'stretch' ,
129- hide_index = True
130- )
97+ col4 , col5 , col6 = st .columns (3 )
98+ with col4 :
99+ st .metric ("✅ Risposte corrette (media classe)" , f"{ percentuale_corrette :.1f} %" )
100+ with col5 :
101+ st .metric ("⏱️ Tempo medio per risposta" , f"{ tempo_medio_globale :.0f} ms" )
102+ with col6 :
103+ st .metric ("❓ Domanda più difficile" , f"Domanda #{ id_domanda_difficile } " )
104+
105+ col7 , col8 = st .columns (2 )
106+ with col7 :
107+ st .metric (
108+ "🥇 Studente migliore" ,
109+ migliore ["nome_utente" ],
110+ f"{ migliore ['risposte_corrette' ]} risposte corrette"
111+ )
112+ with col8 :
113+ st .metric (
114+ "📚 Da migliorare" ,
115+ peggiore ["nome_utente" ],
116+ f"{ peggiore ['risposte_corrette' ]} risposte corrette" ,
117+ delta_color = "inverse"
118+ )
131119
132120# ========================================
133- # SEZIONE 5: GRAFICO A BARRE
121+ # SEZIONE 2: CLASSIFICA STUDENTI (grafico)
134122# ========================================
135- st .header ("📊 Grafico Prestazioni " )
123+ st .header ("🏆 Classifica Studenti " )
136124
137- # Prepara dati per il grafico
138- dati_grafico = classifica .select (["nome_utente" , "risposte_corrette" ])
125+ # Classifica con barre progress: ordine garantito, nessuna libreria extra
126+ max_corrette = classifica ["risposte_corrette" ].max ()
127+
128+ for i , row in enumerate (classifica .iter_rows (named = True )):
129+ st .write (f"{ i + 1 } ° **{ row ['nome_utente' ]} ** — { row ['risposte_corrette' ]} risposte corrette" )
130+ st .progress (int (row ["risposte_corrette" ]) / int (max_corrette ))
131+
132+ # Tabella dettagliata sotto il grafico
133+ with st .expander ("📋 Vedi tabella dettagliata" ):
134+ st .dataframe (
135+ classifica .select ([
136+ "nome_utente" ,
137+ "risposte_corrette" ,
138+ "domande_risposte" ,
139+ "percentuale_corrette" ,
140+ "tempo_medio"
141+ ]),
142+ width = "stretch" ,
143+ hide_index = True ,
144+ column_config = {
145+ "nome_utente" : "Studente" ,
146+ "risposte_corrette" : "✅ Corrette" ,
147+ "domande_risposte" : "❓ Risposte" ,
148+ "percentuale_corrette" : st .column_config .NumberColumn ("% Corrette" , format = "%.1f%%" ),
149+ "tempo_medio" : st .column_config .NumberColumn ("⏱️ Tempo medio (ms)" , format = "%.0f" )
150+ }
151+ )
139152
140- # Crea grafico a barre
141- st .bar_chart (
142- dati_grafico ,
143- x = "nome_utente" ,
144- y = "risposte_corrette" ,
145- width = 'stretch'
153+ # ========================================
154+ # SEZIONE 3: DIFFICOLTÀ DOMANDE
155+ # ========================================
156+ st .header ("📈 Difficoltà Domande" )
157+
158+ difficolta_con_testo = difficolta .join (
159+ df_domande .select (["id_domanda" , "domanda" ]),
160+ on = "id_domanda" ,
161+ how = "left"
162+ )
163+
164+ st .dataframe (
165+ difficolta_con_testo .select (["id_domanda" , "domanda" , "percentuale_corrette" ]),
166+ width = "stretch" ,
167+ hide_index = True ,
168+ column_config = {
169+ "id_domanda" : "ID" ,
170+ "domanda" : "Domanda" ,
171+ "percentuale_corrette" : st .column_config .ProgressColumn (
172+ "% Risposte Corrette" ,
173+ format = "%.1f%%" ,
174+ min_value = 0 ,
175+ max_value = 100
176+ )
177+ }
146178)
147179
148180# ========================================
149- # SEZIONE 6 : TEMPO MEDIO DI RISPOSTA
181+ # SEZIONE 4 : TEMPO DI RISPOSTA PER DOMANDA
150182# ========================================
151- st .header ("⏱️ Tempo Medio di Risposta" )
152-
153- tempo_medio_globale = df_studenti .select (pl .col ("tempo_risposta" ).mean ())[0 , 0 ]
154- st .metric ("Tempo medio per risposta" , f"{ tempo_medio_globale :.0f} ms" )
183+ st .header ("⏱️ Tempo di Risposta per Domanda" )
155184
156- # Grafico tempo per domanda
157185tempo_per_domanda = (
158186 df_studenti
159187 .group_by ("id_domanda" )
165193 tempo_per_domanda ,
166194 x = "id_domanda" ,
167195 y = "tempo_medio" ,
168- width = 'stretch'
169- )
196+ width = "stretch"
197+ )
198+
199+ # ========================================
200+ # SEZIONE 5: DOMANDE E RISPOSTE CORRETTE
201+ # ========================================
202+ with st .expander ("📖 Visualizza domande e risposte corrette" ):
203+ domande_con_risposta = (
204+ df_domande .join (df_risposte , on = "id_domanda" , how = "left" )
205+ .sort ("id_domanda" )
206+ )
207+ for row in domande_con_risposta .iter_rows (named = True ):
208+ numero = row ["numero_risposta_corretta" ]
209+ risposta_corretta = row [f"risposta_{ numero } " ]
210+ st .markdown (f"**#{ row ['id_domanda' ]} — { row ['domanda' ]} **" )
211+ st .success (f"✅ { risposta_corretta } " )
212+ st .divider ()
0 commit comments