diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/EnglishPal.iml b/.idea/EnglishPal.iml new file mode 100644 index 0000000..8b8c395 --- /dev/null +++ b/.idea/EnglishPal.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..7a85af6 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..d90086b --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..86f0b25 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,2 @@ +FROM tiangolo/uwsgi-nginx-flask:python3.6 +COPY ./app /app diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..434c00f --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,34 @@ +pipeline { + agent any + + stages { + stage('MakeDatabasefile') { + steps { + sh 'touch ./app/static/wordfreqapp.db && rm -f ./app/static/wordfreqapp.db' + sh 'cat ./app/static/wordfreqapp.sql | sqlite3 ./app/static/wordfreqapp.db' + } + } + stage('BuildIt') { + steps { + echo 'Building..' + sh 'sudo docker build -t englishpal .' + sh 'sudo docker stop $(docker ps -aq)' + sh 'sudo docker run -d -p 91:80 -v /var/lib/jenkins/workspace/EnglishPal_Pipeline_master/app/static/frequency:/app/static/frequency -t englishpal' + } + } + stage('TestIt') { + steps { + echo 'Testing..' + sh 'sudo docker run -d -p 4444:4444 selenium/standalone-chrome' + sh 'pip3 install pytest -U -q' + sh 'pip3 install selenium -U -q' + sh 'pytest -v -s --html=EnglishPalTestReport.html ./app/test' + } + } + stage('DeployIt') { + steps { + echo 'Deploying (TBD)' + } + } + } +} diff --git a/app/EverydayArticle.py b/app/EverydayArticle.py new file mode 100644 index 0000000..9efce8d --- /dev/null +++ b/app/EverydayArticle.py @@ -0,0 +1,114 @@ +#! /usr/bin/python3 +# -*- coding: utf-8 -*- + +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + +from UseSqlite import RecordQuery +import pickle_idea +import os +import random +from flask import Flask, session +from difficulty import get_difficulty_level, text_difficulty_level, user_difficulty_level +import SqlWords as sql + +app = Flask(__name__) +app.secret_key = 'lunch.time!' + +path_prefix = '/var/www/wordfreq/wordfreq/' +path_prefix = './' # comment this line in deployment + +def load_freq_history(path): + d = {} + if os.path.exists(path): + d = pickle_idea.load_record(path) + return d + +def within_range(x, y, r): + return x > y and abs(x - y) <= r + +def Get(user_word_list, articleID): + + rq = RecordQuery(sql.path_prefix + 'static/wordfreqapp.db') + if articleID == None: + rq.instructions("SELECT * FROM article") + else: + rq.instructions('SELECT * FROM article WHERE article_id=%d' % (articleID)) + rq.do() + result = rq.get_results() + + # Choose article according to reader's level + d1 = load_freq_history(sql.path_prefix + 'static/frequency/frequency.p') + d2 = load_freq_history(sql.path_prefix + 'static/words_and_tests.p') + d3 = get_difficulty_level(d1, d2) + + d = {} + d_user = load_freq_history(user_word_list) + user_level = user_difficulty_level(d_user, d3) # more consideration as user's behaviour is dynamic. Time factor should be considered. + random.shuffle(result) # shuffle list + d = random.choice(result) + text_level = text_difficulty_level(d['text'], d3) + if articleID == None: + for reading in result: + text_level = text_difficulty_level(reading['text'], d3) + #print('TEXT_LEVEL %4.2f' % (text_level)) + if within_range(text_level, user_level, 0.5): + d = reading + break + + s = '

According to your word list, your level is %4.2f and we have chosen an article with a difficulty level of %4.2f for you.

' % (user_level, text_level) + s += '

%s

' % (d['date']) + s += '

%s

' % (d['text']) + s += '

%s

' % (d['source']) + s += '

%s

