Compare commits
	
		
			1 Commits 
		
	
	
		
			master
			...
			Refactor_q
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
									
								
								 | 
						ea16ea6673 | 
| 
						 | 
					@ -1,3 +1,6 @@
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					This module provides functions about article
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
from WordFreq import WordFreq
 | 
					from WordFreq import WordFreq
 | 
				
			||||||
from wordfreqCMD import youdao_link, sort_in_descending_order
 | 
					from wordfreqCMD import youdao_link, sort_in_descending_order
 | 
				
			||||||
from UseSqlite import InsertQuery, RecordQuery
 | 
					from UseSqlite import InsertQuery, RecordQuery
 | 
				
			||||||
| 
						 | 
					@ -46,7 +49,6 @@ def get_today_article(user_word_list, articleID):
 | 
				
			||||||
    d1 = load_freq_history(path_prefix + 'static/frequency/frequency.p')
 | 
					    d1 = load_freq_history(path_prefix + 'static/frequency/frequency.p')
 | 
				
			||||||
    d2 = load_freq_history(path_prefix + 'static/words_and_tests.p')
 | 
					    d2 = load_freq_history(path_prefix + 'static/words_and_tests.p')
 | 
				
			||||||
    d3 = get_difficulty_level(d1, d2)
 | 
					    d3 = get_difficulty_level(d1, d2)
 | 
				
			||||||
 | 
					 | 
				
			||||||
    d = {}
 | 
					    d = {}
 | 
				
			||||||
    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)  # more consideration as user's behaviour is dynamic. Time factor should be considered.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								app/Login.py
								
								
								
								
							
							
						
						
									
										29
									
								
								app/Login.py
								
								
								
								
							| 
						 | 
					@ -1,3 +1,6 @@
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					This module provides methods for Login
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
import hashlib
 | 
					import hashlib
 | 
				
			||||||
import string
 | 
					import string
 | 
				
			||||||
from datetime import datetime, timedelta
 | 
					from datetime import datetime, timedelta
 | 
				
			||||||
| 
						 | 
					@ -7,15 +10,17 @@ 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
def verify_user(username, password):
 | 
					def verify_user(username, password):
 | 
				
			||||||
    rq = RecordQuery(path_prefix + 'static/wordfreqapp.db')
 | 
					    rq = RecordQuery(path_prefix + 'static/wordfreqapp.db')
 | 
				
			||||||
    password = md5(username + password)
 | 
					    password = md5(username + password)
 | 
				
			||||||
    rq.instructions_with_parameters("SELECT * FROM user WHERE name=:username AND password=:password", dict(
 | 
					    rq.instructions_with_parameters(
 | 
				
			||||||
        username=username, password=password))  # the named style https://docs.python.org/3/library/sqlite3.html
 | 
					        "SELECT * FROM user WHERE name=:username AND password=:password",
 | 
				
			||||||
 | 
					        dict(   # the named style https://docs.python.org/3/library/sqlite3.html
 | 
				
			||||||
 | 
					            username=username,
 | 
				
			||||||
 | 
					            password=password))
 | 
				
			||||||
    rq.do_with_parameters()
 | 
					    rq.do_with_parameters()
 | 
				
			||||||
    result = rq.get_results()
 | 
					    result = rq.get_results()
 | 
				
			||||||
    return result != []
 | 
					    return result != []
 | 
				
			||||||
| 
						 | 
					@ -23,12 +28,19 @@ def verify_user(username, password):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def add_user(username, password):
 | 
					def add_user(username, password):
 | 
				
			||||||
    start_date = datetime.now().strftime('%Y%m%d')
 | 
					    start_date = datetime.now().strftime('%Y%m%d')
 | 
				
			||||||
    expiry_date = (datetime.now() + timedelta(days=30)).strftime('%Y%m%d') # will expire after 30 days
 | 
					    # will expire after 30 days
 | 
				
			||||||
 | 
					    expiry_date = (datetime.now() + timedelta(days=30)).strftime('%Y%m%d')
 | 
				
			||||||
    # 将用户名和密码一起加密,以免暴露不同用户的相同密码
 | 
					    # 将用户名和密码一起加密,以免暴露不同用户的相同密码
 | 
				
			||||||
    password = md5(username + password)
 | 
					    password = md5(username + password)
 | 
				
			||||||
    rq = InsertQuery(path_prefix + 'static/wordfreqapp.db')
 | 
					    rq = InsertQuery(path_prefix + 'static/wordfreqapp.db')
 | 
				
			||||||
    rq.instructions_with_parameters("INSERT INTO user VALUES (:username, :password, :start_date, :expiry_date)", dict(
 | 
					    rq.instructions_with_parameters(
 | 
				
			||||||
        username=username, password=password, start_date=start_date, expiry_date=expiry_date))
 | 
					        "INSERT INTO user VALUES (:username, :password, :start_date, :expiry_date)",
 | 
				
			||||||
 | 
					        dict(
 | 
				
			||||||
 | 
					            username=username,
 | 
				
			||||||
 | 
					            password=password,
 | 
				
			||||||
 | 
					            start_date=start_date,
 | 
				
			||||||
 | 
					            expiry_date=expiry_date
 | 
				
			||||||
 | 
					        ))
 | 
				
			||||||
    rq.do_with_parameters()
 | 
					    rq.do_with_parameters()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,7 +108,7 @@ class UserName:
 | 
				
			||||||
        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 is not '.' and c is not '_':
 | 
					            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.'
 | 
				
			||||||
        if self.username in ['signup', 'login', 'logout', 'reset', 'mark', 'back', 'unfamiliar', 'familiar', 'del']:
 | 
					        if self.username in ['signup', 'login', 'logout', 'reset', 'mark', 'back', 'unfamiliar', 'familiar', 'del']:
 | 
				
			||||||
            return 'You used a restricted word as your user name.  Please come up with a better one.'
 | 
					            return 'You used a restricted word as your user name.  Please come up with a better one.'
 | 
				
			||||||
