import mariadb as mdb import json import os from test_list import TestList from question_list import QuestionList from response_option_list import ResponseOptionList from httputils import escape_html def readfile(path): if os.path.exists(path): return open(path).read() class View: def __init__(self, query_args, connector_data = {}): self.args = query_args self.connector_data = connector_data self.db_connection = None self.supported_modes = { "test-list": self.render_test_list, "create-test": self.render_create_test, "edit-test": self.render_edit_test, "delete-test": self.render_delete_test, "view-test": self.render_view_test, "create-question": self.render_create_question, "edit-question": self.render_edit_question, "delete-question": self.render_delete_question, "view-question": self.render_view_question, "create-response-option": self.render_create_response_option, "edit-response-option": self.render_edit_response_option, "delete-response-option": self.render_delete_response_option, "generate-response-options": self.render_generate_response_options, "view-stats": self.render_view_stats } def get_db_connection(self): if not self.db_connection: args = {"host": "127.0.0.1", "port": 3306, "user": "root", "password": "", "database": "test_holder"} settings = json.loads(readfile("cgi/db-settings.json")) args.update(settings) args.update(self.connector_data) self.db_connection = mdb.connect(**args) return self.db_connection def format_page(self, header, subheader, content): base_layout = readfile("html/base_layout.html") base_layout = base_layout.replace("%HEADER%", header) base_layout = base_layout.replace("%SUBHEADER%", subheader) base_layout = base_layout.replace("%CONTENT%", content) return base_layout def render_page(self): dbc = self.get_db_connection() cur = dbc.cursor() if 'mode' in self.args: mode = self.args['mode'] else: mode = "test-list" if mode not in self.supported_modes: header = f"

No such view mode: {mode}

" subheader = f'Повернутися на головну сторінку' content = "" else: header, subheader, content = self.supported_modes[mode](cur) dbc.close() return self.format_page(header, subheader, content) def render_test_list(self, cur): cur.execute("SELECT id FROM test;") test_amount = len(list(cur)) header = f'

Всього тестів: {test_amount}

' if 'search' in self.args: search = self.args['search'] else: search = "" subheader = f'

Створити новий тестПереглянути статистику' tl = TestList(cur) if 'search' in self.args: content = tl.render(self.args['search']) else: content = tl.render() return header, subheader, content def render_create_test(self, cur): header = f"

Створити новий тест

" subheader = "Введіть властивості нового тесту нижче" content = f'''

''' return header, subheader, content def render_edit_test(self, cur): cur.execute(f"SELECT name FROM test WHERE id = {self.args['id']};") test_name = next(iter(cur), [None])[0] if not test_name: header = f"

Такого тесту не існує: {self.args['id']}

" subheader = f'Повернутися на головну сторінку' content = "" return header, subheader, content header = f"

Редагувати тест

" subheader = "Вкажіть нові властивості тесту нижче" content = f'''

''' return header, subheader, content def render_delete_test(self, cur): cur.execute(f"SELECT name FROM test WHERE id = {self.args['id']};") test_name = next(iter(cur), [None])[0] if not test_name: header = f"

Такого тесту не існує: {self.args['id']}

" subheader = f'Повернутися на головну сторінку' content = "" return header, subheader, content header = f"

Точно видалити цей тест?

" subheader = f"{test_name}" content = f'''
Так, видалити
Ні, залишити
''' return header, subheader, content def render_view_test(self, cur): cur.execute(f"SELECT name FROM test WHERE id = {self.args['id']};") test_name = next(iter(cur), [None])[0] if not test_name: header = f"

Такого тесту не існує: {self.args['id']}

" subheader = f'Повернутися на головну сторінку' content = "" return header, subheader, content header = f'#{self.args["id"]}{test_name}' subheader = f'Додати запитанняРедагувати тест' content = QuestionList(cur).render(self.args['id']) content += '
Назад до переліку тестів
' return header, subheader, content def render_create_question(self, cur): header = f"

Додати нове запитання

" subheader = "Введіть властивості нового запитання нижче" content = f'''


