initial development checkpoint 4
This commit is contained in:
parent
54377708b0
commit
fbdc014bf4
|
@ -54,11 +54,17 @@ class Question:
|
|||
rop = ResponseOptionPool(cur)
|
||||
return "<br>".join([i.render_short() for i in rop.select_by_question_id(self.id)])
|
||||
|
||||
def get_correct_response_percentage(self, cur):
|
||||
rop = ResponseOptionPool(cur)
|
||||
response_options = rop.select_by_question_id(self.id)
|
||||
return sum([int(i.get_correctness()) for i in response_options]) / len(response_options) * 100
|
||||
|
||||
def render_short(self, cur):
|
||||
time_label = self.get_time_label()
|
||||
response_options = self.get_response_option_short_list(cur)
|
||||
correct_percentage = round(self.get_correct_response_percentage(cur))
|
||||
|
||||
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">{time_label}</span><div class="response-option-short-list">{response_options}</div><div class="controls"><a class="sub-button" href="/index.py?mode=edit-question&id={self.id}">Редагувати</a><a class="scary-button" href="/index.py?mode=delete-question&id={self.id}">Видалити</a></div></div>'
|
||||
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">{time_label}<br>{correct_percentage}% відповідей правильні</span><div class="response-option-short-list">{response_options}</div><div class="controls"><a class="magic-button" href="?mode=generate-response-options&id={self.id}">Згенерувати відповіді</a><a class="sub-button" href="/index.py?mode=edit-question&id={self.id}">Редагувати</a><a class="scary-button" href="/index.py?mode=delete-question&id={self.id}">Видалити</a></div></div>'
|
||||
|
||||
class QuestionPool:
|
||||
def __init__(self, db):
|
||||
|
|
|
@ -22,7 +22,7 @@ class ResponseOption:
|
|||
return self.questionID
|
||||
|
||||
def get_correctness(self):
|
||||
return correctness
|
||||
return self.correctness
|
||||
|
||||
def render_short(self):
|
||||
if self.correctness:
|
||||
|
|
|
@ -17,7 +17,7 @@ class Test:
|
|||
return self.name
|
||||
|
||||
def render_short(self):
|
||||
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>'
|
||||
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="controls"><a class="sub-button" href="?mode=edit-test&id={self.id}">Редагувати</a><a class="scary-button" href="?mode=delete-test&id={self.id}">Видалити</a></div></div>'
|
||||
|
||||
class TestPool:
|
||||
def __init__(self, db):
|
||||
|
|
|
@ -13,3 +13,34 @@ class QuestionList:
|
|||
rendered_questions = [i.render_short(self.cursor) for i in qp.iter()]
|
||||
|
||||
return "\n".join(rendered_questions)
|
||||
|
||||
def count(self):
|
||||
qp = QuestionPool(self.cursor)
|
||||
return len(qp.object_pool.pool)
|
||||
|
||||
def get_avg_time(self):
|
||||
qp = QuestionPool(self.cursor)
|
||||
avg_time = sum([i.get_max_time() for i in qp.iter()]) / len(qp.object_pool.pool)
|
||||
return self.get_time_label(avg_time)
|
||||
|
||||
def get_time_label(self, max_time):
|
||||
total_time = 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"{round(hours)} год.")
|
||||
if minutes:
|
||||
total_label.append(f"{round(minutes)} хв.")
|
||||
if seconds:
|
||||
total_label.append(f"{round(seconds)} c.")
|
||||
|
||||
return " ".join(total_label)
|
||||
|
|
|
@ -13,3 +13,10 @@ class ResponseOptionList:
|
|||
rendered_response_options = [i.render_full() for i in rop.iter()]
|
||||
|
||||
return "\n".join(rendered_response_options)
|
||||
|
||||
def count(self, correct = False):
|
||||
rop = ResponseOptionPool(self.cursor)
|
||||
if correct:
|
||||
return len([i for i in rop.object_pool.pool if i.get_correctness()])
|
||||
else:
|
||||
return len(rop.object_pool.pool)
|
||||
|
|
|
@ -6,7 +6,14 @@ class TestList:
|
|||
def __init__(self, cursor):
|
||||
self.cursor = cursor
|
||||
|
||||
def render(self):
|
||||
def render(self, *args):
|
||||
tp = TestPool(self.cursor)
|
||||
if len(args) > 0:
|
||||
rendered_chunks = [i.render_short() for i in tp.object_pool.pool if args[0] in i.get_name()]
|
||||
else:
|
||||
rendered_chunks = [i.render_short() for i in tp.object_pool.pool]
|
||||
return "\n".join(rendered_chunks)
|
||||
|
||||
def count(self):
|
||||
tp = TestPool(self.cursor)
|
||||
return len(tp.object_pool.pool)
|
||||
|
|
|
@ -20,6 +20,8 @@ class View:
|
|||
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,
|
||||
|
@ -28,6 +30,8 @@ class View:
|
|||
"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):
|
||||
|
@ -80,9 +84,18 @@ class View:
|
|||
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>'
|
||||
if 'search' in self.args:
|
||||
search = self.args['search']
|
||||
else:
|
||||
search = ""
|
||||
|
||||
content = TestList(cur).render()
|
||||
subheader = f'<form action="/index.py"><input name="search" placeholder="Шукати тести" value="{search}"></form><br><a class="generic-button" href="?mode=create-test">Створити новий тест</a><a class="sub-button" href="?mode=view-stats">Переглянути статистику</a>'
|
||||
|
||||
tl = TestList(cur)
|
||||
if 'search' in self.args:
|
||||
content = tl.render(self.args['search'])
|
||||
else:
|
||||
content = tl.render()
|
||||
|
||||
return header, subheader, content
|
||||
|
||||
|
@ -93,11 +106,50 @@ class View:
|
|||
content = f'''<form action="/create-test.py">
|
||||
<label for="name">Назва тесту:</label>
|
||||
<input type="text" name="name" placeholder="Введіть назву..." required><br>
|
||||
<input type="submit" value="Створити">
|
||||
<input type="submit" class="submit-button" value="Створити">
|
||||
</form>'''
|
||||
|
||||
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"<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-test.py">
|
||||
<input type="text" name="id" value="{self.args['id']}" style="display:none;">
|
||||
<label for="name">Назва тесту:</label>
|
||||
<input type="text" name="name" placeholder="Введіть назву..." value="{test_name}" required><br>
|
||||
<input type="submit" class="submit-button" value="Зберегти">
|
||||
</form>'''
|
||||
|
||||
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"<h2>Такого тесту не існує: {self.args['id']}</h2>"
|
||||
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
|
||||
content = ""
|
||||
return header, subheader, content
|
||||
|
||||
header = f"<h2>Точно видалити цей тест?</h2>"
|
||||
subheader = f"<i>{test_name}</i>"
|
||||
|
||||
content = f'''<div class="return-button-centerer"><a class="delete-button" href="/delete-test.py?id={self.args["id"]}">Так, видалити</a><br><a class="cancel-button" href="/">Ні, залишити</a></div>'''
|
||||
|
||||
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]
|
||||
|
@ -110,7 +162,7 @@ class View:
|
|||
|
||||
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>'
|
||||
subheader = f'<a class="generic-button" href="?mode=create-question&test_id={self.args["id"]}">Додати запитання</a><a class="sub-button" href="?mode=edit-test&id={self.args["id"]}">Редагувати тест</a>'
|
||||
|
||||
content = QuestionList(cur).render(self.args['id'])
|
||||
content += '<div class="return-button-centerer"><a class="return-button" href="/index.py">Назад до переліку тестів</a></div>'
|
||||
|
@ -127,7 +179,7 @@ class View:
|
|||
<input type="text" name="title" placeholder="Введіть запитання..." required><br>
|
||||
<label for="mtime">Максимальний час на відповідь (в сек):</label>
|
||||
<input type="number" name="mtime" placeholder="Наприклад, 120"><br>
|
||||
<input type="submit" value="Додати">
|
||||
<input type="submit" class="submit-button" value="Додати">
|
||||
</form>'''
|
||||
|
||||
return header, subheader, content
|
||||
|
@ -151,7 +203,7 @@ class View:
|
|||
<input type="text" name="title" placeholder="Введіть запитання..." value="{escape_html(question_title)}" required><br>
|
||||
<label for="mtime">Максимальний час на відповідь (в сек):</label>
|
||||
<input type="number" name="mtime" placeholder="Наприклад, 120" value="{question_max_time}"><br>
|
||||
<input type="submit" value="Зберегти зміни">
|
||||
<input type="submit" class="submit-button" value="Зберегти">
|
||||
</form>'''
|
||||
|
||||
return header, subheader, content
|
||||
|
@ -172,7 +224,7 @@ class View:
|
|||
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'''<a class="delete-button" href="/delete-question.py?id={self.args["id"]}">Так, видалити</a><br><a class="cancel-button" href="/index.py?mode=view-test&id={test_id}">Ні, залишити</a>'''
|
||||
content = f'''<div class="return-button-centerer"><a class="delete-button" href="/delete-question.py?id={self.args["id"]}">Так, видалити</a><br><a class="cancel-button" href="/index.py?mode=view-test&id={test_id}">Ні, залишити</a></div>'''
|
||||
|
||||
return header, subheader, content
|
||||
|
||||
|
@ -211,7 +263,7 @@ class View:
|
|||
<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="Додати">
|
||||
<input type="submit" class="submit-button" value="Додати">
|
||||
</form>'''
|
||||
|
||||
return header, subheader, content
|
||||
|
@ -227,7 +279,7 @@ class View:
|
|||
<input type="text" name="id" value="{self.args["id"]}" style="display:none;">
|
||||
<label for="label">Текст відповіді:</label>
|
||||
<input type="text" name="label" placeholder="Введіть текст відповіді..." value="{respose_option_label}" required><br>
|
||||
<input type="submit" value="Оновити">
|
||||
<input type="submit" class="submit-button" value="Зберегти">
|
||||
</form>'''
|
||||
|
||||
return header, subheader, content
|
||||
|
@ -242,6 +294,38 @@ class View:
|
|||
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'''<a class="delete-button" href="/delete-response-option.py?id={self.args["id"]}">Так, видалити</a><br><a class="cancel-button" href="/index.py?mode=view-question&id={quest_id}">Ні, залишити</a>'''
|
||||
content = f'''<div class="return-button-centerer"><a class="delete-button" href="/delete-response-option.py?id={self.args["id"]}">Так, видалити</a><br><a class="cancel-button" href="/index.py?mode=view-question&id={quest_id}">Ні, залишити</a></div>'''
|
||||
|
||||
return header, subheader, content
|
||||
|
||||
def render_generate_response_options(self, cur):
|
||||
header = f"<h2>Генерація варіантів відповідей</h2>"
|
||||
subheader = f"<i>Вкажіть параметри генерації нижче</i>"
|
||||
|
||||
content = f'''<form action="/generate-response-options.py">
|
||||
<input type="text" name="id" value="{self.args["id"]}" style="display:none;">
|
||||
<label for="label">Кількість варіантів:</label>
|
||||
<input type="number" name="amount" placeholder="Наприклад, 4" required><br>
|
||||
<input type="submit" class="magic-button" value="Згенерувати">
|
||||
</form>'''
|
||||
|
||||
return header, subheader, content
|
||||
|
||||
def render_view_stats(self, cur):
|
||||
header = f"<h2>Статистика системи</h2>"
|
||||
subheader = f'<a class="sub-button" href="/">Повернутися на головну сторінку</a>'
|
||||
content = f''''''
|
||||
|
||||
test_count = TestList(cur).count()
|
||||
content += f'<div class="piece-of-stats"><span class="header">Тести</span>Всього тестів: {test_count}</div>'
|
||||
|
||||
question_count = QuestionList(cur).count()
|
||||
question_avg_time = QuestionList(cur).get_avg_time()
|
||||
content += f'<div class="piece-of-stats"><span class="header">Запитання</span>Всього запитань: {question_count} (в середньому по {round(question_count/test_count, 3)} зап./тест)<br>В середньому на запитання дається {question_avg_time}</div>'
|
||||
|
||||
rol = ResponseOptionList(cur)
|
||||
response_option_count = rol.count()
|
||||
response_option_count_correct = rol.count(correct = True)
|
||||
content += f'<div class="piece-of-stats"><span class="header">Варіанти відповідей</span>Всього варіантів відповідей: {response_option_count}<br>З-поміж них правильних: {response_option_count_correct} ({round(response_option_count_correct/response_option_count*100, 2)}%)</div>'
|
||||
|
||||
return header, subheader, content
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
--yellow-gradient: linear-gradient(45deg, #ffe88d, #fff8b7);
|
||||
--yellow-gradient-bright: linear-gradient(45deg, #ffeba1, #fffacb);
|
||||
--blue-gradient-subtle: linear-gradient(45deg, #e7ebff, #e7efff);
|
||||
--blue-gradient-glassy: linear-gradient(45deg, #fff9, #fff9);
|
||||
--blue-glassy: #fff9;
|
||||
--red-gradient: linear-gradient(45deg, #ffd2cc, #ffcccc);
|
||||
--magical: linear-gradient(45deg, #e0f2ff, #e4fff0, #eee0ff);
|
||||
}
|
||||
|
||||
* {
|
||||
|
@ -34,11 +35,9 @@ header .top-half, header .lower-half {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
header .top-half {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
header .lower-half input {
|
||||
header .top-half,
|
||||
header .lower-half input
|
||||
{
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
|
@ -58,7 +57,10 @@ header .lower-half a.generic-button,
|
|||
header .lower-half a.sub-button,
|
||||
main * a.sub-button,
|
||||
main * a.scary-button,
|
||||
main a.return-button
|
||||
main a.return-button,
|
||||
main a.delete-button,
|
||||
main a.cancel-button,
|
||||
main a.magic-button
|
||||
{
|
||||
text-decoration: none;
|
||||
border-radius: 15px;
|
||||
|
@ -67,9 +69,7 @@ main a.return-button
|
|||
font-weight: 700;
|
||||
margin: 4px;
|
||||
margin-top: 0;
|
||||
padding: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
padding: 10px 20px 10px 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,8 @@ header .lower-half a.generic-button:hover {
|
|||
|
||||
header .lower-half a.sub-button,
|
||||
main * a.sub-button,
|
||||
main a.return-button
|
||||
main a.return-button,
|
||||
main a.cancel-button
|
||||
{
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
@ -97,26 +98,45 @@ main * div.controls
|
|||
justify-content: end;
|
||||
}
|
||||
|
||||
main * a.sub-button {
|
||||
}
|
||||
|
||||
main * a.scary-button
|
||||
main * a.scary-button,
|
||||
main a.delete-button
|
||||
{
|
||||
background: var(--red-gradient);
|
||||
color: #500;
|
||||
}
|
||||
|
||||
|
||||
main a.magic-button
|
||||
{
|
||||
background: var(--magical);
|
||||
/*
|
||||
animation-name: magic-ani;
|
||||
animation-duration: 6s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: linear;
|
||||
*/
|
||||
}
|
||||
|
||||
main .test-short,
|
||||
main .question-short,
|
||||
main .response-option
|
||||
main .response-option,
|
||||
main .piece-of-stats
|
||||
{
|
||||
padding: 20px;
|
||||
background: var(--blue-gradient-glassy);
|
||||
background: var(--blue-glassy);
|
||||
margin-bottom: 16px;
|
||||
border-radius: 14px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
main .piece-of-stats .header
|
||||
{
|
||||
display: block;
|
||||
font-size: 16pt;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
main .test-short a.test-link,
|
||||
main .question-short a.question-link {
|
||||
display: block;
|
||||
|
@ -151,6 +171,52 @@ main * .sub-title {
|
|||
margin-top: 12px;
|
||||
}
|
||||
|
||||
main form label
|
||||
{
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
main form input,
|
||||
header .lower-half form input
|
||||
{
|
||||
display: block;
|
||||
border-radius: 20px;
|
||||
padding: 12px 30px 12px 30px;
|
||||
font-size: 15pt;
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
border: 1px solid #fff;
|
||||
transition-duration: 300ms;
|
||||
}
|
||||
|
||||
main form input:focus,
|
||||
header .lower-half form input:focus
|
||||
{
|
||||
outline: none;
|
||||
border: 1px solid;
|
||||
transition-duration: 300ms;
|
||||
}
|
||||
|
||||
|
||||
main form input[type=submit]
|
||||
{
|
||||
width: auto;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
padding: 12px 30px 12px 30px;
|
||||
background: var(--yellow-gradient);
|
||||
font-weight: 600;
|
||||
font-size: 15pt;
|
||||
}
|
||||
|
||||
main form input[type=submit]:hover
|
||||
{
|
||||
cursor: pointer;
|
||||
background: var(--yellow-gradient-bright);
|
||||
}
|
||||
|
||||
main * .response-option-short-list
|
||||
{
|
||||
margin-top: 12px;
|
||||
|
@ -166,7 +232,8 @@ main * .response-option-short
|
|||
font-weight: 500;
|
||||
}
|
||||
|
||||
main .response-option a.response-option-mark {
|
||||
main .response-option a.response-option-mark
|
||||
{
|
||||
font-size: 16pt;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
|
@ -183,8 +250,24 @@ main .return-button-centerer
|
|||
display: grid;
|
||||
}
|
||||
|
||||
main a.return-button
|
||||
main a.return-button,
|
||||
main a.delete-button,
|
||||
main a.cancel-button
|
||||
{
|
||||
margin: auto;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
header .lower-half form input
|
||||
{
|
||||
transition-duration: 300ms;
|
||||
|
||||
@keyframes magic-ani
|
||||
{
|
||||
0% {
|
||||
filter: hue-rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
filter: hue-rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import mariadb as mdb
|
||||
import traceback
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
from httputils import parse_query, escape_sql_string
|
||||
|
||||
def readfile(path):
|
||||
if os.path.exists(path):
|
||||
return open(path).read()
|
||||
|
||||
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)
|
||||
|
||||
db_connection = mdb.connect(**args)
|
||||
|
||||
args = parse_query(os.environ['QUERY_STRING'])
|
||||
|
||||
if not 'id' in args:
|
||||
print("Content-Type: text/plain; charset=UTF-8\r\n\r\nВи не зазначили ідентифікатор тесту\r\n")
|
||||
sys.exit(0)
|
||||
|
||||
cur = db_connection.cursor()
|
||||
|
||||
try:
|
||||
#cur.execute(f"SELECT test.id FROM test JOIN question ON test.id = question.tstID WHERE question.id = {args['id']};")
|
||||
#test_id = iter(cur).__next__()[0]
|
||||
|
||||
cur.execute(f"DELETE FROM test WHERE id = {args['id']};")
|
||||
db_connection.commit()
|
||||
|
||||
print(f"Location: /\r\n\r\n")
|
||||
except Exception as e:
|
||||
print(f"Content-Type: text/plain; charset=UTF-8\r\n\r\nНе вдалося видалити запитання ({e})\r\n{traceback.format_exc()}\r\n")
|
|
@ -0,0 +1,44 @@
|
|||
import mariadb as mdb
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
from httputils import parse_query, escape_sql_string
|
||||
|
||||
def readfile(path):
|
||||
if os.path.exists(path):
|
||||
return open(path).read()
|
||||
|
||||
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)
|
||||
|
||||
db_connection = mdb.connect(**args)
|
||||
|
||||
args = parse_query(os.environ['QUERY_STRING'])
|
||||
|
||||
if not 'id' in args:
|
||||
print("Content-Type: text/plain; charset=UTF-8\r\n\r\nВи не зазначили ідентифікатор тесту\r\n")
|
||||
sys.exit(0)
|
||||
|
||||
if not 'name' in args:
|
||||
print("Content-Type: text/plain; charset=UTF-8\r\n\r\nВи не зазначили назву тесту\r\n")
|
||||
sys.exit(0)
|
||||
|
||||
cur = db_connection.cursor()
|
||||
|
||||
try:
|
||||
cur.execute(f"UPDATE test SET name = '{escape_sql_string(args['name'])}' WHERE id = {args['id']};")
|
||||
db_connection.commit()
|
||||
|
||||
#cur.execute(f"SELECT id FROM question ORDER BY id DESC;")
|
||||
|
||||
#new_id = iter(cur).__next__()[0]
|
||||
print(f"Location: /index.py?mode=view-test&id={args['id']}\r\n\r\n")
|
||||
except Exception as e:
|
||||
print(f"Content-Type: text/plain; charset=UTF-8\r\n\r\nНе вдалося змінити тест ({e})\r\n")
|
|
@ -0,0 +1,56 @@
|
|||
import mariadb as mdb
|
||||
import random
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
from httputils import parse_query, escape_sql_string
|
||||
|
||||
def readfile(path):
|
||||
if os.path.exists(path):
|
||||
return open(path).read()
|
||||
|
||||
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)
|
||||
|
||||
db_connection = mdb.connect(**args)
|
||||
|
||||
args = parse_query(os.environ['QUERY_STRING'])
|
||||
|
||||
if not 'id' in args:
|
||||
print("Content-Type: text/plain; charset=UTF-8\r\n\r\nВи не зазначили ідентифікатор запитання, до якого генеруватимуться варіанти відповідей\r\n")
|
||||
sys.exit(0)
|
||||
|
||||
if not 'amount' in args:
|
||||
print("Content-Type: text/plain; charset=UTF-8\r\n\r\nВи не зазначили кількість нових варіантів відповідей\r\n")
|
||||
sys.exit(0)
|
||||
|
||||
cur = db_connection.cursor()
|
||||
|
||||
try:
|
||||
chosen_the_right_one = False
|
||||
for i in range(int(args['amount'])):
|
||||
if not chosen_the_right_one:
|
||||
if int(args['amount']) == i + 1:
|
||||
correct = True
|
||||
else:
|
||||
correct = random.random() > 0.6
|
||||
else:
|
||||
correct = False
|
||||
|
||||
label = str(random.randint(0, 120))
|
||||
if correct:
|
||||
chosen_the_right_one = True
|
||||
|
||||
cur.execute(f"INSERT INTO response_option ( label, qstID, corct ) VALUES ( '{escape_sql_string(label)}', {args['id']}, {correct} );")
|
||||
db_connection.commit()
|
||||
|
||||
print(f"Location: /index.py?mode=view-question&id={args['id']}\r\n\r\n")
|
||||
except Exception as e:
|
||||
print(f"Content-Type: text/plain; charset=UTF-8\r\n\r\nНе вдалося згенерувати варіанти відповідей ({e})\r\n")
|
Loading…
Reference in New Issue