forked from mrlan/EnglishPal
Compare commits
16 Commits
master
...
Bug393-Tan
Author | SHA1 | Date |
---|---|---|
倪玲丽 | e19d1ae51b | |
倪玲丽 | 782783040a | |
倪玲丽 | 9a95842b7c | |
倪玲丽 | 3e0b8a0235 | |
Hui Lan | b22c654f0f | |
倪玲丽 | d402bb45cb | |
倪玲丽 | cdf6180901 | |
倪玲丽 | 38837c9c2f | |
黄子睿 | a0ddf4bdad | |
倪玲丽 | df64065dcc | |
倪玲丽 | ce28b91bd5 | |
倪玲丽 | d6bd24ee1c | |
Hui Lan | e9e2bd3d23 | |
Hui Lan | 320a99d479 | |
Hui Lan | 3eca9234a9 | |
覃艳美 | 8924166975 |
|
@ -1,14 +1,8 @@
|
||||||
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 os
|
||||||
import random, glob
|
import random
|
||||||
import hashlib
|
import pickle_idea
|
||||||
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_for_user, text_difficulty_level, user_difficulty_level
|
from difficulty import get_difficulty_level_for_user, text_difficulty_level, user_difficulty_level
|
||||||
|
from UseSqlite import RecordQuery
|
||||||
|
|
||||||
path_prefix = '/var/www/wordfreq/wordfreq/'
|
path_prefix = '/var/www/wordfreq/wordfreq/'
|
||||||
path_prefix = './' # comment this line in deployment
|
path_prefix = './' # comment this line in deployment
|
||||||
|
@ -33,19 +27,26 @@ def get_article_body(s):
|
||||||
|
|
||||||
|
|
||||||
def get_today_article(user_word_list, visited_articles):
|
def get_today_article(user_word_list, visited_articles):
|
||||||
|
'''
|
||||||
|
根据用户的单词列表和阅读过的文章返回需要的文章的全部信息
|
||||||
|
'''
|
||||||
rq = RecordQuery(path_prefix + 'static/wordfreqapp.db')
|
rq = RecordQuery(path_prefix + 'static/wordfreqapp.db')
|
||||||
if visited_articles is None:
|
if visited_articles is None:
|
||||||
visited_articles = {
|
visited_articles = {
|
||||||
"index" : 0, # 为 article_ids 的索引
|
"index": 0, # 为 article_ids 的索引
|
||||||
"article_ids": [] # 之前显示文章的id列表,越后越新
|
"article_ids": [] # 之前显示文章的id列表,越后越新
|
||||||
}
|
}
|
||||||
if visited_articles["index"] > len(visited_articles["article_ids"])-1: # 生成新的文章,因此查找所有的文章
|
if visited_articles["index"] > len(visited_articles["article_ids"])-1: # 生成新的文章,因此查找所有的文章
|
||||||
rq.instructions("SELECT * FROM article")
|
rq.instructions("SELECT * FROM article")
|
||||||
else: # 生成阅读过的文章,因此查询指定 article_id 的文章
|
else: # 生成阅读过的文章,因此查询指定 article_id 的文章
|
||||||
if visited_articles["article_ids"][visited_articles["index"]] == 'null': # 可能因为直接刷新页面导致直接去查询了'null',因此当刷新的页面的时候,需要直接进行“上一篇”操作
|
# 可能因为直接刷新页面导致直接去查询了'null',因此当刷新的页面的时候,需要直接进行“上一篇”操作
|
||||||
|
if visited_articles["article_ids"][visited_articles["index"]] == 'null':
|
||||||
visited_articles["index"] -= 1
|
visited_articles["index"] -= 1
|
||||||
visited_articles["article_ids"].pop()
|
visited_articles["article_ids"].pop()
|
||||||
rq.instructions('SELECT * FROM article WHERE article_id=%d' % (visited_articles["article_ids"][visited_articles["index"]]))
|
rq.instructions(
|
||||||
|
f'SELECT * FROM article WHERE article_id='
|
||||||
|
f'{visited_articles["article_ids"][visited_articles["index"]]}'
|
||||||
|
)
|
||||||
rq.do()
|
rq.do()
|
||||||
result = rq.get_results()
|
result = rq.get_results()
|
||||||
random.shuffle(result)
|
random.shuffle(result)
|
||||||
|
@ -58,19 +59,23 @@ def get_today_article(user_word_list, visited_articles):
|
||||||
d = None
|
d = None
|
||||||
result_of_generate_article = "not found"
|
result_of_generate_article = "not found"
|
||||||
d_user = load_freq_history(user_word_list)
|
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.
|
# 更多的考虑,因为用户的行为是动态的。应考虑时间因素。
|
||||||
|
user_level = user_difficulty_level(d_user, d3)
|
||||||
text_level = 0
|
text_level = 0
|
||||||
if visited_articles["index"] > len(visited_articles["article_ids"])-1: # 生成新的文章
|
if visited_articles["index"] > len(visited_articles["article_ids"])-1: # 生成新的文章
|
||||||
amount_of_visited_articles = len(visited_articles["article_ids"])
|
amount_of_visited_articles = len(visited_articles["article_ids"])
|
||||||
amount_of_existing_articles = result.__len__()
|
amount_of_existing_articles = len(result)
|
||||||
if amount_of_visited_articles == amount_of_existing_articles: # 如果当前阅读过的文章的数量 == 存在的文章的数量,即所有的书本都阅读过了
|
# 如果当前阅读过的文章的数量 == 存在的文章的数量,即所有的书本都阅读过了
|
||||||
|
if amount_of_visited_articles == amount_of_existing_articles:
|
||||||
result_of_generate_article = "had read all articles"
|
result_of_generate_article = "had read all articles"
|
||||||
else:
|
else:
|
||||||
for k in range(3): # 最多尝试3次
|
for k in range(3): # 最多尝试3次
|
||||||
for reading in result:
|
for reading in result:
|
||||||
text_level = text_difficulty_level(reading['text'], d3)
|
text_level = text_difficulty_level(reading['text'], d3)
|
||||||
factor = random.gauss(0.8, 0.1) # a number drawn from Gaussian distribution with a mean of 0.8 and a stand deviation of 1
|
# 从高斯分布中得出的平均值为 0.8,站位偏差为 1 的数字
|
||||||
if reading['article_id'] not in visited_articles["article_ids"] and within_range(text_level, user_level, (8.0 - user_level) * factor): # 新的文章之前没有出现过且符合一定范围的水平
|
factor = random.gauss(0.8, 0.1)
|
||||||
|
# 新的文章之前没有出现过且符合一定范围的水平
|
||||||
|
if reading['article_id'] not in visited_articles["article_ids"] and within_range(text_level, user_level, (8.0 - user_level) * factor):
|
||||||
d = reading
|
d = reading
|
||||||
visited_articles["article_ids"].append(d['article_id']) # 列表添加新的文章id;下面进行
|
visited_articles["article_ids"].append(d['article_id']) # 列表添加新的文章id;下面进行
|
||||||
result_of_generate_article = "found"
|
result_of_generate_article = "found"
|
||||||
|
@ -87,8 +92,8 @@ def get_today_article(user_word_list, visited_articles):
|
||||||
today_article = None
|
today_article = None
|
||||||
if d:
|
if d:
|
||||||
today_article = {
|
today_article = {
|
||||||
"user_level": '%4.2f' % user_level,
|
"user_level": f'{user_level:4.2f}',
|
||||||
"text_level": '%4.2f' % text_level,
|
"text_level": f'{text_level:4.2f}',
|
||||||
"date": d['date'],
|
"date": d['date'],
|
||||||
"article_title": get_article_title(d['text']),
|
"article_title": get_article_title(d['text']),
|
||||||
"article_body": get_article_body(d['text']),
|
"article_body": get_article_body(d['text']),
|
||||||
|
|
13
app/Login.py
13
app/Login.py
|
@ -1,7 +1,6 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
import string
|
import string
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from UseSqlite import InsertQuery, RecordQuery
|
|
||||||
|
|
||||||
def md5(s):
|
def md5(s):
|
||||||
'''
|
'''
|
||||||
|
@ -12,14 +11,13 @@ def md5(s):
|
||||||
h = hashlib.md5(s.encode(encoding='utf-8'))
|
h = hashlib.md5(s.encode(encoding='utf-8'))
|
||||||
return h.hexdigest()
|
return h.hexdigest()
|
||||||
|
|
||||||
# import model.user after the defination of md5(s) to avoid circular import
|
from app.model.user import get_user_by_username, insert_user, update_password_by_username
|
||||||
from model.user import get_user_by_username, insert_user, update_password_by_username
|
|
||||||
|
|
||||||
path_prefix = '/var/www/wordfreq/wordfreq/'
|
path_prefix = '/var/www/wordfreq/wordfreq/'
|
||||||
path_prefix = './' # comment this line in deployment
|
path_prefix = './' # comment this line in deployment
|
||||||
|
|
||||||
def verify_pass(newpass,oldpass):
|
def verify_pass(newpass,oldpass):
|
||||||
if(newpass==oldpass):
|
if newpass==oldpass:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,8 +61,7 @@ def get_expiry_date(username):
|
||||||
user = get_user_by_username(username)
|
user = get_user_by_username(username)
|
||||||
if user is None:
|
if user is None:
|
||||||
return '20191024'
|
return '20191024'
|
||||||
else:
|
return user.expiry_date
|
||||||
return user.expiry_date
|
|
||||||
|
|
||||||
class UserName:
|
class UserName:
|
||||||
def __init__(self, username):
|
def __init__(self, username):
|
||||||
|
@ -77,6 +74,7 @@ class UserName:
|
||||||
return 'Period (.) is not allowed as the first letter in the user name.'
|
return 'Period (.) is not allowed as the first letter in the user name.'
|
||||||
if ' ' in self.username: # a user name must not include a whitespace
|
if ' ' in self.username: # a user name must not include a whitespace
|
||||||
return 'Whitespace is not allowed in the user name.'
|
return 'Whitespace is not allowed in the user name.'
|
||||||
|
|
||||||
for c in self.username: # a user name must not include special characters, except non-leading periods or underscores
|
for c in self.username: # a user name must not include special characters, except non-leading periods or underscores
|
||||||
if c in string.punctuation and c != '.' and c != '_':
|
if c in string.punctuation and c != '.' and c != '_':
|
||||||
return f'{c} is not allowed in the user name.'
|
return f'{c} is not allowed in the user name.'
|
||||||
|
@ -91,5 +89,4 @@ class WarningMessage:
|
||||||
self.s = s
|
self.s = s
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return UserName(self.s).validate()
|
return UserName(self.s).validate()
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
# Copyright 2019 (C) Hui Lan <hui.lan@cantab.net>
|
# Copyright 2019 (C) Hui Lan <hui.lan@cantab.net>
|
||||||
# Written permission must be obtained from the author for commercial uses.
|
# Written permission must be obtained from the author for commercial uses.
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
from wordfreqCMD import remove_punctuation, freq, sort_in_descending_order
|
|
||||||
import string
|
import string
|
||||||
|
from wordfreqCMD import remove_punctuation, freq, sort_in_descending_order
|
||||||
|
|
||||||
|
|
||||||
class WordFreq:
|
class WordFreq:
|
||||||
def __init__(self, s):
|
def __init__(self, s):
|
||||||
|
@ -17,7 +17,7 @@ class WordFreq:
|
||||||
if len(word) > 0 and word[0] in string.ascii_letters:
|
if len(word) > 0 and word[0] in string.ascii_letters:
|
||||||
lst.append(t)
|
lst.append(t)
|
||||||
return sort_in_descending_order(lst)
|
return sort_in_descending_order(lst)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
f = WordFreq('BANANA; Banana, apple ORANGE Banana banana.')
|
f = WordFreq('BANANA; Banana, apple ORANGE Banana banana.')
|
||||||
|
|
|
@ -6,7 +6,6 @@ Yaml.py
|
||||||
./layout/partial/footer.html
|
./layout/partial/footer.html
|
||||||
'''
|
'''
|
||||||
import yaml as YAML
|
import yaml as YAML
|
||||||
import os
|
|
||||||
|
|
||||||
path_prefix = './' # comment this line in deployment
|
path_prefix = './' # comment this line in deployment
|
||||||
|
|
||||||
|
|
|
@ -1,46 +1,44 @@
|
||||||
from flask import *
|
from flask import Blueprint, request, render_template, jsonify,session,redirect, url_for,escape
|
||||||
from Login import check_username_availability, verify_user, add_user, get_expiry_date, change_password, WarningMessage
|
from Login import check_username_availability, verify_user, add_user,get_expiry_date, change_password, WarningMessage
|
||||||
|
|
||||||
|
|
||||||
# 初始化蓝图
|
# 初始化蓝图
|
||||||
accountService = Blueprint("accountService", __name__)
|
accountService = Blueprint("accountService", __name__)
|
||||||
|
|
||||||
### Sign-up, login, logout ###
|
### sign-up, login, logout, reset###
|
||||||
@accountService.route("/signup", methods=['GET', 'POST'])
|
@accountService.route("/signup", methods=['GET', 'POST'])
|
||||||
def signup():
|
def signup():
|
||||||
'''
|
'''
|
||||||
注册
|
注册
|
||||||
:return: 根据注册是否成功返回不同界面
|
:return: 根据注册是否成功返回不同界面
|
||||||
'''
|
'''
|
||||||
|
# GET方法直接返回注册页面
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
# GET方法直接返回注册页面
|
|
||||||
return render_template('signup.html')
|
return render_template('signup.html')
|
||||||
elif request.method == 'POST':
|
|
||||||
# POST方法需判断是否注册成功,再根据结果返回不同的内容
|
# POST方法需判断是否注册成功,再根据结果返回不同的内容
|
||||||
username = escape(request.form['username'])
|
username = escape(request.form['username'])
|
||||||
password = escape(request.form['password'])
|
password = escape(request.form['password'])
|
||||||
|
#! 添加如下代码为了过滤注册时的非法字符
|
||||||
#! 添加如下代码为了过滤注册时的非法字符
|
warn = WarningMessage(username)
|
||||||
warn = WarningMessage(username)
|
if str(warn) != 'OK':
|
||||||
if str(warn) != 'OK':
|
return jsonify({'status': '3', 'warn': str(warn)})
|
||||||
return jsonify({'status': '3', 'warn': str(warn)})
|
available = check_username_availability(username)
|
||||||
|
# 用户名不可用
|
||||||
available = check_username_availability(username)
|
if not available:
|
||||||
if not available: # 用户名不可用
|
return jsonify({'status': '0'})
|
||||||
return jsonify({'status': '0'})
|
# 用户名可用,添加账户信息
|
||||||
else: # 添加账户信息
|
add_user(username, password)
|
||||||
add_user(username, password)
|
verified = verify_user(username, password)
|
||||||
verified = verify_user(username, password)
|
# 注册成功,写入session
|
||||||
if verified:
|
if verified:
|
||||||
# 写入session
|
session['logged_in'] = True
|
||||||
session['logged_in'] = True
|
session[username] = username
|
||||||
session[username] = username
|
session['username'] = username
|
||||||
session['username'] = username
|
session['expiry_date'] = get_expiry_date(username)
|
||||||
session['expiry_date'] = get_expiry_date(username)
|
session['visited_articles'] = None
|
||||||
session['visited_articles'] = None
|
return jsonify({'status': '2'})
|
||||||
return jsonify({'status': '2'})
|
# 验证失败
|
||||||
else:
|
return jsonify({'status': '1'})
|
||||||
return jsonify({'status': '1'})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,26 +48,25 @@ def login():
|
||||||
登录
|
登录
|
||||||
:return: 根据登录是否成功返回不同页面
|
:return: 根据登录是否成功返回不同页面
|
||||||
'''
|
'''
|
||||||
|
# GET方法直接返回登录页面
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
# GET请求
|
|
||||||
return render_template('login.html')
|
return render_template('login.html')
|
||||||
elif request.method == 'POST':
|
|
||||||
# POST方法用于判断登录是否成功
|
# POST方法用于判断登录是否成功,检查数据库并验证用户,再根据结果返回不同的内容
|
||||||
# check database and verify user
|
username = escape(request.form['username'])
|
||||||
username = escape(request.form['username'])
|
password = escape(request.form['password'])
|
||||||
password = escape(request.form['password'])
|
verified = verify_user(username, password)
|
||||||
verified = verify_user(username, password)
|
# 登录成功,写入session
|
||||||
if verified:
|
if verified:
|
||||||
# 登录成功,写入session
|
session['logged_in'] = True
|
||||||
session['logged_in'] = True
|
session[username] = username
|
||||||
session[username] = username
|
session['username'] = username
|
||||||
session['username'] = username
|
user_expiry_date = get_expiry_date(username)
|
||||||
user_expiry_date = get_expiry_date(username)
|
session['expiry_date'] = user_expiry_date
|
||||||
session['expiry_date'] = user_expiry_date
|
session['visited_articles'] = None
|
||||||
session['visited_articles'] = None
|
return jsonify({'status': '1'})
|
||||||
return jsonify({'status': '1'})
|
#验证失败
|
||||||
else:
|
return jsonify({'status': '0'})
|
||||||
return jsonify({'status': '0'})
|
|
||||||
|
|
||||||
|
|
||||||
@accountService.route("/logout", methods=['GET', 'POST'])
|
@accountService.route("/logout", methods=['GET', 'POST'])
|
||||||
|
@ -95,16 +92,18 @@ def reset():
|
||||||
username = session['username']
|
username = session['username']
|
||||||
if username == '':
|
if username == '':
|
||||||
return redirect('/login')
|
return redirect('/login')
|
||||||
|
|
||||||
|
# GET请求返回修改密码页面
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
# GET请求返回修改密码页面
|
|
||||||
return render_template('reset.html', username=session['username'], state='wait')
|
return render_template('reset.html', username=session['username'], state='wait')
|
||||||
else:
|
|
||||||
# POST请求用于提交修改后信息
|
# POST请求用于提交修改后信息
|
||||||
old_password = escape(request.form['old-password'])
|
old_password = escape(request.form['old-password'])
|
||||||
new_password = escape(request.form['new-password'])
|
new_password = escape(request.form['new-password'])
|
||||||
flag = change_password(username, old_password, new_password) # flag表示是否修改成功
|
flag = change_password(username, old_password, new_password) # flag表示是否修改成功
|
||||||
if flag:
|
# 修改成功
|
||||||
session['logged_in'] = False
|
if flag:
|
||||||
return jsonify({'status':'1'}) # 修改成功
|
session['logged_in'] = False
|
||||||
else:
|
return jsonify({'status':'1'})
|
||||||
return jsonify({'status':'2'}) # 修改失败
|
# 修改失败
|
||||||
|
return jsonify({'status':'2'})
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
# System Library
|
# System Library
|
||||||
from flask import *
|
from flask import Blueprint, session, render_template, request, flash
|
||||||
|
|
||||||
# Personal library
|
# Personal library
|
||||||
from Yaml import yml
|
from Yaml import yml
|
||||||
from model.user import *
|
from model.user import get_users, update_password_by_username
|
||||||
from model.article import *
|
from model.user import update_expiry_time_by_username, get_user_by_username
|
||||||
|
from model.article import get_number_of_articles, get_page_articles
|
||||||
|
from model.article import delete_article_by_id, add_article
|
||||||
ADMIN_NAME = "lanhui" # unique admin name
|
ADMIN_NAME = "lanhui" # unique admin name
|
||||||
_cur_page = 1 # current article page
|
_cur_page = 1 # current article page
|
||||||
_page_size = 5 # article sizes per page
|
_page_size = 5 # article sizes per page
|
||||||
adminService = Blueprint("admin_service", __name__)
|
adminService = Blueprint("admin_service", __name__)
|
||||||
|
|
||||||
|
|
||||||
def check_is_admin():
|
def check_is_admin():
|
||||||
# 未登录,跳转到未登录界面
|
# 未登录,跳转到未登录界面
|
||||||
if not session.get("logged_in"):
|
if not session.get("logged_in"):
|
||||||
|
@ -26,6 +26,10 @@ def check_is_admin():
|
||||||
|
|
||||||
@adminService.route("/admin", methods=["GET"])
|
@adminService.route("/admin", methods=["GET"])
|
||||||
def admin():
|
def admin():
|
||||||
|
'''
|
||||||
|
判断是否是管理员登录
|
||||||
|
:return:不同页面
|
||||||
|
'''
|
||||||
is_admin = check_is_admin()
|
is_admin = check_is_admin()
|
||||||
if is_admin != "pass":
|
if is_admin != "pass":
|
||||||
return is_admin
|
return is_admin
|
||||||
|
@ -37,6 +41,11 @@ def admin():
|
||||||
|
|
||||||
@adminService.route("/admin/article", methods=["GET", "POST"])
|
@adminService.route("/admin/article", methods=["GET", "POST"])
|
||||||
def article():
|
def article():
|
||||||
|
'''
|
||||||
|
管理文章
|
||||||
|
可添加文章、删除文章
|
||||||
|
return:不同页面
|
||||||
|
'''
|
||||||
global _cur_page, _page_size
|
global _cur_page, _page_size
|
||||||
|
|
||||||
is_admin = check_is_admin()
|
is_admin = check_is_admin()
|
||||||
|
@ -49,16 +58,15 @@ def article():
|
||||||
max(1, int(request.args.get("size", 5))), _article_number
|
max(1, int(request.args.get("size", 5))), _article_number
|
||||||
) # 最小的size是1
|
) # 最小的size是1
|
||||||
_cur_page = min(
|
_cur_page = min(
|
||||||
max(1, int(request.args.get("page", 1))), _article_number // _page_size + (_article_number % _page_size > 0)
|
max(1, int(request.args.get("page", 1))),
|
||||||
|
_article_number // _page_size + (_article_number % _page_size > 0)
|
||||||
) # 最小的page是1
|
) # 最小的page是1
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return "page parmas must be int!"
|
return "page parmas must be int!"
|
||||||
|
|
||||||
_articles = get_page_articles(_cur_page, _page_size)
|
_articles = get_page_articles(_cur_page, _page_size)
|
||||||
for article in _articles: # 获取每篇文章的title
|
for _article in _articles: # 获取每篇文章的title
|
||||||
article.title = article.text.split("\n")[0]
|
_article.title = _article.text.split("\n")[0]
|
||||||
article.content = '<br/>'.join(article.text.split("\n")[1:])
|
_article.content = '<br/>'.join(_article.text.split("\n")[1:])
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"article_number": _article_number,
|
"article_number": _article_number,
|
||||||
"text_list": _articles,
|
"text_list": _articles,
|
||||||
|
@ -72,19 +80,19 @@ def article():
|
||||||
context["article_number"] = article_len
|
context["article_number"] = article_len
|
||||||
context["text_list"] = get_page_articles(_cur_page, _page_size)
|
context["text_list"] = get_page_articles(_cur_page, _page_size)
|
||||||
_articles = get_page_articles(_cur_page, _page_size)
|
_articles = get_page_articles(_cur_page, _page_size)
|
||||||
for article in _articles: # 获取每篇文章的title
|
for _article in _articles: # 获取每篇文章的title
|
||||||
article.title = article.text.split("\n")[0]
|
_article.title = _article.text.split("\n")[0]
|
||||||
context["text_list"] = _articles
|
context["text_list"] = _articles
|
||||||
|
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
try:
|
try:
|
||||||
delete_id = int(request.args.get("delete_id", 0))
|
delete_id = int(request.args.get("delete_id", 0))
|
||||||
except:
|
except ValueError:
|
||||||
return "Delete article ID must be int!"
|
return "Delete article ID must be int!"
|
||||||
if delete_id: # delete article
|
if delete_id: # delete article
|
||||||
delete_article_by_id(delete_id)
|
delete_article_by_id(delete_id)
|
||||||
_update_context()
|
_update_context()
|
||||||
elif request.method == "POST":
|
else:
|
||||||
data = request.form
|
data = request.form
|
||||||
content = data.get("content", "")
|
content = data.get("content", "")
|
||||||
source = data.get("source", "")
|
source = data.get("source", "")
|
||||||
|
@ -102,17 +110,21 @@ def article():
|
||||||
|
|
||||||
@adminService.route("/admin/user", methods=["GET", "POST"])
|
@adminService.route("/admin/user", methods=["GET", "POST"])
|
||||||
def user():
|
def user():
|
||||||
|
'''
|
||||||
|
用户管理
|
||||||
|
可修改用户密码,过期日期
|
||||||
|
return:不同页面
|
||||||
|
'''
|
||||||
is_admin = check_is_admin()
|
is_admin = check_is_admin()
|
||||||
if is_admin != "pass":
|
if is_admin != "pass":
|
||||||
return is_admin
|
return is_admin
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"user_list": get_users(),
|
"user_list": get_users(),
|
||||||
"username": session.get("username"),
|
"username": session.get("username"),
|
||||||
}
|
}
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = request.form
|
data = request.form
|
||||||
username = data.get("username","")
|
username = data.get("username", "")
|
||||||
new_password = data.get("new_password", "")
|
new_password = data.get("new_password", "")
|
||||||
expiry_time = data.get("expiry_time", "")
|
expiry_time = data.get("expiry_time", "")
|
||||||
if username:
|
if username:
|
||||||
|
@ -127,6 +139,9 @@ def user():
|
||||||
|
|
||||||
@adminService.route("/admin/expiry", methods=["GET"])
|
@adminService.route("/admin/expiry", methods=["GET"])
|
||||||
def user_expiry_time():
|
def user_expiry_time():
|
||||||
|
'''
|
||||||
|
返回用户的过期日期
|
||||||
|
'''
|
||||||
is_admin = check_is_admin()
|
is_admin = check_is_admin()
|
||||||
if is_admin != "pass":
|
if is_admin != "pass":
|
||||||
return is_admin
|
return is_admin
|
||||||
|
@ -135,8 +150,7 @@ def user_expiry_time():
|
||||||
if not username:
|
if not username:
|
||||||
return "Username can't be empty."
|
return "Username can't be empty."
|
||||||
|
|
||||||
user = get_user_by_username(username)
|
existed_user = get_user_by_username(username)
|
||||||
if not user:
|
if not existed_user:
|
||||||
return "User does not exist."
|
return "User does not exist."
|
||||||
|
return existed_user.expiry_date
|
||||||
return user.expiry_date
|
|
||||||
|
|
|
@ -6,15 +6,14 @@
|
||||||
# Purpose: compute difficulty level of a English text
|
# Purpose: compute difficulty level of a English text
|
||||||
|
|
||||||
import pickle
|
import pickle
|
||||||
import math
|
|
||||||
from wordfreqCMD import remove_punctuation, freq, sort_in_descending_order, sort_in_ascending_order
|
|
||||||
import snowballstemmer
|
import snowballstemmer
|
||||||
|
from wordfreqCMD import remove_punctuation, freq, sort_in_descending_order, sort_in_ascending_order
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def load_record(pickle_fname):
|
def load_record(pickle_fname):
|
||||||
f = open(pickle_fname, 'rb')
|
with open(pickle_fname, 'rb') as f:
|
||||||
d = pickle.load(f)
|
d = pickle.load(f)
|
||||||
f.close()
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,9 +52,7 @@ def get_difficulty_level_for_user(d1, d2):
|
||||||
stemmer = snowballstemmer.stemmer('english')
|
stemmer = snowballstemmer.stemmer('english')
|
||||||
|
|
||||||
for k in d1: # 用户的词
|
for k in d1: # 用户的词
|
||||||
if k in d2: # 如果用户的词以原型的形式存在于词库d2中
|
if k not in d2: # 如果用户的词以原型的形式不存在于词库d2中
|
||||||
continue # 无需评级,跳过
|
|
||||||
else:
|
|
||||||
stem = stemmer.stemWord(k)
|
stem = stemmer.stemWord(k)
|
||||||
if stem in d2: # 如果用户的词的词根存在于词库d2的词根库中
|
if stem in d2: # 如果用户的词的词根存在于词库d2的词根库中
|
||||||
d2[k] = d2[stem] # 按照词根进行评级
|
d2[k] = d2[stem] # 按照词根进行评级
|
||||||
|
@ -88,6 +85,9 @@ def revert_dict(d):
|
||||||
|
|
||||||
|
|
||||||
def user_difficulty_level(d_user, d):
|
def user_difficulty_level(d_user, d):
|
||||||
|
'''
|
||||||
|
得到用户词汇的难度水平
|
||||||
|
'''
|
||||||
d_user2 = revert_dict(d_user) # key is date, and value is a list of words added in that date
|
d_user2 = revert_dict(d_user) # key is date, and value is a list of words added in that date
|
||||||
count = 0
|
count = 0
|
||||||
geometric = 1
|
geometric = 1
|
||||||
|
@ -242,10 +242,7 @@ We need — for our farmers, our manufacturers, for, frankly, unions and non-uni
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# f = open('bbc-fulltext/bbc/entertainment/001.txt')
|
# f = open('bbc-fulltext/bbc/entertainment/001.txt')
|
||||||
f = open('wordlist.txt')
|
with open('wordlist.txt', encoding='utf-8') as f:
|
||||||
s = f.read()
|
s = f.read()
|
||||||
f.close()
|
|
||||||
|
|
||||||
print(text_difficulty_level(s, d3))
|
|
||||||
|
|
||||||
|
|
||||||
|
print(text_difficulty_level(s, d3))
|
22
app/main.py
22
app/main.py
|
@ -1,17 +1,24 @@
|
||||||
#! /usr/bin/python3
|
#! /usr/bin/python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
# Copyright 2019 (C) Hui Lan <hui.lan@cantab.net>
|
# Copyright 2019 (C) Hui Lan <hui.lan@cantab.net>
|
||||||
# Written permission must be obtained from the author for commercial uses.
|
# Written permission must be obtained from the author for commercial uses.
|
||||||
###########################################################################
|
###########################################################################
|
||||||
from flask import escape
|
import glob
|
||||||
from Login import *
|
from flask import Flask, request, redirect, render_template, url_for, escape
|
||||||
from Article import *
|
from WordFreq import WordFreq
|
||||||
|
import pickle_idea
|
||||||
|
from wordfreqCMD import sort_in_descending_order
|
||||||
|
from Article import load_freq_history, total_number_of_essays
|
||||||
import Yaml
|
import Yaml
|
||||||
from user_service import userService
|
from user_service import userService
|
||||||
from account_service import accountService
|
from account_service import accountService
|
||||||
from admin_service import adminService, ADMIN_NAME
|
from admin_service import adminService, ADMIN_NAME
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.secret_key = 'lunch.time!'
|
app.secret_key = 'lunch.time!'
|
||||||
|
|
||||||
|
@ -51,8 +58,7 @@ def appears_in_test(word, d):
|
||||||
'''
|
'''
|
||||||
if not word in d:
|
if not word in d:
|
||||||
return ''
|
return ''
|
||||||
else:
|
return ','.join(d[word])
|
||||||
return ','.join(d[word])
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/mark", methods=['GET', 'POST'])
|
@app.route("/mark", methods=['GET', 'POST'])
|
||||||
|
@ -70,8 +76,8 @@ def mark_word():
|
||||||
d = pickle_idea.merge_frequency(lst, lst_history)
|
d = pickle_idea.merge_frequency(lst, lst_history)
|
||||||
pickle_idea.save_frequency_to_pickle(d, path_prefix + 'static/frequency/frequency.p')
|
pickle_idea.save_frequency_to_pickle(d, path_prefix + 'static/frequency/frequency.p')
|
||||||
return redirect(url_for('mainpage'))
|
return redirect(url_for('mainpage'))
|
||||||
else: # 不回应GET请求
|
# 不回应GET请求
|
||||||
return 'Under construction'
|
return 'Under construction'
|
||||||
|
|
||||||
|
|
||||||
@app.route("/", methods=['GET', 'POST'])
|
@app.route("/", methods=['GET', 'POST'])
|
||||||
|
@ -91,7 +97,7 @@ def mainpage():
|
||||||
pickle_idea.save_frequency_to_pickle(d, path_prefix + 'static/frequency/frequency.p')
|
pickle_idea.save_frequency_to_pickle(d, path_prefix + 'static/frequency/frequency.p')
|
||||||
return render_template('mainpage_post.html', lst=lst, yml=Yaml.yml)
|
return render_template('mainpage_post.html', lst=lst, yml=Yaml.yml)
|
||||||
|
|
||||||
elif request.method == 'GET': # when we load a html page
|
if request.method == 'GET': # when we load a html page
|
||||||
random_ads = get_random_ads()
|
random_ads = get_random_ads()
|
||||||
number_of_essays = total_number_of_essays()
|
number_of_essays = total_number_of_essays()
|
||||||
d = load_freq_history(path_prefix + 'static/frequency/frequency.p')
|
d = load_freq_history(path_prefix + 'static/frequency/frequency.p')
|
||||||
|
|
|
@ -19,15 +19,15 @@ def lst2dict(lst, d):
|
||||||
for x in lst:
|
for x in lst:
|
||||||
word = x[0]
|
word = x[0]
|
||||||
freq = x[1]
|
freq = x[1]
|
||||||
if not word in d:
|
if word not in d:
|
||||||
d[word] = freq
|
d[word] = freq
|
||||||
else:
|
else:
|
||||||
d[word] += freq
|
d[word] += freq
|
||||||
|
|
||||||
|
|
||||||
def dict2lst(d):
|
def dict2lst(d):
|
||||||
return list(d.items()) # a list of (key, value) pairs
|
return list(d.items()) # a list of (key, value) pairs
|
||||||
|
|
||||||
|
|
||||||
def merge_frequency(lst1, lst2):
|
def merge_frequency(lst1, lst2):
|
||||||
d = {}
|
d = {}
|
||||||
|
@ -37,29 +37,27 @@ def merge_frequency(lst1, lst2):
|
||||||
|
|
||||||
|
|
||||||
def load_record(pickle_fname):
|
def load_record(pickle_fname):
|
||||||
f = open(pickle_fname, 'rb')
|
with open(pickle_fname, 'rb') as f:
|
||||||
d = pickle.load(f)
|
d = pickle.load(f)
|
||||||
f.close()
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
def save_frequency_to_pickle(d, pickle_fname):
|
def save_frequency_to_pickle(d, pickle_fname):
|
||||||
f = open(pickle_fname, 'wb')
|
with open(pickle_fname, 'wb') as f:
|
||||||
#exclusion_lst = ['one', 'no', 'has', 'had', 'do', 'that', 'have', 'by', 'not', 'but', 'we', 'this', 'my', 'him', 'so', 'or', 'as', 'are', 'it', 'from', 'with', 'be', 'can', 'for', 'an', 'if', 'who', 'whom', 'whose', 'which', 'the', 'to', 'a', 'of', 'and', 'you', 'i', 'he', 'she', 'they', 'me', 'was', 'were', 'is', 'in', 'at', 'on', 'their', 'his', 'her', 's', 'said', 'all', 'did', 'been', 'w']
|
#exclusion_lst = ['one', 'no', 'has', 'had', 'do', 'that', 'have', 'by', 'not', 'but', 'we', 'this', 'my', 'him', 'so', 'or', 'as', 'are', 'it', 'from', 'with', 'be', 'can', 'for', 'an', 'if', 'who', 'whom', 'whose', 'which', 'the', 'to', 'a', 'of', 'and', 'you', 'i', 'he', 'she', 'they', 'me', 'was', 'were', 'is', 'in', 'at', 'on', 'their', 'his', 'her', 's', 'said', 'all', 'did', 'been', 'w']
|
||||||
exclusion_lst = []
|
exclusion_lst = []
|
||||||
d2 = {}
|
d2 = {}
|
||||||
for k in d:
|
for k in d:
|
||||||
if not k in exclusion_lst and not k.isnumeric() and len(k) > 1:
|
if not k in exclusion_lst and not k.isnumeric() and len(k) > 1:
|
||||||
d2[k] = d[k]
|
d2[k] = d[k]
|
||||||
pickle.dump(d2, f)
|
pickle.dump(d2, f)
|
||||||
f.close()
|
|
||||||
|
|
||||||
def unfamiliar(path,word):
|
def unfamiliar(path,word):
|
||||||
f = open(path,"rb")
|
with open(path,"rb") as f:
|
||||||
dic = pickle.load(f)
|
dic = pickle.load(f)
|
||||||
dic[word] += [datetime.now().strftime('%Y%m%d%H%M')]
|
dic[word] += [datetime.now().strftime('%Y%m%d%H%M')]
|
||||||
fp = open(path,"wb")
|
with open(path,"wb") as fp:
|
||||||
pickle.dump(dic,fp)
|
pickle.dump(dic,fp)
|
||||||
|
|
||||||
def familiar(path,word):
|
def familiar(path,word):
|
||||||
f = open(path,"rb")
|
f = open(path,"rb")
|
||||||
|
@ -68,8 +66,8 @@ def familiar(path,word):
|
||||||
del dic[word][0]
|
del dic[word][0]
|
||||||
else:
|
else:
|
||||||
dic.pop(word)
|
dic.pop(word)
|
||||||
fp = open(path,"wb")
|
with open(path,"wb") as f:
|
||||||
pickle.dump(dic,fp)
|
pickle.dump(dic,f)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ def deleteRecord(path,word):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print("sorry")
|
print("sorry")
|
||||||
with open(path, 'wb') as ff:
|
with open(path, 'wb') as ff:
|
||||||
pickle.dump(db, ff)
|
pickle.dump(db, ff)
|
||||||
|
|
||||||
def dict2lst(d):
|
def dict2lst(d):
|
||||||
if len(d) > 0:
|
if len(d) > 0:
|
||||||
|
@ -43,7 +43,7 @@ def dict2lst(d):
|
||||||
for k in d:
|
for k in d:
|
||||||
lst.append((k, [datetime.now().strftime('%Y%m%d%H%M')]))
|
lst.append((k, [datetime.now().strftime('%Y%m%d%H%M')]))
|
||||||
return lst
|
return lst
|
||||||
elif isinstance(d[keys[0]], list):
|
if isinstance(d[keys[0]], list):
|
||||||
return list(d.items()) # a list of (key, value) pairs
|
return list(d.items()) # a list of (key, value) pairs
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
@ -56,21 +56,19 @@ def merge_frequency(lst1, lst2):
|
||||||
|
|
||||||
|
|
||||||
def load_record(pickle_fname):
|
def load_record(pickle_fname):
|
||||||
f = open(pickle_fname, 'rb')
|
with open(pickle_fname, 'rb') as f:
|
||||||
d = pickle.load(f)
|
d = pickle.load(f)
|
||||||
f.close()
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
def save_frequency_to_pickle(d, pickle_fname):
|
def save_frequency_to_pickle(d, pickle_fname):
|
||||||
f = open(pickle_fname, 'wb')
|
with open(pickle_fname, 'wb') as f:
|
||||||
exclusion_lst = ['one', 'no', 'has', 'had', 'do', 'that', 'have', 'by', 'not', 'but', 'we', 'this', 'my', 'him', 'so', 'or', 'as', 'are', 'it', 'from', 'with', 'be', 'can', 'for', 'an', 'if', 'who', 'whom', 'whose', 'which', 'the', 'to', 'a', 'of', 'and', 'you', 'i', 'he', 'she', 'they', 'me', 'was', 'were', 'is', 'in', 'at', 'on', 'their', 'his', 'her', 's', 'said', 'all', 'did', 'been', 'w']
|
exclusion_lst = ['one', 'no', 'has', 'had', 'do', 'that', 'have', 'by', 'not', 'but', 'we', 'this', 'my', 'him', 'so', 'or', 'as', 'are', 'it', 'from', 'with', 'be', 'can', 'for', 'an', 'if', 'who', 'whom', 'whose', 'which', 'the', 'to', 'a', 'of', 'and', 'you', 'i', 'he', 'she', 'they', 'me', 'was', 'were', 'is', 'in', 'at', 'on', 'their', 'his', 'her', 's', 'said', 'all', 'did', 'been', 'w']
|
||||||
d2 = {}
|
d2 = {}
|
||||||
for k in d:
|
for k in d:
|
||||||
if not k in exclusion_lst and not k.isnumeric() and not len(k) < 2:
|
if not k in exclusion_lst and not k.isnumeric() and not len(k) < 2:
|
||||||
d2[k] = list(sorted(d[k])) # 原先这里是d2[k] = list(sorted(set(d[k])))
|
d2[k] = list(sorted(d[k])) # 原先这里是d2[k] = list(sorted(set(d[k])))
|
||||||
pickle.dump(d2, f)
|
pickle.dump(d2, f)
|
||||||
f.close()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,4 +84,4 @@ if __name__ == '__main__':
|
||||||
d = load_record('frequency.p')
|
d = load_record('frequency.p')
|
||||||
lst1 = dict2lst(d)
|
lst1 = dict2lst(d)
|
||||||
d = merge_frequency(lst2, lst1)
|
d = merge_frequency(lst2, lst1)
|
||||||
print(d)
|
print(d)
|
|
@ -29,3 +29,7 @@ function onReadClick() {
|
||||||
function onChooseClick() {
|
function onChooseClick() {
|
||||||
isChoose = !isChoose;
|
isChoose = !isChoose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (performance.navigation.type == 1) { //如果网页刷新,停止播放声音
|
||||||
|
Reader.stopRead();
|
||||||
|
}
|
|
@ -22,33 +22,19 @@ function getWord() {
|
||||||
|
|
||||||
function highLight() {
|
function highLight() {
|
||||||
if (!isHighlight) return;
|
if (!isHighlight) return;
|
||||||
let articleContent = document.getElementById("article").innerText; //将原来的.innerText改为.innerHtml,使用innerText会把原文章中所包含的<br>标签去除,导致处理后的文章内容失去了原来的格式
|
let articleContent = document.getElementById("article").innerText;
|
||||||
let pickedWords = document.getElementById("selected-words"); // words picked to the text area
|
let pickedWords = document.getElementById("selected-words"); // words picked to the text area
|
||||||
let dictionaryWords = document.getElementById("selected-words2"); // words appearing in the user's new words list
|
let dictionaryWords = document.getElementById("selected-words2"); // words appearing in the user's new words list
|
||||||
let allWords = ""; //初始化allWords的值,避免进入判断后编译器认为allWords未初始化的问题
|
let allWords = dictionaryWords === null ? pickedWords.value + " " : pickedWords.value + " " + dictionaryWords.value;
|
||||||
if(dictionaryWords != null){//增加一个判断,检查生词本里面是否为空,如果为空,allWords只添加选中的单词
|
const list = allWords.split(" "); // 将所有的生词放入一个list中,用于后续处理
|
||||||
allWords = pickedWords.value + " " + dictionaryWords.value;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
allWords = pickedWords.value + " ";
|
|
||||||
}
|
|
||||||
const list = allWords.split(" ");//将所有的生词放入一个list中,用于后续处理
|
|
||||||
for (let i = 0; i < list.length; ++i) {
|
for (let i = 0; i < list.length; ++i) {
|
||||||
list[i] = list[i].replace(/(^\s*)|(\s*$)/g, ""); //消除单词两边的空字符
|
list[i] = list[i].replace(/(^\W*)|(\W*$)/g, ""); // 消除单词两边的非单词字符
|
||||||
list[i] = list[i].replace('|', "");
|
if (list[i] != "" && "<mark>".indexOf(list[i]) === -1 && "</mark>".indexOf(list[i]) === -1) {
|
||||||
list[i] = list[i].replace('?', "");
|
// 返回所有匹配单词的集合, 正则表达式RegExp()中, "\b"匹配一个单词的边界, g 表示全局匹配, i 表示对大小写不敏感。
|
||||||
if (list[i] !== "" && "<mark>".indexOf(list[i]) === -1 && "</mark>".indexOf(list[i]) === -1) {
|
let matches = new Set(articleContent.match(new RegExp("\\b" + list[i] + "\\b", "gi")));
|
||||||
//将文章中所有出现该单词word的地方改为:"<mark>" + word + "<mark>"。 正则表达式RegExp()中,"\\b"代表单词边界匹配。
|
for (let word of matches) {
|
||||||
|
// 将文章中所有出现该单词word的地方改为:"<mark>" + word + "<mark>"。
|
||||||
//修改代码
|
articleContent = articleContent.replace(new RegExp("\\b" + word + "\\b", "g"), "<mark>" + word + "</mark>");
|
||||||
let articleContent_fb = articleContent; //文章副本
|
|
||||||
while(articleContent_fb.toLowerCase().indexOf(list[i].toLowerCase()) !== -1 && list[i]!=""){
|
|
||||||
//找到副本中和list[i]匹配的第一个单词(第一种匹配情况),并赋值给list[i]。
|
|
||||||
const index = articleContent_fb.toLowerCase().indexOf(list[i].toLowerCase());
|
|
||||||
list[i] = articleContent_fb.substring(index, index + list[i].length);
|
|
||||||
|
|
||||||
articleContent_fb = articleContent_fb.substring(index + list[i].length); // 使用副本中list[i]之后的子串替换掉副本
|
|
||||||
articleContent = articleContent.replace(new RegExp("\\b"+list[i]+"\\b","g"),"<mark>" + list[i] + "</mark>");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,8 @@
|
||||||
{# <div class="alert alert-warning" role="alert">Congratulations! {{ message }}</div>#}
|
{# <div class="alert alert-warning" role="alert">Congratulations! {{ message }}</div>#}
|
||||||
{# {% endfor %}#}
|
{# {% endfor %}#}
|
||||||
|
|
||||||
<button class="btn btn-success" id="load_next_article" onclick="load_next_article()"> 下一篇 Next Article </button>
|
<button class="btn btn-success" id="load_next_article" onclick="load_next_article();Reader.stopRead()"> 下一篇 Next Article </button>
|
||||||
<button class="btn btn-success" id="load_pre_article" onclick="load_pre_article()" > 上一篇 Previous Article </button>
|
<button class="btn btn-success" id="load_pre_article" onclick="load_pre_article();Reader.stopRead()" > 上一篇 Previous Article </button>
|
||||||
|
|
||||||
<p><b>阅读文章并回答问题</b></p>
|
<p><b>阅读文章并回答问题</b></p>
|
||||||
<div id="text-content">
|
<div id="text-content">
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
<p><b>收集生词吧</b> (可以在正文中划词,也可以复制黏贴)</p>
|
<p><b>收集生词吧</b> (可以在正文中划词,也可以复制黏贴)</p>
|
||||||
<form method="post" action="/{{ username }}/userpage">
|
<form method="post" action="/{{ username }}/userpage">
|
||||||
<textarea name="content" id="selected-words" rows="10" cols="120"></textarea><br/>
|
<textarea name="content" id="selected-words" rows="10" cols="120"></textarea><br/>
|
||||||
<input type="submit" value="把生词加入我的生词库"/>
|
<input type="submit" value="把生词加入我的生词库" onclick="Reader.stopRead()"/>
|
||||||
<input type="reset" value="清除"/>
|
<input type="reset" value="清除"/>
|
||||||
</form>
|
</form>
|
||||||
{% if session.get['thisWord'] %}
|
{% if session.get['thisWord'] %}
|
||||||
|
|
|
@ -1,17 +1,10 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from flask import render_template, session, url_for, redirect, request, json, escape, Blueprint
|
||||||
from admin_service import ADMIN_NAME
|
from admin_service import ADMIN_NAME
|
||||||
from flask import *
|
|
||||||
|
|
||||||
# from app import Yaml
|
|
||||||
# from app.Article import get_today_article, load_freq_history
|
|
||||||
# from app.WordFreq import WordFreq
|
|
||||||
# from app.wordfreqCMD import sort_in_descending_order
|
|
||||||
|
|
||||||
import Yaml
|
import Yaml
|
||||||
from Article import get_today_article, load_freq_history
|
from Article import get_today_article, load_freq_history
|
||||||
from WordFreq import WordFreq
|
from WordFreq import WordFreq
|
||||||
from wordfreqCMD import sort_in_descending_order
|
from wordfreqCMD import sort_in_descending_order
|
||||||
|
|
||||||
import pickle_idea
|
import pickle_idea
|
||||||
import pickle_idea2
|
import pickle_idea2
|
||||||
|
|
||||||
|
@ -23,7 +16,7 @@ path_prefix = './' # comment this line in deployment
|
||||||
|
|
||||||
@userService.route("/get_next_article/<username>",methods=['GET','POST'])
|
@userService.route("/get_next_article/<username>",methods=['GET','POST'])
|
||||||
def get_next_article(username):
|
def get_next_article(username):
|
||||||
user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username)
|
user_freq_record = path_prefix + 'static/frequency/' + 'frequency_{username}.pickle'
|
||||||
session['old_articleID'] = session.get('articleID')
|
session['old_articleID'] = session.get('articleID')
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
visited_articles = session.get("visited_articles")
|
visited_articles = session.get("visited_articles")
|
||||||
|
@ -44,7 +37,7 @@ def get_next_article(username):
|
||||||
|
|
||||||
@userService.route("/get_pre_article/<username>",methods=['GET'])
|
@userService.route("/get_pre_article/<username>",methods=['GET'])
|
||||||
def get_pre_article(username):
|
def get_pre_article(username):
|
||||||
user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username)
|
user_freq_record = path_prefix + 'static/frequency/' + f'frequency_{username}.pickle'
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
visited_articles = session.get("visited_articles")
|
visited_articles = session.get("visited_articles")
|
||||||
if(visited_articles["index"]==0):
|
if(visited_articles["index"]==0):
|
||||||
|
@ -85,7 +78,7 @@ def familiar(username, word):
|
||||||
:param word:
|
:param word:
|
||||||
:return:
|
:return:
|
||||||
'''
|
'''
|
||||||
user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username)
|
user_freq_record = path_prefix + 'static/frequency/' + f'frequency_{username}.pickle'
|
||||||
pickle_idea.familiar(user_freq_record, word)
|
pickle_idea.familiar(user_freq_record, word)
|
||||||
session['thisWord'] = word # 1. put a word into session
|
session['thisWord'] = word # 1. put a word into session
|
||||||
session['time'] = 1
|
session['time'] = 1
|
||||||
|
@ -100,7 +93,7 @@ def deleteword(username, word):
|
||||||
:param word: 单词
|
:param word: 单词
|
||||||
:return: 重定位到用户界面
|
:return: 重定位到用户界面
|
||||||
'''
|
'''
|
||||||
user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username)
|
user_freq_record = path_prefix + 'static/frequency/' + f'frequency_{username}.pickle'
|
||||||
pickle_idea2.deleteRecord(user_freq_record, word)
|
pickle_idea2.deleteRecord(user_freq_record, word)
|
||||||
# 模板userpage_get.html中删除单词是异步执行,而flash的信息后续是同步执行的,所以注释这段代码;同时如果这里使用flash但不提取信息,则会影响 signup.html的显示。bug复现:删除单词后,点击退出,点击注册,注册页面就会出现提示信息
|
# 模板userpage_get.html中删除单词是异步执行,而flash的信息后续是同步执行的,所以注释这段代码;同时如果这里使用flash但不提取信息,则会影响 signup.html的显示。bug复现:删除单词后,点击退出,点击注册,注册页面就会出现提示信息
|
||||||
# flash(f'{word} is no longer in your word list.')
|
# flash(f'{word} is no longer in your word list.')
|
||||||
|
@ -126,7 +119,7 @@ def userpage(username):
|
||||||
# 获取session里的用户名
|
# 获取session里的用户名
|
||||||
username = session.get('username')
|
username = session.get('username')
|
||||||
|
|
||||||
user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username)
|
user_freq_record = path_prefix + 'static/frequency/' + f'frequency_{username}.pickle'
|
||||||
|
|
||||||
if request.method == 'POST': # when we submit a form
|
if request.method == 'POST': # when we submit a form
|
||||||
content = escape(request.form['content'])
|
content = escape(request.form['content'])
|
||||||
|
@ -134,7 +127,7 @@ def userpage(username):
|
||||||
lst = f.get_freq()
|
lst = f.get_freq()
|
||||||
return render_template('userpage_post.html',username=username,lst = lst, yml=Yaml.yml)
|
return render_template('userpage_post.html',username=username,lst = lst, yml=Yaml.yml)
|
||||||
|
|
||||||
elif request.method == 'GET': # when we load a html page
|
if request.method == 'GET': # when we load a html page
|
||||||
d = load_freq_history(user_freq_record)
|
d = load_freq_history(user_freq_record)
|
||||||
lst = pickle_idea2.dict2lst(d)
|
lst = pickle_idea2.dict2lst(d)
|
||||||
lst2 = []
|
lst2 = []
|
||||||
|
@ -167,7 +160,7 @@ def user_mark_word(username):
|
||||||
:return: 重定位到用户界面
|
:return: 重定位到用户界面
|
||||||
'''
|
'''
|
||||||
username = session[username]
|
username = session[username]
|
||||||
user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username)
|
user_freq_record = path_prefix + 'static/frequency/' + f'frequency_{username}.pickle'
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
# 提交标记的单词
|
# 提交标记的单词
|
||||||
d = load_freq_history(user_freq_record)
|
d = load_freq_history(user_freq_record)
|
||||||
|
@ -178,13 +171,11 @@ def user_mark_word(username):
|
||||||
d = pickle_idea2.merge_frequency(lst, lst_history)
|
d = pickle_idea2.merge_frequency(lst, lst_history)
|
||||||
pickle_idea2.save_frequency_to_pickle(d, user_freq_record)
|
pickle_idea2.save_frequency_to_pickle(d, user_freq_record)
|
||||||
return redirect(url_for('user_bp.userpage', username=username))
|
return redirect(url_for('user_bp.userpage', username=username))
|
||||||
else:
|
return 'Under construction'
|
||||||
return 'Under construction'
|
|
||||||
|
|
||||||
def get_time():
|
def get_time():
|
||||||
'''
|
'''
|
||||||
获取当前时间
|
获取当前时间
|
||||||
:return: 当前时间
|
:return: 当前时间
|
||||||
'''
|
'''
|
||||||
return datetime.now().strftime('%Y%m%d%H%M') # upper to minutes
|
return datetime.now().strftime('%Y%m%d%H%M') # upper to minutes
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import string
|
import string
|
||||||
import operator
|
import os
|
||||||
import os, sys # 引入模块sys,因为我要用里面的sys.argv列表中的信息来读取命令行参数。
|
import sys # 引入模块sys,因为我要用里面的sys.argv列表中的信息来读取命令行参数。
|
||||||
import pickle_idea
|
import pickle_idea
|
||||||
|
|
||||||
def freq(fruit):
|
def freq(fruit):
|
||||||
|
@ -18,7 +18,7 @@ def freq(fruit):
|
||||||
'''
|
'''
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
fruit = fruit.lower() # 字母转小写
|
fruit = fruit.lower() # 字母转小写
|
||||||
flst = fruit.split() # 字符串转成list
|
flst = fruit.split() # 字符串转成list
|
||||||
c = collections.Counter(flst)
|
c = collections.Counter(flst)
|
||||||
|
@ -32,19 +32,18 @@ def youdao_link(s): # 有道链接
|
||||||
|
|
||||||
|
|
||||||
def file2str(fname):#文件转字符
|
def file2str(fname):#文件转字符
|
||||||
f = open(fname) #打开
|
with open(fname, encoding="utf-8") as f:
|
||||||
s = f.read() #读取
|
s = f.read()
|
||||||
f.close() #关闭
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def remove_punctuation(s): # 这里是s是形参 (parameter)。函数被调用时才给s赋值。
|
def remove_punctuation(s): # 这里是s是形参 (parameter)。函数被调用时才给s赋值。
|
||||||
special_characters = '\_©~<=>+/[]*&$%^@.,?!:;#()"“”—‘’{}|' # 把里面的字符都去掉
|
special_characters = r'\_©~<=>+/[]*&$%^@.,?!:;#()"“”—‘’{}|' # 把里面的字符都去掉
|
||||||
for c in special_characters:
|
for c in special_characters:
|
||||||
s = s.replace(c, ' ') # 防止出现把 apple,apple 移掉逗号后变成 appleapple 情况
|
s = s.replace(c, ' ') # 防止出现把 apple,apple 移掉逗号后变成 appleapple 情况
|
||||||
s = s.replace('--', ' ')
|
s = s.replace('--', ' ')
|
||||||
s = s.strip() # 去除前后的空格
|
s = s.strip() # 去除前后的空格
|
||||||
|
|
||||||
if '\'' in s:
|
if '\'' in s:
|
||||||
n = len(s)
|
n = len(s)
|
||||||
t = '' # 用来收集我需要保留的字符
|
t = '' # 用来收集我需要保留的字符
|
||||||
|
@ -78,11 +77,10 @@ def make_html_page(lst, fname): # 只是在wordfreqCMD.py中的main函数中调
|
||||||
count = 1
|
count = 1
|
||||||
for x in lst:
|
for x in lst:
|
||||||
# <a href="">word</a>
|
# <a href="">word</a>
|
||||||
s += '<p>%d <a href="%s">%s</a> (%d)</p>' % (count, youdao_link(x[0]), x[0], x[1])
|
s += f'<p>{count} <a href="{youdao_link(x[0])}">{x[0]}</a> ({x[1]})</p>'
|
||||||
count += 1
|
count += 1
|
||||||
f = open(fname, 'w')
|
with open(fname, 'w', encoding="utf-8") as f:
|
||||||
f.write(s)
|
f.write(s)
|
||||||
f.close()
|
|
||||||
|
|
||||||
|
|
||||||
## main(程序入口)
|
## main(程序入口)
|
||||||
|
@ -101,10 +99,10 @@ if __name__ == '__main__':
|
||||||
s = remove_punctuation(s) # 这里是s是实参(argument),里面有值
|
s = remove_punctuation(s) # 这里是s是实参(argument),里面有值
|
||||||
L = freq(s)
|
L = freq(s)
|
||||||
for x in sort_in_descending_order(L):
|
for x in sort_in_descending_order(L):
|
||||||
print('%s\t%d\t%s' % (x[0], x[1], youdao_link(x[0])))#函数导出
|
print(f'{x[0]}\t{x[1]}\t{youdao_link(x[0])}' )#函数导出
|
||||||
|
|
||||||
# 把频率的结果放result.html中
|
# 把频率的结果放result.html中
|
||||||
make_html_page(sort_in_descending_order(L), 'result.html')
|
make_html_page(sort_in_descending_order(L), 'result.html')
|
||||||
|
|
||||||
print('\nHistory:\n')
|
print('\nHistory:\n')
|
||||||
if os.path.exists('frequency.p'):
|
if os.path.exists('frequency.p'):
|
||||||
|
@ -118,6 +116,3 @@ if __name__ == '__main__':
|
||||||
lst_history = pickle_idea.dict2lst(d)
|
lst_history = pickle_idea.dict2lst(d)
|
||||||
d = pickle_idea.merge_frequency(L, lst_history)
|
d = pickle_idea.merge_frequency(L, lst_history)
|
||||||
pickle_idea.save_frequency_to_pickle(d, 'frequency.p')
|
pickle_idea.save_frequency_to_pickle(d, 'frequency.p')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue