chengjie 3 місяців тому
батько
коміт
b920382f92

+ 3 - 178
src/api/yjbdc/enhanceFormsOfWords.js

@@ -1,3 +1,5 @@
1
+import { stringUtils } from '../../util/stringClass.js';
2
+
1 3
 /**
2 4
  * 计算两个字符串之间的Levenshtein距离(编辑距离)
3 5
  * @param {string} a - 第一个字符串
@@ -113,184 +115,7 @@ export function enhanceFormsOfWords(jsonObj, userWords) {
113 115
      * @returns {boolean} - 是否符合变形规则
114 116
      */
115 117
     function checkSpecialWordForms(word, base) {
116
-        // 处理以y结尾的单词变为复数时,y变为ies的情况 (如cry -> cries)
117
-        if (base.endsWith('y') && word === base.slice(0, -1) + 'ies') {
118
-            return true;
119
-        }
120
-        
121
-        // 处理以fe结尾的单词变为复数时,fe变为ves的情况 (如knife -> knives)
122
-        if (base.endsWith('fe') && word === base.slice(0, -2) + 'ves') {
123
-            return true;
124
-        }
125
-        
126
-        // 处理以f结尾的单词变为复数时,f变为ves的情况 (如leaf -> leaves)
127
-        if (base.endsWith('f') && word === base.slice(0, -1) + 'ves') {
128
-            return true;
129
-        }
130
-        
131
-        // 处理常规的第三人称单数形式(动词后加s或es)
132
-        if (word === base + 's' || word === base + 'es') {
133
-            return true;
134
-        }
135
-        
136
-        // 处理反向情况:如果base是word加s或es
137
-        if (base === word + 's' || base === word + 'es') {
138
-            return true;
139
-        }
140
-        
141
-        // 处理动词的过去式和过去分词
142
-        // 常规动词加-ed
143
-        if (word === base + 'ed') {
144
-            return true;
145
-        }
146
-        // 以e结尾的动词加-d
147
-        if (base.endsWith('e') && word === base + 'd') {
148
-            return true;
149
-        }
150
-        // 以辅音+y结尾的动词,y变i再加-ed
151
-        if (base.length > 1 && 
152
-            base.endsWith('y') && 
153
-            !'aeiou'.includes(base.charAt(base.length - 2)) && 
154
-            word === base.slice(0, -1) + 'ied') {
155
-            return true;
156
-        }
157
-        
158
-        // 处理动词的现在分词
159
-        // 以e结尾的动词,去e加-ing
160
-        if (base.endsWith('e') && word === base.slice(0, -1) + 'ing') {
161
-            return true;
162
-        }
163
-        // 常规动词加-ing
164
-        if (word === base + 'ing') {
165
-            return true;
166
-        }
167
-        
168
-        // 处理形容词的比较级和最高级
169
-        // 常规形容词加-er/-est
170
-        if (word === base + 'er' || word === base + 'est') {
171
-            return true;
172
-        }
173
-        // 以e结尾的形容词加-r/-st
174
-        if (base.endsWith('e') && (word === base + 'r' || word === base + 'st')) {
175
-            return true;
176
-        }
177
-        // 以辅音+y结尾的形容词,y变i再加-er/-est
178
-        if (base.length > 1 && 
179
-            base.endsWith('y') && 
180
-            !'aeiou'.includes(base.charAt(base.length - 2)) && 
181
-            (word === base.slice(0, -1) + 'ier' || word === base.slice(0, -1) + 'iest')) {
182
-            return true;
183
-        }
184
-        
185
-        // 处理副词的形成
186
-        // 常规形容词加-ly
187
-        if (word === base + 'ly') {
188
-            return true;
189
-        }
190
-        // 以y结尾的形容词,y变i加-ly
191
-        if (base.endsWith('y') && word === base.slice(0, -1) + 'ily') {
192
-            return true;
193
-        }
194
-        
195
-        // 处理反向情况
196
-        // 如果word是变形后的单词,base是基本形式
197
-        
198
-        // 过去式/过去分词 -> 基本形式
199
-        if (word.endsWith('ed') && base === word.slice(0, -2)) {
200
-            return true;
201
-        }
202
-        // 以e结尾的动词加d -> 基本形式
203
-        if (word.endsWith('d') && !word.endsWith('ed') && base === word.slice(0, -1)) {
204
-            return true;
205
-        }
206
-        // 以辅音+y结尾变为ied -> 基本形式
207
-        if (word.endsWith('ied') && base === word.slice(0, -3) + 'y') {
208
-            return true;
209
-        }
210
-        
211
-        // 现在分词 -> 基本形式
212
-        if (word.endsWith('ing')) {
213
-            // 常规情况
214
-            if (base === word.slice(0, -3)) {
215
-                return true;
216
-            }
217
-            // 以e结尾的动词去e加ing
218
-            if (base.endsWith('e') && base === word.slice(0, -3) + 'e') {
219
-                return true;
220
-            }
221
-        }
222
-        
223
-        // 比较级/最高级 -> 基本形式
224
-        if (word.endsWith('er') && base === word.slice(0, -2)) {
225
-            return true;
226
-        }
227
-        if (word.endsWith('est') && base === word.slice(0, -3)) {
228
-            return true;
229
-        }
230
-        // 以e结尾的形容词
231
-        if (word.endsWith('r') && !word.endsWith('er') && base.endsWith('e') && base === word.slice(0, -1)) {
232
-            return true;
233
-        }
234
-        if (word.endsWith('st') && !word.endsWith('est') && base.endsWith('e') && base === word.slice(0, -2)) {
235
-            return true;
236
-        }
237
-        // 以辅音+y结尾变为ier/iest
238
-        if (word.endsWith('ier') && base === word.slice(0, -3) + 'y') {
239
-            return true;
240
-        }
241
-        if (word.endsWith('iest') && base === word.slice(0, -4) + 'y') {
242
-            return true;
243
-        }
244
-        
245
-        // 副词 -> 形容词
246
-        if (word.endsWith('ly') && base === word.slice(0, -2)) {
247
-            return true;
248
-        }
249
-        // 以y结尾变为ily
250
-        if (word.endsWith('ily') && base === word.slice(0, -3) + 'y') {
251
-            return true;
252
-        }
253
-        
254
-        // 处理不规则动词过去式 (如go -> went, is -> was)
255
-        const irregularVerbs = {
256
-            'go': ['went', 'gone', 'going', 'goes'],
257
-            'be': ['am', 'is', 'are', 'was', 'were', 'been', 'being'],
258
-            'do': ['did', 'done', 'doing', 'does'],
259
-            'have': ['has', 'had', 'having'],
260
-            'say': ['said', 'saying', 'says'],
261
-            'make': ['made', 'making', 'makes'],
262
-            'get': ['got', 'gotten', 'getting', 'gets'],
263
-            'know': ['knew', 'known', 'knowing', 'knows'],
264
-            'take': ['took', 'taken', 'taking', 'takes'],
265
-            'see': ['saw', 'seen', 'seeing', 'sees'],
266
-            'come': ['came', 'coming', 'comes'],
267
-            'think': ['thought', 'thinking', 'thinks'],
268
-            'look': ['looked', 'looking', 'looks'],
269
-            'want': ['wanted', 'wanting', 'wants'],
270
-            'give': ['gave', 'given', 'giving', 'gives'],
271
-            'use': ['used', 'using', 'uses'],
272
-            'find': ['found', 'finding', 'finds'],
273
-            'tell': ['told', 'telling', 'tells'],
274
-            'ask': ['asked', 'asking', 'asks'],
275
-            'work': ['worked', 'working', 'works'],
276
-            'seem': ['seemed', 'seeming', 'seems'],
277
-            'feel': ['felt', 'feeling', 'feels'],
278
-            'try': ['tried', 'trying', 'tries'],
279
-            'leave': ['left', 'leaving', 'leaves'],
280
-            'call': ['called', 'calling', 'calls']
281
-        };
282
-        
283
-        // 检查是否是不规则动词的变形
284
-        if (irregularVerbs[base] && irregularVerbs[base].includes(word)) {
285
-            return true;
286
-        }
287
-        
288
-        if (Object.entries(irregularVerbs).some(([verb, forms]) => 
289
-            verb === word && forms.includes(base))) {
290
-            return true;
291
-        }
292
-        
293
-        return false;
118
+        return stringUtils.checkSpecialWordForms(word, base);
294 119
     }
295 120
     
296 121
     // 处理用户提供的每个单词

+ 1 - 1
src/api/yjbdc/yjbdcController.js

