From 8924166975aeb7517efc14e1aed5b1af1aeb8bba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A6=83=E8=89=B3=E7=BE=8E?= <3183597872@qq.com> Date: Sun, 12 Jun 2022 21:23:34 +0800 Subject: [PATCH 01/88] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=87=B3=20'static\js'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "static\\js/fillword.js" | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 "static\\js/fillword.js" diff --git "a/static\\js/fillword.js" "b/static\\js/fillword.js" new file mode 100644 index 0000000..9843331 --- /dev/null +++ "b/static\\js/fillword.js" @@ -0,0 +1,32 @@ +isRead = true; +isChoose = true; +var reader = window.speechSynthesis; // 全局定义朗读者,以便朗读和暂停 +reader.cancel();// 初始化时清空reader列表 +function getWord(){ + var word = window.getSelection?window.getSelection():document.selection.createRange().text; + return word; +} +function fillinWord(){ + var word = getWord(); + if (isRead) read(word); + if (!isChoose) return; + var element = document.getElementById("selected-words"); + element.value = element.value + " " + word; +} +document.getElementById("text-content").addEventListener("click", fillinWord, false); +function read(s){ + var msg = new SpeechSynthesisUtterance(s); + reader.speak(msg); + console.log("+++++++++++++"); +} + +function onReadClick(){ + isRead = !isRead; + if(!isRead){ + reader.cancel(); + } +} +function onChooseClick(){ + isChoose = !isChoose; +} + From 320a99d4793e03c40cd9f4d8267264ab67bb5ede Mon Sep 17 00:00:00 2001 From: Hui Lan Date: Mon, 24 Apr 2023 11:38:16 +0800 Subject: [PATCH 02/88] Move Tan Yanmei's fillword.js to app/static/js/tanyanmei-fillword.js. Delete the strange folder static js. --- app/static/js/tanyanmei-fillword.js | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 app/static/js/tanyanmei-fillword.js diff --git a/app/static/js/tanyanmei-fillword.js b/app/static/js/tanyanmei-fillword.js new file mode 100644 index 0000000..49a8bc2 --- /dev/null +++ b/app/static/js/tanyanmei-fillword.js @@ -0,0 +1,33 @@ +isRead = true; +isChoose = true; +var reader = window.speechSynthesis; // 全局定义朗读者,以便朗读和暂停 +reader.cancel();// 初始化时清空reader列表 +function getWord(){ + var word = window.getSelection?window.getSelection():document.selection.createRange().text; + return word; +} +function fillinWord(){ + var word = getWord(); + if (isRead) read(word); + if (!isChoose) return; + var element = document.getElementById("selected-words"); + element.value = element.value + " " + word; +} +document.getElementById("text-content").addEventListener("click", fillinWord, false); +function read(s){ + var msg = new SpeechSynthesisUtterance(s); + reader.speak(msg); + console.log("+++++++++++++"); +} + +function onReadClick(){ + isRead = !isRead; + if(!isRead){ + reader.cancel(); + } +} +function onChooseClick(){ + isChoose = !isChoose; +} + +∑∑ From e9e2bd3d2353b64e05724327210849f1fcf363fc Mon Sep 17 00:00:00 2001 From: Hui Lan Date: Mon, 24 Apr 2023 11:43:43 +0800 Subject: [PATCH 03/88] Remove static\js --- "static\\js/fillword.js" | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 "static\\js/fillword.js" diff --git "a/static\\js/fillword.js" "b/static\\js/fillword.js" deleted file mode 100644 index 9843331..0000000 --- "a/static\\js/fillword.js" +++ /dev/null @@ -1,32 +0,0 @@ -isRead = true; -isChoose = true; -var reader = window.speechSynthesis; // 全局定义朗读者,以便朗读和暂停 -reader.cancel();// 初始化时清空reader列表 -function getWord(){ - var word = window.getSelection?window.getSelection():document.selection.createRange().text; - return word; -} -function fillinWord(){ - var word = getWord(); - if (isRead) read(word); - if (!isChoose) return; - var element = document.getElementById("selected-words"); - element.value = element.value + " " + word; -} -document.getElementById("text-content").addEventListener("click", fillinWord, false); -function read(s){ - var msg = new SpeechSynthesisUtterance(s); - reader.speak(msg); - console.log("+++++++++++++"); -} - -function onReadClick(){ - isRead = !isRead; - if(!isRead){ - reader.cancel(); - } -} -function onChooseClick(){ - isChoose = !isChoose; -} - From ce28b91bd5c3aef42d38f09ffffbd2080d56b503 Mon Sep 17 00:00:00 2001 From: Ni Lingli <1195621865@qq.com> Date: Sat, 6 May 2023 18:18:12 +0800 Subject: [PATCH 04/88] =?UTF-8?q?=E5=B1=8F=E5=B9=95=E5=88=B7=E6=96=B0?= =?UTF-8?q?=EF=BC=8C=E5=81=9C=E6=AD=A2=E9=98=85=E8=AF=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/static/js/fillword.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/static/js/fillword.js b/app/static/js/fillword.js index ba249dd..abaac2f 100644 --- a/app/static/js/fillword.js +++ b/app/static/js/fillword.js @@ -65,4 +65,7 @@ function onChooseClick() { function stopRead() { reader.cancel(); -} \ No newline at end of file +} +if (performance.navigation.type == 1) { //如果网页刷新,停止播放声音 + stopRead() + } \ No newline at end of file From df64065dcc64fd14c1e4ab36946d735cb08a0212 Mon Sep 17 00:00:00 2001 From: Ni Lingli <1195621865@qq.com> Date: Sat, 6 May 2023 18:19:24 +0800 Subject: [PATCH 05/88] =?UTF-8?q?=E7=82=B9=E5=87=BB=E4=B8=8A=E4=B8=8B?= =?UTF-8?q?=E7=AF=87=EF=BC=8C=E5=81=9C=E6=AD=A2=E9=98=85=E8=AF=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/templates/userpage_get.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html index b5e16aa..40fa75e 100644 --- a/app/templates/userpage_get.html +++ b/app/templates/userpage_get.html @@ -47,9 +47,9 @@ {# #} {# {% endfor %}#} - 下一篇 Next Article + 下一篇 Next Article {% if session.get('existing_articles') != None and session.get('existing_articles')["index"] !=0 %} - 上一篇 Previous Article + 上一篇 Previous Article {% endif %}

阅读文章并回答问题