| 
						 | 
					@ -110,4 +122,3 @@ class WarningMessage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return UserName(self.s).validate()
 | 
					        return UserName(self.s).validate()
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,9 +2,12 @@
 | 
				
			||||||
# 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
 | 
					This module produces word frequency
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
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):
 | 
				
			||||||
| 
						 | 
					@ -22,4 +25,3 @@ class WordFreq:
 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    f = WordFreq('BANANA; Banana, apple ORANGE Banana banana.')
 | 
					    f = WordFreq('BANANA; Banana, apple ORANGE Banana banana.')
 | 
				
			||||||
    print(f.get_freq())
 | 
					    print(f.get_freq())
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,41 +1,43 @@
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					This module provides services about account.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
from flask import *
 | 
					from flask import *
 | 
				
			||||||
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
 | 
				
			||||||
@accountService.route("/signup", methods=['GET', 'POST'])
 | 
					@accountService.route("/signup", methods=['GET', 'POST'])
 | 
				
			||||||
def signup():
 | 
					def signup():
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
    注册
 | 
					    注册
 | 
				
			||||||
    :return: 根据注册是否成功返回不同界面
 | 
					    :return: 根据注册是否成功返回不同界面
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
    if request.method == 'GET':
 | 
					 | 
				
			||||||
    # GET方法直接返回注册页面
 | 
					    # GET方法直接返回注册页面
 | 
				
			||||||
 | 
					    if request.method == 'GET':
 | 
				
			||||||
        return render_template('signup.html')
 | 
					        return render_template('signup.html')
 | 
				
			||||||
    elif request.method == 'POST':
 | 
					    if 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'])
 | 
				
			||||||
        password2 = escape(request.form['password2'])
 | 
					        password2 = escape(request.form['password2'])
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        #! 添加如下代码为了过滤注册时的非法字符
 | 
					        #! 添加如下代码为了过滤注册时的非法字符
 | 
				
			||||||
        warn = WarningMessage(username)
 | 
					        warn = WarningMessage(username)
 | 
				
			||||||
        if str(warn) != 'OK':
 | 
					        if str(warn) != 'OK':
 | 
				
			||||||
            return str(warn)
 | 
					            return str(warn)
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        available = check_username_availability(username)
 | 
					        available = check_username_availability(username)
 | 
				
			||||||
        if not available: # 用户名不可用
 | 
					        if not available: # 用户名不可用
 | 
				
			||||||
            flash('用户名 %s 已经被注册。' % (username))
 | 
					            flash('用户名 %s 已经被注册。' % (username))
 | 
				
			||||||
            return render_template('signup.html')
 | 
					            return render_template('signup.html')
 | 
				
			||||||
        elif len(password.strip()) < 4: # 密码过短
 | 
					        if len(password.strip()) < 4: # 密码过短
 | 
				
			||||||
            return '密码过于简单。'
 | 
					            return '密码过于简单。'
 | 
				
			||||||
        elif password != password2:
 | 
					        if password != password2:
 | 
				
			||||||
            return '确认密码与输入密码不一致!'
 | 
					            return '确认密码与输入密码不一致!'
 | 
				
			||||||
        else: # 添加账户信息
 | 
					        add_user(username, password)# 添加账户信息
 | 
				
			||||||
            add_user(username, password)
 | 
					 | 
				
			||||||
        verified = verify_user(username, password)
 | 
					        verified = verify_user(username, password)
 | 
				
			||||||
        if verified:
 | 
					        if verified:
 | 
				
			||||||
            # 写入session
 | 
					            # 写入session
 | 
				
			||||||
| 
						 | 
					@ -46,11 +48,9 @@ def signup():
 | 
				
			||||||
            session['articleID'] = None
 | 
					            session['articleID'] = None
 | 
				
			||||||
            return '<p>恭喜,你已成功注册, 你的用户名是 <a href="%s">%s</a>。</p>\
 | 
					            return '<p>恭喜,你已成功注册, 你的用户名是 <a href="%s">%s</a>。</p>\
 | 
				
			||||||
            <p><a href="/%s">开始使用</a> <a href="/">返回首页</a><p/>' % (username, username, username)
 | 
					            <p><a href="/%s">开始使用</a> <a href="/">返回首页</a><p/>' % (username, username, username)
 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
        return '用户名密码验证失败。'
 | 
					        return '用户名密码验证失败。'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
@accountService.route("/login", methods=['GET', 'POST'])
 | 
					@accountService.route("/login", methods=['GET', 'POST'])
 | 
				
			||||||
def login():
 | 
					def login():
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
| 
						 | 
					@ -62,11 +62,10 @@ def login():
 | 
				
			||||||
        if not session.get('logged_in'):
 | 
					        if not session.get('logged_in'):
 | 
				
			||||||
            # 未登录,返回登录页面
 | 
					            # 未登录,返回登录页面
 | 
				
			||||||
            return render_template('login.html')
 | 
					            return render_template('login.html')
 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
        # 已登录,提示信息并显示登出按钮
 | 
					        # 已登录,提示信息并显示登出按钮
 | 
				
			||||||
        return '你已登录 <a href="/%s">%s</a>。 登出点击<a href="/logout">这里</a>。' % (
 | 
					        return '你已登录 <a href="/%s">%s</a>。 登出点击<a href="/logout">这里</a>。' % (
 | 
				
			||||||
                session['username'], session['username'])
 | 
					                session['username'], session['username'])
 | 
				
			||||||
    elif request.method == 'POST':
 | 
					    if request.method == 'POST':
 | 
				
			||||||
        # POST方法用于判断登录是否成功
 | 
					        # POST方法用于判断登录是否成功
 | 
				
			||||||
        # check database and verify user
 | 
					        # check database and verify user
 | 
				
			||||||
        username = escape(request.form['username'])
 | 
					        username = escape(request.form['username'])
 | 
				
			||||||