@@ -1234,7 +1234,7 @@ export async function GetWordChinese(ctx) {
1234 1234
         // 如果没有找到结果,尝试查找单词的原形
1235 1235
         if (!result || result.length === 0) {
1236 1236
             // 使用stringUtils.getWordBaseForm获取可能的原形
1237
-            const possibleBaseWords = stringUtils.getWordBaseForm(param.Word);
1237
+            const possibleBaseWords = stringUtils.getWordAllForms(param.Word);
1238 1238
             
1239 1239
             // 尝试每个可能的原形
1240 1240
             for (const baseWord of possibleBaseWords) {

+ 25 - 11
src/test/build.test.js

@@ -58,26 +58,40 @@ async function runScript(){
58 58
             //aiProvider="ali-qwen-plus";
59 59
             //生成例句
60 60
             let result = await aiController.generateArticle(content, aiProvider);
61
-            const variable = "Hello, World!";
62
-            // if (typeof variable === 'string') {
63
-            //     console.log('变量是字符串');
64
-            // } else {
65
-            //     result=JSON.stringify(result);
66
-            //     result=stringUtils.ReplaceAllString(result,"\r","");
67
-            //     result=stringUtils.ReplaceAllString(result,"\n","");
68
-            // }
61
+            
62
+            console.log("result1:"+result);
63
+            //console.log(result.indexOf("{")); 
64
+            if (result.indexOf("```json")>0){
65
+                console.log("```json");
66
+                console.log(result.indexOf("```json"));
67
+                result=result.substring(result.indexOf("```json")+7);
68
+                result=result.substring(0,result.lastIndexOf("```"));
69
+            }
70
+            else if (result.indexOf("```")>0){
71
+                console.log("```");
72
+                console.log(result.indexOf("```"));
73
+                
74
+                result=result.substring(result.indexOf("```")+3);
75
+                result=result.substring(0,result.lastIndexOf("```"));
76
+            }
77
+            console.log("result2:"+result);
69 78
 
70
-            //console.log(result);
79
+            result=result.replace("\"\":","\":");
80
+            result=result.replace("\"\" :","\" :");
81
+            result=result.replace(":\"\"",":\"");
82
+            result=result.replace(": \"\"",": \"");
83
+            result=result.replace(",\"\"",",\"");
84
+            result=result.replace("\"\",","\",");
71 85
 
72
-            result=result.replace("\"\": ","\": ");
73 86
             result=result.replace("\"\":","\":");
87
+            result=result.replace("\"\" :","\" :");
74 88
             result=result.replace(":\"\"",":\"");
75 89
             result=result.replace(": \"\"",": \"");
76 90
             result=result.replace(",\"\"",",\"");
77 91
             result=result.replace("\"\",","\",");
78 92
 
79
-            result=result.substring(result.lastIndexOf("{\"word"),result.lastIndexOf("}]}")+3);
80 93
 
94
+            
81 95
             //console.log(result); 
82 96
             let sql2="update Words set ExampleSentence=? where ID="+item.ID+";";
83 97
             await commonModel.RunSql(result,sql2);

+ 18 - 8
src/test/build.test2.js

@@ -11,7 +11,7 @@ async function runScript(){
11 11
         let list = await commonModel.RunSql(null,sql);
12 12
         let count=list.length;
13 13
 
14
-        const start=8995;
14
+        const start=0;
15 15
         //count=10;
16 16
         // 添加延时函数,确保每分钟只发送9次请求(约每6.67秒一次请求)
17 17
         // const delay = (ms ) => new Promise(resolve => setTimeout(resolve, ms));
@@ -25,13 +25,23 @@ async function runScript(){
25 25
             word=item.Word;
26 26
             let exampleSentence=item.ExampleSentence;
27 27
             if (exampleSentence){
28
-                exampleSentence=JSON.parse(exampleSentence);
29
-                let sql2="update Words set ExampleSentence=?,Level='"+exampleSentence.CEFR_Level+"' where BookID<>110 and BookID not in (141,142,143,144,145,146,161,162,163,164,165,166,167,168) and ExampleSentence is null and Word='"+word+"';";
30
-                //console.log(sql2);
31
-                await commonModel.RunSql(item.ExampleSentence,sql2);
28
+                try{
29
+                    exampleSentence=JSON.parse(exampleSentence);
30
+                    let sql2="update Words set ExampleSentence=?,Level='"+exampleSentence.CEFR_Level+"' where BookID<>110 and BookID not in (141,142,143,144,145,146,161,162,163,164,165,166,167,168) and ExampleSentence is null and Word='"+word+"';";
31
+                    //console.log(sql2);
32
+                    await commonModel.RunSql(item.ExampleSentence,sql2);
33
+                }
34
+                catch(e){
35
+                    //let sql2="update Words set ExampleSentence='' where ID="+id+";";
36
+                    console.log("出错:"+word);
37
+
38
+                    process.exit(1);
39
+                    //await commonModel.RunSql(item.ExampleSentence,sql2);
40
+                }
32 41
             }
33 42
             else{
34 43
                 console.log( word +" 空");
44
+                process.exit(1);
35 45
             }
36 46
             console.log( i +"/"+ list.length);
37 47
             
@@ -43,15 +53,15 @@ async function runScript(){
43 53
         }
44 54
         
45 55
         console.log("完成");
56
+
57
+                    process.exit(1);
46 58
     } catch (error) {
47 59
         console.log(id + " " +word);
48 60
         console.error('Error executing script:', error);
61
+        process.exit(1);
49 62
     }
50 63
 }
51 64
 
52
-
53
-
54
-
55 65
 async function runScript2(){
56 66
     let id,word;
57 67
     try {

+ 55 - 41
src/test/build.test3.js

@@ -7,11 +7,11 @@ async function runScript(){
7 7
     let id,word;
8 8
     try {
9 9
         
10
-        const sql="select * from Words where BookID=110 and ExampleSentence is not null order by ID;;"
10
+        const sql="select * from Words where BookID=110 and ExampleSentence is not null order by ID;"
11 11
         let list = await commonModel.RunSql(null,sql);
12 12
         let count=list.length;
13 13
 
14
-        const start=3630;
14
+        const start=0;
15 15
         //const start=0;
16 16
         //count=1;
17 17
 
@@ -27,52 +27,66 @@ async function runScript(){
27 27
             word=item.Word;
28 28
             let exampleSentence=item.ExampleSentence;
29 29
             if (exampleSentence){
30
-                exampleSentence=JSON.parse(exampleSentence);
31
-                //console.log(exampleSentence);
32
-                let sql2="select * from MiaoguoLiteracy where Word='"+word+"';";
33
-                let list2= await commonModel.RunSql(null,sql2);
30
+                try{
31
+                    exampleSentence=JSON.parse(exampleSentence);
32
+                    //console.log(exampleSentence);
33
+                    let sql2="select * from MiaoguoLiteracy where Word='"+word+"';";
34
+                    let list2= await commonModel.RunSql(null,sql2);
34 35
 
35
-                for(let j=0;j<list2.length;j++){
36
-                    let json=list2[j].JSONString;
37
-                    json=JSON.parse(json);
38
-
39
-                    //console.log(json);
40
-                    
41
-                    if (json.ENG){
42
-                        let arrSentence=[];
36
+                    for(let j=0;j<list2.length;j++){
37
+                        let json=list2[j].JSONString;
43 38
                         
44
-                        for(let k=0;k<exampleSentence.Sentences.length;k++){
45
-                            let obj=[];
46
-                            let sentence1=exampleSentence.Sentences[k].Sentence;
47
-                            
48
-                            sentence1=stringUtils.ReplaceAllString(sentence1,word,"[线]"+word+"[/线]");
49
-                            
50
-                            if (sentence1.substring(0,word.length).toLowerCase()==word.toLowerCase()){
51
-                                let word1=sentence1.substring(0,word.length);
52
-                                sentence1=sentence1.replace(word1,"[线]"+word1+"[/线]");
53
-                            }
54
-                            
55
-                            //console.log(sentence1);
56
-                            
57
-                            obj.push(sentence1);
58
-                            obj.push(exampleSentence.Sentences[k].Translate);
59
-                            arrSentence.push(obj);
39
+                        json=JSON.parse(json);
40
+
41
+                        //console.log(json);
42
+                        if (json.ENG 
43
+                            && json.ENG.ExamplesSentences 
44
+                            && json.ENG.ExamplesSentences.length>0 
45
+                            && json.ENG.ExamplesSentences[0][0].indexOf("[线]")<0 
46
+                        ){
47
+                            console.log(id+" "+word);
48
+                            // if (json.ENG){
49
+                            //     let arrSentence=[];
50
+                                
51
+                            //     for(let k=0;k<exampleSentence.Sentences.length;k++){
52
+                            //         let obj=[];
53
+                            //         let sentence1=exampleSentence.Sentences[k].Sentence;
54
+                                    
55
+                            //         sentence1=stringUtils.ReplaceAllString(sentence1,word,"[线]"+word+"[/线]");
56
+                                    
57
+                            //         if (sentence1.substring(0,word.length).toLowerCase()==word.toLowerCase()){
58
+                            //             let word1=sentence1.substring(0,word.length);
59
+                            //             sentence1=sentence1.replace(word1,"[线]"+word1+"[/线]");
60
+                            //         }
61
+                            //         //console.log(sentence1);
62
+                                    
63
+                            //         obj.push(sentence1);
64
+                            //         obj.push(exampleSentence.Sentences[k].Translate);
65
+                            //         arrSentence.push(obj);
66
+                            //     }
67
+                            //     if (!json.ENG.ExamplesSentences)
68
+                            //         json.ENG.ExamplesSentences=[];
69
+                                
70
+                            //     json.ENG.ExamplesSentences=arrSentence;
71
+                            // }
72
+                            // json.ENG.CEFR_Level=exampleSentence.CEFR_Level;
73
+
74
+                            // json=JSON.stringify(json);
75
+                            // let sql3="update MiaoguoLiteracy set JSONString=? where ID="+list2[j].ID+";";
76
+                            // //console.log(sql3);
77
+                            // //console.log(json);
78
+                            // await commonModel.RunSql(json,sql3);
60 79
                         }
61
-                        if (!json.ENG.ExamplesSentences)
62
-                            json.ENG.ExamplesSentences=[];
63
-                        
64
-                        json.ENG.ExamplesSentences=arrSentence;
65 80
                     }
66
-                    json.ENG.CEFR_Level=exampleSentence.CEFR_Level;
67 81
 
68
-                    json=JSON.stringify(json);
69
-                    let sql3="update MiaoguoLiteracy set JSONString=? where ID="+list2[j].ID+";";
70
-                    //console.log(sql3);
71
-                    //console.log(json);
72
-                    await commonModel.RunSql(json,sql3);
82
+                }
83
+                catch(e){
84
+                    let sql2="update Words set ExampleSentence='' where ID="+id+";";
85
+                    console.log("出错:"+word);
86
+                    await commonModel.RunSql(item.ExampleSentence,sql2);
73 87
                 }
74 88
             }
75
-            console.log(i +"/"+ list.length+" "+word);
89
+            //console.log(i +"/"+ list.length+" "+word);
76 90
             
77 91
             // 在每次请求后添加延时,除非是最后一个请求
78 92
             // if (i < count - 1) {

+ 129 - 0
src/test/build.test31.js

@@ -0,0 +1,129 @@
1
+import commonModel from '../model/commonModel.js';
2
+import fs from 'fs';
3
+import { stringUtils } from '../util/stringClass.js';
4
+import aiController from '../api/yjbdc/aiController.js';
5
+
6
+async function runScript(){
7
+    let id,word;
8
+    try {
9
+        
10
+        const sql="select * from Words where BookID=110 order by ID;"
11
+        let list = await commonModel.RunSql(null,sql);
12
+        
13
+        const start=0;
14
+        //const start=0;
15
+        let count=list.length;
16
+        //count=100;
17
+
18
+        // 添加延时函数,确保每分钟只发送9次请求(约每6.67秒一次请求)
19
+        // const delay = (ms ) => new Promise(resolve => setTimeout(resolve, ms));
20
+        // const requestDelay = 300; // 7秒,确保每分钟最多9次请求
21
+        
22
+        for(let i=start;i<count;i++){
23
+            let item=list[i];
24
+
25
+            id=item.ID;
26
+            //获得单词
27
+            word=item.Word;
28
+            let exampleSentence=item.ExampleSentence;
29
+            if (exampleSentence){
30
+                try{
31
+                    if (exampleSentence.indexOf("\"\"")>=0){
32
+                        exampleSentence=exampleSentence("\"\"Sentences\"\"","\"Sentences\"");
33
+                        exampleSentence=exampleSentence("\"\",","\",");
34
+                        exampleSentence=exampleSentence(",\"\"",",\"");
35
+                        exampleSentence=exampleSentence("\"\":","\":");
36
+                        exampleSentence=exampleSentence(":\"\"",":\"");
37
+                        let sql5="update Words set ExampleSentence='"+exampleSentence+"' where ID="+id+";";
38
+                        //console.log(exampleSentence);
39
+                        await commonModel.RunSql(null,sql5);
40
+                    }
41
+
42
+                    exampleSentence=JSON.parse(exampleSentence);
43
+                    //console.log(exampleSentence);
44
+                    let sql2="select * from MiaoguoLiteracy where Word='"+word+"';";
45
+                    let list2= await commonModel.RunSql(null,sql2);
46
+
47
+                    for(let j=0;j<list2.length;j++){
48
+                        let json=list2[j].JSONString;
49
+                        
50
+                        json=JSON.parse(json);
51
+
52
+                        //console.log(json);
53
+                        let b=false;
54
+                        if (json.ENG && json.ENG.ExamplesSentences){
55
+                            
56
+                            for(let k=0;k<json.ENG.ExamplesSentences.length;k++){
57
+                                debugger;
58
+                                let sentence1=json.ENG.ExamplesSentences[k][0];
59
+
60
+                                if (sentence1.indexOf("[线]")<0){
61
+                                    //console.log("word:"+word);
62
+                                    let words=stringUtils.getWordAllForms(word);
63
+
64
+                                    for(let n=0;n<words.length;n++){
65
+                                        if (sentence1.indexOf(words[n])>=0){
66
+                                            sentence1=sentence1.replace(words[n],"[线]"+words[n]+"[/线]");
67
+                                            break;
68
+                                        }
69
+                                        else{
70
+                                            let word1=words[n].charAt(0).toUpperCase() + words[n].slice(1).toLowerCase();
71
+                                            if (sentence1.indexOf(word1)>=0){
72
+                                                sentence1=sentence1.replace(word1,"[线]"+word1+"[/线]");
73
+                                                break;
74
+                                            }
75
+                                        }
76
+                                    }
77
+                                    //console.log("words:"+words.join(", "));
78
+                                    //console.log("sentence1:"+sentence1);
79
+                                    json.ENG.ExamplesSentences[k][0]=sentence1;
80
+                                    b=true;
81
+                                }
82
+                            }
83
+                        }
84
+
85
+                        if (b){
86
+                            json.ENG.CEFR_Level=exampleSentence.CEFR_Level;
87
+
88
+                            json=JSON.stringify(json);
89
+                            let sql3="update MiaoguoLiteracy set JSONString=? where ID="+list2[j].ID+";";
90
+                            // //console.log(sql3);
91
+                            // //console.log(json);
92
+                            await commonModel.RunSql(json,sql3);
93
+                        }
94
+                        
95
+                    }
96
+
97
+                }
98
+                catch(e){
99
+                    // let sql2="update Words set ExampleSentence='' where ID="+id+";";
100
+
101
+                    // await commonModel.RunSql(item.ExampleSentence,sql2);
102
+                    console.log("出错:"+word);
103
+                    console.log("error:"+e);
104
+                    process.exit(1);
105
+                }
106
+            }
107
+            console.log(i +"/"+ list.length+" "+word);
108
+            
109
+            // 在每次请求后添加延时,除非是最后一个请求
110
+            // if (i < count - 1) {
111
+            //     console.log(`等待 ${requestDelay/1000} 秒后继续下一个请求...`);
112
+            //     await delay(requestDelay);
113
+            // }
114
+        }
115
+        
116
+        console.log("完成");
117
+        process.exit(1);
118
+
119
+    } catch (error) {
120
+        console.log(id + " " +word);
121
+        console.error('Error executing script:', error);
122
+        throw new Error('终止程序');
123
+        process.exit(1);
124
+    }
125
+}
126
+
127
+runScript().catch(error => {
128
+    console.error('Error in runScript:', error);
129
+});

+ 22 - 0
src/test/build.test32.js

@@ -0,0 +1,22 @@
1
+import commonModel from '../model/commonModel.js';
2
+import fs from 'fs';
3
+import { stringUtils } from '../util/stringClass.js';
4
+
5
+function runScript(a,b,fuhao){
6
+    if (fuhao=="+")
7
+        return a+b;
8
+    if (fuhao=="-")
9
+        return a-b;
10
+    if (fuhao=="×")
11
+        return a*b;
12
+    if (fuhao=="÷")
13
+        return a/b;
14
+
15
+    if (fuhao=="²")
16
+        return a*a;
17
+    
18
+}
19
+
20
+let a=123,b=456;
21
+let result=runScript(a,b,"²");
22
+console.log(a+"÷"+b+"="+result);

+ 110 - 0
src/test/build.test4.js

@@ -0,0 +1,110 @@
1
+import commonModel from '../model/commonModel.js';
2
+import fs from 'fs';
3
+import { stringUtils } from '../util/stringClass.js';
4
+import aiController from '../api/yjbdc/aiController.js';
5
+
6
+async function runScript(){
7
+    try {
8
+        
9
+        //按照高频单词的使用频率排序,列出所有单词
10
+        const sql="select * from Words where Word='';";
11
+        let list = await commonModel.RunSql(null,sql);
12
+        let count=list.length;
13
+        console.log(count);
14
+        const start=0;
15
+        //count=2;
16
+
17
+        // 添加延时函数,确保每分钟只发送9次请求(约每6.67秒一次请求)
18
+        const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
19
+        const requestDelay = 7000; // 7秒,确保每分钟最多9次请求
20
+        
21
+        for(let i=start;i<count;i++){
22
+            let item=list[i];
23
+
24
+            //获得单词
25
+            const word=item.Word;
26
+
27
+            let content={
28
+                "instruction": "用单词"+word+"生成例句,中国学生学习英文使用",
29
+                "requirements": [
30
+                    "判断单词在CEFR的最低级别,比如experience是B1",
31
+                    "用单词最常用的含义生成最低级别到C1各两句例句,比如experience生成B1、B2、C1各两句",
32
+                    "单词允许类似过去式、复数等变形",
33
+                    "提供例句翻译",
34
+                    "格式要求是JSON格式,完全遵循output_format,另外生成不要有重复“\"”",
35
+                    "如果有多个方案,直接给最好的"
36
+                ],
37
+                "output_format":{
38
+                    "word":"单词",
39
+                    "CEFR_Level":"A1",
40
+                    "Sentences": [
41
+                        {
42
+                        "Sentence":"句子1",
43
+                        "Translate": "翻译1",
44
+                        "Level": "A1",
45
+                        },{
46
+                        "Sentence":"句子2",
47
+                        "Translate": "翻译2",
48
+                        "Level": "A2",
49
+                        },
50
+                    ]
51
+                }
52
+            };
53
+            content=JSON.stringify(content);
54
+            //console.log(content);
55
+
56
+            let aiProvider="llama-4-maverick-17b-128e-instruct";
57
+
58
+            //aiProvider="ali-qwen-plus";
59
+            //生成例句
60
+            let result = await aiController.generateArticle(content, aiProvider);
61
+            
62
+
63
+            console.log("result1:"+result);
64
+            //console.log(result.indexOf("{")); 
65
+            if (result.indexOf("```json")>0){
66
+                console.log("```json");
67
+                console.log(result.indexOf("```json"));
68
+                result=result.substring(result.indexOf("```json")+7);
69
+                result=result.substring(0,result.lastIndexOf("```"));
70
+            }
71
+            else if (result.indexOf("```")>0){
72
+                console.log("```");
73
+                console.log(result.indexOf("```"));
74
+                
75
+                result=result.substring(result.indexOf("```")+3);
76
+                result=result.substring(0,result.lastIndexOf("```"));
77
+            }
78
+            console.log("result2:"+result); 
79
+
80
+            result=result.replace("\"\": ","\": ");
81
+            result=result.replace("\"\":","\":");
82
+            result=result.replace(":\"\"",":\"");
83
+            result=result.replace(": \"\"",": \"");
84
+            result=result.replace(",\"\"",",\"");
85
+            result=result.replace("\"\",","\",");
86
+
87
+            let sql2="update Words set ExampleSentence=? where ID="+item.ID+";";
88
+            await commonModel.RunSql(result,sql2);
89
+            
90
+            console.log( i +"/"+ list.length+" "+word);
91
+            
92
+            // 在每次请求后添加延时,除非是最后一个请求
93
+            if (i < count - 1) {
94
+                console.log(`等待 ${requestDelay/1000} 秒后继续下一个请求...`);
95
+                await delay(requestDelay);
96
+            }
97
+        }
98
+        
99
+        console.log("完成");
100
+        process.exit(1);
101
+    } catch (error) {
102
+        console.error('Error executing script:', error);
103
+        process.exit(1);
104
+    }
105
+}
106
+
107
+// 处理Promise并添加错误捕获
108
+runScript().catch(error => {
109
+    console.error('Error in runScript:', error);
110
+});

+ 610 - 162
src/util/stringClass.js

@@ -67,162 +67,281 @@ import os from 'os';
67 67
  * @property {Function} cleanWord - 清理单词中的非字母字符
68 68
  * @property {Function} extractEnglishWords - 从文本中提取英语单词
69 69
  */
70
+
70 71
 // 不规则动词映射
71 72
 const irregularVerbs = {
72
-    'go': ['went', 'gone', 'going', 'goes'],
73
-    'be': ['am', 'is', 'are', 'was', 'were', 'been', 'being'],
74
-    'do': ['did', 'done', 'doing', 'does'],
75
-    'have': ['has', 'had', 'having'],
76
-    'say': ['said', 'saying', 'says'],
77
-    'make': ['made', 'making', 'makes'],
78
-    'get': ['got', 'gotten', 'getting', 'gets'],
79
-    'know': ['knew', 'known', 'knowing', 'knows'],
80
-    'take': ['took', 'taken', 'taking', 'takes'],
81
-    'see': ['saw', 'seen', 'seeing', 'sees'],
82
-    'come': ['came', 'coming', 'comes'],
83
-    'think': ['thought', 'thinking', 'thinks'],
84
-    'look': ['looked', 'looking', 'looks'],
85
-    'want': ['wanted', 'wanting', 'wants'],
86
-    'give': ['gave', 'given', 'giving', 'gives'],
87
-    'use': ['used', 'using', 'uses'],
88
-    'find': ['found', 'finding', 'finds'],
89
-    'tell': ['told', 'telling', 'tells'],
90
-    'ask': ['asked', 'asking', 'asks'],
91
-    'work': ['worked', 'working', 'works'],
92
-    'seem': ['seemed', 'seeming', 'seems'],
93
-    'feel': ['felt', 'feeling', 'feels'],
94
-    'try': ['tried', 'trying', 'tries'],
95
-    'leave': ['left', 'leaving', 'leaves'],
96
-    'call': ['called', 'calling', 'calls'],
97
-    'fly': ['flew', 'flown', 'flying', 'flies'],
98
-    'break': ['broke', 'broken', 'breaking', 'breaks'],
99
-    'buy': ['bought', 'buying', 'buys'],
100
-    'bring': ['brought', 'bringing', 'brings'],
101
-    'build': ['built', 'building', 'builds'],
102
-    'choose': ['chose', 'chosen', 'choosing', 'chooses'],
103
-    'catch': ['caught', 'catching', 'catches'],
104
-    'draw': ['drew', 'drawn', 'drawing', 'draws'],
105
-    'drink': ['drank', 'drunk', 'drinking', 'drinks'],
106
-    'drive': ['drove', 'driven', 'driving', 'drives'],
107
-    'eat': ['ate', 'eaten', 'eating', 'eats'],
108
-    'fall': ['fell', 'fallen', 'falling', 'falls'],
109
-    'forget': ['forgot', 'forgotten', 'forgetting', 'forgets'],
110
-    'grow': ['grew', 'grown', 'growing', 'grows'],
111
-    'hear': ['heard', 'hearing', 'hears'],
112
-    'keep': ['kept', 'keeping', 'keeps'],
113
-    'lead': ['led', 'leading', 'leads'],
114
-    'learn': ['learnt', 'learned', 'learning', 'learns'],
115
-    'lose': ['lost', 'losing', 'loses'],
116
-    'pay': ['paid', 'paying', 'pays'],
117
-    'read': ['read', 'reading', 'reads'],
118
-    'run': ['ran', 'run', 'running', 'runs'],
119
-    'rise': ['rose', 'risen', 'rising', 'rises'],
120
-    'ride': ['rode', 'ridden', 'riding', 'rides'],
121
-    'ring': ['rang', 'rung', 'ringing', 'rings'],
122
-    'set': ['set', 'setting', 'sets'],
123
-    'sit': ['sat', 'sitting', 'sits'],
124
-    'speak': ['spoke', 'spoken', 'speaking', 'speaks'],
125
-    'spend': ['spent', 'spending', 'spends'],
126
-    'stand': ['stood', 'standing', 'stands'],
127
-    'swim': ['swam', 'swum', 'swimming', 'swims'],
128
-    'teach': ['taught', 'teaching', 'teaches'],
129
-    'understand': ['understood', 'understanding', 'understands'],
130
-    'write': ['wrote', 'written', 'writing', 'writes'],
131
-    'win': ['won', 'winning', 'wins'],
132
-    'wear': ['wore', 'worn', 'wearing', 'wears'],
133
-    'throw': ['threw', 'thrown', 'throwing', 'throws'],
134
-    'sing': ['sang', 'sung', 'singing', 'sings'],
135
-    'sleep': ['slept', 'sleeping', 'sleeps'],
136
-    'sell': ['sold', 'selling', 'sells'],
137
-    'send': ['sent', 'sending', 'sends'],
138
-    'put': ['put', 'putting', 'puts'],
139
-    'meet': ['met', 'meeting', 'meets'],
140
-    'let': ['let', 'letting', 'lets'],
141
-    'hold': ['held', 'holding', 'holds'],
142
-    'cut': ['cut', 'cutting', 'cuts'],
143
-    'cost': ['cost', 'costing', 'costs'],
144
-    'become': ['became', 'become', 'becoming', 'becomes'],
145
-    'begin': ['began', 'begun', 'beginning', 'begins'],
146
-    'bend': ['bent', 'bending', 'bends'],
147
-    'bet': ['bet', 'betting', 'bets'],
148
-    'bite': ['bit', 'bitten', 'biting', 'bites'],
149
-    'blow': ['blew', 'blown', 'blowing', 'blows'],
150
-    'feed': ['fed', 'feeding', 'feeds'],
151
-    'fight': ['fought', 'fighting', 'fights'],
152
-    'freeze': ['froze', 'frozen', 'freezing', 'freezes'],
153
-    'hang': ['hung', 'hanging', 'hangs'],
154
-    'hide': ['hid', 'hidden', 'hiding', 'hides'],
155
-    'hit': ['hit', 'hitting', 'hits'],
156
-    'hurt': ['hurt', 'hurting', 'hurts'],
157
-    'lay': ['laid', 'laying', 'lays'],
158
-    'lie': ['lay', 'lain', 'lying', 'lies'],
159
-    'light': ['lit', 'lighting', 'lights'],
160
-    'mean': ['meant', 'meaning', 'means'],
161
-    'prove': ['proved', 'proven', 'proving', 'proves'],
162
-    'shake': ['shook', 'shaken', 'shaking', 'shakes'],
163
-    'shine': ['shone', 'shining', 'shines'],
164
-    'shoot': ['shot', 'shooting', 'shoots'],
165
-    'show': ['showed', 'shown', 'showing', 'shows'],
166
-    'shut': ['shut', 'shutting', 'shuts'],
167
-    'steal': ['stole', 'stolen', 'stealing', 'steals'],
168
-    'stick': ['stuck', 'sticking', 'sticks'],
169
-    'strike': ['struck', 'striking', 'strikes'],
170
-    'swear': ['swore', 'sworn', 'swearing', 'swears'],
171
-    'sweep': ['swept', 'sweeping', 'sweeps'],
172
-    'tear': ['tore', 'torn', 'tearing', 'tears'],
173
-    'wake': ['woke', 'woken', 'waking', 'wakes'],
174
-    'bear': ['bore', 'born', 'bearing', 'bears'],
175
-    'beat': ['beat', 'beaten', 'beating', 'beats'],
176
-    'burst': ['burst', 'bursting', 'bursts'],
177
-    'deal': ['dealt', 'dealing', 'deals'],
178
-    'dig': ['dug', 'digging', 'digs'],
179
-    'forbid': ['forbade', 'forbidden', 'forbidding', 'forbids'],
180
-    'forecast': ['forecast', 'forecasting', 'forecasts'],
73
+    'arise': ['arose', 'arisen', 'arising', 'arises'],
74
+    'awake': ['awoke', 'awoken', 'awaking', 'awakes'],
75
+    'backslide': ['backslid', 'backslidden', 'backsliding', 'backslides'],
76
+    'become': ['became', 'become', 'becoming', 'becomes'], // 已有,但确保完整
77
+    'behold': ['beheld', 'beholding', 'beholds'],
78
+    'bend': ['bent', 'bending', 'bends'], 
79
+    'bet': ['bet', 'betting', 'bets'], 
80
+    'bid': ['bid', 'bidding', 'bids'],
81
+    'bind': ['bound', 'binding', 'binds'],
82
+    'bleed': ['bled', 'bleeding', 'bleeds'],
83
+    'blow': ['blew', 'blown', 'blowing', 'blows'], 
84
+    'break': ['broke', 'broken', 'breaking', 'breaks'], 
85
+    'breed': ['bred', 'breeding', 'breeds'],
86
+    'bring': ['brought', 'bringing', 'brings'], 
87
+    'build': ['built', 'building', 'builds'], 
88
+    'burn': ['burnt', 'burned', 'burning', 'burns'],
89
+    'burst': ['burst', 'bursting', 'bursts'], 
90
+    'buy': ['bought', 'buying', 'buys'], 
91
+    'cast': ['cast', 'casting', 'casts'],
92
+    'catch': ['caught', 'catching', 'catches'], 
93
+    'choose': ['chose', 'chosen', 'choosing', 'chooses'], 
94
+    'cling': ['clung', 'clinging', 'clings'],
95
+    'come': ['came', 'coming', 'comes'], 
96
+    'cost': ['cost', 'costing', 'costs'], 
97
+    'creep': ['crept', 'creeping', 'creeps'],
98
+    'cut': ['cut', 'cutting', 'cuts'], 
99
+    'deal': ['dealt', 'dealing', 'deals'], 
100
+    'dig': ['dug', 'digging', 'digs'], 
101
+    'dive': ['dove', 'dived', 'diving', 'dives'],
102
+    'do': ['did', 'done', 'doing', 'does'], 
103
+    'draw': ['drew', 'drawn', 'drawing', 'draws'], 
104
+    'dream': ['dreamt', 'dreamed', 'dreaming', 'dreams'],
105
+    'drink': ['drank', 'drunk', 'drinking', 'drinks'], 
106
+    'drive': ['drove', 'driven', 'driving', 'drives'], 
107
+    'eat': ['ate', 'eaten', 'eating', 'eats'], 
108
+    'fall': ['fell', 'fallen', 'falling', 'falls'], 
109
+    'feed': ['fed', 'feeding', 'feeds'], 
110
+    'feel': ['felt', 'feeling', 'feels'], 
111
+    'fight': ['fought', 'fighting', 'fights'], 
112
+    'find': ['found', 'finding', 'finds'], 
113
+    'fit': ['fit', 'fitted', 'fitting', 'fits'],
114
+    'flee': ['fled', 'fleeing', 'flees'],
115
+    'fling': ['flung', 'flinging', 'flings'],
116
+    'fly': ['flew', 'flown', 'flying', 'flies'], 
117
+    'forbid': ['forbade', 'forbidden', 'forbidding', 'forbids'], 
118
+    'forget': ['forgot', 'forgotten', 'forgetting', 'forgets'], 
181 119
     'forgive': ['forgave', 'forgiven', 'forgiving', 'forgives'],
182
-    'grind': ['ground', 'grinding', 'grinds'],
183
-    'kneel': ['knelt', 'kneeling', 'kneels'],
184
-    'knit': ['knit', 'knitting', 'knits'],
185
-    'lean': ['leant', 'leaning', 'leans'],
186
-    'leap': ['leapt', 'leaping', 'leaps'],
187
-    'lend': ['lent', 'lending', 'lends'],
188
-    'mistake': ['mistook', 'mistaken', 'mistaking', 'mistakes'],
189
-    'overcome': ['overcame', 'overcome', 'overcoming', 'overcomes'],
190
-    'overtake': ['overtook', 'overtaken', 'overtaking', 'overtakes'],
191
-    'rid': ['rid', 'ridding', 'rids'],
192
-    'seek': ['sought', 'seeking', 'seeks'],
193
-    'sew': ['sewed', 'sewn', 'sewing', 'sews'],
194
-    'slay': ['slew', 'slain', 'slaying', 'slays'],
195
-    'slide': ['slid', 'sliding', 'slides'],
196
-    'sling': ['slung', 'slinging', 'slings'],
197
-    'slit': ['slit', 'slitting', 'slits'],
198
-    'smell': ['smelt', 'smelling', 'smells'],
199
-    'sow': ['sowed', 'sown', 'sowing', 'sows'],
200
-    'spell': ['spelt', 'spelling', 'spells'],
201
-    'spill': ['spilt', 'spilling', 'spills'],
202
-    'spit': ['spat', 'spitting', 'spits'],
203
-    'split': ['split', 'splitting', 'splits'],
204
-    'spread': ['spread', 'spreading', 'spreads'],
205
-    'spring': ['sprang', 'sprung', 'springing', 'springs'],
206
-    'stink': ['stank', 'stunk', 'stinking', 'stinks'],
207
-    'stride': ['strode', 'stridden', 'striding', 'strides'],
208
-    'string': ['strung', 'stringing', 'strings'],
209
-    'strive': ['strove', 'striven', 'striving', 'strives'],
210
-    'sweat': ['sweat', 'sweating', 'sweats'],
211
-    'swell': ['swelled', 'swollen', 'swelling', 'swells'],
212
-    'swing': ['swung', 'swinging', 'swings'],
213
-    'thrust': ['thrust', 'thrusting', 'thrusts'],
214
-    'tread': ['trod', 'trodden', 'treading', 'treads'],
215
-    'undergo': ['underwent', 'undergone', 'undergoing', 'undergoes'],
216
-    'undertake': ['undertook', 'undertaken', 'undertaking', 'undertakes'],
217
-    'upset': ['upset', 'upsetting', 'upsets'],
218
-    'weave': ['wove', 'woven', 'weaving', 'weaves'],
219
-    'weep': ['wept', 'weeping', 'weeps'],
220
-    'wind': ['wound', 'winding', 'winds'],
221
-    'withdraw': ['withdrew', 'withdrawn', 'withdrawing', 'withdraws'],
222
-    'wring': ['wrung', 'wringing', 'wrings']
120
+    'freeze': ['froze', 'frozen', 'freezing', 'freezes'], 
121
+    'get': ['got', 'gotten', 'getting', 'gets'], 
122
+    'give': ['gave', 'given', 'giving', 'gives'], 
123
+    'go': ['went', 'gone', 'going', 'goes'], 
124
+    'grind': ['ground', 'grinding', 'grinds'], 
125
+    'grow': ['grew', 'grown', 'growing', 'grows'], 
126
+    'hang': ['hung', 'hanging', 'hangs'], 
127
+    'have': ['has', 'had', 'having'], 
128
+    'hear': ['heard', 'hearing', 'hears'], 
129
+    'hide': ['hid', 'hidden', 'hiding', 'hides'], 
130
+    'hit': ['hit', 'hitting', 'hits'], 
131
+    'hold': ['held', 'holding', 'holds'], 
132
+    'hurt': ['hurt', 'hurting', 'hurts'], 
133
+    'keep': ['kept', 'keeping', 'keeps'], 
134
+    'kneel': ['knelt', 'kneeling', 'kneels'], 
135
+    'know': ['knew', 'known', 'knowing', 'knows'], 
136
+    'lay': ['laid', 'laying', 'lays'], 
137
+    'lead': ['led', 'leading', 'leads'], 
138
+    'lean': ['leant', 'leaning', 'leans'], 
139
+    'leap': ['leapt', 'leaping', 'leaps'], 
140
+    'learn': ['learnt', 'learned', 'learning', 'learns'], 
141
+    'leave': ['left', 'leaving', 'leaves'], 
142
+    'lend': ['lent', 'lending', 'lends'], 
143
+    'let': ['let', 'letting', 'lets'], 
144
+    'lie': ['lay', 'lain', 'lying', 'lies'], 
145
+    'light': ['lit', 'lighting', 'lights'], 
146
+    'lose': ['lost', 'losing', 'loses'], 
147
+    'make': ['made', 'making', 'makes'], 
148
+    'mean': ['meant', 'meaning', 'means'], 
149
+    'meet': ['met', 'meeting', 'meets'], 
150
+    'mistake': ['mistook', 'mistaken', 'mistaking', 'mistakes'], 
151
+    'pay': ['paid', 'paying', 'pays'], 
152
+    'put': ['put', 'putting', 'puts'], 
153
+    'quit': ['quit', 'quitting', 'quits'],
154
+    'read': ['read', 'reading', 'reads'], 
155
+    'ride': ['rode', 'ridden', 'riding', 'rides'], 
156
+    'ring': ['rang', 'rung', 'ringing', 'rings'], 
157
+    'rise': ['rose', 'risen', 'rising', 'rises'], 
158
+    'run': ['ran', 'run', 'running', 'runs'], 
159
+    'say': ['said', 'saying', 'says'], 
160
+    'see': ['saw', 'seen', 'seeing', 'sees'], 
161
+    'seek': ['sought', 'seeking', 'seeks'], 
162
+    'sell': ['sold', 'selling', 'sells'], 
163
+    'send': ['sent', 'sending', 'sends'], 
164
+    'set': ['set', 'setting', 'sets'], 
165
+    'shake': ['shook', 'shaken', 'shaking', 'shakes'], 
166
+    'shed': ['shed', 'shedding', 'sheds'],
167
+    'shine': ['shone', 'shining', 'shines'], 
168
+    'shoot': ['shot', 'shooting', 'shoots'], 
169
+    'show': ['showed', 'shown', 'showing', 'shows'], 
170
+    'shrink': ['shrank', 'shrunk', 'shrinking', 'shrinks'],
171
+    'shut': ['shut', 'shutting', 'shuts'], 
172
+    'sing': ['sang', 'sung', 'singing', 'sings'], 
173
+    'sink': ['sank', 'sunk', 'sinking', 'sinks'],
174
+    'sit': ['sat', 'sitting', 'sits'], 
175
+    'sleep': ['slept', 'sleeping', 'sleeps'], 
176
+    'slide': ['slid', 'sliding', 'slides'], 
177
+    'sling': ['slung', 'slinging', 'slings'], 
178
+    'slink': ['slunk', 'slinking', 'slinks'],
179
+    'smell': ['smelt', 'smelling', 'smells'], 
180
+    'speak': ['spoke', 'spoken', 'speaking', 'speaks'], 
181
+    'speed': ['sped', 'speeding', 'speeds'],
182
+    'spell': ['spelt', 'spelling', 'spells'], 
183
+    'spend': ['spent', 'spending', 'spends'], 
184
+    'spill': ['spilt', 'spilling', 'spills'], 
185
+    'spin': ['spun', 'spinning', 'spins'],
186
+    'spit': ['spat', 'spitting', 'spits'], 
187
+    'split': ['split', 'splitting', 'splits'], 
188
+    'spread': ['spread', 'spreading', 'spreads'], 
189
+    'spring': ['sprang', 'sprung', 'springing', 'springs'], 
190
+    'stand': ['stood', 'standing', 'stands'], 
191
+    'steal': ['stole', 'stolen', 'stealing', 'steals'], 
192
+    'stick': ['stuck', 'sticking', 'sticks'], 
193
+    'sting': ['stung', 'stinging', 'stings'],
194
+    'stink': ['stank', 'stunk', 'stinking', 'stinks'], 
195
+    'strike': ['struck', 'striking', 'strikes'], 
196
+    'strive': ['strove', 'striven', 'striving', 'strives'], 
197
+    'swear': ['swore', 'sworn', 'swearing', 'swears'], 
198
+    'sweep': ['swept', 'sweeping', 'sweeps'], 
199
+    'swim': ['swam', 'swum', 'swimming', 'swims'], 
200
+    'swing': ['swung', 'swinging', 'swings'], 
201
+    'take': ['took', 'taken', 'taking', 'takes'], 
202
+    'teach': ['taught', 'teaching', 'teaches'], 
203
+    'tear': ['tore', 'torn', 'tearing', 'tears'], 
204
+    'tell': ['told', 'telling', 'tells'], 
205
+    'think': ['thought', 'thinking', 'thinks'], 
206
+    'throw': ['threw', 'thrown', 'throwing', 'throws'], 
207
+    'thrust': ['thrust', 'thrusting', 'thrusts'], 
208
+    'tread': ['trod', 'trodden', 'treading', 'treads'], 
209
+    'undergo': ['underwent', 'undergone', 'undergoing', 'undergoes'], 
210
+    'understand': ['understood', 'understanding', 'understands'], 
211
+    'undertake': ['undertook', 'undertaken', 'undertaking', 'undertakes'], 
212
+    'upset': ['upset', 'upsetting', 'upsets'], 
213
+    'wake': ['woke', 'woken', 'waking', 'wakes'], 
214
+    'wear': ['wore', 'worn', 'wearing', 'wears'], 
215
+    'weave': ['wove', 'woven', 'weaving', 'weaves'], 
216
+    'weep': ['wept', 'weeping', 'weeps'], 
217
+    'win': ['won', 'winning', 'wins'], 
218
+    'wind': ['wound', 'winding', 'winds'], 
219
+    'withdraw': ['withdrew', 'withdrawn', 'withdrawing', 'withdraws'], 
220
+    'wring': ['wrung', 'wringing', 'wrings'] 
221
+};
222
+
223
+// 不规则形容词/副词映射表
224
+const irregularAdjectives = {
225
+    'good': ['better', 'best'],
226
+    'bad': ['worse', 'worst'],
227
+    'many': ['more', 'most'],
228
+    'much': ['more', 'most'],
229
+    'little': ['less', 'least'],
230
+    'far': ['further', 'furthest', 'farther', 'farthest'],
231
+    'old': ['older', 'oldest', 'elder', 'eldest'],
232
+    'late': ['later', 'latest', 'latter', 'last'],
233
+    'well': ['better', 'best'],
234
+    'ill': ['worse', 'worst'],
235
+    'easy': ['easier', 'easiest'],
236
+    'happy': ['happier', 'happiest'],
237
+    'busy': ['busier', 'busiest'],
238
+    'pretty': ['prettier', 'prettiest'],
239
+    'heavy': ['heavier', 'heaviest'],
240
+    'simple': ['simpler', 'simplest'],
241
+    'clever': ['cleverer', 'cleverest'],
242
+    'narrow': ['narrower', 'narrowest'],
243
+    'quiet': ['quieter', 'quietest'],
244
+    'large': ['larger', 'largest'],
245
+    'small': ['smaller', 'smallest'],
246
+    'big': ['bigger', 'biggest'],
247
+    'hot': ['hotter', 'hottest'],
248
+    'tall': ['taller', 'tallest'],
249
+    'short': ['shorter', 'shortest'],
250
+    'long': ['longer', 'longest'],
251
+    'high': ['higher', 'highest'],
252
+    'low': ['lower', 'lowest'],
253
+    'deep': ['deeper', 'deepest'],
254
+    'wide': ['wider', 'widest'],
255
+    'near': ['nearer', 'nearest'],
256
+    'clean': ['cleaner', 'cleanest'],
257
+    'quick': ['quicker', 'quickest'],
258
+    'slow': ['slower', 'slowest'],
259
+    'strong': ['stronger', 'strongest'],
260
+    'weak': ['weaker', 'weakest'],
261
+    'young': ['younger', 'youngest'],
262
+    'rich': ['richer', 'richest'],
263
+    'poor': ['poorer', 'poorest'],
264
+    'thick': ['thicker', 'thickest'],
265
+    'thin': ['thinner', 'thinnest'],
266
+    'fast': ['faster', 'fastest'],
267
+    'hard': ['harder', 'hardest'],
268
+    'soft': ['softer', 'softest'],
269
+    'warm': ['warmer', 'warmest'],
270
+    'cool': ['cooler', 'coolest'],
271
+    'cold': ['colder', 'coldest'],
272
+    'bright': ['brighter', 'brightest'],
273
+    'dark': ['darker', 'darkest'],
274
+    'light': ['lighter', 'lightest'],
275
+    'loud': ['louder', 'loudest'],
276
+    'sweet': ['sweeter', 'sweetest'],
277
+    'sour': ['sourer', 'sourest'],
278
+    'bitter': ['bitterer', 'bitterest'],
279
+    'nice': ['nicer', 'nicest'],
280
+    'fine': ['finer', 'finest'],
281
+    'brave': ['braver', 'bravest'],
282
+    'calm': ['calmer', 'calmest'],
283
+    'cute': ['cuter', 'cutest'],
284
+    'fair': ['fairer', 'fairest'],
285
+    'fresh': ['fresher', 'freshest'],
286
+    'full': ['fuller', 'fullest'],
287
+    'glad': ['gladder', 'gladdest'],
288
+    'great': ['greater', 'greatest'],
289
+    'kind': ['kinder', 'kindest'],
290
+    'new': ['newer', 'newest'],
291
+    'odd': ['odder', 'oddest'],
292
+    'rare': ['rarer', 'rarest'],
293
+    'real': ['realer', 'realest'],
294
+    'safe': ['safer', 'safest'],
295
+    'same': ['samer', 'samest'],
296
+    'sure': ['surer', 'surest'],
297
+    'true': ['truer', 'truest'],
298
+    'wise': ['wiser', 'wisest']
299
+};
300
+
301
+// 特殊不规则名词复数形式
302
+const irregularNouns = {
303
+    'child': ['children'],
304
+    'man': ['men'],
305
+    'woman': ['women'],
306
+    'foot': ['feet'],
307
+    'tooth': ['teeth'],
308
+    'goose': ['geese'],
309
+    'mouse': ['mice'],
310
+    'ox': ['oxen'],
311
+    'person': ['people'],
312
+    'louse': ['lice'],
313
+    'leaf': ['leaves'],
314
+    'life': ['lives'],
315
+    'knife': ['knives'],
316
+    'wife': ['wives'],
317
+    'half': ['halves'],
318
+    'wolf': ['wolves'],
319
+    'shelf': ['shelves'],
320
+    'self': ['selves'],
321
+    'calf': ['calves'],
322
+    'thief': ['thieves'],
323
+    'deer': ['deer'],
324
+    'sheep': ['sheep'],
325
+    'fish': ['fish'],
326
+    'series': ['series'],
327
+    'species': ['species'],
328
+    'aircraft': ['aircraft'],
329
+    'information': ['information'],
330
+    'money': ['money'],
331
+    'rice': ['rice'],
332
+    'equipment': ['equipment'],
333
+    'furniture': ['furniture'],
334
+    'datum': ['data'],
335
+    'phenomenon': ['phenomena'],
336
+    'criterion': ['criteria']
223 337
 };
224 338
 
225 339
 export const stringUtils = {
340
+    // 导出不规则字典
341
+    irregularVerbs,
342
+    irregularAdjectives,
343
+    irregularNouns,
344
+
226 345
     //给字符串左侧补零
227 346
     AddZero: (str, length) => {
228 347
         while (str.length < length) {
@@ -881,25 +1000,165 @@ export const stringUtils = {
881 1000
         return result;
882 1001
     },
883 1002
     
1003
+
1004
+    
884 1005
     /**
885
-     * 获取单词的原形(基本形式)
886
-     * @param {string} word - 要转换的单词
887
-     * @returns {string[]} - 可能的原形单词数组
1006
+     * 获取单词的所有变形形式
1007
+     * @param {string} word - 要获取变形的单词
1008
+     * @returns {string[]} - 单词的所有变形形式数组
888 1009
      */
889
-    getWordBaseForm: (word) => {
1010
+    getWordAllForms: (word) => {
1011
+        if (!word || typeof word !== 'string') {
1012
+            return [];
1013
+        }
1014
+        word = word.trim();
1015
+        if (word === '') {
1016
+            return [];
1017
+        }
1018
+        
1019
+        // 保留原始单词,包括大小写和标点符号
1020
+        const originalWord = word;
1021
+        
1022
+        // 处理缩写词中的撇号
1023
+        const hasApostrophe = word.includes("'");
1024
+        
1025
+        // 转换为小写进行处理
890 1026
         const lowerWord = word.toLowerCase();
891
-        const possibleBaseWords = [];
892 1027
         
893
-        // 检查是否是不规则动词的变形
894
-        for (const [base, forms] of Object.entries(irregularVerbs)) {
895
-            if (forms.includes(lowerWord)) {
896
-                possibleBaseWords.push(base);
897
-                return possibleBaseWords; // 不规则动词直接返回原形
1028
+        // 使用Set存储所有可能的变形,避免重复
1029
+        const allForms = new Set([lowerWord]); // 初始包含原单词
1030
+        
1031
+        // 如果原始单词与小写形式不同,也添加原始单词
1032
+        if (originalWord !== lowerWord) {
1033
+            allForms.add(originalWord);
1034
+        }
1035
+        
1036
+        // 可以考虑添加一个标志来避免重复检查
1037
+        let foundIrregular = false;
1038
+        // 检查是否是不规则动词
1039
+        for (const [base, forms] of Object.entries(stringUtils.irregularVerbs)) {
1040
+            if (base === lowerWord || forms.includes(lowerWord)) {
1041
+                // 添加原形和所有变形
1042
+                allForms.add(base);
1043
+                forms.forEach(form => allForms.add(form));
1044
+                foundIrregular = true;
1045
+                break;
1046
+            }
1047
+        }
1048
+        
1049
+        // 不规则形容词/副词检查后应该也考虑是否返回
1050
+        for (const [base, forms] of Object.entries(stringUtils.irregularAdjectives)) {
1051
+            if (base === lowerWord || forms.includes(lowerWord)) {
1052
+                // 添加原形和所有变形
1053
+                allForms.add(base);
1054
+                forms.forEach(form => allForms.add(form));
1055
+                foundIrregular = true;
1056
+                break;
1057
+            }
1058
+        }
1059
+
1060
+        // 不规则名词检查后也应该设置标志
1061
+        if (stringUtils.irregularNouns[lowerWord]) {
1062
+            stringUtils.irregularNouns[lowerWord].forEach(form => allForms.add(form));
1063
+            foundIrregular = true;
1064
+        }
1065
+
1066
+        // 不规则名词复数形式检查后也应该设置标志
1067
+        for (const [singular, plurals] of Object.entries(stringUtils.irregularNouns)) {
1068
+            if (plurals.includes(lowerWord)) {
1069
+                allForms.add(singular);
1070
+                plurals.forEach(form => allForms.add(form));
1071
+                foundIrregular = true;
1072
+                break;
898 1073
             }
899 1074
         }
900 1075
         
901 1076
         // 处理规则变形
1077
+        // 特殊处理一些常见的副词和特殊单词,避免错误的词干提取和变形
1078
+        const specialWords = {
1079
+            // 情态动词
1080
+            'can': ['can', 'could', 'cannot', "can't"],
1081
+            'may': ['may', 'might'],
1082
+            'shall': ['shall', 'should', "shouldn't"],
1083
+            'will': ['will', 'would', "won't", "wouldn't"],
1084
+            'must': ['must', 'have to', 'has to', 'had to', "mustn't"],
1085
+            
1086
+            // 副词
1087
+            'early': ['early', 'earlier', 'earliest'],
1088
+            'only': ['only'],
1089
+            'likely': ['likely', 'more likely', 'most likely'],
1090
+            'friendly': ['friendly', 'friendlier', 'friendliest'],
1091
+            'lovely': ['lovely', 'lovelier', 'loveliest'],
1092
+            'timely': ['timely', 'timelier', 'timeliest'],
1093
+            'weekly': ['weekly'],
1094
+            'monthly': ['monthly'],
1095
+            'yearly': ['yearly'],
1096
+            'daily': ['daily'],
1097
+            'badly': ['badly', 'worse', 'worst'], // 对应bad的副词形式
1098
+            
1099
+            // 特殊动词
1100
+            'play': ['play', 'plays', 'played', 'playing'],
1101
+            'stay': ['stay', 'stays', 'stayed', 'staying'],
1102
+            'pay': ['pay', 'pays', 'paid', 'paying'],
1103
+            'lay': ['lay', 'lays', 'laid', 'laying'],
1104
+            'say': ['say', 'says', 'said', 'saying'],
1105
+            
1106
+            // 特殊名词
1107
+            'box': ['box', 'boxes'],
1108
+            'fox': ['fox', 'foxes'],
1109
+            'tax': ['tax', 'taxes'],
1110
+            'bush': ['bush', 'bushes'],
1111
+            'dish': ['dish', 'dishes'],
1112
+            'church': ['church', 'churches'],
1113
+            'tomato': ['tomato', 'tomatoes'],
1114
+            'potato': ['potato', 'potatoes'],
1115
+            'hero': ['hero', 'heroes'],
1116
+            'echo': ['echo', 'echoes'],
1117
+
1118
+            'its': ['its'], // 物主代词
1119
+            'it\'s': ['it\'s'], // it is 的缩写
1120
+            'I\'m': ['I\'m'], // I am 的缩写
1121
+            'don\'t': ['don\'t'], // do not 的缩写
1122
+            'doesn\'t': ['doesn\'t'], // does not 的缩写
1123
+            'we\'re': ['we are'],
1124
+            'they\'re': ['they are'],
1125
+            'you\'re': ['you are'],
1126
+            'he\'s': ['he is', 'he has'],
1127
+            'she\'s': ['she is', 'she has'],
1128
+            'it\'d': ['it would', 'it had'],
1129
+            'we\'d': ['we would', 'we had'],
1130
+            'they\'d': ['they would', 'they had'],
1131
+            'couldn\'t': ['could not'],
1132
+            'should\'ve': ['should have'],
1133
+            'would\'ve': ['would have'],
1134
+            'could\'ve': ['could have']
1135
+        };
1136
+        
1137
+        // 如果是特殊单词,直接返回预定义的变形
1138
+        if (specialWords[lowerWord]) {
1139
+            specialWords[lowerWord].forEach(form => allForms.add(form));
1140
+            return [...allForms];
1141
+        }
1142
+        
1143
+        // 检查是否是特殊单词的变形
1144
+        for (const [base, forms] of Object.entries(specialWords)) {
1145
+            if (forms.includes(lowerWord)) {
1146
+                forms.forEach(form => allForms.add(form));
1147
+                return [...allForms];
1148
+            }
1149
+        }
1150
+        
1151
+        // 获取单词的原形(基本形式)
1152
+        const possibleBaseWords = [];
1153
+        
1154
+        // 特殊单词列表,这些单词不应被识别为任何变形
1155
+        const specialBaseWords = ['this', 'is', 'was', 'has', 'his', 'its', 'us', 'yes', 'thus', 'plus'];
1156
+        if (specialBaseWords.includes(lowerWord)) {
1157
+            possibleBaseWords.push(lowerWord);
1158
+            return [...allForms];
1159
+        }
902 1160
         
1161
+        // 处理规则变形
903 1162
         // 处理过去式/过去分词 (-ed)
904 1163
         if (lowerWord.endsWith('ed')) {
905 1164
             possibleBaseWords.push(lowerWord.slice(0, -2)); // 常规情况 (walked -> walk)
@@ -992,7 +1251,7 @@ export const stringUtils = {
992 1251
         if (lowerWord.endsWith('ily')) {
993 1252
             possibleBaseWords.push(lowerWord.slice(0, -3) + 'y'); // 如 happily -> happy
994 1253
         }
995
-        
1254
+
996 1255
         // 处理复数形式
997 1256
         if (lowerWord.endsWith('s') && !lowerWord.endsWith('ss')) {
998 1257
             possibleBaseWords.push(lowerWord.slice(0, -1)); // 常规情况 (books -> book)
@@ -1040,6 +1299,195 @@ export const stringUtils = {
1040 1299
         // 去重并过滤掉过短的单词
1041 1300
         const uniqueBaseWords = [...new Set(possibleBaseWords)].filter(w => w.length >= 2);
1042 1301
         
1043
-        return uniqueBaseWords;
1302
+        // 如果没有找到任何可能的原形,或者所有可能的原形都不是有效单词,则返回单词本身
1303
+        if (uniqueBaseWords.length === 0 || !uniqueBaseWords.some(w => w === lowerWord || w.length >= 3)) {
1304
+            // 清空可能不正确的原形
1305
+            uniqueBaseWords.length = 0;
1306
+            uniqueBaseWords.push(lowerWord);
1307
+        }
1308
+        
1309
+        // 添加所有可能的原形到变形集合中
1310
+        uniqueBaseWords.forEach(base => allForms.add(base));
1311
+        
1312
+        // 判断词性的简单启发式规则
1313
+        const adjectiveSuffixes = ['ful', 'ous', 'ive', 'ic', 'al', 'ent', 'ant', 'able', 'ible', 'ary', 'ory', 'ish'];
1314
+        const verbSuffixes = ['ize', 'ise', 'ate', 'ify', 'en'];
1315
+        const nounSuffixes = ['tion', 'sion', 'ment', 'ness', 'ity', 'hood', 'ship', 'dom', 'ism', 'ist'];
1316
+        const adverbSuffixes = ['ly', 'ward', 'wise'];// 副词后缀
1317
+
1318
+        
1319
+        // 一些常见的形容词
1320
+        const commonAdjectives = ['good', 'bad', 'big', 'small', 'high', 'low', 'long', 'short', 'old', 'new', 
1321
+                                 'fast', 'slow', 'hard', 'soft', 'hot', 'cold', 'warm', 'cool', 'rich', 'poor', 
1322
+                                 'thick', 'thin', 'wide', 'narrow', 'deep', 'shallow', 'strong', 'weak', 'young', 
1323
+                                 'old', 'bright', 'dark', 'light', 'heavy', 'easy', 'hard', 'clean', 'dirty', 
1324
+                                 'full', 'empty', 'dry', 'wet', 'sick', 'healthy', 'loud', 'quiet', 'sweet', 
1325
+                                 'sour', 'bitter', 'nice', 'mean', 'kind', 'cruel', 'brave', 'afraid', 'happy', 
1326
+                                 'sad', 'angry', 'calm', 'busy', 'free', 'cheap', 'expensive', 'safe', 'dangerous'];
1327
+        
1328
+        // 一些常见的动词
1329
+        const commonVerbs = ['go', 'come', 'get', 'give', 'make', 'take', 'put', 'set', 'let', 'run', 'move', 
1330
+                            'walk', 'talk', 'look', 'see', 'hear', 'feel', 'think', 'know', 'find', 'want', 
1331
+                            'need', 'use', 'try', 'ask', 'work', 'call', 'help', 'play', 'stop', 'start', 
1332
+                            'turn', 'show', 'tell', 'say', 'write', 'read', 'sing', 'eat', 'drink', 'sleep', 
1333
+                            'sit', 'stand', 'lie', 'fall', 'rise', 'leave', 'reach', 'like', 'love', 'hate', 
1334
+                            'hope', 'live', 'die', 'buy', 'sell', 'pay', 'build', 'break', 'cut', 'open', 'close'];
1335
+        
1336
+        // 检查是否是形容词
1337
+        let isLikelyAdjective = adjectiveSuffixes.some(suffix => lowerWord.endsWith(suffix)) || 
1338
+                            commonAdjectives.includes(lowerWord) ||
1339
+                            (lowerWord.length <= 6 && !nounSuffixes.some(suffix => lowerWord.endsWith(suffix)));
1340
+
1341
+        // 检查是否是动词
1342
+        let isLikelyVerb = verbSuffixes.some(suffix => lowerWord.endsWith(suffix)) || 
1343
+                        commonVerbs.includes(lowerWord) ||
1344
+                        (lowerWord.length <= 5 && !adjectiveSuffixes.some(suffix => lowerWord.endsWith(suffix)) && 
1345
+                        !nounSuffixes.some(suffix => lowerWord.endsWith(suffix)));
1346
+
1347
+        // 检查是否是副词
1348
+        let isLikelyAdverb = adverbSuffixes.some(suffix => lowerWord.endsWith(suffix));
1349
+                
1350
+        // 动词变形 (如果可能是动词)
1351
+        if (isLikelyVerb && lowerWord.length >= 2) {
1352
+            // 第三人称单数
1353
+            if (lowerWord.endsWith('s') || lowerWord.endsWith('x') || lowerWord.endsWith('ch') || lowerWord.endsWith('sh') || lowerWord.endsWith('z')) {
1354
+                allForms.add(lowerWord + 'es');
1355
+            } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1356
+                allForms.add(lowerWord.slice(0, -1) + 'ies');
1357
+            } else {
1358
+                allForms.add(lowerWord + 's');
1359
+            }
1360
+            
1361
+            // 过去式和过去分词 (-ed)
1362
+            if (lowerWord.endsWith('e')) {
1363
+                allForms.add(lowerWord + 'd');
1364
+            } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1365
+                allForms.add(lowerWord.slice(0, -1) + 'ied');
1366
+            } else if (lowerWord.length > 2 && 
1367
+                      !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1368
+                      ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1369
+                      !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1370
+                // 双写末尾辅音字母的情况,如 stop -> stopped
1371
+                allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'ed');
1372
+            } else {
1373
+                allForms.add(lowerWord + 'ed');
1374
+            }
1375
+            
1376
+            // 现在分词 (-ing)
1377
+            if (lowerWord.endsWith('ie')) {
1378
+                allForms.add(lowerWord.slice(0, -2) + 'ying');
1379
+            } else if (lowerWord.endsWith('e') && lowerWord.length > 2) {
1380
+                allForms.add(lowerWord.slice(0, -1) + 'ing');
1381
+            } else if (lowerWord.length > 2 && 
1382
+                      !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1383
+                      ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1384
+                      !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1385
+                // 双写末尾辅音字母的情况,如 run -> running
1386
+                allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'ing');
1387
+            } else {
1388
+                allForms.add(lowerWord + 'ing');
1389
+            }
1390
+        }
1391
+        
1392
+        // 形容词和副词变形 (如果可能是形容词或副词)
1393
+        if ((isLikelyAdjective || isLikelyAdverb) && lowerWord.length >= 3 && 
1394
+            !lowerWord.endsWith('ing') && !lowerWord.endsWith('ed') && 
1395
+            lowerWord.length <= 8) { // 限制长度,避免生成不必要的变形
1396
+            
1397
+            // 检查是否是多音节形容词,这些通常使用 more/most 而不是 -er/-est
1398
+            const isMultisyllabic = lowerWord.length > 7 || 
1399
+                                   lowerWord.endsWith('ful') || 
1400
+                                   lowerWord.endsWith('ous') || 
1401
+                                   lowerWord.endsWith('ive') || 
1402
+                                   lowerWord.endsWith('ic') || 
1403
+                                   lowerWord.endsWith('al') || 
1404
+                                   lowerWord.endsWith('ent') || 
1405
+                                   lowerWord.endsWith('ant') || 
1406
+                                   lowerWord.endsWith('able') || 
1407
+                                   lowerWord.endsWith('ible');
1408
+            
1409
+            // 只为短形容词生成比较级和最高级
1410
+            if (!isMultisyllabic) {
1411
+                // 比较级 (-er)
1412
+                if (lowerWord.endsWith('e')) {
1413
+                    allForms.add(lowerWord + 'r');
1414
+                } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1415
+                    allForms.add(lowerWord.slice(0, -1) + 'ier');
1416
+                } else if (lowerWord.length > 2 && 
1417
+                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1418
+                          ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1419
+                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1420
+                    // 双写末尾辅音字母的情况,如 big -> bigger
1421
+                    allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'er');
1422
+                } else {
1423
+                    allForms.add(lowerWord + 'er');
1424
+                }
1425
+                
1426
+                // 最高级 (-est)
1427
+                if (lowerWord.endsWith('e')) {
1428
+                    allForms.add(lowerWord + 'st');
1429
+                } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1430
+                    allForms.add(lowerWord.slice(0, -1) + 'iest');
1431
+                } else if (lowerWord.length > 2 && 
1432
+                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 1)) && 
1433
+                          ['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2)) && 
1434
+                          !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 3))) {
1435
+                    // 双写末尾辅音字母的情况,如 big -> biggest
1436
+                    allForms.add(lowerWord + lowerWord.charAt(lowerWord.length - 1) + 'est');
1437
+                } else {
1438
+                    allForms.add(lowerWord + 'est');
1439
+                }
1440
+            }
1441
+            
1442
+            // 副词变形 (-ly),只为真正的形容词生成副词形式
1443
+            if (!lowerWord.endsWith('ly')) {
1444
+                if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1445
+                    allForms.add(lowerWord.slice(0, -1) + 'ily');
1446
+                } else if (lowerWord.endsWith('le')) {
1447
+                    allForms.add(lowerWord.slice(0, -1) + 'y');
1448
+                } else {
1449
+                    allForms.add(lowerWord + 'ly');
1450
+                }
1451
+            }
1452
+        }
1453
+        
1454
+        // 名词复数形式 (对大多数单词都适用)
1455
+        if (lowerWord.length >= 2 && !lowerWord.endsWith('ing') && !lowerWord.endsWith('ed')) {
1456
+            if (lowerWord.endsWith('s') || lowerWord.endsWith('x') || lowerWord.endsWith('ch') || lowerWord.endsWith('sh') || lowerWord.endsWith('z')) {
1457
+                allForms.add(lowerWord + 'es');
1458
+            } else if (lowerWord.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(lowerWord.charAt(lowerWord.length - 2))) {
1459
+                allForms.add(lowerWord.slice(0, -1) + 'ies');
1460
+            } else if (lowerWord.endsWith('f')) {
1461
+                allForms.add(lowerWord.slice(0, -1) + 'ves');
1462
+            } else if (lowerWord.endsWith('fe')) {
1463
+                allForms.add(lowerWord.slice(0, -2) + 'ves');
1464
+            } else {
1465
+                allForms.add(lowerWord + 's');
1466
+            }
1467
+        }
1468
+        
1469
+        return [...allForms];
1044 1470
     },
1471
+    
1472
+    /**
1473
+     * 检查单词是否符合特定的变形规则
1474
+     * @param {string} word - 要检查的单词
1475
+     * @param {string} base - 基本形式
1476
+     * @returns {boolean} - 是否符合变形规则
1477
+     */
1478
+    checkSpecialWordForms(word, base) {
1479
+        // 使用 getWordAllForms 获取基本形式的所有可能变形
1480
+        const baseForms = this.getWordAllForms(base);
1481
+        if (baseForms.includes(word)) {
1482
+            return true;
1483
+        }
1484
+        
1485
+        // 反向检查:如果 word 是基本形式,base 是变形
1486
+        const wordForms = this.getWordAllForms(word);
1487
+        if (wordForms.includes(base)) {
1488
+            return true;
1489
+        }
1490
+        
1491
+        return false;
1492
+    }
1045 1493
 }