import json import os import random import gradio as gr from dotenv import load_dotenv from constants import MODELS, MODELS_PATH, BOOKS from utils import save_results load_dotenv() if os.getenv("ENV_TYPE") == "dev": MODELS["Test"] = "test" MODELS_PATH["Test"] = "test" BOOKS["Test"] = "test.json" questions_data = [] current_question_index = 0 answers_log = [] # Log for saving answers feedback_questions = "" def get_question(): global questions_data, current_question_index question = questions_data[current_question_index] question_text = f"# Питання:\n## {question['question']}" answers = [answer['answer'] for answer in question['answers']] random.shuffle(answers) return question_text, answers def load_questions(model, book, student_name, class_name): global questions_data, current_question_index current_question_index = 0 answers_log.clear() if not model or not book or not student_name or not class_name: return "# Будь ласка, заповніть усі поля!", [] model_path = MODELS_PATH[model] book_filename = BOOKS[book] file_path = os.path.join("questions", model_path, book_filename) if not os.path.exists(file_path): return f"Файл за шляхом {file_path} не знайдено.", [] with open(file_path, "r", encoding="utf-8") as file: questions_data = json.load(file) if questions_data: return get_question() else: return "У файлі немає питань.", [] def get_next_question(selected_answer): global current_question_index, answers_log, feedback_questions if not selected_answer: question_text, answers = get_question() return ( question_text, # question_radio gr.update(choices=answers, value=None, interactive=True, visible=True), # answer_radio gr.update(visible=True), # next_button gr.update(visible=False), # feedback_input gr.update(visible=False), # rating_slider gr.update(visible=False), # submit_feedback_button gr.update(visible=False), # rating_text gr.update(visible=False), # question_correct gr.update(visible=False), # answers_correct gr.update(visible=False), # interesting_question gr.update(visible=False, value=""), # feedback_questions_output ) # Writing answer in log answers_log.append({ "selected": selected_answer, "isCorrect": any(answer['answer'] == selected_answer and answer['isCorrect'] for answer in questions_data[current_question_index]['answers']) }) # Move to the next question current_question_index += 1 if current_question_index < len(questions_data): question_text, answers = get_question() return ( question_text, # question_radio gr.update(choices=answers, value=None, interactive=True, visible=True), # answer_radio gr.update(visible=True), # next_button gr.update(visible=False), # feedback_input gr.update(visible=False), # rating_slider gr.update(visible=False), # submit_feedback_button gr.update(visible=False), # rating_text gr.update(visible=False), # question_correct gr.update(visible=False), # answers_correct gr.update(visible=False), # interesting_question gr.update(visible=False, value=""), # feedback_questions_output ) else: # All questions are completed — ask for feedback question_text = "# Дякуємо за участь у тесті!\n# Передивіться тест та ваші відповіді\n# Залиште, будь ласка, свій відгук в кінці сторінки і оцініть тест.\n---" feedback_questions = prepare_questions_for_feedback(questions_data, answers_log) return ( question_text, # question_radio gr.update(visible=False, value=None), # answer_radio gr.update(visible=False), # next_button gr.update(visible=True), # feedback_input gr.update(visible=True), # rating_slider gr.update(visible=True), # submit_feedback_button gr.update(visible=True), # rating_text gr.update(visible=True), # question_correct gr.update(visible=True), # answers_correct gr.update(visible=True), # interesting_question gr.update(visible=True, value=feedback_questions), # feedback_questions_output ) def summarize_results(student_name, class_name, model, book, feedback, rating, question_correct, answers_correct, interesting_question): global questions_data, answers_log, feedback_questions questions = [] if not feedback or question_correct is None or answers_correct is None or interesting_question is None or rating is None: return ( "# Залиште відгук про тест!", # question_output gr.update(visible=True), # feedback_input gr.update(visible=True), # rating_slider gr.update(visible=True), # submit_feedback_button gr.update(visible=True), # question_correct gr.update(visible=True), # answers_correct gr.update(visible=True), # interesting_question gr.update(visible=True), # rating_text gr.update(visible=True, value=feedback_questions), # feedback_questions_output gr.update(visible=True), # feedback_not_provided ) for question, answer in zip(questions_data, answers_log): questions.append({ "question": question, "answer": answer }) save_results( student_name, class_name, MODELS[model], book, questions, feedback, rating, question_correct, answers_correct, interesting_question ) correct_answers_count = sum(1 for answer in answers_log if answer['isCorrect']) total_questions = len(questions_data) grade_12 = (correct_answers_count / total_questions) * 12 summary = ( f"# Усі питання пройдено!\n\n" f"## Ви відповіли правильно на {correct_answers_count} з {total_questions} питань.\n\n" f"## Оцінка за 12-бальною шкалою: {grade_12:.2f}.\n\n" ) return ( summary, # question_output gr.update(visible=False, value=""), # feedback_input gr.update(visible=False, value=None), # rating_slider gr.update(visible=False), # submit_feedback_button gr.update(visible=False, value=""), # question_correct gr.update(visible=False, value=""), # answers_correct gr.update(visible=False, value=""), # interesting_question gr.update(visible=False), # rating_text gr.update(visible=False, value=""), # feedback_questions_output gr.update(visible=False), # feedback_not_provided ) def prepare_questions_for_feedback(questions, answer_log): feedback = [] for i, question in enumerate(questions): question_text = f"## Питання: {question['question']}." answers_text = "\n".join( [f"* {ans['answer']}" for ans in question['answers']] ) user_answer = f"## Ваша відповідь:\n* {answer_log[i]['selected']}" feedback.append(f"{question_text}\n## Відповіді:\n{answers_text}\n{user_answer}\n---") return "\n".join(feedback) with gr.Blocks() as demo: with gr.Column(): gr.Markdown("# Оберіть модель та книгу, щоб завантажити питання") student_name_input = gr.Textbox(label="Ваше ім'я") class_name_input = gr.Textbox(label="Ваш клас") model_radio = gr.Radio(list(MODELS.keys()), label="Оберіть модель") book_radio = gr.Radio(list(BOOKS.keys()), label="Оберіть книгу") load_button = gr.Button("Завантажити питання") question_output = gr.Markdown(label="Питання") answer_radio = gr.Radio([], label="Варіанти відповіді", interactive=True, visible=False) next_button = gr.Button("Наступне питання", visible=False) feedback_questions_output = gr.Markdown(label="Пройдені питання", value="Nothing", visible=False) rating_text = gr.Markdown( "### Шкала оцінювання:\n\n#### -2 — дуже погано\n\n#### -1 — погано\n\n#### 0 — задовільно\n\n#### 1 — добре\n\n#### 2 — відмінно", visible=False) feedback_not_provided = gr.Markdown("# Заповніть поля відгуку та залишіть оцінку!", visible=False) question_correct_radio = gr.Radio([-2, -1, 0, 1, 2], label="Чи коректно поставлені запитання?", visible=False, interactive=True) answers_correct_radio = gr.Radio([-2, -1, 0, 1, 2], label="Чи коректно поставлені варіанти відповідей?", visible=False, interactive=True) interesting_question_radio = gr.Radio([-2, -1, 0, 1, 2], label="Чи цікаві були запитання?", visible=False, interactive=True) feedback_input = gr.Textbox(label="Будь-який коментар про тест (за бажанням)", visible=False) rating_buttons = gr.Radio([-2, -1, 0, 1, 2], label="Оцініть тест", visible=False, interactive=True) submit_feedback_button = gr.Button("Завершити тест", visible=False) def update_question(model, book, student_name, class_name): question, answers = load_questions(model, book, student_name, class_name) is_field_filled = len(answers) > 0 return ( question, # question_output gr.update(choices=answers, interactive=True, visible=is_field_filled), # answer_radio gr.update(visible=is_field_filled), # next_button gr.update(visible=False, value=""), # feedback_input gr.update(visible=False, value=None), # rating_buttons gr.update(visible=False), # submit_feedback_button gr.update(visible=False), # rating_text gr.update(visible=False, value=""), # question_correct gr.update(visible=False, value=""), # answers_correct gr.update(visible=False, value=""), # interesting_question gr.update(visible=False, value=""), # feedback_questions_output gr.update(visible=False), # feedback_not_provided ) load_button.click( update_question, inputs=[ model_radio, book_radio, student_name_input, class_name_input, ], outputs=[ question_output, answer_radio, next_button, feedback_input, rating_buttons, submit_feedback_button, rating_text, question_correct_radio, answers_correct_radio, interesting_question_radio, feedback_questions_output, feedback_not_provided, ] ) next_button.click( get_next_question, inputs=[answer_radio], outputs=[ question_output, answer_radio, next_button, feedback_input, rating_buttons, submit_feedback_button, rating_text, question_correct_radio, answers_correct_radio, interesting_question_radio, feedback_questions_output, ] ) submit_feedback_button.click( summarize_results, inputs=[ student_name_input, class_name_input, model_radio, book_radio, feedback_input, rating_buttons, question_correct_radio, answers_correct_radio, interesting_question_radio, ], outputs=[ question_output, feedback_input, rating_buttons, submit_feedback_button, question_correct_radio, answers_correct_radio, interesting_question_radio, rating_text, feedback_questions_output, feedback_not_provided, ] ) if __name__ == "__main__": demo.launch()