initial development checkpoint 2

This commit is contained in:
2024-05-28 17:47:08 +03:00
parent 26e912c03a
commit b4c1a23ce2
14 changed files with 618 additions and 67 deletions

View File

@@ -1,4 +1,4 @@
from object_pool import ObjectPool
from db.object_pool import ObjectPool
class Question:
def init(self, sID, title, max_time, test_id):
@@ -24,6 +24,32 @@ class Question:
def get_test_id(self):
return self.test_id
def render_short(self):
total_time = self.max_time
hours = total_time // 3600
total_time -= hours * 3600
minutes = total_time // 60
total_time -= minutes * 60
seconds = total_time
total_label = []
if hours:
total_label.append(f"{hours} год.")
if minutes:
total_label.append(f"{minutes} хв.")
if seconds:
total_label.append(f"{seconds} c.")
total_time = " ".join(total_label)
if int(self.max_time) > 0:
return f'<div class="question-short"><a class="question-link" href="/index.py?mode=view-question&id={self.id}"><span class="sub-label">#{self.id}</span><span class="main-label">{self.title}</span></a><span class="sub-title">На відповідь є {total_time}</span></div>'
else:
return f'<div class="question-short"><a class="question-link" href="/index.py?mode=view-question&id={self.id}"><span class="sub-label">#{self.id}</span><span class="main-label">{self.title}</span></a><span class="sub-title">Час на відповідь не обмежений</span></div>'
'''
class QuestionPool:
def __init__(self):
@@ -36,8 +62,14 @@ class QuestionPool:
'''
class QuestionPool:
def __init__(self):
def __init__(self, db):
self.object_pool = ObjectPool("question", Question)
if db:
self.object_pool.load_from_db(db)
def iter(self):
return iter(self.object_pool.pool)
def select_by_test_id(self, test_id):
return [i for i in self.object_pool.pool if i.get_test_id() == int(test_id)]

View File

@@ -1,4 +1,4 @@
from object_pool import ObjectPool
from db.object_pool import ObjectPool
class ResponseOption:
def init(self, sID, label, questionID, correctness):
@@ -24,20 +24,31 @@ class ResponseOption:
def get_correctness(self):
return correctness
class ResponceOptionPool:
def __init__(self):
def render_short(self):
if self.correctness:
c_mark = "+ "
else:
c_mark = " "
return f'<span class="response-option-short">{c_mark} {self.label}</span>'
def render_full(self):
if self.correctness:
c_mark = "+"
else:
c_mark = "-"
return f'<div class="response-option"><a class="response-option-mark" href="/flip-correctness.py?res_opt_id={self.id}">{c_mark}</a><span class="response-option-label">{self.label}</span><br><div class="controls"><a class="sub-button" href="/index.py?mode=edit-response-option&id={self.id}">Редагувати</a><a class="scary-button" href="/index.py?mode=delete-response-option&id={self.id}">Видалити</a></div></div>'
class ResponseOptionPool:
def __init__(self, db):
self.object_pool = ObjectPool("response_option", ResponseOption)
if db:
self.object_pool.load_from_db(db)
'''
class ResponceOptionPool:
def __init__(self):
self.pool = []
def iter(self):
return iter(self.object_pool.pool)
def load_from_db(self, cur):
db.execute("SELECT * FROM response_option;")
self.pool = [ResponseOption().init_from_data(i) for i in cur]
return self
'''
def select_by_question_id(self, question_id):
return [i for i in self.object_pool.pool if i.get_question_id() == int(question_id)]

View File

@@ -17,7 +17,7 @@ class Test:
return self.name
def render_short(self):
return f'<div class="test-short"><a class="header-link">#{self.sID} {self.name}</a></div>'
return f'<div class="test-short"><a class="test-link" href="/index.py?mode=view-test&id={self.id}"><span class="sub-label">#{self.id}</span><span class="main-label">{self.name}</span></a></div>'
class TestPool:
def __init__(self, db):

View File

@@ -0,0 +1,15 @@
from db.question import QuestionPool
class QuestionList:
def __init__(self, cursor):
self.cursor = cursor
def render(self, test_id = None):
qp = QuestionPool(self.cursor)
if test_id:
rendered_questions = [i.render_short() for i in qp.select_by_test_id(test_id)]
else:
rendered_questions = [i.render_short() for i in qp.iter()]
return "\n".join(rendered_questions)

View File

@@ -0,0 +1,15 @@
from db.response_option import ResponseOptionPool
class ResponseOptionList:
def __init__(self, cursor):
self.cursor = cursor
def render(self, question_id = None):
rop = ResponseOptionPool(self.cursor)
if question_id:
rendered_response_options = [i.render_full() for i in rop.select_by_question_id(question_id)]
else:
rendered_response_options = [i.render_full() for i in rop.iter()]
return "\n".join(rendered_response_options)

