initial commit
This commit is contained in:
commit
26e912c03a
|
@ -0,0 +1,3 @@
|
||||||
|
server/cgi/db-settings.json
|
||||||
|
server/venv/
|
||||||
|
**/__pycache__/
|
|
@ -0,0 +1,10 @@
|
||||||
|
class ObjectPool:
|
||||||
|
def __init__(self, selector, constructor):
|
||||||
|
self.selector = selector
|
||||||
|
self.constructor = constructor
|
||||||
|
self.pool = []
|
||||||
|
|
||||||
|
def load_from_db(self, cur):
|
||||||
|
cur.execute(f"SELECT * FROM {self.selector};")
|
||||||
|
self.pool = [self.constructor().init_from_data(i) for i in cur]
|
||||||
|
return self
|
|
@ -0,0 +1,43 @@
|
||||||
|
from object_pool import ObjectPool
|
||||||
|
|
||||||
|
class Question:
|
||||||
|
def init(self, sID, title, max_time, test_id):
|
||||||
|
self.id = sID
|
||||||
|
self.title = title
|
||||||
|
self.max_time = max_time
|
||||||
|
self.test_id = test_id
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def init_from_data(self, data):
|
||||||
|
return self.init(*data)
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
def get_title(self):
|
||||||
|
return self.title
|
||||||
|
|
||||||
|
def get_max_time(self):
|
||||||
|
return self.max_time
|
||||||
|
|
||||||
|
def get_test_id(self):
|
||||||
|
return self.test_id
|
||||||
|
|
||||||
|
'''
|
||||||
|
class QuestionPool:
|
||||||
|
def __init__(self):
|
||||||
|
self.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
|
||||||
|
'''
|
||||||
|
|
||||||
|
class QuestionPool:
|
||||||
|
def __init__(self):
|
||||||
|
self.object_pool = ObjectPool("question", Question)
|
||||||
|
|
||||||
|
if db:
|
||||||
|
self.object_pool.load_from_db(db)
|
|
@ -0,0 +1,32 @@
|
||||||
|
from object_pool import ObjectPool
|
||||||
|
|
||||||
|
class Response:
|
||||||
|
def init(self, rID, optionID, pupilID, delay):
|
||||||
|
self.id = rID
|
||||||
|
self.optionID = optionID
|
||||||
|
self.pupilID = pupilID
|
||||||
|
self.delay = delay
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def init_from_data(self, data):
|
||||||
|
return self.init(*data)
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
def get_option_id(self):
|
||||||
|
return self.optionID
|
||||||
|
|
||||||
|
def get_pupil_id(self):
|
||||||
|
return self.pupilID
|
||||||
|
|
||||||
|
def get_delay(self):
|
||||||
|
return delay
|
||||||
|
|
||||||
|
class ResponsePool:
|
||||||
|
def __init__(self, db = None):
|
||||||
|
self.object_pool = ObjectPool("response", Response)
|
||||||
|
|
||||||
|
if db:
|
||||||
|
self.object_pool.load_from_db(db)
|
|
@ -0,0 +1,43 @@
|
||||||
|
from object_pool import ObjectPool
|
||||||
|
|
||||||
|
class ResponseOption:
|
||||||
|
def init(self, sID, label, questionID, correctness):
|
||||||
|
self.id = sID
|
||||||
|
self.label = label
|
||||||
|
self.questionID = questionID
|
||||||
|
self.correctness = correctness
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def init_from_data(self, data):
|
||||||
|
return self.init(*data)
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
def get_label(self):
|
||||||
|
return self.label
|
||||||
|
|
||||||
|
def get_question_id(self):
|
||||||
|
return self.questionID
|
||||||
|
|
||||||
|
def get_correctness(self):
|
||||||
|
return correctness
|
||||||
|
|
||||||
|
class ResponceOptionPool:
|
||||||
|
def __init__(self):
|
||||||
|
self.object_pool = ObjectPool("response_option", ResponseOption)
|
||||||
|
|
||||||
|
if db:
|
||||||
|
self.object_pool.load_from_db(db)
|
||||||
|
|
||||||
|
'''
|
||||||
|
class ResponceOptionPool:
|
||||||
|
def __init__(self):
|
||||||
|
self.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
|
||||||
|
'''
|
|
@ -0,0 +1,27 @@
|
||||||
|
from db.object_pool import ObjectPool
|
||||||
|
|
||||||
|
class Test:
|
||||||
|
def init(self, sID, name):
|
||||||
|
self.id = sID
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def init_from_data(self, data):
|
||||||
|
return self.init(*data)
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def render_short(self):
|
||||||
|
return f'<div class="test-short"><a class="header-link">#{self.sID} {self.name}</a></div>'
|
||||||
|
|
||||||
|
class TestPool:
|
||||||
|
def __init__(self, db):
|
||||||
|
self.object_pool = ObjectPool("test", Test)
|
||||||
|
|
||||||
|
if db:
|
||||||
|
self.object_pool.load_from_db(db)
|
|
@ -0,0 +1,12 @@
|
||||||
|
import mariadb as mdb
|
||||||
|
|
||||||
|
from db.test import TestPool
|
||||||
|
|
||||||
|
class TestList:
|
||||||
|
def __init__(self, cursor):
|
||||||
|
self.cursor = cursor
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
tp = TestPool(self.cursor)
|
||||||
|
rendered_chunks = [i.render_short() for i in tp.object_pool.pool]
|
||||||
|
return "\n".join(rendered_chunks)
|
|
@ -0,0 +1,77 @@
|
||||||
|
import mariadb as mdb
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
from test_list import TestList
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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 == "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:
|
||||||
|
header = f"<h2>No such view mode: {mode}</h2>"
|
||||||
|
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
|
||||||
|
content = ""
|
||||||
|
|
||||||
|
dbc.close()
|
||||||
|
return self.format_page(header, subheader, content)
|
|
@ -0,0 +1,8 @@
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>%TITLE%</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/css/base_style.css">
|
||||||
|
<head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<div class="top-half">%HEADER%</div>
|
||||||
|
<div class="lower-half">%SUBHEADER%</div>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
%CONTENT%
|
||||||
|
</main>
|
||||||
|
</body>
|
|
@ -0,0 +1,31 @@
|
||||||
|
def decode_url(url):
|
||||||
|
i = 0
|
||||||
|
end = len(url)
|
||||||
|
|
||||||
|
decode_buffer = ''
|
||||||
|
char_buffer = bytearray()
|
||||||
|
|
||||||
|
while i < end:
|
||||||
|
if url[i] == '%':
|
||||||
|
try:
|
||||||
|
char_buffer.append(int(f'0x{url[i+1:i+3]}', 16))
|
||||||
|
decode_buffer += char_buffer.decode("UTF-8")
|
||||||
|
del char_buffer[:]
|
||||||
|
i += 3
|
||||||
|
except:
|
||||||
|
i += 3
|
||||||
|
else:
|
||||||
|
decode_buffer += url[i]
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return decode_buffer
|
||||||
|
|
||||||
|
def parse_query(query):
|
||||||
|
query_items = [i for i in query.split("&") if i]
|
||||||
|
|
||||||
|
query_dict = {}
|
||||||
|
for i in query_items:
|
||||||
|
k, v = i.split("=")
|
||||||
|
query_dict[decode_url(k)] = decode_url(v)
|
||||||
|
|
||||||
|
return query_dict
|
|
@ -0,0 +1,51 @@
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
print(f"PWD: {os.getcwd()}", file=sys.stderr)
|
||||||
|
|
||||||
|
print(f"Environ: {os.environ}", file=sys.stderr)
|
||||||
|
|
||||||
|
sys.path.insert(0, "/root/ipz-server-1/server/cgi/")
|
||||||
|
|
||||||
|
from view import View
|
||||||
|
from httputils import parse_query
|
||||||
|
'''
|
||||||
|
def decode_url(url):
|
||||||
|
i = 0
|
||||||
|
end = len(url)
|
||||||
|
|
||||||
|
decode_buffer = ''
|
||||||
|
char_buffer = bytearray()
|
||||||
|
|
||||||
|
while i < end:
|
||||||
|
if url[i] == '%':
|
||||||
|
try:
|
||||||
|
char_buffer.append(int(f'0x{url[i+1:i+3]}', 16))
|
||||||
|
decode_buffer += char_buffer.decode("UTF-8")
|
||||||
|
del char_buffer[:]
|
||||||
|
i += 3
|
||||||
|
except:
|
||||||
|
i += 3
|
||||||
|
else:
|
||||||
|
decode_buffer += url[i]
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return decode_buffer
|
||||||
|
|
||||||
|
query = [i for i in os.environ['QUERY_STRING'].split("&") if i]
|
||||||
|
|
||||||
|
query_dict = {}
|
||||||
|
for i in query:
|
||||||
|
k, v = i.split("=")
|
||||||
|
query_dict[decode_url(k)] = decode_url(v)
|
||||||
|
'''
|
||||||
|
|
||||||
|
query_dict = parse_query(os.environ['QUERY_STRING'])
|
||||||
|
|
||||||
|
view = View(query_dict)
|
||||||
|
html_page = view.render_page()
|
||||||
|
page_length = len(html_page.encode("UTF-8"))
|
||||||
|
|
||||||
|
print(f"Content-Type: text/html; charset=UTF-8\r\n" + \
|
||||||
|
f"Content-Length: {page_length}\r\n" + \
|
||||||
|
f"\r\n" + \
|
||||||
|
f"{html_page}")
|
Loading…
Reference in New Issue