' % (get_question_part(d['question'])) + s = s.replace('\n', '
') + s += '%s' % (get_answer_part(d['question'])) + session['articleID'] = d['article_id'] + return s + +def get_question_part(s): + s = s.strip() + result = [] + flag = 0 + for line in s.split('\n'): + line = line.strip() + if line == 'QUESTION': + result.append(line) + flag = 1 + elif line == 'ANSWER': + flag = 0 + elif flag == 1: + result.append(line) + return '\n'.join(result) + + +def get_answer_part(s): + s = s.strip() + result = [] + flag = 0 + for line in s.split('\n'): + line = line.strip() + if line == 'ANSWER': + flag = 1 + elif flag == 1: + result.append(line) + # https://css-tricks.com/snippets/javascript/showhide-element/ + js = ''' + + ''' + html_code = js + html_code += '\n' + html_code += '\n' + html_code += '\n' % ('\n'.join(result)) + return html_code \ No newline at end of file diff --git a/app/SqlWords.py b/app/SqlWords.py new file mode 100644 index 0000000..1976168 --- /dev/null +++ b/app/SqlWords.py @@ -0,0 +1,63 @@ +#! /usr/bin/python3 +# -*- coding: utf-8 -*- + +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + +from UseSqlite import InsertQuery, RecordQuery +from datetime import datetime +from flask import Flask + +app = Flask(__name__) +app.secret_key = 'lunch.time!' + +path_prefix = '/var/www/wordfreq/wordfreq/' +path_prefix = './' # comment this line in deployment + + +def verify_user(name, password): + rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') + rq.instructions("SELECT * FROM user WHERE name='%s' AND password='%s'" % (name, password)) + rq.do() + result = rq.get_results() + return result != [] + + +def add_user(name, password): + start_date = datetime.now().strftime('%Y%m%d') + expiry_date = '20211230' + rq = InsertQuery(path_prefix + 'static/wordfreqapp.db') + rq.instructions("INSERT INTO user Values ('%s', '%s', '%s', '%s')" % (name, password, start_date, expiry_date)) + rq.do() + +def get_user(): + rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') + rq.instructions("SELECT name FROM user") + rq.do() + result = rq.get_results() + return result + +def check_username_availability(name): + rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') + rq.instructions("SELECT * FROM user WHERE name='%s'" % (name)) + rq.do() + result = rq.get_results() + return result == [] + + +def get_expiry_date(name): + rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') + rq.instructions("SELECT expiry_date FROM user WHERE name='%s'" % (name)) + rq.do() + result = rq.get_results() + if len(result) > 0: + return result[0]['expiry_date'] + else: + return '20191024' + + + + + diff --git a/app/main(1).py b/app/main(1).py new file mode 100644 index 0000000..518fa48 --- /dev/null +++ b/app/main(1).py @@ -0,0 +1,300 @@ +#! /usr/bin/python3 +# -*- coding: utf-8 -*- + +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + +from WordFreq import WordFreq +from wordfreqCMD import youdao_link, sort_in_descending_order +from UseSqlite import InsertQuery, RecordQuery +import pickle_idea, pickle_idea2 +import os +import random, glob +from datetime import datetime +from flask import Flask, request, redirect, render_template, url_for, session, abort, flash +from difficulty import get_difficulty_level, text_difficulty_level, user_difficulty_level +import EverydayArticle as today +import SqlWords as sql + +app = Flask(__name__) +app.secret_key = 'lunch.time!' + +path_prefix = '/var/www/wordfreq/wordfreq/' +path_prefix = './' # comment this line in deployment + + +def get_random_image(path): + img_path = random.choice(glob.glob(os.path.join(path, '*.jpg'))) + return img_path[img_path.rfind('/static'):] + + +def get_random_ads(): + ads = random.choice(['个性化分析精准提升', '你的专有单词本', '智能捕捉阅读弱点,针对性提高你的阅读水平']) + return ads + + +def load_freq_history(path): + d = {} + if os.path.exists(path): + d = pickle_idea.load_record(path) + return d + + +def appears_in_test(word, d): + if not word in d: + return '' + else: + return ','.join(d[word]) + + +def get_time(): + return datetime.now().strftime('%Y%m%d%H%M') # upper to minutes + + +@app.route("//reset", methods=['GET', 'POST']) +def user_reset(username): + if request.method == 'GET': + session['articleID'] = None + return redirect(url_for('userpage', username=username)) + else: + return 'Under construction' + + +@app.route("/mark", methods=['GET', 'POST']) +def mark_word(): + if request.method == 'POST': + d = load_freq_history(path_prefix + 'static/frequency/frequency.p') + lst_history = pickle_idea.dict2lst(d) + lst = [] + for word in request.form.getlist('marked'): + lst.append((word, 1)) + d = pickle_idea.merge_frequency(lst, lst_history) + pickle_idea.save_frequency_to_pickle(d, path_prefix + 'static/frequency/frequency.p') + return redirect(url_for('mainpage')) + else: + return 'Under construction' + + +@app.route("/", methods=['GET', 'POST']) +def mainpage(): + if request.method == 'POST': # when we submit a form + content = request.form['content'] + f = WordFreq(content) + lst = f.get_freq() + page = '
\n' + count = 1 + for x in lst: + page += '

%d: %s (%d)

\n' % ( + count, youdao_link(x[0]), x[0], x[1], x[0]) + count += 1 + page += ' \n' + page += '
\n' + # save history + d = load_freq_history(path_prefix + 'static/frequency/frequency.p') + lst_history = pickle_idea.dict2lst(d) + d = pickle_idea.merge_frequency(lst, lst_history) + pickle_idea.save_frequency_to_pickle(d, path_prefix + 'static/frequency/frequency.p') + + return page + elif request.method == 'GET': # when we load a html page + user = '' + youdao = {} + Eword = {} + EwordNum = {} + if session.get('logged_in'): + user = session['username'] + random_ads = get_random_ads() + d = load_freq_history(path_prefix + 'static/frequency/frequency.p') + xi = 1 + if len(d) > 0: + for x in sort_in_descending_order(pickle_idea.dict2lst(d)): + if x[1] <= 99: + break + youdao[xi] = youdao_link(x[0]) + Eword[xi] = x[0] + EwordNum[xi] = x[1] + xi = xi + 1 + + return render_template('homepage.html', user=user, random_ads=random_ads, youdao=youdao, Eword=Eword, + EwordNum=EwordNum, xi=xi) + + +@app.route("//mark", methods=['GET', 'POST']) +def user_mark_word(username): + username = session[username] + user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) + if request.method == 'POST': + d = load_freq_history(user_freq_record) + lst_history = pickle_idea2.dict2lst(d) + lst = [] + for word in request.form.getlist('marked'): + lst.append((word, [get_time()])) + d = pickle_idea2.merge_frequency(lst, lst_history) + pickle_idea2.save_frequency_to_pickle(d, user_freq_record) + return redirect(url_for('userpage', username=username)) + else: + return 'Under construction' + + +@app.route("/", methods=['GET', 'POST']) +def userpage(username): + if not session.get('logged_in'): + return '

请先登录

' + + user_expiry_date = session.get('expiry_date') + if datetime.now().strftime('%Y%m%d') > user_expiry_date: + return '

账号 %s 过期。

为了提高服务质量,English Pal 收取会员费用, 每天0元。

请决定你要试用的时间长度,扫描下面支付宝二维码支付。 支付时请注明English Pal Membership Fee。 我们会于12小时内激活账号。

支付宝二维码

如果有问题,请加开发者微信 torontohui。

登出

' % ( + username) + + username = session.get('username') + + user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) + + if request.method == 'POST': # when we submit a form + content = request.form['content'] + f = WordFreq(content) + lst = f.get_freq() + page = '' + page += '' + page += '

勾选不认识的单词

' + page += '
\n' % (username) + page += ' \n' + count = 1 + words_tests_dict = pickle_idea.load_record(path_prefix + 'static/words_and_tests.p') + for x in lst: + page += '

%d: %s (%d)

\n' % ( + count, youdao_link(x[0]), appears_in_test(x[0], words_tests_dict), x[0], x[1], x[0]) + count += 1 + page += '
\n' + return page + + elif request.method == 'GET': # when we load a html page + # page = '\n' + # page += '\n' + # page += '\n' # forbid treating numbers as cell numbers in smart phones + # page += 'EnglishPal Study Room for %s' % (username) + # page += '

English Pal for %s 登出

' % (username) + # page += '

下一篇

' % (username) + # page += '

阅读文章并回答问题

\n' + # page += '
%s
' % (today.Get(user_freq_record, session['articleID'])) + # page += '

收集生词吧 (可以在正文中划词,也可以复制黏贴)

' + # page += '
' % (username) + # page += '
' + # page += ' ' + # page += ' ' + # page += '
\n' + # page += ''' + # + # ''' + user = '' + youdao = {} + word = {} + freq = {} + fff = {} + xi = 1 + dayartical = today.Get(user_freq_record, session['articleID']); + d = load_freq_history(user_freq_record) + if len(d) > 0: + # page += '

