1- from IPython .display import HTML
21import json
32import uuid
43
4+ from IPython .display import HTML
5+
56
67def create_answer_box (question_id , rows = 4 ):
7- """Create an answer box with a submit button."""
8+ """Create an answer box with an info popup button."""
89 return HTML (f"""
910 <div style="padding: 5px; border-radius: 5px; margin: 10px 0;">
1011 <textarea id="answer-{ question_id } " rows="{ rows } " style="width: 100%; margin-top: 10px; padding: 10px; border: 1px solid #ced4da; border-radius: 4px;" placeholder="Ihre Antwort"></textarea>
11- <button id="btn-answer-{ question_id } " onclick="lockAnswer('answer- { question_id } ')" style="margin-top: 5px; padding: 5px 12px; background-color: #00305e; color: white; border: none; border-radius: 4px; cursor: pointer;">Bestätigen </button>
12+ <button id="btn-answer-{ question_id } " onclick="alert('Ihre Eingabe wird nicht überprüft oder gespeichert. Dieses Textfeld dient lediglich Ihrer eigenen Reflexion und der aktiven Wiedergabe der Lerninhalte. ')" style="margin-top: 5px; padding: 5px 12px; background-color: #00305e; color: white; border: none; border-radius: 4px; cursor: pointer;">OK </button>
1213 </div>
1314 """ )
1415
1516
1617class DragDropQuiz :
1718 """
1819 A simple drag-and-drop quiz generator for Jupyter Books.
19-
20+
2021 Usage:
2122 quiz = DragDropQuiz()
2223 quiz.create_matching_quiz(
@@ -26,14 +27,16 @@ class DragDropQuiz:
2627 correct_mapping={"Description 1": "Option A", "Description 2": "Option B", "Description 3": "Option C"}
2728 )
2829 """
29-
30+
3031 def __init__ (self ):
3132 self .quiz_counter = 0
32-
33- def create_matching_quiz (self , title , descriptions , options , correct_mapping , show_feedback = True , feedback_messages = None ):
33+
34+ def create_matching_quiz (
35+ self , title , descriptions , options , correct_mapping , show_feedback = True , feedback_messages = None
36+ ):
3437 """
3538 Create a drag-and-drop matching quiz.
36-
39+
3740 Parameters:
3841 - title (str): The quiz title/question
3942 - descriptions (list): List of items to be matched (static labels)
@@ -44,33 +47,33 @@ def create_matching_quiz(self, title, descriptions, options, correct_mapping, sh
4447 """
4548 self .quiz_counter += 1
4649 quiz_id = f"drag_drop_quiz_{ self .quiz_counter } _{ uuid .uuid4 ().hex [:8 ]} "
47-
50+
4851 # Set default feedback messages if none provided
4952 if feedback_messages is None :
5053 feedback_messages = {
5154 "correct" : "Perfekt! Alle {total} Zuordnungen sind korrekt!" ,
5255 "incorrect" : "Leider sind keine Zuordnungen korrekt. Versuchen Sie es noch einmal!" ,
53- "partial" : "Teilweise richtig: {correct} von {total} Zuordnungen sind korrekt."
56+ "partial" : "Teilweise richtig: {correct} von {total} Zuordnungen sind korrekt." ,
5457 }
55-
56- # Convert correct mapping to use indices for earlier elements, but map option texts directly
58+
59+ # Convert correct mapping to use indices for easier JavaScript handling
5760 desc_to_idx = {desc : i for i , desc in enumerate (descriptions )}
58-
61+ opt_to_idx = {opt : i for i , opt in enumerate (options )}
62+
5963 correct_pairs = []
6064 for desc , opt in correct_mapping .items ():
61- if desc in desc_to_idx :
62- # We store the string `opt` instead of the index so duplicate texts work
63- correct_pairs .append ([desc_to_idx [desc ], opt ])
64-
65+ if desc in desc_to_idx and opt in opt_to_idx :
66+ correct_pairs .append ([desc_to_idx [desc ], opt_to_idx [opt ]])
67+
6568 html_content = self ._generate_html (
6669 quiz_id , title , descriptions , options , correct_pairs , show_feedback , feedback_messages
6770 )
68-
71+
6972 return HTML (html_content )
70-
73+
7174 def _generate_html (self , quiz_id , title , descriptions , options , correct_pairs , show_feedback , feedback_messages ):
7275 """Generate the complete HTML for the drag-and-drop quiz."""
73-
76+
7477 # Generate static description labels with drop zones
7578 description_zones = ""
7679 for i , desc in enumerate (descriptions ):
@@ -82,7 +85,7 @@ def _generate_html(self, quiz_id, title, descriptions, options, correct_pairs, s
8285 </div>
8386 </div>
8487 '''
85-
88+
8689 # Generate draggable options
8790 draggable_options = ""
8891 for i , option in enumerate (options ):
@@ -91,29 +94,29 @@ def _generate_html(self, quiz_id, title, descriptions, options, correct_pairs, s
9194 { option }
9295 </div>
9396 '''
94-
97+
9598 return f'''
9699 <div class="drag-drop-quiz" id="{ quiz_id } ">
97100 <div class="quiz-title">{ title } </div>
98-
101+
99102 <div class="quiz-main">
100103 <div class="descriptions-container">
101104 { description_zones }
102105 </div>
103106 </div>
104-
107+
105108 <div class="options-container">
106109 <div class="options-title">Ziehen Sie diese zu den passenden Beschreibungen</div>
107110 <div class="options-list" id="{ quiz_id } _options">
108111 { draggable_options }
109112 </div>
110113 </div>
111-
114+
112115 <div class="quiz-controls">
113116 <button class="quiz-button" onclick="checkAnswer_{ quiz_id } ()">Antwort prüfen</button>
114117 <button class="quiz-button reset-button" onclick="resetQuiz_{ quiz_id } ()">Zurücksetzen</button>
115118 </div>
116-
119+
117120 <div id="{ quiz_id } _feedback"></div>
118121 </div>
119122 <script>
@@ -131,5 +134,3 @@ def _generate_html(self, quiz_id, title, descriptions, options, correct_pairs, s
131134 }});
132135 </script>
133136 '''
134-
135-
0 commit comments