From 88a5cd83b47a9dfb5a832936095c7b99ce0d8179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Smodi=C5=A1?= Date: Tue, 25 Aug 2015 14:20:42 +0200 Subject: Implemented methods to fetch a list of available problems and the problem description. JavaScript no longer parses pythonic problem descriptions, instead they are loaded by server and JSONized. --- server/__init__.py | 30 ++++++++++++++++++++++++++---- server/problems.py | 28 +++++++++++++++++++++++++++- server/prolog_session.py | 8 +++++--- server/user_session.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 8 deletions(-) (limited to 'server') diff --git a/server/__init__.py b/server/__init__.py index f2c73b7..9f2469d 100644 --- a/server/__init__.py +++ b/server/__init__.py @@ -3,8 +3,28 @@ import multiprocessing.managers from . import user_session from . import prolog_session +import server.problems -__all__ = ['user_session'] +__all__ = ['user_session', 'prolog_session', 'problems', 'start'] + +class Codeq(object): + _method_to_typeid_ = { + 'get_session_by_id': 'UserSession', + 'get_or_create_session': 'UserSession', + 'authenticate_and_create_session': 'UserSession' + } + + def get_session_by_id(self, sid): + return user_session.get_session_by_id(sid) + + def get_or_create_session(self, uid, username, sid=None): + return user_session.get_or_create_session(uid, username, sid) + + def authenticate_and_create_session(self, username, password): + return user_session.authenticate_and_create_session(username, password) + + def list_problems_in_groups(self, language): + return server.problems.list_problems_in_groups(language) class CodeqManager(multiprocessing.managers.BaseManager): pass @@ -14,9 +34,11 @@ class UserSessionProxy(multiprocessing.managers.BaseProxy): CodeqManager.register('PrologSession') CodeqManager.register('UserSession', proxytype=UserSessionProxy) -CodeqManager.register('get_session_by_id', callable=user_session.get_session_by_id, proxytype=UserSessionProxy) -CodeqManager.register('get_or_create_session', callable=user_session.get_or_create_session, proxytype=UserSessionProxy) -CodeqManager.register('authenticate_and_create_session', callable=user_session.authenticate_and_create_session, proxytype=UserSessionProxy) +#CodeqManager.register('get_session_by_id', callable=user_session.get_session_by_id, proxytype=UserSessionProxy) +#CodeqManager.register('get_or_create_session', callable=user_session.get_or_create_session, proxytype=UserSessionProxy) +#CodeqManager.register('authenticate_and_create_session', callable=user_session.authenticate_and_create_session, proxytype=UserSessionProxy) +#CodeqManager.register('list_problems_in_groups', callable=server.problems.list_problems_in_groups) +CodeqManager.register('Codeq', callable=Codeq, method_to_typeid=Codeq._method_to_typeid_) def start(): m = CodeqManager(address=('localhost', 16231), authkey=b'c0d3q3y') diff --git a/server/problems.py b/server/problems.py index 7fb2606..bce72fe 100644 --- a/server/problems.py +++ b/server/problems.py @@ -3,6 +3,7 @@ import sys import importlib.machinery import threading +from db import get_connection, return_connection #sys.path.append('/home/aless/job/codeq/source/codeq-problems/') _path_prefix = '/home/aless/job/codeq/source/codeq-problems/' @@ -45,7 +46,6 @@ def load_problems(language, tuples, tail_module): modules = [] for problem_group, problem in tuples: mod = '{0}.problems.{1}.{2}.{3}'.format(language, problem_group, problem, tail_module) - print('importing {}'.format(mod)) modules.append(load_module(mod)) return modules @@ -81,3 +81,29 @@ def solutions_for_problems(language, tuples): if f: facts.add(f) return '\n'.join(facts) + '\n' + '\n'.join(solutions) + +def list_problems_in_groups(language): + conn = get_connection() + try: + cur = conn.cursor() + try: + cur.arraysize = 1000 + cur.execute("select g.identifier, g.name, p.identifier, p.name from problem p inner join problem_group g on g.id = p.problem_group_id where p.language_id = (select id from language where identifier = %s) order by g.identifier, p.identifier", (language,)) + result = [] + previous_group_name = '' + current_sublist = None + row = cur.fetchone() + while row: + current_group_name = row[0] + if previous_group_name != current_group_name: + current_sublist = [] + result.append({'identifier': current_group_name, 'name': row[1], 'problems': current_sublist}) + previous_group_name = current_group_name + current_sublist.append({'identifier': row[2], 'name': row[3]}) + row = cur.fetchone() + return result + finally: + cur.close() + finally: + conn.commit() + return_connection(conn) diff --git a/server/prolog_session.py b/server/prolog_session.py index e00afd8..c21d929 100644 --- a/server/prolog_session.py +++ b/server/prolog_session.py @@ -86,7 +86,7 @@ class PrologSession(object): prolog.engine.stop(self._engine_id) self._engine_id = None - def run_for_user(self, user_id, language, problem_group, problem, program, query): + def run_for_user(self, user_id, problem_id, program, query): """A "shorthand" method to start a Prolog session, load correct solutions of all user's solved problems and the given program, and ask a query. """ @@ -94,10 +94,12 @@ class PrologSession(object): try: cur = conn.cursor() try: - cur.execute('select l.id, p.id from problem p inner join problem_group g on g.id = p.problem_group_id inner join language l on l.id = p.language_id where l.identifier = %s and g.identifier = %s and p.identifier = %s', (language, problem_group, problem)) + cur.execute('select l.id, l.identifier, g.identifier, p.identifier from problem p inner join problem_group g on g.id = p.problem_group_id inner join language l on l.id = p.language_id where p.id = %s', (problem_id,)) row = cur.fetchone() language_id = row[0] - problem_id = row[1] + language = row[1] + problem_group = row[2] + problem = row[3] cur.execute('select g.identifier, p.identifier from solution s inner join problem p on p.id = s.problem_id inner join problem_group g on g.id = p.problem_group_id where s.codeq_user_id = %s and s.done = True and s.problem_id != %s and p.language_id = %s', (user_id, problem_id, language_id)) solved_problems = cur.fetchall() finally: diff --git a/server/user_session.py b/server/user_session.py index b12d6f1..bb4179d 100644 --- a/server/user_session.py +++ b/server/user_session.py @@ -6,6 +6,7 @@ import hashlib import base64 import random from . import prolog_session +from . import problems import db from errors.session import NoSuchSession, AuthenticationFailed @@ -51,6 +52,33 @@ class UserSession(object): self.prolog_session = prolog_session.PrologSession() # lazy init return self.prolog_session + def get_problem_data(self, language, problem_group, problem): + mod = problems.load_problem(language, problem_group, problem, 'en') + conn = db.get_connection() + try: + cur = conn.cursor() + try: + cur.execute("select l.id, l.name, g.id, g.name, p.id, p.name from problem p inner join language l on l.id = p.language_id inner join problem_group g on g.id = p.problem_group_id where l.identifier = %s and g.identifier = %s and p.identifier = %s", (language, problem_group, problem)) + row = cur.fetchone() + problem_id = row[4] + result = { + 'language': {'id': row[0], 'identifier': language, 'name': row[1]}, + 'problem_group': {'id': row[2], 'identifier': problem_group, 'name': row[3]}, + 'problem': {'id': problem_id, 'identifier': problem, 'name': row[5], 'slug': mod.slug, 'description': mod.description, 'hint': mod.hint} + } + cur.execute("select content from solution where problem_id = %s and codeq_user_id = %s", (problem_id, self.uid)) + row = cur.fetchone() + if row: + result['solution'] = row[0] + else: + result['solution'] = '' + return result + finally: + cur.close() + finally: + conn.commit() + db.return_connection(conn) + def __del__(self): # no locking needed if GC is removing us, as there cannot be any concurrent access by definition if hasattr(self, 'prolog_session') and (self.prolog_session is not None): -- cgit v1.2.1