我的生词簿

' + lst = pickle_idea2.dict2lst(d) + lst2 = [] + for t in lst: + lst2.append((t[0], len(t[1]))) + for x in sort_in_descending_order(lst2): + word[xi] = x[0] + freq[xi] = x[1] + if isinstance(d[word], list): # d[word] is a list of dates + fff[xi] = 1 + # + # if freq > 1: + # page += '

%s (%d)

\n' % (youdao_link(word), word, '; '.join(d[word]), freq) + # else: + # page += '

%s (%d)

\n' % (youdao_link(word), word, '; '.join(d[word]), freq) + elif isinstance(d[word], int): # d[word] is a frequency. to migrate from old format. + # page += '%s%d\n' % (youdao_link(word), word, freq) + fff[xi] = 0 + xi = xi + 1 + + return render_template('userpage.html', user=user, dayartical=dayartical, youdao=youdao, word=word, freq=freq, + xi=xi, fff=fff) + + +### Sign-up, login, logout ### +@app.route("/signup", methods=['GET', 'POST']) +def signup(): + if request.method == 'GET': + return render_template('signup.html') + elif request.method == 'POST': + username = request.form['username'] + password = request.form['password'] + + available = sql.check_username_availability(username) + if not available: + flash('用户名 %s 已经被注册。' % (username)) + return render_template('signup.html') + elif len(password.strip()) < 4: + return '密码过于简单。' + else: + sql.add_user(username, password) + verified = sql.verify_user(username, password) + if verified: + session['logged_in'] = True + session[username] = username + session['username'] = username + return '