View File

@@ -3,6 +3,10 @@ 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):
@@ -13,6 +17,15 @@ class View:
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,
"view-test": self.render_view_test,
"create-question": self.render_create_question,
"edit-question": self.render_edit_question,
"view-question": self.render_view_question,
"create-response-option": self.render_create_response_option,
}
def get_db_connection(self):
if not self.db_connection:
@@ -49,29 +62,124 @@ class View:
else:
mode = "test-list"
if mode == "test-list":
cur.execute("SELECT id FROM test;")
test_amount = len(list(cur))
header = f'<h2>Всього тестів: {test_amount}</h2>'
subheader = f'<input placeholder="Шукати тести"><br><a class="generic-button" href="?mode=create-test">Створити тест</a>'
content = TestList(cur).render()
elif mode == "create-test":
header = f"<h2>Створити новий тест"
subheader = "<i>Введіть властивості нового тесту нижче</i>"
content = f'''<form action="/create-test.py">
<label for="name">Назва тесту:</label><br>
<input type="text" name="name" placeholder="Введіть назву..." required>
<input type="submit" value="Створити">
</form>'''
else:
if mode not in self.supported_modes:
header = f"<h2>No such view mode: {mode}</h2>"
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
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'<h2>Всього тестів: {test_amount}</h2>'
subheader = f'<input placeholder="Шукати тести"><br><a class="generic-button" href="?mode=create-test">Створити новий тест</a>'
content = TestList(cur).render()
return header, subheader, content
def render_create_test(self, cur):
header = f"<h2>Створити новий тест</h2>"
subheader = "<i>Введіть властивості нового тесту нижче</i>"
content = f'''<form action="/create-test.py">
<label for="name">Назва тесту:</label>
<input type="text" name="name" placeholder="Введіть назву..." required><br>
<input type="submit" value="Створити">
</form>'''
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"<h2>Такого тесту не існує: {self.args['id']}</h2>"
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
content = ""
return header, subheader, content
header = f'<span class="view-test-id-tag">#{self.args["id"]}</span><span class="view-test-main-tag">{test_name}</span>'
subheader = f'<a class="generic-button" href="?mode=create-question&test_id={self.args["id"]}">Додати запитання</a>'
content = QuestionList(cur).render(self.args['id'])
return header, subheader, content
def render_create_question(self, cur):
header = f"<h2>Додати нове запитання</h2>"
subheader = "<i>Введіть властивості нового запитання нижче</i>"
content = f'''<form action="/create-question.py">
<input type="text" name="test_id" value="{self.args["test_id"]}" style="display:none;">
<label for="title">Текст запитання:</label>
<input type="text" name="title" placeholder="Введіть запитання..." required><br>
<label for="mtime">Максимальний час на відповідь (в сек):</label>
<input type="number" name="mtime" placeholder="Наприклад, 120"><br>
<input type="submit" value="Додати">
</form>'''
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"<h2>Такого запитання не існує: {self.args['id']}</h2>"
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
content = ""
return header, subheader, content
header = f"<h2>Змінити запитання</h2>"
subheader = "<i>Відредагуйте властивості запитання нижче</i>"
content = f'''<form action="/edit-question.py">
<input type="text" name="question_id" value="{self.args["id"]}" style="display:none;">
<label for="title">Текст запитання:</label>
<input type="text" name="title" placeholder="Введіть запитання..." value="{escape_html(question_title)}" required><br>
<label for="mtime">Максимальний час на відповідь (в сек):</label>
<input type="number" name="mtime" placeholder="Наприклад, 120"><br>
<input type="submit" value="Зберегти зміни">
</form>'''
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"<h2>Такого запитання не існує: {self.args['id']}</h2>"
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
content = ""
return header, subheader, content
header = f'<span class="view-test-id-tag">#{self.args["id"]}</span><span class="view-test-main-tag">{question_name}</span>'
subheader = f'<a class="generic-button" href="?mode=create-response-option&question_id={self.args["id"]}">Додати варіант відповіді</a>' + \
f'<a class="sub-button" href="?mode=edit-question&id={self.args["id"]}">Редагувати запитання</a>'
content = ResponseOptionList(cur).render(self.args['id'])
return header, subheader, content
def render_create_response_option(self, cur):
header = f"<h2>Додати новий варіант відповіді</h2>"
subheader = "<i>Введіть властивості варіанту відповіді нижче</i>"
content = f'''<form action="/create-response-option.py">
<input type="text" name="question_id" value="{self.args["question_id"]}" style="display:none;">
<label for="label">Текст відповіді:</label>
<input type="text" name="label" placeholder="Введіть текст відповіді..." required><br>
<input type="submit" value="Додати">
</form>'''
return header, subheader, content