Загрузка данных


#---------------------------------------------------ГРАФИЧЕСКИЙ ТЕСТЕР---------------------------------------------------

import tkinter as tk
from tkinter import filedialog, messagebox
from docx import Document
import re

INVISIBLE_MARKER = "\u200b"


class QuizApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Интерактивный тест (невидимая проверка)")
        self.root.geometry("700x600")

        self.questions = []
        self.current_q_index = 0
        self.correct_count = 0

        # UI Элементы
        self.lbl_info = tk.Label(root, text="Загрузите сгенерированный тест (.docx)", font=("Arial", 12))
        self.lbl_info.pack(pady=20)

        self.btn_load = tk.Button(root, text="Выбрать файл теста", command=self.load_quiz, width=25)
        self.btn_load.pack()

        self.quiz_frame = tk.Frame(root)

        self.lbl_question = tk.Label(self.quiz_frame, text="", font=("Arial", 11, "bold"), wraplength=600,
                                     justify="left")
        self.lbl_question.pack(pady=20)

        self.var_choice = tk.StringVar()
        self.options_container = tk.Frame(self.quiz_frame)
        self.options_container.pack(pady=10)

        self.lbl_feedback = tk.Label(self.quiz_frame, text="", font=("Arial", 10, "italic"))
        self.lbl_feedback.pack(pady=10)

        self.btn_check = tk.Button(self.quiz_frame, text="Проверить ответ", command=self.check_answer,
                                   state=tk.DISABLED, width=20)
        self.btn_check.pack(pady=5)

        self.btn_next = tk.Button(self.quiz_frame, text="Следующий вопрос", command=self.next_question,
                                  state=tk.DISABLED, width=20)
        self.btn_next.pack(pady=5)

    def load_quiz(self):
        file_path = filedialog.askopenfilename(filetypes=[("Word documents", "*.docx")])
        if not file_path: return

        try:
            doc = Document(file_path)
            full_text = ""
            for p in doc.paragraphs:
                full_text += p.text + "\n"

            # Разбиваем текст по "Вопрос №"
            raw_blocks = re.split(r'Вопрос №\d+:', full_text)

            self.questions = []
            for block in raw_blocks:
                if "---" in block:
                    content = block.split("---")[0].strip()
                    lines = [l.strip() for l in content.split('\n') if l.strip()]

                    if len(lines) > 1:
                        question_text = lines[0]
                        options_raw = lines[1:]

                        correct_text = ""
                        clean_options = []

                        for opt in options_raw:
                            if ')' in opt:
                                actual_text = opt.split(')', 1)[1].strip()
                            else:
                                actual_text = opt.strip()

                            if INVISIBLE_MARKER in actual_text:
                                actual_text = actual_text.replace(INVISIBLE_MARKER, "")
                                correct_text = actual_text

                            clean_options.append(actual_text)

                        if correct_text:
                            self.questions.append({
                                "question": question_text,
                                "options": clean_options,
                                "correct": correct_text
                            })

            if not self.questions:
                messagebox.showerror("Ошибка", "Не найдено вопросов с метками правильных ответов.")
                return

            self.btn_load.pack_forget()
            self.lbl_info.pack_forget()
            self.quiz_frame.pack(fill="both", expand=True)
            self.display_question()

        except Exception as e:
            messagebox.showerror("Ошибка", f"Ошибка: {e}")

    def display_question(self):
        for widget in self.options_container.winfo_children():
            widget.destroy()

        self.lbl_feedback.config(text="", fg="black")
        self.btn_next.config(state=tk.DISABLED)
        self.btn_check.config(state=tk.DISABLED)

        q_data = self.questions[self.current_q_index]
        self.lbl_question.config(
            text=f"Вопрос {self.current_q_index + 1} из {len(self.questions)}:\n\n{q_data['question']}")

        self.var_choice.set(None)

        for option in q_data['options']:
            rb = tk.Radiobutton(self.options_container, text=option, variable=self.var_choice,
                                value=option, font=("Arial", 10), wraplength=600, justify="left",
                                command=lambda: self.btn_check.config(state=tk.NORMAL))
            rb.pack(anchor="w", pady=2)

    def check_answer(self):
        user_choice = self.var_choice.get()
        correct_answer = self.questions[self.current_q_index]["correct"]

        for child in self.options_container.winfo_children():
            child.configure(state=tk.DISABLED)

        if user_choice == correct_answer:
            self.lbl_feedback.config(text="ПРАВИЛЬНО!", fg="green")
            self.correct_count += 1
        else:
            self.lbl_feedback.config(text=f"ОШИБКА!\nПравильный ответ: {correct_answer}", fg="red")

        self.btn_check.config(state=tk.DISABLED)
        self.btn_next.config(state=tk.NORMAL)

    def next_question(self):
        self.current_q_index += 1
        if self.current_q_index < len(self.questions):
            self.display_question()
        else:
            messagebox.showinfo("Итог",
                                f"Тест пройден!\nВаш результат: {self.correct_count} из {len(self.questions)}")
            self.root.destroy()


if __name__ == "__main__":
    root = tk.Tk()
    app = QuizApp(root)
    root.mainloop()