恭喜,你已成功注册, 你的用户名是 %s

\ +

开始使用 返回首页

' % (username, username, username) + else: + return '用户名密码验证失败。' + + +@app.route("/login", methods=['GET', 'POST']) +def login(): + if request.method == 'GET': + if not session.get('logged_in'): + return render_template('login.html') + else: + return '你已登录 %s。 登出点击这里。' % ( + session['username'], session['username']) + elif request.method == 'POST': + # check database and verify user + username = request.form['username'] + password = request.form['password'] + verified = sql.verify_user(username, password) + if verified: + session['logged_in'] = True + session[username] = username + session['username'] = username + user_expiry_date = sql.get_expiry_date(username) + session['expiry_date'] = user_expiry_date + session['articleID'] = None + return redirect(url_for('userpage', username=username)) + else: + return '无法通过验证。' + + +@app.route("/logout", methods=['GET', 'POST']) +def logout(): + session['logged_in'] = False + return redirect(url_for('mainpage')) + + +if __name__ == '__main__': + # app.secret_key = os.urandom(16) + # app.run(debug=False, port='6000') + app.run(debug=True) + # app.run(debug=True, port='6000') + # app.run(host='0.0.0.0', debug=True, port='6000') + diff --git a/app/main.py b/app/main.py index 1356f12..1c0918d 100644 --- a/app/main.py +++ b/app/main.py @@ -15,7 +15,8 @@ from datetime import datetime from flask import Flask, request, redirect, render_template, url_for, session, abort, flash from difficulty import get_difficulty_level, text_difficulty_level, user_difficulty_level - +import EverydayArticle as today +import SqlWords as sql app = Flask(__name__) app.secret_key = 'lunch.time!' @@ -28,7 +29,7 @@ def get_random_image(path): def get_random_ads(): ads = random.choice(['个性化分析精准提升', '你的专有单词本', '智能捕捉阅读弱点,针对性提高你的阅读水平']) - return ads + '。 试试吧!' + return ads def load_freq_history(path): d = {} @@ -36,83 +37,6 @@ def load_freq_history(path): d = pickle_idea.load_record(path) return d -def verify_user(username, password): - rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') - rq.instructions("SELECT * FROM user WHERE name='%s' AND password='%s'" % (username, password)) - rq.do() - result = rq.get_results() - return result != [] - -def add_user(username, password): - start_date = datetime.now().strftime('%Y%m%d') - expiry_date = '20211230' - rq = InsertQuery(path_prefix + 'static/wordfreqapp.db') - rq.instructions("INSERT INTO user Values ('%s', '%s', '%s', '%s')" % (username, password, start_date, expiry_date)) - rq.do() - - -def check_username_availability(username): - rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') - rq.instructions("SELECT * FROM user WHERE name='%s'" % (username)) - rq.do() - result = rq.get_results() - return result == [] - -def get_expiry_date(username): - rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') - rq.instructions("SELECT expiry_date FROM user WHERE name='%s'" % (username)) - rq.do() - result = rq.get_results() - if len(result) > 0: - return result[0]['expiry_date'] - else: - return '20191024' - - - -def within_range(x, y, r): - return x > y and abs(x - y) <= r - - -def get_today_article(user_word_list, articleID): - - rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') - if articleID == None: - rq.instructions("SELECT * FROM article") - else: - rq.instructions('SELECT * FROM article WHERE article_id=%d' % (articleID)) - rq.do() - result = rq.get_results() - - # Choose article according to reader's level - d1 = load_freq_history(path_prefix + 'static/frequency/frequency.p') - d2 = load_freq_history(path_prefix + 'static/words_and_tests.p') - d3 = get_difficulty_level(d1, d2) - - d = {} - d_user = load_freq_history(user_word_list) - user_level = user_difficulty_level(d_user, d3) # more consideration as user's behaviour is dynamic. Time factor should be considered. - random.shuffle(result) # shuffle list - d = random.choice(result) - text_level = text_difficulty_level(d['text'], d3) - if articleID == None: - for reading in result: - text_level = text_difficulty_level(reading['text'], d3) - #print('TEXT_LEVEL %4.2f' % (text_level)) - if within_range(text_level, user_level, 0.5): - d = reading - break - - s = '