| 
						 | 
					@ -81,7 +80,6 @@ def login():
 | 
				
			||||||
            session['expiry_date'] = user_expiry_date
 | 
					            session['expiry_date'] = user_expiry_date
 | 
				
			||||||
            session['articleID'] = None
 | 
					            session['articleID'] = None
 | 
				
			||||||
            return redirect(url_for('user_bp.userpage', username=username))
 | 
					            return redirect(url_for('user_bp.userpage', username=username))
 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
        return '无法通过验证。'
 | 
					        return '无法通过验证。'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,17 +109,14 @@ def reset():
 | 
				
			||||||
    if request.method == 'GET':
 | 
					    if request.method == 'GET':
 | 
				
			||||||
        # 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'])
 | 
				
			||||||
 | 
					 | 
				
			||||||
    re_new_password = escape(request.form['re-new-password'])  # 确认新密码
 | 
					    re_new_password = escape(request.form['re-new-password'])  # 确认新密码
 | 
				
			||||||
    if re_new_password != new_password: #验证新密码两次输入是否相同
 | 
					    if re_new_password != new_password: #验证新密码两次输入是否相同
 | 
				
			||||||
        return '新密码不匹配,请重新输入'
 | 
					        return '新密码不匹配,请重新输入'
 | 
				
			||||||
    if len(new_password) < 4: #验证新密码长度,原则参照注册模块
 | 
					    if len(new_password) < 4: #验证新密码长度,原则参照注册模块
 | 
				
			||||||
        return '密码过于简单。(密码长度至少4位)'
 | 
					        return '密码过于简单。(密码长度至少4位)'
 | 
				
			||||||
 | 
					 | 
				
			||||||
    flag = change_password(username, old_password, new_password) # flag表示是否修改成功
 | 
					    flag = change_password(username, old_password, new_password) # flag表示是否修改成功
 | 
				
			||||||
    if flag:
 | 
					    if flag:
 | 
				
			||||||
        session['logged_in'] = False
 | 
					        session['logged_in'] = False
 | 
				
			||||||
| 
						 | 
					@ -134,8 +129,7 @@ window.location.href="/login";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
'''
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        else:
 | 
					
 | 
				
			||||||
            return \
 | 
					 | 
				
			||||||
'''
 | 
					'''
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
alert('密码修改失败');
 | 
					alert('密码修改失败');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,8 +3,10 @@
 | 
				
			||||||
# Written permission must be obtained from the author for commercial uses.
 | 
					# Written permission must be obtained from the author for commercial uses.
 | 
				
			||||||
###########################################################################
 | 
					###########################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Purpose: compute difficulty level of a English text
 | 
					"""
 | 
				
			||||||
 | 
					This module provides functions for calculating user words difficulty
 | 
				
			||||||
 | 
					Purpose: compute difficulty level of a English text
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
import pickle
 | 
					import pickle
 | 
				
			||||||
import math
 | 
					import math
 | 
				
			||||||
from wordfreqCMD import remove_punctuation, freq, sort_in_descending_order, sort_in_ascending_order
 | 
					from wordfreqCMD import remove_punctuation, freq, sort_in_descending_order, sort_in_ascending_order
 | 
				
			||||||
| 
						 | 
					@ -52,7 +54,6 @@ def get_difficulty_level(d1, d2):
 | 
				
			||||||
    return d
 | 
					    return d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
def revert_dict(d):
 | 
					def revert_dict(d):
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
    In d, word is the key, and value is a list of dates.
 | 
					    In d, word is the key, and value is a list of dates.
 | 
				
			||||||
| 
						 | 
					@ -62,7 +63,8 @@ def revert_dict(d):
 | 
				
			||||||
    for k in d:
 | 
					    for k in d:
 | 
				
			||||||
        if type(d[k]) is list:  # d[k] is a list of dates.
 | 
					        if type(d[k]) is list:  # d[k] is a list of dates.
 | 
				
			||||||
            lst = d[k]
 | 
					            lst = d[k]
 | 
				
			||||||
        elif type(d[k]) is int: # for backward compatibility.  d was sth like {'word':1}.  The value d[k] is not a list of dates, but a number representing how frequent this word had been added to the new word book. 
 | 
					        elif type(d[
 | 
				
			||||||
 | 
					                      k]) is int:  # for backward compatibility.  d was sth like {'word':1}.  The value d[k] is not a list of dates, but a number representing how frequent this word had been added to the new word book.
 | 
				
			||||||
            freq = d[k]
 | 
					            freq = d[k]
 | 
				
			||||||
            lst = freq * ['2021082019']  # why choose this date?  No particular reasons.  I fix the bug in this date.
 | 
					            lst = freq * ['2021082019']  # why choose this date?  No particular reasons.  I fix the bug in this date.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +81,8 @@ 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
 | 
				
			||||||
    for date in sorted(d_user2.keys(), reverse=True): # most recently added words are more important while determining user's level
 | 
					    for date in sorted(d_user2.keys(),
 | 
				
			||||||
 | 
					                       reverse=True):  # most recently added words are more important while determining user's level
 | 
				
			||||||
        lst = d_user2[date]  # a list of words
 | 
					        lst = d_user2[date]  # a list of words
 | 
				
			||||||
        lst2 = []  # a list of tuples, (word, difficulty level)
 | 
					        lst2 = []  # a list of tuples, (word, difficulty level)
 | 
				
			||||||
        for word in lst:
 | 
					        for word in lst:
 | 
				
			||||||
| 
						 | 
					@ -125,17 +128,13 @@ def text_difficulty_level(s, d):
 | 
				
			||||||
    return geometric ** (1 / max(count, 1))
 | 
					    return geometric ** (1 / max(count, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    d1 = load_record('frequency.p')
 | 
					    d1 = load_record('frequency.p')
 | 
				
			||||||
    # print(d1)
 | 
					    # print(d1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    d2 = load_record('words_and_tests.p')
 | 
					    d2 = load_record('words_and_tests.p')
 | 
				
			||||||
    # print(d2)
 | 
					    # print(d2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    d3 = get_difficulty_level(d1, d2)
 | 
					    d3 = get_difficulty_level(d1, d2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = '''
 | 
					    s = '''
 | 
				
			||||||
| 
						 | 
					@ -197,7 +196,6 @@ Amidst the aftermath of this shocking referendum vote, there is great uncertaint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
'''
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    s = '''
 | 
					    s = '''
 | 
				
			||||||