''' return header, subheader, content def render_edit_question(self, cur): cur.execute(f"SELECT title, mtime FROM question WHERE id = {self.args['id']};") question_title, question_max_time = next(iter(cur), [None, None]) if not question_title: header = f"

Такого запитання не існує: {self.args['id']}

" subheader = f'Повернутися на головну сторінку' content = "" return header, subheader, content header = f"

Змінити запитання

" subheader = "Відредагуйте властивості запитання нижче" content = f'''


''' return header, subheader, content def render_delete_question(self, cur): cur.execute(f"SELECT title FROM question WHERE id = {self.args['id']};") question_title = next(iter(cur), [None])[0] if not question_title: header = f"

Такого запитання не існує: {self.args['id']}

" subheader = f'Повернутися на головну сторінку' content = "" return header, subheader, content header = f"

Точно видалити запитання?

" subheader = f"{question_title}" cur.execute(f"SELECT test.id FROM test JOIN question ON test.id = question.tstID WHERE question.id = {self.args['id']};") test_id = iter(cur).__next__()[0] content = f'''
Так, видалити
Ні, залишити
''' return header, subheader, content def render_view_question(self, cur): cur.execute(f"SELECT title FROM question WHERE id = {self.args['id']};") question_name = next(iter(cur), [None])[0] if not question_name: header = f"

Такого запитання не існує: {self.args['id']}

" subheader = f'Повернутися на головну сторінку' content = "" return header, subheader, content header = f'#{self.args["id"]}{question_name}' subheader = f'Додати варіант відповіді' + \ f'Редагувати запитання' content = ResponseOptionList(cur).render(self.args['id']) cur.execute(f"""SELECT test.id FROM test JOIN question ON test.id = question.tstID WHERE question.id = {self.args['id']};""") test_id = iter(cur).__next__()[0] content += f'
Назад до тесту
' return header, subheader, content def render_create_response_option(self, cur): header = f"

Додати новий варіант відповіді

" subheader = "Введіть властивості варіанту відповіді нижче" content = f'''

''' return header, subheader, content def render_edit_response_option(self, cur): cur.execute(f"SELECT label FROM response_option WHERE id = {self.args['id']};") respose_option_label = next(iter(cur), [None])[0] header = f"

Редагувати варіант відповіді

" subheader = "Введіть властивості варіанту відповіді нижче" content = f'''

''' return header, subheader, content def render_delete_response_option(self, cur): cur.execute(f"SELECT label FROM response_option WHERE id = {self.args['id']};") response_option_label = next(iter(cur), [None])[0] header = f"

Точно видалити цей варіант відповіді?

" subheader = f"{response_option_label}" cur.execute(f"SELECT question.id FROM question JOIN response_option ON question.id = response_option.qstID WHERE response_option.id = {self.args['id']};") quest_id = iter(cur).__next__()[0] content = f'''
Так, видалити
Ні, залишити
''' return header, subheader, content def render_generate_response_options(self, cur): header = f"

Генерація варіантів відповідей

" subheader = f"Вкажіть параметри генерації нижче" content = f'''

''' return header, subheader, content def render_view_stats(self, cur): header = f"

Статистика системи

" subheader = f'Повернутися на головну сторінку' content = f'''''' test_count = TestList(cur).count() content += f'
ТестиВсього тестів: {test_count}
' question_count = QuestionList(cur).count() question_avg_time = QuestionList(cur).get_avg_time() content += f'
ЗапитанняВсього запитань: {question_count} (в середньому по {round(question_count/test_count, 3)} зап./тест)
В середньому на запитання дається {question_avg_time}
' rol = ResponseOptionList(cur) response_option_count = rol.count() response_option_count_correct = rol.count(correct = True) content += f'
Варіанти відповідейВсього варіантів відповідей: {response_option_count}
З-поміж них правильних: {response_option_count_correct} ({round(response_option_count_correct/response_option_count*100, 2)}%)
' return header, subheader, content