serve.py 6.44 KB
#!/opt/local/bin/python3.6

import os
import json
import random

import markdown
import tornado.ioloop
import tornado.web
from tornado import template

import questions

# markdown helper
def md(text):
    return markdown.markdown(text,
        extensions=[
            'markdown.extensions.tables',
            'markdown.extensions.fenced_code',
            'markdown.extensions.codehilite',
            'markdown.extensions.def_list',
            'markdown.extensions.sane_lists'
        ])

# ----------------------------------------------------------------------------
class LearnApp(object):
    def __init__(self):
        self.factory = questions.QuestionFactory()
        self.factory.load_files(['questions.yaml'], 'demo')
        self.online = {}
        self.q = None

    # returns dictionary
    def next_question(self):
        # print('next question')
        # q = self.factory.generate('math-expressions')
        questions = list(self.factory)
        # print(questions)
        q = self.factory.generate(random.choice(questions))
        # print(q)
        self.q = q
        return q

    def login(self, uid):
        print('LearnApp.login')
        self.online[uid] = {
            'name': 'john',
        }
        print(self.online)


# ----------------------------------------------------------------------------
class Application(tornado.web.Application):
    def __init__(self):
        settings = {
            'template_path': os.path.join(os.path.dirname(__file__), 'templates'),
            'static_path':   os.path.join(os.path.dirname(__file__), 'static'),
            'static_url_prefix': '/static/',  # this is the default
            'xsrf_cookies': False, # FIXME see how to do it...
            'cookie_secret': '__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__', # FIXME
            'login_url': '/login',
            'debug': True,
        }
        handlers = [
            (r'/', MainHandler),
            (r'/login',    LoginHandler),
            (r'/logout',   LogoutHandler),
            (r'/learn',         LearnHandler),
            (r'/question',      QuestionHandler),
        ]
        super().__init__(handlers, **settings)
        self.learn = LearnApp()

# ----------------------------------------------------------------------------
# Base handler common to all handlers.
class BaseHandler(tornado.web.RequestHandler):
    @property
    def learn(self):
        return self.application.learn

    def get_current_user(self):
        user_cookie = self.get_secure_cookie("user")
        # print('base.get_current_user -> ', user_cookie)
        if user_cookie:
            return user_cookie # json.loads(user_cookie)

# ----------------------------------------------------------------------------
class MainHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        self.redirect('/learn')

# ----------------------------------------------------------------------------
# /auth/login  and  /auth/logout
# ----------------------------------------------------------------------------
class LoginHandler(BaseHandler):
    def get(self):
        self.render('login.html')

    def post(self):
        print('login.post')
        uid = self.get_body_argument('uid')
        pw = self.get_body_argument('pw')
        # FIXME check password ver examplo do blog tornado.
        self.set_secure_cookie('user', uid)
        self.application.learn.login(uid)
        self.redirect('/learn')

# ----------------------------------------------------------------------------
class LogoutHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        name = tornado.escape.xhtml_escape(self.current_user)
        print('logout '+name)
        self.clear_cookie('user')
        self.redirect(self.get_argument('next', '/'))

# ----------------------------------------------------------------------------
# /learn
# ----------------------------------------------------------------------------
class LearnHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        print('learn.get')
        user = self.current_user.decode('utf-8')
        # name = self.application.learn.online[user]
        print('  user = '+str(user))
        self.render('learn.html', name='aa', uid=user) # FIXME

# ----------------------------------------------------------------------------
# respond to AJAX to get a JSON question
class QuestionHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        self.redirect('/')

    @tornado.web.authenticated
    def post(self):
        print('---------------\nquestion.post')
        # experiment answering one question and correct it
        ref = self.get_body_arguments('question_ref')
        print('Reference' + str(ref))

        question = self.application.learn.q # get current question
        print('=====================================')
        print('  ' + str(question))
        print('-------------------------------------')


        if question is not None:
            ans = self.get_body_arguments('answer')
            print('  answer = ' + str(ans))
            question['answer'] = ans          # insert answer
            grade = question.correct()       # correct answer
            print('  grade = ' + str(grade))

            correct = grade > 0.99999
            if correct:
                question = self.application.learn.next_question()

        else:
            correct = True # to animate correctly
            question = self.application.learn.next_question()

        templates = {
            'checkbox':     'question-checkbox.html',
            'radio':        'question-radio.html',
            'text':         'question-text.html',
            'text_regex':   'question-text.html',
            'text_numeric': 'question-text.html',
            'textarea':     'question-textarea.html',
        }
        html_out = self.render_string(templates[question['type']],
            question=question, # the dictionary with the question??
            md=md,  # passes function that renders markdown to html
            )
        self.write({
            'html': tornado.escape.to_unicode(html_out),
            'correct': correct,
            })


# ----------------------------------------------------------------------------
def main():
    server = Application()
    server.listen(8080)
    try:
        print('--- start ---')
        tornado.ioloop.IOLoop.current().start()
    except KeyboardInterrupt:
        tornado.ioloop.IOLoop.current().stop()
        print('\n--- stop ---')

if __name__ == "__main__":
    main()