According to your word list, your level is %4.2f and we have chosen an article with a difficulty level of %4.2f for you.

' % (user_level, text_level) - s += '

%s

' % (d['date']) - s += '

%s

' % (d['text']) - s += '

%s

' % (d['source']) - s += '

%s

' % (get_question_part(d['question'])) - s = s.replace('\n', '
') - s += '%s' % (get_answer_part(d['question'])) - session['articleID'] = d['article_id'] - return s - def appears_in_test(word, d): if not word in d: @@ -124,54 +48,6 @@ def appears_in_test(word, d): def get_time(): return datetime.now().strftime('%Y%m%d%H%M') # upper to minutes - -def get_question_part(s): - s = s.strip() - result = [] - flag = 0 - for line in s.split('\n'): - line = line.strip() - if line == 'QUESTION': - result.append(line) - flag = 1 - elif line == 'ANSWER': - flag = 0 - elif flag == 1: - result.append(line) - return '\n'.join(result) - - -def get_answer_part(s): - s = s.strip() - result = [] - flag = 0 - for line in s.split('\n'): - line = line.strip() - if line == 'ANSWER': - flag = 1 - elif flag == 1: - result.append(line) - # https://css-tricks.com/snippets/javascript/showhide-element/ - js = ''' - - ''' - html_code = js - html_code += '\n' - html_code += '\n' - html_code += '\n' % ('\n'.join(result)) - return html_code - - - @app.route("//reset", methods=['GET', 'POST']) def user_reset(username): if request.method == 'GET': @@ -218,40 +94,88 @@ def mainpage(): return page elif request.method == 'GET': # when we load a html page - page = ''' - - - - - EnglishPal 英文单词高效记 - - - - ''' - page += '

English Pal - Learn English in a smart way!

' + user = '' + youdao = {} + Eword = {} + EwordNum = {} if session.get('logged_in'): - page += ' %s

\n' % (session['username'], session['username']) - else: - page += '

登录 成为会员 使用说明

\n' - #page += '

advertisement

' % (get_random_image(path_prefix + 'static/img/')) - page += '

%s

' % (get_random_ads()) - page += '

粘帖1篇文章 (English only)

' - page += '
' - page += '
' - page += ' ' - page += ' ' - page += '
' + user=session['username'] + random_ads = get_random_ads() d = load_freq_history(path_prefix + 'static/frequency/frequency.p') + xi = 1 if len(d) > 0: - page += '

最常见的词

' for x in sort_in_descending_order(pickle_idea.dict2lst(d)): if x[1] <= 99: break - page += '%s %d\n' % (youdao_link(x[0]), x[0], x[1]) + youdao[xi] = youdao_link(x[0]) + Eword[xi] = x[0] + EwordNum[xi] = x[1] + xi=xi+1 + + return render_template('homepage.html', user=user,random_ads=random_ads,youdao=youdao,Eword=Eword,EwordNum=EwordNum,xi=xi) - page += '' + + + +@app.route("//search", methods=['GET', 'POST']) +def user_others(username): + username = session.get('username') + if request.method == 'POST': # when we submit a form + page = '\n' + page += '\n' + page += '\n' # forbid treating numbers as cell numbers in smart phones + page += '

所查看用户共同的生词 返回

' % (username) + Users = request.form.getlist('usernames') + nums = len (Users) + result = {} + + for uu in Users: + x1=path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % uu + d1 = load_freq_history(x1) + list1 = pickle_idea2.dict2lst(d1) + pickle_idea2.lst2dict2(list1, result) + if nums == 1: + lst = result + # print(type(lst)) + lst2 = [] + for t in lst: + lst2.append((t, lst[t])) + for x in sort_in_descending_order(lst2): + word = x[0] + freq = x[1] + page += '

%s (%d)

\n' % ( + youdao_link(word), word, freq) + else: + lst = result + #print(type(lst)) + lst2 = [] + for t in lst: + if lst[t] == 1: + continue + else: + lst2.append((t, lst[t])) + if lst2 == []: + page += 'They don\'t have words they don\'t know\n' + else: + for x in sort_in_descending_order(lst2): + word = x[0] + freq = x[1] + page += '

%s (%d)

\n' % (youdao_link(word), word, freq) return page + if request.method == 'GET': # when we submit a form + lst = sql.get_user() + page = '' + page += '' + page += '

勾选想要察看的用户 返回

'% (username) + page += '
\n'% (username) + page += ' \n' + count = 1 + for x in lst: + page += '

%d: %s

\n' % (count, x['name'],x['name']) + count += 1 + page += '
\n' + return page @app.route("//mark", methods=['GET', 'POST']) def user_mark_word(username): @@ -269,49 +193,48 @@ def user_mark_word(username): else: return 'Under construction' - - @app.route("/", methods=['GET', 'POST']) def userpage(username): - if not session.get('logged_in'): return '

请先登录

' user_expiry_date = session.get('expiry_date') if datetime.now().strftime('%Y%m%d') > user_expiry_date: - return '

账号 %s 过期。

为了提高服务质量,English Pal 收取会员费用, 每天0元。

请决定你要试用的时间长度,扫描下面支付宝二维码支付。 支付时请注明English Pal Membership Fee。 我们会于12小时内激活账号。

支付宝二维码

如果有问题,请加开发者微信 torontohui。

登出

' % (username) + return '

账号 %s 过期。

为了提高服务质量,English Pal 收取会员费用, 每天0元。

请决定你要试用的时间长度,扫描下面支付宝二维码支付。 支付时请注明English Pal Membership Fee。 我们会于12小时内激活账号。

支付宝二维码

如果有问题,请加开发者微信 torontohui。

登出

' % ( + username) - username = session.get('username') - user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) - + user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) + if request.method == 'POST': # when we submit a form content = request.form['content'] f = WordFreq(content) lst = f.get_freq() - page = '' - page += '' + page = '' + page += '' page += '

勾选不认识的单词

' page += '
\n' % (username) - page += ' \n' + page += ' \n' count = 1 - words_tests_dict = pickle_idea.load_record(path_prefix + 'static/words_and_tests.p') + words_tests_dict = pickle_idea.load_record(path_prefix + 'static/words_and_tests.p') for x in lst: - page += '

%d: %s (%d)

\n' % (count, youdao_link(x[0]), appears_in_test(x[0], words_tests_dict), x[0], x[1], x[0]) + page += '

%d: %s (%d)

\n' % ( + count, youdao_link(x[0]), (x[0], words_tests_dict), x[0], x[1], x[0]) count += 1 page += '
\n' return page - - elif request.method == 'GET': # when we load a html page + + elif request.method == 'GET': # when we load a html page page = '\n' page += '\n' - page += '\n' # forbid treating numbers as cell numbers in smart phones + page += '\n' # forbid treating numbers as cell numbers in smart phones page += 'EnglishPal Study Room for %s' % (username) page += '

English Pal for %s 登出

' % (username) + page += '

查看其他人的共同生词

'% (username) page += '

下一篇

' % (username) page += '

阅读文章并回答问题

\n' - page += '
%s
' % (get_today_article(user_freq_record, session['articleID'])) + page += '
%s
' % (today.Get(user_freq_record, session['articleID'])) page += '

收集生词吧 (可以在正文中划词,也可以复制黏贴)

' page += '
' % (username) page += '
' @@ -332,7 +255,7 @@ def userpage(username): document.getElementById("text-content").addEventListener("touchstart", fillinWord, false); ''' - + d = load_freq_history(user_freq_record) if len(d) > 0: page += '

