#! /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, get_flashed_messages from difficulty import get_difficulty_level, text_difficulty_level, user_difficulty_level 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 total_number_of_essays(): rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') rq.instructions("SELECT * FROM article") rq.do() result = rq.get_results() return len(result) def load_freq_history(path): d = {} if os.path.exists(path): d = pickle_idea.load_record(path) return d def verify_user(username, password): rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') rq.instructions_with_parameters("SELECT * FROM user WHERE name=? AND password=?", (username, password)) rq.do_with_parameters() 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_article_title(s): return s.split('\n')[0] def get_article_body(s): lst = s.split('\n') lst.pop(0) # remove the first line return '\n'.join(lst) 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 = '' % (user_level, text_level) s += '

Article added on: %s

' % (d['date']) s += '
' article_title = get_article_title(d['text']) article_body = get_article_body(d['text']) s += '

%s

' % (article_title) s += '

%s

' % (article_body) s += '

%s

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

%s

' % (get_question_part(d['question'])) s = s.replace('\n', '
') s += '%s' % (get_answer_part(d['question'])) s += '
' session['articleID'] = d['article_id'] return s 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 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 def get_flashed_messages_if_any(): messages = get_flashed_messages() s = '' for message in messages: s += '' return s @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 page = ''' EnglishPal 英文单词高效记 ''' page += '
' page += '

English Pal - Learn English smartly!

' 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 += '' % (total_number_of_essays()) page += '

粘帖1篇文章 (English only)

' page += '
' page += '
' page += ' ' page += ' ' page += '
' d = load_freq_history(path_prefix + 'static/frequency/frequency.p') 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]) page += ' ' page += '
' page += '' return page @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("///unfamiliar", methods=['GET', 'POST']) def unfamiliar(username,word): user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) pickle_idea.unfamiliar(user_freq_record,word) session['thisWord'] = word # 1. put a word into session session['time'] = 1 return redirect(url_for('userpage', username=username)) @app.route("///familiar", methods=['GET', 'POST']) def familiar(username,word): user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) pickle_idea.familiar(user_freq_record,word) session['thisWord'] = word # 1. put a word into session session['time'] = 1 return redirect(url_for('userpage', username=username)) @app.route("///del", methods=['GET', 'POST']) def deleteword(username,word): user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) pickle_idea2.deleteRecord(user_freq_record,word) flash(f'{word} is no longer in your word list.') return redirect(url_for('userpage', username=username)) @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 += '' page += 'EnglishPal Study Room for %s' % (username) page += '
' page += '

English Pal for %s 登出

' % (username) page += get_flashed_messages_if_any() page += '

阅读文章并回答问题

\n' page += '

下一篇 Next Article

' % (username) page += '
%s
' % (get_today_article(user_freq_record, session['articleID'])) page += '

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

' page += '
' % (username) page += '
' page += ' ' page += ' ' page += '
\n' page += ''' ''' if session.get('thisWord'): page += ''' ''' 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 = x[0] freq = x[1] if session.get('thisWord') == x[0] and session.get('time') == 1: page += '' # 3. anchor session['time'] = 0 # discard anchor 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,username, word,username,word, username,word) else: page += '

%s(%d) 熟悉 不熟悉 删除

\n' % (youdao_link(word), word, '; '.join(d[word]), freq,username, word,username,word, username,word) 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 += '' page += '
' return page ### 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 = 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) if verified: session['logged_in'] = True session[username] = username session['username'] = username session['expiry_date'] = get_expiry_date(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 = verify_user(username, password) if verified: session['logged_in'] = True session[username] = username session['username'] = username user_expiry_date = 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')