JayLacoma commited on
Commit
3c2230b
1 Parent(s): 8a2b26c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +348 -0
app.py ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Extended Big Five questionnaire with subtraits and their questions
2
+ questionnaire = {
3
+ "openness": {
4
+ "imagination": [
5
+ "Me gusta soñar despierto o pensar en ideas abstractas y fantásticas.",
6
+ "Al resolver problemas, a menudo se me ocurren soluciones creativas o poco convencionales."
7
+ ],
8
+ "aesthetic_sensitivity": [
9
+ "Me conmueve profundamente el arte, la música o la naturaleza.",
10
+ "A menudo busco la belleza en mi entorno, como disfrutar de las puestas de sol o de espacios bien diseñados."
11
+ ],
12
+ "intellectual_curiosity": [
13
+ "Me gusta aprender sobre nuevos temas solo por el placer de aprender.",
14
+ "Me atraen las ideas complejas o teóricas, como la filosofía o la mecánica cuántica."
15
+ ],
16
+ "adventure_seeking": [
17
+ "Prefiero probar nuevas actividades, como viajar a lugares desconocidos o probar comidas exóticas.",
18
+ "Me siento cómodo tomando riesgos para explorar nuevas oportunidades."
19
+ ],
20
+ "emotional_openness": [
21
+ "Estoy dispuesto a expresar mis sentimientos más profundos, incluso si son complicados o vulnerables.",
22
+ "A menudo reflexiono sobre cómo mis emociones dan forma a mis experiencias."
23
+ ],
24
+ },
25
+ "conscientiousness": {
26
+ "self_discipline": [
27
+ "Puedo persistir con las tareas incluso cuando se vuelven aburridas o difíciles.",
28
+ "A menudo completo proyectos antes de las fechas límite."
29
+ ],
30
+ "orderliness": [
31
+ "Me gusta mantener mi espacio de trabajo, mi hogar o mi horario bien organizado.",
32
+ "Me siento incómodo en entornos desordenados o caóticos."
33
+ ],
34
+ "dutifulness": [
35
+ "Siento una fuerte obligación de cumplir con mis compromisos, incluso cuando es inconveniente.",
36
+ "A menudo me siento culpable si no cumplo con las expectativas de los demás."
37
+ ],
38
+ "achievement_striving": [
39
+ "Me fijo metas ambiciosas y trabajo duro para alcanzarlas.",
40
+ "Disfruto de sentirme productivo y realizado después de un día ajetreado."
41
+ ],
42
+ "cautiousness": [
43
+ "Me tomo el tiempo de sopesar los pros y los contras antes de tomar decisiones.",
44
+ "Tengo cuidado de evitar riesgos, incluso si pueden dar lugar a grandes recompensas."
45
+ ],
46
+ },
47
+ "extraversion": {
48
+ "sociability": [
49
+ "Me siento con energía después de pasar tiempo con otras personas.",
50
+ "Disfruto de las reuniones grandes y de conocer gente nueva."
51
+ ],
52
+ "assertiveness": [
53
+ "Tengo confianza para expresar mis opiniones, incluso en entornos grupales.",
54
+ "A menudo tomo la iniciativa en la organización de eventos o actividades."
55
+ ],
56
+ "energy_level": [
57
+ "Tengo mucha energía física y mental durante todo el día.",
58
+ "Disfruto de los entornos de ritmo rápido con estimulación constante."
59
+ ],
60
+ "excitement_seeking": [
61
+ "Me atraen las actividades emocionantes, como las montañas rusas, el paracaidismo o los viajes de aventura.",
62
+ "Me aburro rápidamente en entornos rutinarios o de baja energía."
63
+ ],
64
+ "positive_emotions": [
65
+ "A menudo me siento alegre, entusiasta y optimista.",
66
+ "Soy bueno para levantar el ánimo de las personas que me rodean."
67
+ ],
68
+ },
69
+ "agreeableness": {
70
+ "trust": [
71
+ "Creo que la mayoría de las personas tienen buenas intenciones.",
72
+ "Me siento cómodo confiando en que los demás hagan su parte en un proyecto grupal."
73
+ ],
74
+ "altruism": [
75
+ "Disfruto ayudando a los demás, incluso si requiere un esfuerzo o sacrificio adicional.",
76
+ "Encuentro satisfacción en el voluntariado o en apoyar una causa."
77
+ ],
78
+ "modesty": [
79
+ "Me siento incómodo alardeando de mis logros o habilidades.",
80
+ "Evito llamar la atención sobre mí mismo, incluso cuando merezco reconocimiento."
81
+ ],
82
+ "compassion": [
83
+ "Me doy cuenta rápidamente cuando los demás están molestos o necesitan consuelo.",
84
+ "Hago todo lo posible para que los demás se sientan cuidados y apoyados."
85
+ ],
86
+ "cooperation": [
87
+ "Estoy dispuesto a hacer concesiones para evitar conflictos.",
88
+ "Priorizo la armonía del grupo por encima de mis propias preferencias en entornos de equipo."
89
+ ],
90
+ },
91
+ "neuroticism": {
92
+ "anxiety": [
93
+ "A menudo me preocupan los acontecimientos futuros o los posibles problemas.",
94
+ "Me siento tenso o nervioso en situaciones desconocidas o de mucha presión."
95
+ ],
96
+ "anger": [
97
+ "Me siento frustrado o irritado fácilmente.",
98
+ "A veces, las pequeñas molestias me hacen perder los estribos."
99
+ ],
100
+ "depression": [
101
+ "A menudo me siento triste, desanimado o desmotivado, incluso cuando no hay una razón clara.",
102
+ "Me resulta difícil disfrutar de actividades que antes me hacían feliz."
103
+ ],
104
+ "self_consciousness": [
105
+ "Me preocupa demasiado lo que los demás piensen de mí.",
106
+ "A menudo me siento avergonzado o juzgado en situaciones sociales."
107
+ ],
108
+ "vulnerability": [
109
+ "Me resulta difícil afrontar situaciones estresantes o grandes cambios en la vida",
110
+ "Me siento abrumado cuando me enfrento a desafíos, incluso si son manejables".
111
+ ],
112
+ },
113
+ }
114
+
115
+ import json
116
+ import numpy as np
117
+ import gradio as gr
118
+ import plotly.graph_objects as go
119
+ from scipy.stats import percentileofscore
120
+
121
+ # Define TRAIT_COLORS
122
+ TRAIT_COLORS = {
123
+ "openness": "blue",
124
+ "conscientiousness": "green",
125
+ "extraversion": "orange",
126
+ "agreeableness": "purple",
127
+ "neuroticism": "red"
128
+ }
129
+
130
+ # Flatten questions dynamically
131
+ def build_questions():
132
+ return [
133
+ (trait, sub_trait, q)
134
+ for trait, sub_traits in questionnaire.items()
135
+ for sub_trait, qs in sub_traits.items()
136
+ for q in qs
137
+ ]
138
+
139
+ questions = build_questions()
140
+
141
+ # Initialize state
142
+ state = {"current_question": 0, "responses": []}
143
+
144
+ # Compute scores with percentiles and z-scores
145
+ def compute_scores_and_percentiles(responses):
146
+ scores = {}
147
+ idx = 0
148
+ for trait, sub_traits in questionnaire.items():
149
+ for sub_trait, qs in sub_traits.items():
150
+ mean_score = np.mean(responses[idx:idx + len(qs)])
151
+ scores[f"{trait}_{sub_trait}"] = mean_score
152
+ idx += len(qs)
153
+
154
+ # Convert scores to arrays for percentile/z-score calculations
155
+ values = np.array(list(scores.values()))
156
+ z_scores = (values - np.mean(values)) / np.std(values)
157
+ percentiles = [percentileofscore(values, score) for score in values]
158
+
159
+ return scores, z_scores, percentiles
160
+
161
+ # Create chart with colors, percentiles, and z-scores
162
+ def create_chart(scores, z_scores, percentiles):
163
+ subtraits = [key.split("_")[1] for key in scores.keys()]
164
+ values = list(scores.values())
165
+ trait_keys = [key.split("_")[0] for key in scores.keys()]
166
+ colors = [TRAIT_COLORS[trait] for trait in trait_keys]
167
+
168
+ # Create a bar chart
169
+ fig = go.Figure()
170
+
171
+ for i, (trait, color) in enumerate(TRAIT_COLORS.items()):
172
+ indices = [j for j, t in enumerate(trait_keys) if t == trait]
173
+ trait_subtraits = [subtraits[j] for j in indices]
174
+ trait_values = [values[j] for j in indices]
175
+ trait_z_scores = [z_scores[j] for j in indices]
176
+ trait_percentiles = [percentiles[j] for j in indices]
177
+
178
+ fig.add_trace(
179
+ go.Bar(
180
+ x=trait_subtraits,
181
+ y=trait_values,
182
+ name=trait.capitalize(),
183
+ marker_color=color,
184
+ text=[
185
+ f"Score: {v:.2f}<br>Z-score: {z:.2f}<br>Percentile: {p:.1f}%"
186
+ for v, z, p in zip(trait_values, trait_z_scores, trait_percentiles)
187
+ ],
188
+ hoverinfo="text"
189
+ )
190
+ )
191
+
192
+ fig.update_layout(
193
+ title="Trait Breakdown with Percentiles and Z-Scores",
194
+ xaxis_title="Subtraits",
195
+ yaxis_title="Average Score (1-10)",
196
+ plot_bgcolor="black",
197
+ paper_bgcolor="black",
198
+ font=dict(color="white"),
199
+ legend=dict(
200
+ title="Traits",
201
+ bgcolor="black",
202
+ bordercolor="gray",
203
+ borderwidth=1
204
+ )
205
+ )
206
+ return fig
207
+
208
+ # Progress gauge
209
+ def plot_progress(current, total, question_text, question_num):
210
+ progress = (current / total) * 100
211
+ fig = go.Figure(go.Indicator(
212
+ mode="gauge+number",
213
+ value=progress,
214
+ gauge={
215
+ 'axis': {'range': [0, 100]},
216
+ 'bar': {'color': 'purple'},
217
+ 'bgcolor': 'black',
218
+ 'steps': [
219
+ {'range': [0, 25], 'color': 'darkviolet'},
220
+ {'range': [25, 50], 'color': 'violet'},
221
+ {'range': [50, 75], 'color': 'magenta'},
222
+ {'range': [75, 100], 'color': 'plum'}
223
+ ],
224
+ },
225
+ domain={'x': [0, 1], 'y': [0, 1]}
226
+ ))
227
+
228
+ fig.add_annotation(
229
+ x=0.5, y=-0.2, text=f"Question {question_num} / {total}", showarrow=False,
230
+ font=dict(size=14, color='white'), align="center"
231
+ )
232
+
233
+ fig.update_layout(
234
+ title={
235
+ 'text': f"<b>{question_text}</b>",
236
+ 'font': {'size': 20, 'color': "white"},
237
+ 'x': 0.5,
238
+ 'xanchor': 'center',
239
+ 'y': 0.85,
240
+ },
241
+ margin=dict(t=170),
242
+ plot_bgcolor='black',
243
+ paper_bgcolor='black',
244
+ font=dict(color='white'),
245
+ )
246
+
247
+ return fig
248
+
249
+ # Start test
250
+ def start_test():
251
+ state["current_question"] = 0
252
+ state["responses"] = []
253
+ question = questions[state["current_question"]][2]
254
+ return (
255
+ question,
256
+ plot_progress(0, len(questions), question, 1),
257
+ gr.update(visible=True),
258
+ gr.update(visible=False),
259
+ )
260
+
261
+
262
+
263
+
264
+
265
+ # Save Plotly chart as HTML
266
+ def save_plotly_html(chart, file_name="results_chart.html"):
267
+ chart.write_html(file_name)
268
+ print(f"Chart saved to {file_name}")
269
+
270
+ # Save test results as a JSON file
271
+ def save_results(responses, file_name="test_results.json"):
272
+ with open(file_name, "w") as f:
273
+ json.dump({"responses": responses}, f, indent=4)
274
+ print(f"Results saved to {file_name}")
275
+
276
+ # Modified next_question to save results and chart
277
+ def next_question(response):
278
+ state["responses"].append(int(response))
279
+ state["current_question"] += 1
280
+
281
+ if state["current_question"] >= len(questions):
282
+ scores, z_scores, percentiles = compute_scores_and_percentiles(state["responses"])
283
+ result_chart = create_chart(scores, z_scores, percentiles)
284
+
285
+ # Save results and chart
286
+ save_results(state["responses"], "test_results.json")
287
+ save_plotly_html(result_chart, "results_chart.html")
288
+
289
+ return "Test Complete! Your results:", result_chart, gr.update(visible=False), gr.update(visible=True)
290
+
291
+ question = questions[state["current_question"]][2]
292
+ return (
293
+ question,
294
+ plot_progress(
295
+ state["current_question"], len(questions),
296
+ question, state["current_question"] + 1
297
+ ),
298
+ gr.update(visible=True),
299
+ gr.update(visible=False),
300
+ )
301
+
302
+ def create_gradio_app():
303
+ with gr.Blocks() as app:
304
+ gr.Markdown("## Extended Big Five Personality Test")
305
+
306
+ # UI Elements
307
+ start_button = gr.Button("Start Test")
308
+ question_text = gr.Textbox(label="Question", interactive=False, visible=True)
309
+ button_group = gr.Radio([str(i) for i in range(1, 11)], label="Your Response (1-10)", visible=True)
310
+ progress_gauge = gr.Plot()
311
+ result_output = gr.Textbox(label="Results", visible=True)
312
+ download_results = gr.File(label="Download Results JSON", visible=False)
313
+ download_chart = gr.File(label="Download Chart HTML", visible=True)
314
+
315
+ # Start Test Logic
316
+ start_button.click(
317
+ start_test,
318
+ outputs=[question_text, progress_gauge, button_group, result_output]
319
+ )
320
+
321
+ # Question Logic
322
+ def handle_next_question(response):
323
+ output = next_question(response)
324
+
325
+ # Check if the test is complete to enable downloads
326
+ if state["current_question"] >= len(questions):
327
+ return (*output, "test_results.json", "results_chart.html")
328
+ else:
329
+ return (*output, None, None)
330
+
331
+ # Respond to button changes and enable downloads after test completion
332
+ button_group.change(
333
+ handle_next_question,
334
+ inputs=button_group,
335
+ outputs=[
336
+ question_text, progress_gauge, button_group, result_output,
337
+ download_results, download_chart
338
+ ]
339
+ )
340
+
341
+ return app
342
+
343
+
344
+ # Launch the Gradio app
345
+ app = create_gradio_app()
346
+
347
+ # Launch the app locally
348
+ app.launch()