我的生词簿

' @@ -343,15 +266,16 @@ def userpage(username): for x in sort_in_descending_order(lst2): word = x[0] freq = x[1] - if isinstance(d[word], list): # d[word] is a list of dates + if isinstance(d[word], list): # d[word] is a list of dates if freq > 1: - page += '

%s (%d)

\n' % (youdao_link(word), word, '; '.join(d[word]), freq) + page += '

%s (%d)

\n' % ( + youdao_link(word), word, freq) else: - page += '

%s (%d)

\n' % (youdao_link(word), word, '; '.join(d[word]), freq) - elif isinstance(d[word], int): # d[word] is a frequency. to migrate from old format. - page += '%s%d\n' % (youdao_link(word), word, freq) - - + page += '

%s (%d)

\n' % ( + youdao_link(word), word, freq) + elif isinstance(d[word], int): # d[word] is a frequency. to migrate from old format. + page += '%s%d\n' % (youdao_link(word), word, freq) + return page ### Sign-up, login, logout ### @@ -363,15 +287,15 @@ def signup(): username = request.form['username'] password = request.form['password'] - available = check_username_availability(username) + available = sql.check_username_availability(username) if not available: flash('用户名 %s 已经被注册。' % (username)) return render_template('signup.html') elif len(password.strip()) < 4: return '密码过于简单。' else: - add_user(username, password) - verified = verify_user(username, password) + sql.add_user(username, password) + verified = sql.verify_user(username, password) if verified: session['logged_in'] = True session[username] = username @@ -393,12 +317,12 @@ def login(): # check database and verify user username = request.form['username'] password = request.form['password'] - verified = verify_user(username, password) + verified = sql.verify_user(username, password) if verified: session['logged_in'] = True session[username] = username session['username'] = username - user_expiry_date = get_expiry_date(username) + user_expiry_date = sql.get_expiry_date(username) session['expiry_date'] = user_expiry_date session['articleID'] = None return redirect(url_for('userpage', username=username)) diff --git a/app/pickle_idea2.py b/app/pickle_idea2.py index 91a5b11..f2e75fb 100644 --- a/app/pickle_idea2.py +++ b/app/pickle_idea2.py @@ -25,6 +25,14 @@ def lst2dict(lst, d): else: d[word] += dates +def lst2dict2(lst1, d): + for x in lst1: + word = x[0] + dates = 1 + if not word in d: + d[word] = dates + else: + d[word] += dates def dict2lst(d): if len(d) > 0: diff --git a/app/templates/homepage.html b/app/templates/homepage.html new file mode 100644 index 0000000..ebbd7d8 --- /dev/null +++ b/app/templates/homepage.html @@ -0,0 +1,27 @@ + + + + + + 王天豪EnglishPal 英文单词高效记 + + +

