#controllers/login.py import config, os, uuid, pydf from copy import deepcopy from bottle import Bottle, template, request, response, redirect from verify_email import verify_email from models import userdb from models.certificate import Certificate class Login(Bottle): def __init__(self): super().__init__() self.get('/', callback=self.index) self.post('/user', callback=self.postUser) self.get('/update', callback=self.updateUser) self.get('/logout', callback=self.logout) self.userdb = userdb.Userdb() self.template = Certificate() def index(self): kdict = deepcopy(config.kdict) kdict['blogTitle'] = "ចុះឈ្មោះ" return template('login', data=kdict) def postUser(self): kdict = deepcopy(config.kdict) username = request.forms.getunicode('fusername') password = request.forms.getunicode('fpassword') email = request.forms.getunicode('femail') checkEmail = verify_email(email) if checkEmail and username and password: result = self.userdb.checkUser(username, password, email) if result: response.set_cookie('logged-in', result[0], path='/', secret=kdict['secretKey']) redirect('/') else: result = self.userdb.checkUsername(username) if not result: response.set_cookie('logged-in', username, path='/', secret=kdict['secretKey']) self.userdb.insert(username, password, email, 1, False) redirect('/') else: kdict['message'] = 'ឈ្មោះអ្នកប្រើប្រាស់នេះត្រូវបានគេប្រើរួចហើយ។' return template('login', data=kdict) else: if not checkEmail: kdict['message'] = 'Email របស់លោកអ្នកមិនត្រឹមត្រូវទេ។' return template('login', data=kdict) elif not (username or password): kdict['message'] = 'ត្រូវមានឈ្មោះអ្នកប្រើប្រាស់និងពាក្យសំងាត់។' return template('login', data=kdict) def logout(self): kdict = deepcopy(config.kdict) username = request.get_cookie('logged-in', secret=kdict['secretKey']) if username: self.userdb.deleteUser(username) response.delete_cookie('logged-in', path='/', secret=kdict['secretKey']) redirect('/') def updateUser(self): kdict = deepcopy(config.kdict) username = request.get_cookie('logged-in', secret=kdict['secretKey']) if username: grade = self.userdb.checkUsername(username) if grade[2] < 8: self.userdb.updateUser(username) return {'grade':grade[2]} elif grade[2] == 8: pdfFile = self.createPdf(username) return {'grade':grade[2], 'pdf':pdfFile} else: return {'grade':grade[2]} def createPdf(self, username=0): id = str(uuid.uuid4().int) pdfFile = '/static/pdfs/'+id+'.pdf' template = self.template.substitute() options = { 'page-size': 'Letter', 'margin-top': '0', 'margin-right': '0', 'margin-bottom': '0', 'margin-left': '0', 'encoding': "UTF-8", 'orientation': 'Landscape' } if 'DYNO' in os.environ: pdf = pydf.generate_pdf(template, **options) with open('public/pdfs/'+ id +'.pdf', 'wb') as f: f.write(pdf) f.close() else: import pdfkit pdf = pdfkit.from_string(template, False, options=options) with open('public/pdfs/'+ id +'.pdf', 'wb') as f: f.write(pdf) f.close() return pdfFile
//public/js/practice.js class Typing{ constructor(practice){ this.letters = practice; this.counter = Math.floor(Math.random() * (this.letters).length); this.usedCounter = this.counter; this.nextKey = this.letters[this.counter][0]; this.pressedKey = 0; this.mistake = 0; this.scoreLetter = 0; this.numLetters = 0; this.setClock(); this.setColor(this.nextKey); } setColor(nextKey){ var rightShift = {'A':1,'S':1,'D':1,'F':1,'G':1,'Z':1,'X':1,'C':1,'V':1,'B':1,'Q':1,'W':1,'E':1,'R':1,'T':1, '~':1,'!':1,'@':1,'#':1,'$':1,'%':1}; var leftShift = {'H':1,'J':1,'K':1,'L':1,':':1,'"':1,'N':1,'M':1,'<':1,'>':1,'?':1,'Y':1,'U':1,'I':1,'O':1,'P':1, '{':1,'}':1,'|':1,'^':1,'&':1,'*':1,'(':1,')':1,'_':1,'+':1}; var keys = $(".keyboard-base").children().css({'color':'black'}); for(var index in keys){ var key = keys[index].innerHTML; if(key){ var data = keys[index].getAttribute("data-l"); if(key == "'"){ data += '"'; } if((nextKey == data[5]) || (nextKey == data[6])){ keys[index].focus(); $(keys[index]).css({'color':'teal'}); if(this.nextKey in rightShift){ $('.rightshift').css({'color':'teal'}); }else if(this.nextKey in leftShift){ $('.leftshift').css({'color':'teal'}); } break; } } } $('#letter').html(this.letters[this.counter][2]); } checkKey(key){ if(key == this.nextKey){ this.scoreLetter += 1; while(true){ this.counter = Math.floor(Math.random() * (this.letters).length); if(this.counter != this.usedCounter){ this.usedCounter = this.counter break; } } this.pressedKey = this.nextKey; this.nextKey = this.letters[this.counter][0]; this.setColor(this.nextKey); }else{ document.getElementById('beep').play(); $('#mistake span').html(this.toKhNum(++this.mistake)); } $('#letters span').html(this.toKhNum(++this.numLetters)) } toKhNum(number){ const khNum = {'0':'០', '1':'១', '2':'២', '3':'៣', '4':'៤', '5':'៥', '6':'៦', '7':'៧', '8':'៨', '9':'៩'}; var stringNum = number.toString(); var khNumString = ''; for(var i in stringNum){ khNumString += khNum[stringNum[i]]; } return khNumString; } setClock(){ var second = 0; var minute = 0; var hour = 0; this.minuteTest = 0; this.clock = setInterval(() => { $('#timelapse .second').html(this.toKhNum(++second)); if(second == 60){ second = 0; $('#timelapse .minute').html(this.toKhNum(++minute)); } if(minute == 60){ minute = 0; ++this.minuteTest; $('#timelapse .hour').html(this.toKhNum(++hour)); } if((this.minuteTest <= 2) && (this.scoreLetter >= 5) && (this.mistake <= 10)) this.updateLevel(); }, 1000); } updateLevel(){ clearInterval(this.clock) $.get("login/update", function(data, status){ if(status == "success"){ var grade = typing.toKhNum(data.grade); var message = `<div>សូមអបអរសាទដោយអ្នកបានឆ្លងចូលកំរឹតទី ${grade} ហើយ!!</div>`; if(data.grade === 8){ message = `<div>សូមអបអរសាទដោយអ្នកបានបញ្ចប់កំរឹតទី ${grade} ដែលជាកំរឹតចុងក្រោយ!!</div> <a target="_blank" href="${data.pdf}">នេះជាលិខិតបញ្ជាកសមត្ថភាពរបស់អ្នក</a>`; } $('#info').html(message); $('#level span').html(grade); document.getElementById('level').children[0].innerHTML = grade; } }); } }//end of class
GitHub: https://khmerweb-typing.herokuapp.com
Heroku: https://khmerweb-typing.herokuapp.com/