British Prime Minister Boris Johnson walks towards a voting station during the Brexit referendum in Britain, June 23, 2016. (Photo: EPA-EFE)
 | 
					British Prime Minister Boris Johnson walks towards a voting station during the Brexit referendum in Britain, June 23, 2016. (Photo: EPA-EFE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -218,7 +216,6 @@ The prime minister was forced to ask for an extension to Britain's EU departure
 | 
				
			||||||
Johnson has repeatedly pledged to finalize the first stage, a transition deal, of Britain's EU divorce battle by Oct. 31. A second stage will involve negotiating its future relationship with the EU on trade, security and other salient issues.
 | 
					Johnson has repeatedly pledged to finalize the first stage, a transition deal, of Britain's EU divorce battle by Oct. 31. A second stage will involve negotiating its future relationship with the EU on trade, security and other salient issues.
 | 
				
			||||||
'''
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    s = '''
 | 
					    s = '''
 | 
				
			||||||
Thank you very much. We have a Cabinet meeting. We’ll have a few questions after grace. And, if you would, Ben, please do the honors.
 | 
					Thank you very much. We have a Cabinet meeting. We’ll have a few questions after grace. And, if you would, Ben, please do the honors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -233,17 +230,9 @@ 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')
 | 
					    f = open('wordlist.txt',encoding="utf-8")
 | 
				
			||||||
    s = f.read()
 | 
					    s = f.read()
 | 
				
			||||||
    f.close()
 | 
					    f.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    print(text_difficulty_level(s, d3))
 | 
					    print(text_difficulty_level(s, d3))
 | 
				
			||||||
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,7 +52,6 @@ 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])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,7 +70,7 @@ 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'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,7 +91,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')
 | 
				
			||||||
| 
						 | 
					@ -102,7 +101,6 @@ def mainpage():
 | 
				
			||||||
                               d_len=d_len, lst=lst, yml=Yaml.yml)
 | 
					                               d_len=d_len, lst=lst, yml=Yaml.yml)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
    运行程序
 | 
					    运行程序
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,9 +3,10 @@
 | 
				
			||||||
# Written permission must be obtained from the author for commercial uses.
 | 
					# Written permission must be obtained from the author for commercial uses.
 | 
				
			||||||
###########################################################################
 | 
					###########################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Purpose: dictionary & pickle as a simple means of database.
 | 
					"""
 | 
				
			||||||
# Task: incorporate the functions into wordfreqCMD.py such that it will also show cumulative frequency.
 | 
					  Purpose: dictionary & pickle as a simple means of database.
 | 
				
			||||||
 | 
					  Task: incorporate the functions into wordfreqCMD.py such that it will also show cumulative frequency.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
import pickle
 | 
					import pickle
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 []
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,34 +11,39 @@ function getWord() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function fillInWord() {
 | 
					function fillInWord() {
 | 
				
			||||||
    let word = getWord();
 | 
					    let word = getWord();
 | 
				
			||||||
    if (isRead) read(word);
 | 
					    if (isRead) {read(word);}
 | 
				
			||||||
    if (!isChoose) return;
 | 
					    if (!isChoose) {return;}
 | 
				
			||||||
    const element = document.getElementById("selected-words");
 | 
					    const element = document.getElementById("selected-words");
 | 
				
			||||||
    element.value = element.value + " " + word;
 | 
					    element.value = element.value + " " + word;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
document.getElementById("text-content").addEventListener("click", fillInWord, false);
 | 
					document
 | 
				
			||||||
 | 
					    .getElementById("text-content")
 | 
				
			||||||
 | 
					    .addEventListener("click", fillInWord, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function makeUtterance(str, rate) {
 | 
					function makeUtterance(str, rate) {
 | 
				
			||||||
    let msg = new SpeechSynthesisUtterance(str);
 | 
					    let msg = new SpeechSynthesisUtterance(str);
 | 
				
			||||||
    msg.rate = rate;
 | 
					    msg.rate = rate;
 | 
				
			||||||
    msg.lang = "en-US"; // TODO: add language options menu
 | 
					    msg.lang = "en-US"; // TODO: add language options menu
 | 
				
			||||||
    msg.onboundary = ev => {
 | 
					    msg.onboundary = function(ev) {
 | 
				
			||||||
        if (ev.name == "word") {
 | 
					        if (ev.name === "word") {
 | 
				
			||||||
            current_position = ev.charIndex;
 | 
					            current_position = ev.charIndex;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
    return msg;
 | 
					    return msg;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const sliderValue = document.getElementById("rangeValue"); // 显示值
 | 
					const sliderValue = document.getElementById("rangeValue"); // 显示值
 | 
				
			||||||
const inputSlider = document.getElementById("rangeComponent"); // 滑块元素
 | 
					const inputSlider = document.getElementById("rangeComponent"); // 滑块元素
 | 
				
			||||||
inputSlider.oninput = () => {
 | 
					inputSlider.oninput = function(){
 | 
				
			||||||
    let value = inputSlider.value; // 获取滑块的值
 | 
					    let value = inputSlider.value; // 获取滑块的值
 | 
				
			||||||
    sliderValue.textContent = value + '×';
 | 
					    sliderValue.textContent = value + "×";
 | 
				
			||||||
    if (!reader.speaking) return;
 | 
					    if (!reader.speaking) {return;}
 | 
				
			||||||
    reader.cancel();
 | 
					    reader.cancel();
 | 
				
			||||||
    let msg = makeUtterance(to_speak.substring(original_position + current_position), value);
 | 
					    let msg = makeUtterance(
 | 
				
			||||||
 | 
					        to_speak.substring(original_position + current_position),
 | 
				
			||||||
 | 
					        value
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
    original_position = original_position + current_position;
 | 
					    original_position = original_position + current_position;
 | 
				
			||||||
    current_position = 0;
 | 
					    current_position = 0;
 | 
				
			||||||
    reader.speak(msg);
 | 
					    reader.speak(msg);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,44 +2,60 @@ let isHighlight = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function cancelBtnHandler() {
 | 
					function cancelBtnHandler() {
 | 
				
			||||||
    cancelHighlighting();
 | 
					    cancelHighlighting();
 | 
				
			||||||
    document.getElementById("text-content").removeEventListener("click", fillInWord, false);
 | 
					    document
 | 
				
			||||||
    document.getElementById("text-content").removeEventListener("touchstart", fillInWord, false);
 | 
					        .getElementById("text-content")
 | 
				
			||||||
    document.getElementById("text-content").addEventListener("click", fillInWord2, false);
 | 
					        .removeEventListener("click", fillInWord, false);
 | 
				
			||||||
    document.getElementById("text-content").addEventListener("touchstart", fillInWord2, false);
 | 
					    document.getElementById("text-content")
 | 
				
			||||||
 | 
					        .removeEventListener("touchstart", fillInWord, false);
 | 
				
			||||||
 | 
					    document.getElementById("text-content")
 | 
				
			||||||
 | 
					        .addEventListener("click", fillInWord2, false);
 | 
				
			||||||
 | 
					    document.getElementById("text-content")
 | 
				
			||||||
 | 
					        .addEventListener("touchstart", fillInWord2, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function showBtnHandler() {
 | 
					function showBtnHandler() {
 | 
				
			||||||
    document.getElementById("text-content").removeEventListener("click", fillInWord2, false);
 | 
					    document.getElementById("text-content")
 | 
				
			||||||
    document.getElementById("text-content").removeEventListener("touchstart", fillInWord2, false);
 | 
					        .removeEventListener("click", fillInWord2, false);
 | 
				
			||||||
    document.getElementById("text-content").addEventListener("click", fillInWord, false);
 | 
					    document.getElementById("text-content")
 | 
				
			||||||
    document.getElementById("text-content").addEventListener("touchstart", fillInWord, false);
 | 
					        .removeEventListener("touchstart", fillInWord2, false);
 | 
				
			||||||
 | 
					    document.getElementById("text-content")
 | 
				
			||||||
 | 
					        .addEventListener("click", fillInWord, false);
 | 
				
			||||||
 | 
					    document.getElementById("text-content")
 | 
				
			||||||
 | 
					        .addEventListener("touchstart", fillInWord, false);
 | 
				
			||||||
    highLight();
 | 
					    highLight();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getWord() {
 | 
					function getWord() {
 | 
				
			||||||
    return window.getSelection ? window.getSelection() : document.selection.createRange().text;
 | 
					    return (window.getSelection ?
 | 
				
			||||||
 | 
					            window.getSelection() :
 | 
				
			||||||
 | 
					            document.selection.createRange().text);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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; //将原来的.innerText改为.innerHtml,使用innerText会把原文章中所包含的<br>标签去除,导致处理后的文章内容失去了原来的格式
 | 
				
			||||||
    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 = "";  //初始化allWords的值,避免进入判断后编译器认为allWords未初始化的问题
 | 
				
			||||||
    if(dictionaryWords != null){//增加一个判断,检查生词本里面是否为空,如果为空,allWords只添加选中的单词
 | 
					    if(dictionaryWords !== null){//增加一个判断,检查生词本里面是否为空,如果为空,allWords只添加选中的单词
 | 
				
			||||||
        allWords = pickedWords.value + " " + dictionaryWords.value;
 | 
					        allWords = pickedWords.value + " " + dictionaryWords.value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else{
 | 
					    else{
 | 
				
			||||||
        allWords = pickedWords.value + " ";
 | 
					        allWords = pickedWords.value + " ";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const list = allWords.split(" ");//将所有的生词放入一个list中,用于后续处理
 | 
					    const list = allWords.split(" ");//将所有的生词放入一个list中,用于后续处理
 | 
				
			||||||
    for (let i = 0; i < list.length; ++i) {
 | 
					    for (let i = 0; i < list.length; i+=1) {
 | 
				
			||||||
        list[i] = list[i].replace(/(^\s*)|(\s*$)/g, ""); //消除单词两边的空字符
 | 
					        list[i] = list[i].replace(/(^\s*)|(\s*$)/gm, ""); //消除单词两边的空字符
 | 
				
			||||||
        list[i] = list[i].replace('|', "");
 | 
					        list[i] = list[i].replace("|", "");
 | 
				
			||||||
        list[i] = list[i].replace('?', "");
 | 
					        list[i] = list[i].replace("?", "");
 | 
				
			||||||
        if (list[i] !== "" && "<mark>".indexOf(list[i]) === -1 && "</mark>".indexOf(list[i]) === -1) {
 | 
					        if (list[i] !== "" &&
 | 
				
			||||||
 | 
					            "<mark>".indexOf(list[i]) === -1 &&
 | 
				
			||||||
 | 
					            "</mark>".indexOf(list[i]) === -1
 | 
				
			||||||
 | 
					           ) {
 | 
				
			||||||
        //将文章中所有出现该单词word的地方改为:" <mark>" + word + "<mark> "。 正则表达式RegExp()中,"\\s"代表单词前后必须要有空格,以防止只对单词中的部分字符高亮的情况出现。
 | 
					        //将文章中所有出现该单词word的地方改为:" <mark>" + word + "<mark> "。 正则表达式RegExp()中,"\\s"代表单词前后必须要有空格,以防止只对单词中的部分字符高亮的情况出现。
 | 
				
			||||||
            articleContent = articleContent.replace(new RegExp("\\s"+list[i]+"\\s", "g"), " <mark>" + list[i] + "</mark> ");
 | 
					            articleContent = articleContent.replace(
 | 
				
			||||||
 | 
					                new RegExp("\\s"+list[i]+"\\s", "g"),
 | 
				
			||||||
 | 
					                " <mark>" + list[i] + "</mark> ");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    document.getElementById("article").innerHTML = articleContent;
 | 
					    document.getElementById("article").innerHTML = articleContent;
 | 
				
			||||||
| 
						 | 
					@ -50,21 +66,27 @@ function cancelHighlighting() {
 | 
				
			||||||
    let pickedWords = document.getElementById("selected-words");
 | 
					    let pickedWords = document.getElementById("selected-words");
 | 
				
			||||||
    const dictionaryWords = document.getElementById("selected-words2");
 | 
					    const dictionaryWords = document.getElementById("selected-words2");
 | 
				
			||||||
    const list = pickedWords.value.split(" ");
 | 
					    const list = pickedWords.value.split(" ");
 | 
				
			||||||
    if (pickedWords != null) {
 | 
					    if (pickedWords !== null) {
 | 
				
			||||||
        for (let i = 0; i < list.length; ++i) {
 | 
					        for (let i = 0; i < list.length; i+=1) {
 | 
				
			||||||
            list[i] = list[i].replace(/(^\s*)|(\s*$)/g, "");
 | 
					            list[i] = list[i].replace(/(^\s*)|(\s*$)/gm, "");
 | 
				
			||||||
            if (list[i] !== "") { //原来判断的代码中,替换的内容为“list[i]”这个字符串,这明显是错误的,我们需要替换的是list[i]里的内容
 | 
					            if (list[i] !== "") { //原来判断的代码中,替换的内容为“list[i]”这个字符串,这明显是错误的,我们需要替换的是list[i]里的内容
 | 
				
			||||||
                articleContent = articleContent.replace(new RegExp("<mark>"+list[i]+"</mark>", "g"), list[i]);
 | 
					                articleContent = articleContent.replace(
 | 
				
			||||||
 | 
					                    new RegExp("<mark>"+list[i]+"</mark>", "g"),
 | 
				
			||||||
 | 
					                    list[i]
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (dictionaryWords != null) {
 | 
					    if (dictionaryWords !== null) {
 | 
				
			||||||
        let list2 = pickedWords.value.split(" ");
 | 
					        let list2 = pickedWords.value.split(" ");
 | 
				
			||||||
        for (let i = 0; i < list2.length; ++i) {
 | 
					        for (let i = 0; i < list2.length; i+=1) {
 | 
				
			||||||
            list2 = dictionaryWords.value.split(" ");
 | 
					            list2 = dictionaryWords.value.split(" ");
 | 
				
			||||||
            list2[i] = list2[i].replace(/(^\s*)|(\s*$)/g, "");
 | 
					            list2[i] = list2[i].replace(/(^\s*)|(\s*$)/gm, "");
 | 
				
			||||||
            if (list2[i] !== "") { //原来代码中,替换的内容为“list[i]”这个字符串,这明显是错误的,我们需要替换的是list[i]里的内容
 | 
					            if (list2[i] !== "") { //原来代码中,替换的内容为“list[i]”这个字符串,这明显是错误的,我们需要替换的是list[i]里的内容
 | 
				
			||||||
                articleContent = articleContent.replace(new RegExp("<mark>"+list2[i]+"</mark>", "g"), list2[i]);
 | 
					                articleContent = articleContent.replace(
 | 
				
			||||||
 | 
					                    new RegExp("<mark>"+list2[i]+"</mark>", "g"),
 | 
				
			||||||
 | 
					                    list2[i]
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,17 +3,17 @@ function familiar(theWord) {
 | 
				
			||||||
    let word = $("#word_" + theWord).text();
 | 
					    let word = $("#word_" + theWord).text();
 | 
				
			||||||
    let freq = $("#freq_" + theWord).text();
 | 
					    let freq = $("#freq_" + theWord).text();
 | 
				
			||||||
    $.ajax({
 | 
					    $.ajax({
 | 
				
			||||||
        type:"GET",
 | 
					 | 
				
			||||||
        url:"/" + username + "/" + word + "/familiar",
 | 
					 | 
				
			||||||
        success:function(response){
 | 
					        success:function(response){
 | 
				
			||||||
            let new_freq = freq - 1;
 | 
					            let new_freq = freq - 1;
 | 
				
			||||||
            const allow_move = document.getElementById("move_dynamiclly").checked;
 | 
					            const allow_move = document
 | 
				
			||||||
 | 
					                .getElementById("move_dynamiclly")
 | 
				
			||||||
 | 
					                .checked;
 | 
				
			||||||
            if (allow_move) {
 | 
					            if (allow_move) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (new_freq <= 0) {
 | 
					                if (new_freq <= 0) {
 | 
				
			||||||
                    removeWord(theWord);
 | 
					                    removeWord(theWord);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    renderWord({ word: theWord, freq: new_freq });
 | 
					                    renderWord({ freq: new_freq,word: theWord });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                if(new_freq <1) {
 | 
					                if(new_freq <1) {
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,9 @@ function familiar(theWord) {
 | 
				
			||||||
                    $("#freq_" + theWord).text(new_freq);
 | 
					                    $("#freq_" + theWord).text(new_freq);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        },
 | 
				
			||||||
 | 
					        type:"GET",
 | 
				
			||||||
 | 
					        url:"/" + username + "/" + word + "/familiar"
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,34 +33,38 @@ function unfamiliar(theWord) {
 | 
				
			||||||
    let word = $("#word_" + theWord).text();
 | 
					    let word = $("#word_" + theWord).text();
 | 
				
			||||||
    let freq = $("#freq_" + theWord).text();
 | 
					    let freq = $("#freq_" + theWord).text();
 | 
				
			||||||
    $.ajax({
 | 
					    $.ajax({
 | 
				
			||||||
        type:"GET",
 | 
					 | 
				
			||||||
        url:"/" + username + "/" + word + "/unfamiliar",
 | 
					 | 
				
			||||||
        success:function(response){
 | 
					        success:function(response){
 | 
				
			||||||
            let new_freq = parseInt(freq) + 1;
 | 
					            let new_freq = parseInt(freq) + 1;
 | 
				
			||||||
            const allow_move = document.getElementById("move_dynamiclly").checked;
 | 
					            const allow_move = document
 | 
				
			||||||
 | 
					                .getElementById("move_dynamiclly")
 | 
				
			||||||
 | 
					                .checked;
 | 
				
			||||||
            if (allow_move) {
 | 
					            if (allow_move) {
 | 
				
			||||||
                renderWord({ word: theWord, freq: new_freq });
 | 
					                renderWord({ freq: new_freq,word: theWord  });
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $("#freq_" + theWord).text(new_freq);
 | 
					                $("#freq_" + theWord).text(new_freq);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        },
 | 
				
			||||||
 | 
					        type:"GET",
 | 
				
			||||||
 | 
					        url:"/" + username + "/" + word + "/unfamiliar"
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function delete_word(theWord) {
 | 
					function delete_word(theWord) {
 | 
				
			||||||
    let username = $("#username").text();
 | 
					    let username = $("#username").text();
 | 
				
			||||||
    let word = theWord.replace('&', '&');
 | 
					    let word = theWord.replace("&", "&");
 | 
				
			||||||
    $.ajax({
 | 
					    $.ajax({
 | 
				
			||||||
        type:"GET",
 | 
					 | 
				
			||||||
        url:"/" + username + "/" + word + "/del",
 | 
					 | 
				
			||||||
        success:function(response){
 | 
					        success:function(response){
 | 
				
			||||||
            const allow_move = document.getElementById("move_dynamiclly").checked;
 | 
					            const allow_move = document
 | 
				
			||||||
 | 
					                .getElementById("move_dynamiclly")
 | 
				
			||||||
 | 
					                .checked;
 | 
				
			||||||
            if (allow_move) {
 | 
					            if (allow_move) {
 | 
				
			||||||
                removeWord(theWord);
 | 
					                removeWord(theWord);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $("#p_" + theWord).remove();
 | 
					                $("#p_" + theWord).remove();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        },
 | 
				
			||||||
 | 
					        type:"GET",
 | 
				
			||||||
 | 
					        url:"/" + username + "/" + word + "/del"
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,11 +81,12 @@ function delete_word(theWord) {
 | 
				
			||||||
function parseWord(element) {
 | 
					function parseWord(element) {
 | 
				
			||||||
    const word = element
 | 
					    const word = element
 | 
				
			||||||
        .querySelector("a.btn.btn-light[role=button]")  // 获取当前词频元素的词汇元素
 | 
					        .querySelector("a.btn.btn-light[role=button]")  // 获取当前词频元素的词汇元素
 | 
				
			||||||
        .innerText  // 获取词汇值;
 | 
					        .innerText; // 获取词汇值;
 | 
				
			||||||
    const freq = Number.parseInt(element.querySelector(`#freq_${word}`).innerText);   // 获取词汇的数量
 | 
					    const freq = Number// 获取词汇的数量
 | 
				
			||||||
 | 
					        .parseInt(element.querySelector(`#freq_${word}`).innerText);
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
        word,
 | 
					        freq,
 | 
				
			||||||
        freq
 | 
					        word
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,7 +111,7 @@ function wordTemplate(word) {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function removeWord(word) {
 | 
					function removeWord(word) {
 | 
				
			||||||
    // 根据词频信息删除元素
 | 
					    // 根据词频信息删除元素
 | 
				
			||||||
    word = word.replace('&', '&');
 | 
					    word = word.replace("&", "&");
 | 
				
			||||||
    const element_to_remove = document.getElementById(`p_${word}`);
 | 
					    const element_to_remove = document.getElementById(`p_${word}`);
 | 
				
			||||||
    if (element_to_remove != null) {
 | 
					    if (element_to_remove != null) {
 | 
				
			||||||
        element_to_remove.remove();
 | 
					        element_to_remove.remove();
 | 
				
			||||||
| 
						 | 
					@ -134,7 +141,11 @@ function renderWord(word) {
 | 
				
			||||||
    // 让发生变化的元素抖动
 | 
					    // 让发生变化的元素抖动
 | 
				
			||||||
    new_element.classList.add("shaking");
 | 
					    new_element.classList.add("shaking");
 | 
				
			||||||
    // 移动到该元素
 | 
					    // 移动到该元素
 | 
				
			||||||
    new_element.scrollIntoView({behavior: "smooth", block: "center", inline: "nearest"});
 | 
					    new_element.scrollIntoView({
 | 
				
			||||||
 | 
					        behavior: "smooth",
 | 
				
			||||||
 | 
					        block: "center",
 | 
				
			||||||
 | 
					        inline: "nearest"
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
    // 抖动完毕后删除抖动类
 | 
					    // 抖动完毕后删除抖动类
 | 
				
			||||||
    setTimeout(() => {
 | 
					    setTimeout(() => {
 | 
				
			||||||
        new_element.classList.remove("shaking");
 | 
					        new_element.classList.remove("shaking");
 | 
				
			||||||
| 
						 | 
					@ -145,7 +156,7 @@ function renderWord(word) {
 | 
				
			||||||
 * 从string中创建一个HTML元素并返回
 | 
					 * 从string中创建一个HTML元素并返回
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function elementFromString(string) {
 | 
					function elementFromString(string) {
 | 
				
			||||||
    const d = document.createElement('div');
 | 
					    const d = document.createElement("div");
 | 
				
			||||||
    d.innerHTML = string;
 | 
					    d.innerHTML = string;
 | 
				
			||||||
    return d.children.item(0);
 | 
					    return d.children.item(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					This module provides methods for user_services
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					 | 
				
			||||||
from flask import *
 | 
					from flask import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# from app import Yaml
 | 
					# from app import Yaml
 | 
				
			||||||
| 
						 | 
					@ -36,6 +38,7 @@ def user_reset(username):
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        return 'Under construction'
 | 
					        return 'Under construction'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@userService.route("/<username>/back", methods=['GET'])
 | 
					@userService.route("/<username>/back", methods=['GET'])
 | 
				
			||||||
def user_back(username):
 | 
					def user_back(username):
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
| 
						 | 
					@ -48,7 +51,6 @@ def user_back(username):
 | 
				
			||||||
        return redirect(url_for('user_bp.userpage', username=username))
 | 
					        return redirect(url_for('user_bp.userpage', username=username))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
@userService.route("/<username>/<word>/unfamiliar", methods=['GET', 'POST'])
 | 
					@userService.route("/<username>/<word>/unfamiliar", methods=['GET', 'POST'])
 | 
				
			||||||
def unfamiliar(username, word):
 | 
					def unfamiliar(username, word):
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
| 
						 | 
					@ -141,9 +143,6 @@ def userpage(username):
 | 
				
			||||||
                               words=words)
 | 
					                               words=words)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@userService.route("/<username>/mark", methods=['GET', 'POST'])
 | 
					@userService.route("/<username>/mark", methods=['GET', 'POST'])
 | 
				
			||||||
def user_mark_word(username):
 | 
					def user_mark_word(username):
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,13 +2,16 @@
 | 
				
			||||||
# 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.
 | 
				
			||||||
###########################################################################
 | 
					###########################################################################
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					This Module produces word frequency
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
import collections
 | 
					import collections
 | 
				
			||||||
import string
 | 
					import string
 | 
				
			||||||
import operator
 | 
					import operator
 | 
				
			||||||
import os, sys  # 引入模块sys,因为我要用里面的sys.argv列表中的信息来读取命令行参数。
 | 
					import os, sys  # 引入模块sys,因为我要用里面的sys.argv列表中的信息来读取命令行参数。
 | 
				
			||||||
import pickle_idea
 | 
					import pickle_idea
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def freq(fruit):
 | 
					def freq(fruit):
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
    功能: 把字符串转成列表。 目的是得到每个单词的频率。
 | 
					    功能: 把字符串转成列表。 目的是得到每个单词的频率。
 | 
				
			||||||
| 
						 | 
					@ -18,7 +21,6 @@ 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)
 | 
				
			||||||
| 
						 | 
					@ -85,10 +87,9 @@ def make_html_page(lst, fname):
 | 
				
			||||||
    f.close()
 | 
					    f.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## main(程序入口)
 | 
					# main(程序入口)
 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    num = len(sys.argv)
 | 
					    num = len(sys.argv)
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if num == 1:  # 从键盘读入字符串
 | 
					    if num == 1:  # 从键盘读入字符串
 | 
				
			||||||
        s = input()
 | 
					        s = input()
 | 
				
			||||||
    elif num == 2:  # 从文件读入字符串
 | 
					    elif num == 2:  # 从文件读入字符串
 | 
				
			||||||
| 
						 | 
					@ -97,27 +98,19 @@ if __name__ == '__main__':
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        print('I can accept at most 2 arguments.')
 | 
					        print('I can accept at most 2 arguments.')
 | 
				
			||||||
        sys.exit()  # 结束程序运行, 下面的代码不会被执行了。
 | 
					        sys.exit()  # 结束程序运行, 下面的代码不会被执行了。
 | 
				
			||||||
 | 
					 | 
				
			||||||
    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('%s\t%d\t%s' % (x[0], x[1], 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'):
 | 
				
			||||||
        d = pickle_idea.load_record('frequency.p')
 | 
					        d = pickle_idea.load_record('frequency.p')
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        d = {}
 | 
					        d = {}
 | 
				
			||||||
 | 
					 | 
				
			||||||
    print(sort_in_descending_order(pickle_idea.dict2lst(d)))
 | 
					    print(sort_in_descending_order(pickle_idea.dict2lst(d)))
 | 
				
			||||||
 | 
					 | 
				
			||||||
    # 合并频率
 | 
					    # 合并频率
 | 
				
			||||||
    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