Files changed (1) hide show
  1. app.py +74 -18
app.py CHANGED
@@ -3,6 +3,11 @@ import json
3
  import csv
4
  from datetime import datetime
5
  import os
 
 
 
 
 
6
 
7
  # Data úložiště
8
  RESULTS_FILE = "vysledky_testu.csv"
@@ -19,7 +24,11 @@ if not os.path.exists(FEEDBACK_FILE):
19
  writer = csv.writer(f)
20
  writer.writerow(['timestamp', 'kod_ucastnika', 'typ_testu', 'obtiznost', 'srozumitelnost', 'uzitecnost', 'komentar'])
21
 
22
- # Definice testů
 
 
 
 
23
  TESTS = {
24
  "STAFF": {
25
  "nazev": "Test pro administrativní pracovníky (STAFF)",
@@ -141,7 +150,6 @@ TESTS = {
141
  "nazev": "Test pro akademické pracovníky (ACADEMIC)",
142
  "popis": "12 otázek: 6 základních + 6 metodologických",
143
  "otazky": [
144
- # Základní 1-6
145
  {
146
  "q": "Jaká je struktura akademického promptu?",
147
  "opts": [
@@ -214,7 +222,6 @@ TESTS = {
214
  "spravne": ["A", "C", "D"],
215
  "body": 1
216
  },
217
- # Metodologické 7-12 (po 1.5 bodu)
218
  {
219
  "q": "Které použití AI je přijatelné a které ne?",
220
  "opts": [
@@ -337,12 +344,33 @@ def ulozit_feedback(kod, typ, obtiznost, srozumitelnost, uzitecnost, komentar):
337
  komentar
338
  ])
339
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  # Gradio UI
341
- with gr.Blocks(title="Test AI znalostí KTF UK", theme=gr.themes.Soft()) as demo:
342
  gr.Markdown("# 🎓 Test znalostí: Generativní AI")
343
  gr.Markdown("**Katolická teologická fakulta UK, Praha 2025**")
344
 
345
- # State
346
  user_kod = gr.State("")
347
  user_typ = gr.State("")
348
  user_odpovedi = gr.State({})
@@ -373,7 +401,7 @@ with gr.Blocks(title="Test AI znalostí KTF UK", theme=gr.themes.Soft()) as demo
373
  test_info = gr.Markdown("")
374
 
375
  otazky_ui = []
376
- for i in range(12): # Max počet otázek
377
  with gr.Group(visible=False) as q_group:
378
  q_text = gr.Markdown("")
379
  q_check = gr.CheckboxGroup(label="Vyberte VŠECHNY správné odpovědi")
@@ -385,7 +413,7 @@ with gr.Blocks(title="Test AI znalostí KTF UK", theme=gr.themes.Soft()) as demo
385
  result_md = gr.Markdown("")
386
 
387
  gr.Markdown("### 💬 Zpětná vazba")
388
- gr.Markdown("Pomozte nám zlepšit test:")
389
 
390
  obtiznost = gr.Radio(
391
  choices=["Příliš snadný", "Přiměřený", "Příliš těžký"],
@@ -393,14 +421,14 @@ with gr.Blocks(title="Test AI znalostí KTF UK", theme=gr.themes.Soft()) as demo
393
  )
394
  srozumitelnost = gr.Radio(
395
  choices=["Výborná", "Dobrá", "Špatná"],
396
- label="Srozumitelnost otázek"
397
  )
398
  uzitecnost = gr.Radio(
399
  choices=["Velmi užitečné", "Užitečné", "Málo užitečné"],
400
- label="Užitečnost pro praxi"
401
  )
402
  komentar = gr.Textbox(
403
- label="Váš komentář (nepovinné)",
404
  placeholder="Sdílejte své postřehy...",
405
  lines=3
406
  )
@@ -408,6 +436,28 @@ with gr.Blocks(title="Test AI znalostí KTF UK", theme=gr.themes.Soft()) as demo
408
  feedback_btn = gr.Button("Odeslat zpětnou vazbu", variant="secondary")
409
  feedback_msg = gr.Markdown("")
410
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
411
  # Logika
412
  def start_test(kod, typ):
413
  if not kod or not typ:
@@ -420,7 +470,6 @@ with gr.Blocks(title="Test AI znalostí KTF UK", theme=gr.themes.Soft()) as demo
420
  test = TESTS[typ]
421
  num_q = len(test["otazky"])
422
 
423
- # Připrav UI pro otázky
424
  updates = {
425
  start_msg: f"✅ Test zahájen! Přejděte na záložku 'Test'",
426
  user_kod: kod,
@@ -428,7 +477,6 @@ with gr.Blocks(title="Test AI znalostí KTF UK", theme=gr.themes.Soft()) as demo
428
  test_info: f"## {test['nazev']}\n\n{test['popis']}\n\n**Počet otázek:** {num_q}"
429
  }
430
 
431
- # Zobraz otázky
432
  for i in range(12):
433
  if i < num_q:
434
  q = test["otazky"][i]
@@ -446,25 +494,21 @@ with gr.Blocks(title="Test AI znalostí KTF UK", theme=gr.themes.Soft()) as demo
446
  if not kod or not typ:
447
  return "❌ Chyba: Test nebyl správně zahájen"
448
 
449
- # Sesbírej odpovědi
450
  test = TESTS[typ]
451
  odpovedi = {}
452
  for i in range(len(test["otazky"])):
453
  odpovedi[f"q_{i}"] = args[i] if i < len(args) else []
454
 
455
- # Vyhodnoť
456
  skore, max_skore = vyhodnotit_test(typ, odpovedi)
457
  procenta = (skore / max_skore * 100)
458
 
459
- # Ulož
460
  ulozit_vysledek(kod, typ, skore, max_skore, odpovedi)
461
 
462
- # Výsledek
463
  if typ == "STAFF":
464
  uspech = skore >= 7
465
  pozadavek = "min. 7 bodů"
466
  else:
467
- uspech = skore >= 8 # Zjednodušená podmínka
468
  pozadavek = "min. 8 bodů"
469
 
470
  result = f"""
@@ -474,7 +518,7 @@ with gr.Blocks(title="Test AI znalostí KTF UK", theme=gr.themes.Soft()) as demo
474
 
475
  **Požadavek:** {pozadavek}
476
 
477
- {'🎉 Gratulujeme! Test jste úspěšně absolvovali.' if uspech else '😔 Bohužel jste nesplnili minimální požadavek. Doporučujeme prostudovat příručku a zkusit to znovu.'}
478
 
479
  ---
480
 
@@ -511,6 +555,18 @@ with gr.Blocks(title="Test AI znalostí KTF UK", theme=gr.themes.Soft()) as demo
511
  inputs=[user_kod, user_typ, obtiznost, srozumitelnost, uzitecnost, komentar],
512
  outputs=[feedback_msg]
513
  )
 
 
 
 
 
 
 
 
 
 
 
 
514
 
515
  if __name__ == "__main__":
516
  demo.launch(share=True)
 
3
  import csv
4
  from datetime import datetime
5
  import os
6
+ import hashlib
7
+
8
+ # ADMIN HESLO - Změňte toto!
9
+ ADMIN_PASSWORD_HASH = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8" # "password" - ZMĚŇTE!
10
+ # Pro vytvoření vlastního hashe: import hashlib; hashlib.sha256("vase_heslo".encode()).hexdigest()
11
 
12
  # Data úložiště
13
  RESULTS_FILE = "vysledky_testu.csv"
 
24
  writer = csv.writer(f)
25
  writer.writerow(['timestamp', 'kod_ucastnika', 'typ_testu', 'obtiznost', 'srozumitelnost', 'uzitecnost', 'komentar'])
26
 
27
+ def check_admin_password(password):
28
+ """Ověří admin heslo"""
29
+ return hashlib.sha256(password.encode()).hexdigest() == ADMIN_PASSWORD_HASH
30
+
31
+ # Definice testů (bez správných odpovědí viditelných v UI)
32
  TESTS = {
33
  "STAFF": {
34
  "nazev": "Test pro administrativní pracovníky (STAFF)",
 
150
  "nazev": "Test pro akademické pracovníky (ACADEMIC)",
151
  "popis": "12 otázek: 6 základních + 6 metodologických",
152
  "otazky": [
 
153
  {
154
  "q": "Jaká je struktura akademického promptu?",
155
  "opts": [
 
222
  "spravne": ["A", "C", "D"],
223
  "body": 1
224
  },
 
225
  {
226
  "q": "Které použití AI je přijatelné a které ne?",
227
  "opts": [
 
344
  komentar
345
  ])
346
 
347
+ def get_results_csv(password):
348
+ """Vrátí CSV s výsledky - pouze pro admina"""
349
+ if not check_admin_password(password):
350
+ return "❌ Nesprávné heslo"
351
+
352
+ if not os.path.exists(RESULTS_FILE):
353
+ return "📭 Zatím žádné výsledky"
354
+
355
+ with open(RESULTS_FILE, 'r', encoding='utf-8') as f:
356
+ return f.read()
357
+
358
+ def get_feedback_csv(password):
359
+ """Vrátí CSV se zpětnou vazbou - pouze pro admina"""
360
+ if not check_admin_password(password):
361
+ return "❌ Nesprávné heslo"
362
+
363
+ if not os.path.exists(FEEDBACK_FILE):
364
+ return "📭 Zatím žádná zpětná vazba"
365
+
366
+ with open(FEEDBACK_FILE, 'r', encoding='utf-8') as f:
367
+ return f.read()
368
+
369
  # Gradio UI
370
+ with gr.Blocks(title="Test AI znalostí KTF UK") as demo:
371
  gr.Markdown("# 🎓 Test znalostí: Generativní AI")
372
  gr.Markdown("**Katolická teologická fakulta UK, Praha 2025**")
373
 
 
374
  user_kod = gr.State("")
375
  user_typ = gr.State("")
376
  user_odpovedi = gr.State({})
 
401
  test_info = gr.Markdown("")
402
 
403
  otazky_ui = []
404
+ for i in range(12):
405
  with gr.Group(visible=False) as q_group:
406
  q_text = gr.Markdown("")
407
  q_check = gr.CheckboxGroup(label="Vyberte VŠECHNY správné odpovědi")
 
413
  result_md = gr.Markdown("")
414
 
415
  gr.Markdown("### 💬 Zpětná vazba")
416
+ gr.Markdown("Pomozte mi prosím zlepšit kurz:")
417
 
418
  obtiznost = gr.Radio(
419
  choices=["Příliš snadný", "Přiměřený", "Příliš těžký"],
 
421
  )
422
  srozumitelnost = gr.Radio(
423
  choices=["Výborná", "Dobrá", "Špatná"],
424
+ label="Srozumitelnost prezentací"
425
  )
426
  uzitecnost = gr.Radio(
427
  choices=["Velmi užitečné", "Užitečné", "Málo užitečné"],
428
+ label="Užitečnost krzu pro praxi"
429
  )
430
  komentar = gr.Textbox(
431
+ label="Váš komentář ke kurzu (nepovinné)",
432
  placeholder="Sdílejte své postřehy...",
433
  lines=3
434
  )
 
436
  feedback_btn = gr.Button("Odeslat zpětnou vazbu", variant="secondary")
437
  feedback_msg = gr.Markdown("")
438
 
439
+ with gr.Tab("👨‍💼 Admin") as admin_tab:
440
+ gr.Markdown("### 🔒 Administrátorský přístup")
441
+ gr.Markdown("Pouze pro organizátory testu")
442
+
443
+ admin_password = gr.Textbox(
444
+ label="Admin heslo",
445
+ type="password",
446
+ placeholder="Zadejte heslo"
447
+ )
448
+
449
+ with gr.Row():
450
+ results_btn = gr.Button("Stáhnout výsledky", variant="secondary")
451
+ feedback_download_btn = gr.Button("Stáhnout zpětnou vazbu", variant="secondary")
452
+
453
+ admin_output = gr.Textbox(
454
+ label="Data",
455
+ lines=20,
456
+ max_lines=30
457
+ )
458
+
459
+ gr.Markdown("**ℹ️ Poznámka:** Data můžete zkopírovat a uložit jako CSV soubor.")
460
+
461
  # Logika
462
  def start_test(kod, typ):
463
  if not kod or not typ:
 
470
  test = TESTS[typ]
471
  num_q = len(test["otazky"])
472
 
 
473
  updates = {
474
  start_msg: f"✅ Test zahájen! Přejděte na záložku 'Test'",
475
  user_kod: kod,
 
477
  test_info: f"## {test['nazev']}\n\n{test['popis']}\n\n**Počet otázek:** {num_q}"
478
  }
479
 
 
480
  for i in range(12):
481
  if i < num_q:
482
  q = test["otazky"][i]
 
494
  if not kod or not typ:
495
  return "❌ Chyba: Test nebyl správně zahájen"
496
 
 
497
  test = TESTS[typ]
498
  odpovedi = {}
499
  for i in range(len(test["otazky"])):
500
  odpovedi[f"q_{i}"] = args[i] if i < len(args) else []
501
 
 
502
  skore, max_skore = vyhodnotit_test(typ, odpovedi)
503
  procenta = (skore / max_skore * 100)
504
 
 
505
  ulozit_vysledek(kod, typ, skore, max_skore, odpovedi)
506
 
 
507
  if typ == "STAFF":
508
  uspech = skore >= 7
509
  pozadavek = "min. 7 bodů"
510
  else:
511
+ uspech = skore >= 8
512
  pozadavek = "min. 8 bodů"
513
 
514
  result = f"""
 
518
 
519
  **Požadavek:** {pozadavek}
520
 
521
+ {'🎉 Gratulujeme! Test jste úspěšně absolvovali.' if uspech else '😔 Bohužel jste nesplnili minimální požadavek.'}
522
 
523
  ---
524
 
 
555
  inputs=[user_kod, user_typ, obtiznost, srozumitelnost, uzitecnost, komentar],
556
  outputs=[feedback_msg]
557
  )
558
+
559
+ results_btn.click(
560
+ fn=get_results_csv,
561
+ inputs=[admin_password],
562
+ outputs=[admin_output]
563
+ )
564
+
565
+ feedback_download_btn.click(
566
+ fn=get_feedback_csv,
567
+ inputs=[admin_password],
568
+ outputs=[admin_output]
569
+ )
570
 
571
  if __name__ == "__main__":
572
  demo.launch(share=True)