English Pal - Learn English in a smart way!

+ {% if username %} + user

+ {% else %} +

登录 成为会员 使用说明

+ {% endif %} +

{{random_ads}}。 试试吧!

+

粘帖1篇文章 (English only)

+ +
+ + +
+

最常见的词

+ {% for i in range(xi) %} + {{Eword[i]}} {{EwordNum[i]}} + {% endfor %} + + diff --git a/app/templates/userpage.html b/app/templates/userpage.html new file mode 100644 index 0000000..57844b7 --- /dev/null +++ b/app/templates/userpage.html @@ -0,0 +1,49 @@ + + + + + + + EnglishPal Study Room for {{user}} + + + + +
+

English Pal for {{user}} 登出

+

下一篇

+

阅读文章并回答问题

+
{{dayartical}}
+

收集生词吧 (可以在正文中划词,也可以复制黏贴)

+
+
+ + +
+

我的生词簿

+ {% for i in range(xi) %} + {% if fff[i] %} + {% if freq>1 %} +

{{word[i]}} ; ({{freq[i]}})

+ {% else %} +

{{word[i]}} ; ({{freq[i]}})

+ {% endif %} + {% else %} + {{word[i]}} {{freq[i]}} + fff[xi] = 0 + {% endif %} + {{word[i]}} {{freq[i]}} + {% endfor %} + + \ No newline at end of file diff --git a/app/test.py b/app/test.py new file mode 100644 index 0000000..ef9ecbd --- /dev/null +++ b/app/test.py @@ -0,0 +1,83 @@ +#! /usr/bin/python3 +# -*- coding: utf-8 -*- + +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + +from WordFreq import WordFreq +from wordfreqCMD import youdao_link, sort_in_descending_order +from UseSqlite import InsertQuery, RecordQuery +import pickle_idea, pickle_idea2 +import os +import random, glob +from datetime import datetime +from flask import Flask, request, redirect, render_template, url_for, session, abort, flash +from difficulty import get_difficulty_level, text_difficulty_level, user_difficulty_level +import EverydayArticle as today +import SqlWords as sql +app = Flask(__name__) +app.secret_key = 'lunch.time!' +def load_freq_history(path): + d = {} + if os.path.exists(path): + d = pickle_idea.load_record(path) + return d + +path_prefix = '/var/www/wordfreq/wordfreq/' +path_prefix = './' # comment this line in deployment +result={} +d={} +lst = sql.get_user() +x1=path_prefix + 'static/frequency/' + 'frequency_lanhui.pickle' +x2=path_prefix + 'static/frequency/' + 'frequency_lanhui.pickle' +d1 = load_freq_history(x1) +d2 = load_freq_history(x2) +lst1 = pickle_idea2.dict2lst(d1) +lst2 = pickle_idea2.dict2lst(d2) +pickle_idea2.lst2dict2(lst1,d) +print(d) +for xxx in d: + print(xxx) + print(d[xxx]) + print(type(d[xxx])) +# for x in lst1: +# word = x[0] +# dates = x[1] +# if word in d: +# print("1111") +# d[word] += dates +# else: +# print("2222") +# d[word] = dates +# +# for x in lst2: +# word = x[0] +# dates = x[1] +# if word in d: +# print("1111") +# d[word] += dates +# else: +# print("2222") +# d[word] = dates +# m=lst1[0] +# print(m) +# www = m[0] +# print(www) +# if www in lst2: +# print("1111") +# for x in lst1: +# word = x[0] +# dates = x[1] +# if word in lst2: +# print(word) +# if not word in d: +# d[word] = dates +# else: +# d[word] += dates + +# +# print(d1) +# for xx in lst_history: +# print(xx) \ No newline at end of file diff --git "a/\346\274\224\347\244\272\350\247\206\351\242\221" "b/\346\274\224\347\244\272\350\247\206\351\242\221" new file mode 100644 index 0000000..f3db691 --- /dev/null +++ "b/\346\274\224\347\244\272\350\247\206\351\242\221" @@ -0,0 +1,2 @@ +软件项目管理(新功能演示):https://www.bilibili.com/video/BV1wy4y1M7h6/ +软件架构(EnglishPal重构):https://www.bilibili.com/video/BV13y4y1M7Xo/