From a0ddf4bdadb1b9e045314231c42875cdc9ac2cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=AD=90=E7=9D=BF?= <1342954478@qq.com> Date: Sat, 27 May 2023 17:33:37 +0800 Subject: [PATCH 06/88] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=87=B3=20'app/static/js'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复了 Bug492 选中问号出现多个问号的问题。 解决了选中紧跟标点符号的单词,单词能正常显示。 优化了选中较长的文章时页面容易出现卡顿的问题。 --- app/static/js/highlight.js | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/app/static/js/highlight.js b/app/static/js/highlight.js index 0cea31a..927f698 100644 --- a/app/static/js/highlight.js +++ b/app/static/js/highlight.js @@ -22,33 +22,19 @@ function getWord() { function highLight() { if (!isHighlight) return; - let articleContent = document.getElementById("article").innerText; //将原来的.innerText改为.innerHtml,使用innerText会把原文章中所包含的
标签去除,导致处理后的文章内容失去了原来的格式 + let articleContent = document.getElementById("article").innerText; 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 allWords = ""; //初始化allWords的值,避免进入判断后编译器认为allWords未初始化的问题 - if(dictionaryWords != null){//增加一个判断,检查生词本里面是否为空,如果为空,allWords只添加选中的单词 - allWords = pickedWords.value + " " + dictionaryWords.value; - } - else{ - allWords = pickedWords.value + " "; - } - const list = allWords.split(" ");//将所有的生词放入一个list中,用于后续处理 + let allWords = dictionaryWords === null ? pickedWords.value + " " : pickedWords.value + " " + dictionaryWords.value; + const list = allWords.split(" "); // 将所有的生词放入一个list中,用于后续处理 for (let i = 0; i < list.length; ++i) { - list[i] = list[i].replace(/(^\s*)|(\s*$)/g, ""); //消除单词两边的空字符 - list[i] = list[i].replace('|', ""); - list[i] = list[i].replace('?', ""); - if (list[i] !== "" && "".indexOf(list[i]) === -1 && "".indexOf(list[i]) === -1) { - //将文章中所有出现该单词word的地方改为:"" + word + ""。 正则表达式RegExp()中,"\\b"代表单词边界匹配。 - - //修改代码 - 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"),"" + list[i] + ""); + list[i] = list[i].replace(/(^\W*)|(\W*$)/g, ""); // 消除单词两边的非单词字符 + if (list[i] != "" && "".indexOf(list[i]) === -1 && "".indexOf(list[i]) === -1) { + // 返回所有匹配单词的集合, 正则表达式RegExp()中, "\b"匹配一个单词的边界, g 表示全局匹配, i 表示对大小写不敏感。 + let matches = new Set(articleContent.match(new RegExp("\\b" + list[i] + "\\b", "gi"))); + for (let word of matches) { + // 将文章中所有出现该单词word的地方改为:"" + word + ""。 + articleContent = articleContent.replace(new RegExp("\\b" + word + "\\b", "g"), "" + word + ""); } } } From cdf6180901b9f1f47005956eef70dea858b3c20e Mon Sep 17 00:00:00 2001 From: Ni Lingli <1195621865@qq.com> Date: Tue, 30 May 2023 18:48:37 +0800 Subject: [PATCH 07/88] =?UTF-8?q?=E5=88=B7=E6=96=B0=E5=B1=8F=E5=B9=95?= =?UTF-8?q?=EF=BC=8C=E7=82=B9=E5=87=BB=E4=B8=8A=E4=B8=8B=E7=AF=87=EF=BC=8C?= =?UTF-8?q?=E5=8A=A0=E5=85=A5=E7=94=9F=E8=AF=8D=E5=BA=93=EF=BC=8C=E5=81=9C?= =?UTF-8?q?=E6=AD=A2=E9=98=85=E8=AF=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/static/js/fillword.js | 3 +++ app/templates/userpage_get.html | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/static/js/fillword.js b/app/static/js/fillword.js index b967633..57521a7 100644 --- a/app/static/js/fillword.js +++ b/app/static/js/fillword.js @@ -29,3 +29,6 @@ function onReadClick() { function onChooseClick() { isChoose = !isChoose; } +if (performance.navigation.type == 1) { //如果网页刷新,停止播放声音 + stopRead() +} \ No newline at end of file diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html index 68997ef..e503f0b 100644 --- a/app/templates/userpage_get.html +++ b/app/templates/userpage_get.html @@ -49,8 +49,8 @@ {# #} {# {% endfor %}#} - - + +

阅读文章并回答问题

@@ -97,7 +97,7 @@

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


- +
{% if session.get['thisWord'] %} From d402bb45cb287da169439410242e1f773e861b3a Mon Sep 17 00:00:00 2001 From: Ni Lingli <1195621865@qq.com> Date: Wed, 31 May 2023 18:37:05 +0800 Subject: [PATCH 08/88] =?UTF-8?q?=E5=88=B7=E6=96=B0=E5=B1=8F=E5=B9=95?= =?UTF-8?q?=EF=BC=8C=E7=82=B9=E5=87=BB=E4=B8=8A=E4=B8=8B=E7=AF=87=EF=BC=8C?= =?UTF-8?q?=E5=8A=A0=E5=85=A5=E7=94=9F=E8=AF=8D=E5=BA=93=EF=BC=8C=E5=81=9C?= =?UTF-8?q?=E6=AD=A2=E9=98=85=E8=AF=BB(=E6=9B=B4=E6=94=B9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/static/js/fillword.js | 3 ++- app/templates/userpage_get.html | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/static/js/fillword.js b/app/static/js/fillword.js index 57521a7..317373c 100644 --- a/app/static/js/fillword.js +++ b/app/static/js/fillword.js @@ -29,6 +29,7 @@ function onReadClick() { function onChooseClick() { isChoose = !isChoose; } + if (performance.navigation.type == 1) { //如果网页刷新,停止播放声音 - stopRead() + Reader.stopRead(); } \ No newline at end of file diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html index e503f0b..f7ba8da 100644 --- a/app/templates/userpage_get.html +++ b/app/templates/userpage_get.html @@ -49,8 +49,8 @@ {# #} {# {% endfor %}#} - - + +

阅读文章并回答问题

@@ -97,7 +97,7 @@

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


- +
{% if session.get['thisWord'] %} From 682247bff16f94e6572df1e2be5a64120596a3c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=AD=90=E7=9D=BF?= <1342954478@qq.com> Date: Fri, 2 Jun 2023 21:33:21 +0800 Subject: [PATCH 09/88] refactor partial function and code writing specifications --- app/static/js/fillword.js | 3 ++- app/static/js/highlight.js | 48 +++++++++++++-------------------- app/static/js/read.js | 4 +-- app/static/js/word_operation.js | 31 +++++++++------------ 4 files changed, 35 insertions(+), 51 deletions(-) diff --git a/app/static/js/fillword.js b/app/static/js/fillword.js index 317373c..b3a8b42 100644 --- a/app/static/js/fillword.js +++ b/app/static/js/fillword.js @@ -30,6 +30,7 @@ function onChooseClick() { isChoose = !isChoose; } -if (performance.navigation.type == 1) { //如果网页刷新,停止播放声音 +// 如果网页刷新,停止播放声音 +if (performance.getEntriesByType("navigation")[0].type == "reload") { Reader.stopRead(); } \ No newline at end of file diff --git a/app/static/js/highlight.js b/app/static/js/highlight.js index 927f698..76b4793 100644 --- a/app/static/js/highlight.js +++ b/app/static/js/highlight.js @@ -22,48 +22,38 @@ function getWord() { function highLight() { if (!isHighlight) return; - let articleContent = document.getElementById("article").innerText; + let articleContent = document.getElementById("article").innerHTML; // innerHTML保留HTML标签来保持部分格式,且适配不同的浏览器 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 allWords = dictionaryWords === null ? pickedWords.value + " " : pickedWords.value + " " + dictionaryWords.value; - const list = allWords.split(" "); // 将所有的生词放入一个list中,用于后续处理 + const list = allWords.split(" "); // 将所有的生词放入一个list中 + let totalSet = new Set(); for (let i = 0; i < list.length; ++i) { list[i] = list[i].replace(/(^\W*)|(\W*$)/g, ""); // 消除单词两边的非单词字符 - if (list[i] != "" && "".indexOf(list[i]) === -1 && "".indexOf(list[i]) === -1) { + if (list[i] != "" && !totalSet.has(list[i])) { // 返回所有匹配单词的集合, 正则表达式RegExp()中, "\b"匹配一个单词的边界, g 表示全局匹配, i 表示对大小写不敏感。 let matches = new Set(articleContent.match(new RegExp("\\b" + list[i] + "\\b", "gi"))); - for (let word of matches) { - // 将文章中所有出现该单词word的地方改为:"" + word + ""。 - articleContent = articleContent.replace(new RegExp("\\b" + word + "\\b", "g"), "" + word + ""); + if (matches.has("mark")) { + // 优先处理单词为 "mark" 的情况 + totalSet = new Set(["mark", ...totalSet]); } + totalSet = new Set([...totalSet, ...matches]); } + } + // 删除所有的mark标签,防止标签发生嵌套 + articleContent = articleContent.replace(/<(mark)[^>]*>/gi, ""); + articleContent = articleContent.replace(/<(\/mark)[^>]*>/gi, ""); + // 将文章中所有出现该单词word的地方改为:"" + word + ""。 + for (let word of totalSet) { + articleContent = articleContent.replace(new RegExp("\\b" + word + "\\b", "g"), "" + word + ""); } document.getElementById("article").innerHTML = articleContent; } function cancelHighlighting() { - let articleContent = document.getElementById("article").innerText;//将原来的.innerText改为.innerHtml,原因同上 - let pickedWords = document.getElementById("selected-words"); - const dictionaryWords = document.getElementById("selected-words2"); - const list = pickedWords.value.split(" "); - if (pickedWords != null) { - for (let i = 0; i < list.length; ++i) { - list[i] = list[i].replace(/(^\s*)|(\s*$)/g, ""); - if (list[i] !== "") { //原来判断的代码中,替换的内容为“list[i]”这个字符串,这明显是错误的,我们需要替换的是list[i]里的内容 - articleContent = articleContent.replace(new RegExp(""+list[i]+"", "g"), list[i]); - } - } - } - if (dictionaryWords != null) { - let list2 = pickedWords.value.split(" "); - for (let i = 0; i < list2.length; ++i) { - list2 = dictionaryWords.value.split(" "); - list2[i] = list2[i].replace(/(^\s*)|(\s*$)/g, ""); - if (list2[i] !== "") { //原来代码中,替换的内容为“list[i]”这个字符串,这明显是错误的,我们需要替换的是list[i]里的内容 - articleContent = articleContent.replace(new RegExp(""+list2[i]+"", "g"), list2[i]); - } - } - } + let articleContent = document.getElementById("article").innerHTML; + articleContent = articleContent.replace(/<(mark)[^>]*>/gi, ""); + articleContent = articleContent.replace(/<(\/mark)[^>]*>/gi, ""); document.getElementById("article").innerHTML = articleContent; } @@ -85,4 +75,4 @@ function toggleHighlighting() { } } -showBtnHandler(); +showBtnHandler(); \ No newline at end of file diff --git a/app/static/js/read.js b/app/static/js/read.js index 814f627..c28fd26 100644 --- a/app/static/js/read.js +++ b/app/static/js/read.js @@ -9,7 +9,7 @@ var Reader = (function() { msg.rate = rate; msg.lang = "en-US"; msg.onboundary = ev => { - if (ev.name == "word") { + if (ev.name === "word") { current_position = ev.charIndex; } } @@ -32,4 +32,4 @@ var Reader = (function() { read: read, stopRead: stopRead }; -})(); +}) (); diff --git a/app/static/js/word_operation.js b/app/static/js/word_operation.js index f043cce..dcf38ff 100644 --- a/app/static/js/word_operation.js +++ b/app/static/js/word_operation.js @@ -5,15 +5,14 @@ function familiar(theWord) { $.ajax({ type:"GET", url:"/" + username + "/" + word + "/familiar", - success:function(response){ + success:function(response) { let new_freq = freq - 1; const allow_move = document.getElementById("move_dynamiclly").checked; if (allow_move) { - if (new_freq <= 0) { removeWord(theWord); } else { - renderWord({ word: theWord, freq: new_freq }); + renderWord({word: theWord, freq: new_freq}); } } else { if(new_freq <1) { @@ -33,11 +32,11 @@ function unfamiliar(theWord) { $.ajax({ type:"GET", url:"/" + username + "/" + word + "/unfamiliar", - success:function(response){ + success:function(response) { let new_freq = parseInt(freq) + 1; const allow_move = document.getElementById("move_dynamiclly").checked; if (allow_move) { - renderWord({ word: theWord, freq: new_freq }); + renderWord({word: theWord, freq: new_freq}); } else { $("#freq_" + theWord).text(new_freq); } @@ -51,7 +50,7 @@ function delete_word(theWord) { $.ajax({ type:"GET", url:"/" + username + "/" + word + "/del", - success:function(response){ + success:function(response) { const allow_move = document.getElementById("move_dynamiclly").checked; if (allow_move) { removeWord(theWord); @@ -114,7 +113,7 @@ function removeWord(word) { // 根据词频信息删除元素 word = word.replace('&', '&'); const element_to_remove = document.getElementById(`p_${word}`); - if (element_to_remove != null) { + if (element_to_remove !== null) { element_to_remove.remove(); } } @@ -129,7 +128,7 @@ function renderWord(word) { for (const current of container.children) { const cur_word = parseWord(current); // 找到第一个词频比它小的元素,插入到这个元素前面 - if (compareWord(cur_word, word) == -1) { + if (compareWord(cur_word, word) === -1) { container.insertBefore(new_element, current); inserted = true; break; @@ -165,17 +164,11 @@ function elementFromString(string) { * 当first大于second时返回1 */ function compareWord(first, second) { - if (first.freq < second.freq) { - return -1; + if (first.freq !== second.freq) { + return first.freq < second.freq ? -1 : 1; } - if (first.freq > second.freq) { - return 1; - } - if (first.word < second.word) { - return -1; - } - if (first.word > second.word) { - return 1; + if (first.word !== second.word) { + return first.word < second.word ? -1 : 1; } return 0; -} +} \ No newline at end of file From 9816596cf8942406bf7ae3e66dfdda3c31464da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=AD=90=E7=9D=BF?= <1342954478@qq.com> Date: Fri, 2 Jun 2023 21:34:27 +0800 Subject: [PATCH 10/88] =?UTF-8?q?=E5=88=A0=E9=99=A4=20'app/static/js/tanya?= =?UTF-8?q?nmei-fillword.js'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/static/js/tanyanmei-fillword.js | 33 ----------------------------- 1 file changed, 33 deletions(-) delete mode 100644 app/static/js/tanyanmei-fillword.js diff --git a/app/static/js/tanyanmei-fillword.js b/app/static/js/tanyanmei-fillword.js deleted file mode 100644 index 49a8bc2..0000000 --- a/app/static/js/tanyanmei-fillword.js +++ /dev/null @@ -1,33 +0,0 @@ -isRead = true; -isChoose = true; -var reader = window.speechSynthesis; // 全局定义朗读者,以便朗读和暂停 -reader.cancel();// 初始化时清空reader列表 -function getWord(){ - var word = window.getSelection?window.getSelection():document.selection.createRange().text; - return word; -} -function fillinWord(){ - var word = getWord(); - if (isRead) read(word); - if (!isChoose) return; - var element = document.getElementById("selected-words"); - element.value = element.value + " " + word; -} -document.getElementById("text-content").addEventListener("click", fillinWord, false); -function read(s){ - var msg = new SpeechSynthesisUtterance(s); - reader.speak(msg); - console.log("+++++++++++++"); -} - -function onReadClick(){ - isRead = !isRead; - if(!isRead){ - reader.cancel(); - } -} -function onChooseClick(){ - isChoose = !isChoose; -} - -∑∑ From bb2d0363e4a0416cbcfeb01a0ab65c9b4ee01138 Mon Sep 17 00:00:00 2001 From: Laugh <2636697181@qq.com> Date: Thu, 15 Jun 2023 15:54:46 +0800 Subject: [PATCH 11/88] Feat: update fontsize and margin of some elements --- app/templates/userpage_get.html | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html index 68997ef..ce1c5db 100644 --- a/app/templates/userpage_get.html +++ b/app/templates/userpage_get.html @@ -32,6 +32,17 @@ 40%, 60% { transform: translate3d(+4px, 0, 0); } 50% { transform: translate3d(-4px, 0, 0); } } + + .lead{ + font-size: 17px; + font-family: Arial, Helvetica, sans-serif; + } + + .display-5{ + font-size: 30px; + } + + @@ -49,18 +60,22 @@ {# #} {# {% endfor %}#} - - + +

阅读文章并回答问题

Article added on: {{ today_article["date"] }}


-

+

{{ today_article["article_title"] }}


-

{{ today_article["article_body"] }}


-

{{ today_article['source'] }}


+

{{ today_article["article_body"] }}


+
+
source:
+

{{ today_article['source'] }}


+
+

{{ today_article['question'] }}


{{ yml['footer'] | safe }} diff --git a/build.sh b/build.sh index c86c07b..158a86f 100755 --- a/build.sh +++ b/build.sh @@ -3,9 +3,6 @@ DEPLOYMENT_DIR=/home/lanhui/englishpal2/EnglishPal cd $DEPLOYMENT_DIR pwd -# Install dependencies - -#pip3 install -r requirements.txt # Stop service sudo docker stop EnglishPal @@ -15,7 +12,7 @@ sudo docker rm EnglishPal sudo docker build -t englishpal . # Run the application -sudo docker run --restart=always -d --name EnglishPal -p 90:80 -v ${DEPLOYMENT_DIR}/app/static/frequency:/app/static/frequency --mount type=volume,src=englishpal-db,target=/app -t englishpal # for permanently saving data +sudo docker run --restart=always -d --name EnglishPal -p 90:80 -v ${DEPLOYMENT_DIR}/app/static/frequency:/app/static/frequency --mount type=volume,src=englishpal-db,target=/app/db -t englishpal # for permanently saving data # Save space. Run it after sudo docker run sudo docker system prune -a -f From 25c2e0aca868eed6f7e5eb2376a3154ec60c2373 Mon Sep 17 00:00:00 2001 From: Hui Lan Date: Thu, 10 Aug 2023 14:24:00 +0800 Subject: [PATCH 35/88] README.md: update the path to wordfreqapp.db. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a1a22d4..77f25fa 100644 --- a/README.md +++ b/README.md @@ -61,15 +61,15 @@ My steps for deploying English on a Ubuntu server. All articles are stored in the `article` table in a SQLite file called -`app/wordfreqapp.db`. +`app/db/wordfreqapp.db`. ### Adding new articles -To add articles, open and edit `app/wordfreqapp.db` using DB Browser for SQLite (https://sqlitebrowser.org). +To add articles, open and edit `app/db/wordfreqapp.db` using DB Browser for SQLite (https://sqlitebrowser.org). ### Extending an account's expiry date -By default, an account's expiry is 30 days after first sign-up. To extend account's expiry date, open and edit `user` table in `app/wordfreqapp.db`. Simply update field `expiry_date`. +By default, an account's expiry is 30 days after first sign-up. To extend account's expiry date, open and edit `user` table in `app/db/wordfreqapp.db`. Simply update field `expiry_date`. ### Exporting the database @@ -95,7 +95,7 @@ sqlite3 wordfreqapp.db`. Delete wordfreqapp.db first if it exists. ### Uploading wordfreqapp.db to the server -`pscp wordfreqapp.db lanhui@118.*.*.118:/home/lanhui/englishpal2/EnglishPal/app/static` +`pscp wordfreqapp.db lanhui@118.*.*.118:/home/lanhui/englishpal2/EnglishPal/app/db/` From 06f896a33a1f9cefc9e0e3e496a603056b577a50 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Thu, 10 Aug 2023 15:22:30 +0800 Subject: [PATCH 36/88] Update .gitignore --- .gitignore | 2 ++ app/Article.py | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index f58d558..c83d46b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,12 +2,14 @@ venv/ app/__init__.py app/__pycache__/ +app/.DS_Store app/sqlite_commands.py app/static/usr/*.jpg app/static/img/ app/static/frequency/frequency_*.pickle app/static/frequency/frequency.p app/wordfreqapp.db +app/db/wordfreqapp.db app/static/donate-the-author.jpg app/static/donate-the-author-hidden.jpg app/model/__pycache__/ \ No newline at end of file diff --git a/app/Article.py b/app/Article.py index b24e448..c7e87d3 100644 --- a/app/Article.py +++ b/app/Article.py @@ -10,12 +10,12 @@ from flask import Flask, request, redirect, render_template, url_for, session, a from difficulty import get_difficulty_level_for_user, text_difficulty_level, user_difficulty_level -path_prefix = '/var/www/wordfreq/wordfreq/' -path_prefix = './db/' # comment this line in deployment +path_prefix = './' +db_path_prefix = './db/' # comment this line in deployment def total_number_of_essays(): - rq = RecordQuery(path_prefix + 'wordfreqapp.db') + rq = RecordQuery(db_path_prefix + 'wordfreqapp.db') rq.instructions("SELECT * FROM article") rq.do() result = rq.get_results() @@ -33,7 +33,7 @@ def get_article_body(s): def get_today_article(user_word_list, visited_articles): - rq = RecordQuery(path_prefix + 'wordfreqapp.db') + rq = RecordQuery(db_path_prefix + 'wordfreqapp.db') if visited_articles is None: visited_articles = { "index" : 0, # 为 article_ids 的索引 From e4f870c995957965a1e1e23d342ca869030d50a2 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Thu, 10 Aug 2023 15:25:42 +0800 Subject: [PATCH 37/88] Create folder app/db with a README file. --- app/db/README.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 app/db/README.txt diff --git a/app/db/README.txt b/app/db/README.txt new file mode 100644 index 0000000..bb826a6 --- /dev/null +++ b/app/db/README.txt @@ -0,0 +1 @@ +Put wordfreqapp.db here From 6d15b65e3cd946ae0aff242bdf18412ea6f113d1 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Thu, 10 Aug 2023 19:09:15 +0800 Subject: [PATCH 38/88] Make highlighting text difficulty level work. --- app/templates/userpage_get.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html index 28cc926..d5fb72e 100644 --- a/app/templates/userpage_get.html +++ b/app/templates/userpage_get.html @@ -65,7 +65,7 @@

阅读文章并回答问题

- +

Article added on: {{ today_article["date"] }}



{{ today_article["article_title"] }}


@@ -202,9 +202,8 @@ $('#source').html(today_article['source']); $('#question').html(today_article["question"]); $('#answer').html(today_article["answer"]); - document.querySelector('#text_level').classList.add('display-5'); // enlarge text difficult level for one second - - setTimeout(() => document.querySelector('#text_level').classList.remove('display-5'), 800); + document.querySelector('#text_level').classList.add('mark'); // highlight text difficult level for 2 seconds + setTimeout(() => {document.querySelector('#text_level').classList.remove('mark');}, 2000); } function check_pre(visited_articles){ From 10c291bed200663bcfd5ce82a8f170bd3c2f7918 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Thu, 10 Aug 2023 19:12:30 +0800 Subject: [PATCH 39/88] Highlight user difficulty level too. --- app/templates/userpage_get.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html index d5fb72e..4cc6835 100644 --- a/app/templates/userpage_get.html +++ b/app/templates/userpage_get.html @@ -65,7 +65,7 @@

阅读文章并回答问题

- +

Article added on: {{ today_article["date"] }}



{{ today_article["article_title"] }}


@@ -194,7 +194,7 @@ }); } function update(today_article){ - $('#user-level').html(today_article['user_level']); + $('#user_level').html(today_article['user_level']); $('#text_level').html(today_article["text_level"]); $('#date').html('Article added on: '+today_article["date"]); $('#article_title').html(today_article["article_title"]); @@ -204,6 +204,8 @@ $('#answer').html(today_article["answer"]); document.querySelector('#text_level').classList.add('mark'); // highlight text difficult level for 2 seconds setTimeout(() => {document.querySelector('#text_level').classList.remove('mark');}, 2000); + document.querySelector('#user_level').classList.add('mark'); // do the same thing for user difficulty level + setTimeout(() => {document.querySelector('#user_level').classList.remove('mark');}, 2000); } function check_pre(visited_articles){ From 1b211f107dfbadef56d74526d0708b70ae42bce4 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Fri, 11 Aug 2023 11:59:48 +0800 Subject: [PATCH 40/88] Speed up loading next article The key change is replacing "d1 = load_freq_history(path_prefix + 'static/frequency/ferquency.p)" with "d1 = load_freq_history(user_word_list)" in function get_today_article() from Article.py. Now, with a user_word_list of size about 500, the next article can be loaded within 100ms. The new d1 is much smaller than the old one, therefore the following computation "d3 = get_difficulty_level_for_user(d1, d2)" is much faster. The students did not feel that loading next article is slow; this is because their frequency.p is quite small. Also log information in app/log.txt --- .gitignore | 3 ++- app/Article.py | 10 ++++++++-- app/main.py | 3 --- app/user_service.py | 5 +++++ 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index c83d46b..39b4e3a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ app/wordfreqapp.db app/db/wordfreqapp.db app/static/donate-the-author.jpg app/static/donate-the-author-hidden.jpg -app/model/__pycache__/ \ No newline at end of file +app/model/__pycache__/ +app/log.txt diff --git a/app/Article.py b/app/Article.py index c7e87d3..467224a 100644 --- a/app/Article.py +++ b/app/Article.py @@ -8,7 +8,7 @@ import hashlib 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 - +import logging path_prefix = './' db_path_prefix = './db/' # comment this line in deployment @@ -51,14 +51,20 @@ def get_today_article(user_word_list, visited_articles): random.shuffle(result) # Choose article according to reader's level - d1 = load_freq_history(path_prefix + 'static/frequency/frequency.p') + logging.debug('* get_today_article(): start d1 = ... ') + d1 = load_freq_history(user_word_list) d2 = load_freq_history(path_prefix + 'static/words_and_tests.p') + logging.debug(' ... get_today_article(): get_difficulty_level_for_user() start') d3 = get_difficulty_level_for_user(d1, d2) + logging.debug(' ... get_today_article(): done') d = None result_of_generate_article = "not found" + d_user = load_freq_history(user_word_list) + logging.debug('* get_today_article(): user_difficulty_level() start') user_level = user_difficulty_level(d_user, d3) # more consideration as user's behaviour is dynamic. Time factor should be considered. + logging.debug('* get_today_article(): done') text_level = 0 if visited_articles["index"] > len(visited_articles["article_ids"])-1: # 生成新的文章 amount_of_visited_articles = len(visited_articles["article_ids"]) diff --git a/app/main.py b/app/main.py index f43b36b..19bd889 100644 --- a/app/main.py +++ b/app/main.py @@ -1,6 +1,3 @@ -#! /usr/bin/python3 -# -*- coding: utf-8 -*- - ########################################################################### # Copyright 2019 (C) Hui Lan # Written permission must be obtained from the author for commercial uses. diff --git a/app/user_service.py b/app/user_service.py index 5d601e0..6c208dc 100644 --- a/app/user_service.py +++ b/app/user_service.py @@ -15,6 +15,9 @@ from wordfreqCMD import sort_in_descending_order import pickle_idea import pickle_idea2 +import logging +logging.basicConfig(filename='log.txt', format='%(asctime)s %(message)s', level=logging.DEBUG) + # 初始化蓝图 userService = Blueprint("user_bp", __name__) @@ -32,7 +35,9 @@ def get_next_article(username): else: # 当前不为“null”,直接 index+=1 visited_articles["index"] += 1 session["visited_articles"] = visited_articles + logging.debug('/get_next_article: start calling get_today_arcile()') visited_articles, today_article, result_of_generate_article = get_today_article(user_freq_record, session.get('visited_articles')) + logging.debug('/get_next_arcile: done.') data = { 'visited_articles': visited_articles, 'today_article': today_article, From 83bbd8f6005ee447abdef57ecb555c89abbc03f9 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Fri, 11 Aug 2023 15:48:53 +0800 Subject: [PATCH 41/88] Improve the speed of loading the next article further after incorporating Chen Qiuwei et al.'s suggestions. --- app/difficulty.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/difficulty.py b/app/difficulty.py index cb93768..1bd8d68 100644 --- a/app/difficulty.py +++ b/app/difficulty.py @@ -18,6 +18,7 @@ def load_record(pickle_fname): return d +ENGLISH_WORD_DIFFICULTY_DICT = {} def convert_test_type_to_difficulty_level(d): """ 对原本的单词库中的单词进行难度评级 @@ -39,8 +40,10 @@ def convert_test_type_to_difficulty_level(d): elif 'BBC' in d[k]: result[k] = 8 - return result # {'apple': 4, ...} + global ENGLISH_WORD_DIFFICULTY_DICT + ENGLISH_WORD_DIFFICULTY_DICT = result + return result # {'apple': 4, ...} def get_difficulty_level_for_user(d1, d2): """ @@ -49,7 +52,11 @@ def get_difficulty_level_for_user(d1, d2): 在d2的后面添加单词,没有新建一个新的字典 """ # TODO: convert_test_type_to_difficulty_level() should not be called every time. Each word's difficulty level should be pre-computed. - d2 = convert_test_type_to_difficulty_level(d2) # 根据d2的标记评级{'apple': 4, 'abandon': 4, ...} + if ENGLISH_WORD_DIFFICULTY_DICT == {}: + d2 = convert_test_type_to_difficulty_level(d2) # 根据d2的标记评级{'apple': 4, 'abandon': 4, ...} + else: + d2 = ENGLISH_WORD_DIFFICULTY_DICT + stemmer = snowballstemmer.stemmer('english') for k in d1: # 用户的词 From 9b1d60748d63dd7ff2f0c8a3d49ac888d1612e81 Mon Sep 17 00:00:00 2001 From: Hui Lan Date: Fri, 11 Aug 2023 18:29:35 +0800 Subject: [PATCH 42/88] Increase button size so that it is easier to use on tablets . --- app/templates/userpage_post.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/userpage_post.html b/app/templates/userpage_post.html index 67bdb12..8d479e7 100644 --- a/app/templates/userpage_post.html +++ b/app/templates/userpage_post.html @@ -25,7 +25,7 @@

- + {% for x in lst %} {% set word = x[0]%}

From aaabd3e3bb65ac6ee67ad540ae9bebdd2972f821 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Fri, 11 Aug 2023 18:34:48 +0800 Subject: [PATCH 43/88] Enlarge button size so it is more table-friendly. --- app/templates/userpage_post.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/userpage_post.html b/app/templates/userpage_post.html index 8d479e7..c0e044e 100644 --- a/app/templates/userpage_post.html +++ b/app/templates/userpage_post.html @@ -25,7 +25,7 @@

- + {% for x in lst %} {% set word = x[0]%}

From c110de03939771ab9e4f12db21c71f8609ede102 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Fri, 11 Aug 2023 18:38:35 +0800 Subject: [PATCH 44/88] Better spacing. --- app/templates/userpage_post.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/templates/userpage_post.html b/app/templates/userpage_post.html index c0e044e..a3eb9b6 100644 --- a/app/templates/userpage_post.html +++ b/app/templates/userpage_post.html @@ -20,7 +20,8 @@ EnglishPal Study Room for {{username}} -

+

+

@@ -44,5 +45,6 @@ {% endfor %} {% endif %} +
From dff560cc734117fe07cc3576a08b25980a8b7fc2 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Fri, 11 Aug 2023 18:39:36 +0800 Subject: [PATCH 45/88] Indent code using web-mode. --- app/templates/userpage_post.html | 76 ++++++++++++++++---------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/app/templates/userpage_post.html b/app/templates/userpage_post.html index a3eb9b6..a7ad569 100644 --- a/app/templates/userpage_post.html +++ b/app/templates/userpage_post.html @@ -1,50 +1,50 @@ - - - - + + + + - {{ yml['header'] | safe }} - {% if yml['css']['item'] %} + {{ yml['header'] | safe }} + {% if yml['css']['item'] %} {% for css in yml['css']['item'] %} {% endfor %} - {% endif %} - {% if yml['js']['head'] %} + {% endif %} + {% if yml['js']['head'] %} {% for js in yml['js']['head'] %} - + {% endfor %} - {% endif %} + {% endif %} - EnglishPal Study Room for {{username}} - - -
-

- - -

- - - {% for x in lst %} - {% set word = x[0]%} -

- {{loop.index}} - : - {{word}} - ({{x[1]}}) - -

+ EnglishPal Study Room for {{username}} + + +
+

+ + +

+ + + {% for x in lst %} + {% set word = x[0]%} +

+ {{loop.index}} + : + {{word}} + ({{x[1]}}) + +

- {% endfor %} - - {{ yml['footer'] | safe }} - {% if yml['js']['bottom'] %} - {% for js in yml['js']['bottom'] %} + {% endfor %} + + {{ yml['footer'] | safe }} + {% if yml['js']['bottom'] %} + {% for js in yml['js']['bottom'] %} - {% endfor %} - {% endif %} -
- + {% endfor %} + {% endif %} +
+ From f4df263d6ea29c3019ce479ee2b67d0b403551f0 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Fri, 11 Aug 2023 19:14:51 +0800 Subject: [PATCH 46/88] Flash message is informative. Why not add it? --- app/static/.DS_Store | Bin 0 -> 6148 bytes app/templates/userpage_get.html | 6 +++--- app/user_service.py | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 app/static/.DS_Store diff --git a/app/static/.DS_Store b/app/static/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0c9d7b0bb4d3e8b93b39ac16f84d7f721cd3279b GIT binary patch literal 6148 zcmeHK%Sr=55Ukc5B3^RLael!+7()Dl{D7b_7g;e7!P}nlU4EL?55%zX67V9`&|Nb< zU9)T*wzmP;>hN?2EC9^ujyQUlnxDH*?5Z+Gr1Opgwixh;kN3@_`h3ET;uT;Ht@^ap58~uUqHJ@}hu7ko5?U)$t hm>X}$%P7ja=4+n!!Z9)E%m重设密码

-{# {% for message in flashed_messages %}#} {# 根据user_service.userpage,取消了参数flashed_messages,因此注释了这段代码 #} -{# #} -{# {% endfor %}#} + {% for message in get_flashed_messages() %} + + {% endfor %} diff --git a/app/user_service.py b/app/user_service.py index 6c208dc..27323b8 100644 --- a/app/user_service.py +++ b/app/user_service.py @@ -181,7 +181,11 @@ def user_mark_word(username): for word in request.form.getlist('marked'): lst.append((word, [get_time()])) d = pickle_idea2.merge_frequency(lst, lst_history) - pickle_idea2.save_frequency_to_pickle(d, user_freq_record) + if len(lst_history) > 999: + flash('You have way too many words in your difficult-words book. Delete some first.') + else: + pickle_idea2.save_frequency_to_pickle(d, user_freq_record) + flash('Added %s.' % (', '.join(request.form.getlist('marked')))) return redirect(url_for('user_bp.userpage', username=username)) else: return 'Under construction' From e9ac50422baf0ed7c9020d54fc93d5b75397d014 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Fri, 11 Aug 2023 19:28:53 +0800 Subject: [PATCH 47/88] Make the flash message dismissible. --- .gitignore | 1 + app/static/.DS_Store | Bin 6148 -> 0 bytes app/templates/userpage_get.html | 7 ++++++- 3 files changed, 7 insertions(+), 1 deletion(-) delete mode 100644 app/static/.DS_Store diff --git a/.gitignore b/.gitignore index 39b4e3a..34e28e4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ venv/ app/__init__.py app/__pycache__/ +.DS_Store app/.DS_Store app/sqlite_commands.py app/static/usr/*.jpg diff --git a/app/static/.DS_Store b/app/static/.DS_Store deleted file mode 100644 index 0c9d7b0bb4d3e8b93b39ac16f84d7f721cd3279b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%Sr=55Ukc5B3^RLael!+7()Dl{D7b_7g;e7!P}nlU4EL?55%zX67V9`&|Nb< zU9)T*wzmP;>hN?2EC9^ujyQUlnxDH*?5Z+Gr1Opgwixh;kN3@_`h3ET;uT;Ht@^ap58~uUqHJ@}hu7ko5?U)$t hm>X}$%P7ja=4+n!!Z9)E%m + + {{ yml['header'] | safe }} {% if yml['css']['item'] %} @@ -56,7 +58,10 @@

{% for message in get_flashed_messages() %} - + {% endfor %} From f3aa407c56943d3b692130fd05a4e514a836c73b Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Fri, 11 Aug 2023 19:32:34 +0800 Subject: [PATCH 48/88] Use small letters for In and Up. --- app/templates/login.html | 2 +- app/templates/signup.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/login.html b/app/templates/login.html index 794be80..b8eb118 100644 --- a/app/templates/login.html +++ b/app/templates/login.html @@ -32,7 +32,7 @@
diff --git a/app/templates/signup.html b/app/templates/signup.html index 9030d41..5b3aafe 100644 --- a/app/templates/signup.html +++ b/app/templates/signup.html @@ -53,7 +53,7 @@ You're logged in already! Logout.

From ed1d0fd7143c583ffa9f204a0b51b77309b71dd1 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Fri, 11 Aug 2023 21:02:22 +0800 Subject: [PATCH 49/88] Show only one place after the decimal point. --- app/Article.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Article.py b/app/Article.py index 467224a..acc8aa5 100644 --- a/app/Article.py +++ b/app/Article.py @@ -93,8 +93,8 @@ def get_today_article(user_word_list, visited_articles): today_article = None if d: today_article = { - "user_level": '%4.2f' % user_level, - "text_level": '%4.2f' % text_level, + "user_level": '%4.1f' % user_level, + "text_level": '%4.1f' % text_level, "date": d['date'], "article_title": get_article_title(d['text']), "article_body": get_article_body(d['text']), From d2f30daab1a74e31731bdeb3edc0d05d443c0cb8 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Sat, 12 Aug 2023 15:29:12 +0800 Subject: [PATCH 50/88] Use PonyORM instead of class RecordQuery from UseSqlite.py. Incorporated changes from Pull Request 91 contributed by He Zhengzheng. --- app/Article.py | 16 +++----- app/Login.py | 1 - app/UseSqlite.py | 87 -------------------------------------------- app/model/article.py | 14 +++++++ 4 files changed, 19 insertions(+), 99 deletions(-) delete mode 100644 app/UseSqlite.py diff --git a/app/Article.py b/app/Article.py index acc8aa5..566ceb6 100644 --- a/app/Article.py +++ b/app/Article.py @@ -1,6 +1,5 @@ from WordFreq import WordFreq from wordfreqCMD import youdao_link, sort_in_descending_order -from UseSqlite import InsertQuery, RecordQuery import pickle_idea, pickle_idea2 import os import random, glob @@ -8,6 +7,7 @@ import hashlib 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 model.article import get_all_articles, get_article_by_id, get_number_of_articles import logging path_prefix = './' @@ -15,11 +15,7 @@ db_path_prefix = './db/' # comment this line in deployment def total_number_of_essays(): - rq = RecordQuery(db_path_prefix + 'wordfreqapp.db') - rq.instructions("SELECT * FROM article") - rq.do() - result = rq.get_results() - return len(result) + return get_number_of_articles() def get_article_title(s): @@ -33,21 +29,19 @@ def get_article_body(s): def get_today_article(user_word_list, visited_articles): - rq = RecordQuery(db_path_prefix + 'wordfreqapp.db') if visited_articles is None: visited_articles = { "index" : 0, # 为 article_ids 的索引 "article_ids": [] # 之前显示文章的id列表,越后越新 } if visited_articles["index"] > len(visited_articles["article_ids"])-1: # 生成新的文章,因此查找所有的文章 - rq.instructions("SELECT * FROM article") + result = get_all_articles() else: # 生成阅读过的文章,因此查询指定 article_id 的文章 if visited_articles["article_ids"][visited_articles["index"]] == 'null': # 可能因为直接刷新页面导致直接去查询了'null',因此当刷新的页面的时候,需要直接进行“上一篇”操作 visited_articles["index"] -= 1 visited_articles["article_ids"].pop() - rq.instructions('SELECT * FROM article WHERE article_id=%d' % (visited_articles["article_ids"][visited_articles["index"]])) - rq.do() - result = rq.get_results() + article_id = visited_articles["article_ids"][visited_articles["index"]] + result = get_article_by_id(article_id) random.shuffle(result) # Choose article according to reader's level diff --git a/app/Login.py b/app/Login.py index cd750d1..17d92fa 100644 --- a/app/Login.py +++ b/app/Login.py @@ -1,7 +1,6 @@ import hashlib import string from datetime import datetime, timedelta -from UseSqlite import InsertQuery, RecordQuery def md5(s): ''' diff --git a/app/UseSqlite.py b/app/UseSqlite.py deleted file mode 100644 index ea4baeb..0000000 --- a/app/UseSqlite.py +++ /dev/null @@ -1,87 +0,0 @@ -########################################################################### -# Copyright 2019 (C) Hui Lan -# Written permission must be obtained from the author for commercial uses. -########################################################################### - - -# Reference: Dusty Phillips. Python 3 Objected-oriented Programming Second Edition. Pages 326-328. -# Copyright (C) 2019 Hui Lan - -import sqlite3 - -class Sqlite3Template: - def __init__(self, db_fname): - self.db_fname = db_fname - - def connect(self, db_fname): - self.conn = sqlite3.connect(self.db_fname) - - def instructions(self, query_statement): - raise NotImplementedError() - - def operate(self): - self.conn.row_factory = sqlite3.Row - self.results = self.conn.execute(self.query) # self.query is to be given in the child classes - self.conn.commit() - - def format_results(self): - raise NotImplementedError() - - def do(self): - self.connect(self.db_fname) - self.instructions(self.query) - self.operate() - - def instructions_with_parameters(self, query_statement, parameters): - self.query = query_statement - self.parameters = parameters - - def do_with_parameters(self): - self.connect(self.db_fname) - self.instructions_with_parameters(self.query, self.parameters) - self.operate_with_parameters() - - def operate_with_parameters(self): - self.conn.row_factory = sqlite3.Row - self.results = self.conn.execute(self.query, self.parameters) # self.query is to be given in the child classes - self.conn.commit() - - -class InsertQuery(Sqlite3Template): - def instructions(self, query): - self.query = query - - -class RecordQuery(Sqlite3Template): - def instructions(self, query): - self.query = query - - def format_results(self): - output = [] - for row_dict in self.results.fetchall(): - lst = [] - for k in dict(row_dict): - lst.append( row_dict[k] ) - output.append(', '.join(lst)) - return '\n\n'.join(output) - - def get_results(self): - result = [] - for row_dict in self.results.fetchall(): - result.append( dict(row_dict) ) - return result - - - -if __name__ == '__main__': - - #iq = InsertQuery('RiskDB.db') - #iq.instructions("INSERT INTO inspection Values ('FoodSupplies', 'RI2019051301', '2019-05-13', '{}')") - #iq.do() - #iq.instructions("INSERT INTO inspection Values ('CarSupplies', 'RI2019051302', '2019-05-13', '{[{\"risk_name\":\"elevator\"}]}')") - #iq.do() - - rq = RecordQuery('wordfreqapp.db') - rq.instructions("SELECT * FROM article WHERE level=3") - rq.do() - #print(rq.format_results()) diff --git a/app/model/article.py b/app/model/article.py index 0a6a4d6..bf19ded 100644 --- a/app/model/article.py +++ b/app/model/article.py @@ -32,3 +32,17 @@ def get_page_articles(num, size): x for x in Article.select().order_by(desc(Article.article_id)).page(num, size) ] + + +def get_all_articles(): + articles = [] + with db_session: + for article in Article.select(): + articles.append(article.to_dict()) + return articles + + +def get_article_by_id(article_id): + with db_session: + article = Article.get(article_id=article_id) + return [article.to_dict()] From 8dd6a2a34331ea397f2e3d57ab3a63ee8439826a Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Sat, 12 Aug 2023 17:36:49 +0800 Subject: [PATCH 51/88] Use an arrow for Next Article or Previsou Article --- app/templates/userpage_get.html | 46 ++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html index 433b58e..129405e 100644 --- a/app/templates/userpage_get.html +++ b/app/templates/userpage_get.html @@ -23,26 +23,36 @@ EnglishPal Study Room for {{ username }} @@ -64,8 +74,8 @@
{% endfor %} - - + +

阅读文章并回答问题

From 1e3ac7a379d8d54125763fbcb4db92f25658b777 Mon Sep 17 00:00:00 2001 From: Lan Hui <1348141770@qq.com> Date: Sat, 12 Aug 2023 17:42:25 +0800 Subject: [PATCH 52/88] Use larger buttons --- app/templates/userpage_get.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html index 129405e..5a9bd58 100644 --- a/app/templates/userpage_get.html +++ b/app/templates/userpage_get.html @@ -125,8 +125,8 @@

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


- - + +
{% if session.get['thisWord'] %} {% endfor %} {% endif %} + diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html index 8c684b6..adadd58 100644 --- a/app/templates/userpage_get.html +++ b/app/templates/userpage_get.html @@ -86,7 +86,7 @@

{{ today_article['source'] }}


- +

{{ today_article['question'] }}


- {% endfor %} - {% endif %} + {{ yml['header'] | safe }} + {% if yml['css']['item'] %} + {% for css in yml['css']['item'] %} + + {% endfor %} + {% endif %} + {% if yml['js']['head'] %} + {% for js in yml['js']['head'] %} + + {% endfor %} + {% endif %} - EnglishPal Study Room for {{username}} + EnglishPal Study Room for {{username}} -
-

- - -

-
- - {% for x in lst %} - {% set word = x[0]%} -

- {{loop.index}} - : - {{word}} - ({{x[1]}}) - -

+
+

+ + +

+ + + {% for x in lst %} + {% set word = x[0]%} +

+ {{loop.index}} + : + {{word}} + ({{x[1]}}) + +

- {% endfor %} - - {{ yml['footer'] | safe }} - {% if yml['js']['bottom'] %} + {% endfor %} + + {{ yml['footer'] | safe }} + {% if yml['js']['bottom'] %} {% for js in yml['js']['bottom'] %} - + {% endfor %} - {% endif %} -
+ {% endif %} +
diff --git a/app/test/test_save_selected_words.py b/app/test/test_save_selected_words.py new file mode 100644 index 0000000..4dc5883 --- /dev/null +++ b/app/test/test_save_selected_words.py @@ -0,0 +1,98 @@ +import random +import string +import time + +from selenium import webdriver +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +HOME_PAGE = "http://127.0.0.1:5000/" + +word = [] +uname = 'lanhui' +password = 'l0ve1t' +def has_punctuation(s): #用于检查单词是否包含标点符号 + return [c for c in s if c in string.punctuation] != [] + +def login(driver): + driver.get(HOME_PAGE) + assert 'English Pal - Learn English smartly!' in driver.page_source + # 登录 + login_elem = driver.find_element_by_link_text('登录') + login_elem.click() + + username_input = driver.find_element_by_id('username') + username_input.send_keys(uname) + + password_input = driver.find_element_by_id('password') + password_input.send_keys(password) + + login_btn = driver.find_element_by_xpath('//button[text()="登录"]') # 找到登录按钮 + login_btn.click() + + # 确保页面加载完 + try: + WebDriverWait(driver, 10).until( + EC.title_is("EnglishPal Study Room for " + uname) # 替换为实际的页面标题 + ) + except Exception as e: + print("页面加载失败:", e) + driver.quit() + exit() + assert 'EnglishPal Study Room for ' + uname in driver.title + +def test_save_selected_word(): + global word + # 调用本地chromedriver + driver = webdriver.Chrome(executable_path="C:\Program Files\Google\Chrome\Application\chromedriver.exe") + try: + login(driver) + #点击单词添加到已选单词列表 + # 获取文章内容 + elem = driver.find_element_by_id('text-content') + essay_content = elem.text + + #随机选择单词 长度不小于6个字符,并且不包含标点符号 + elem = driver.find_element_by_id('selected-words') + word = random.choice(essay_content.split()) + while 'font>' in word or 'br>' in word or 'p>' in word or len(word) < 6 or has_punctuation(word): + word = random.choice(essay_content.split()) + print(type(word)) #str + elem.send_keys(word) #单词输入到输入框 + + # 检查单词是否已成功添加到已选列表 + # 再次获取