aardio 文档
aardio 范例: COCA 20000 词汇表
import fonts.fontAwesome;
import win.ui;
/*DSG{{*/
winform = win.form(text="COCA 20000 词汇表";right=963;bottom=598;bgcolor=0xFFFFFF)
winform.add(
btnAskAi={cls="plus";text="问 AI";left=889;top=570;right=955;bottom=599;align="left";bgcolor=0xFFFFFF;color=0x3C3C3C;db=1;dr=1;font=LOGFONT(h=-13);iconColor=0x5757FF;iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF0AA';notify=1;textPadding={left=25};z=4};
btnPractice={cls="plus";text="练习";left=586;top=570;right=651;bottom=599;align="left";bgcolor=0xFFFFFF;color=0x3C3C3C;db=1;dl=1;font=LOGFONT(h=-13);iconColor=0x5757FF;iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF02D';notify=1;textPadding={left=25};z=17};
btnSearch={cls="plus";left=851;top=570;right=881;bottom=596;align="left";border={bottom=1;color=0xFF969696};color=0x3C3C3C;db=1;dr=1;font=LOGFONT(h=-13);iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF002';notify=1;textPadding={left=25};z=14};
btnVoice={cls="plus";text="朗读";left=652;top=570;right=717;bottom=599;align="left";bgcolor=0xFFFFFF;color=0x3C3C3C;db=1;dl=1;font=LOGFONT(h=-13);iconColor=0x008000;iconStyle={align="left";font=LOGFONT(h=-13;name='FontAwesome');padding={left=8}};iconText='\uF028';notify=1;textPadding={left=25};z=5};
chkCet4={cls="checkbox";text="CET4";left=189;top=572;right=241;bottom=597;bgcolor=0xFFFFFF;db=1;dl=1;z=9};
chkCet6={cls="checkbox";text="CET6";left=242;top=572;right=294;bottom=597;bgcolor=0xFFFFFF;db=1;dl=1;z=10};
chkGk={cls="checkbox";text="高考";left=135;top=572;right=187;bottom=597;bgcolor=0xFFFFFF;db=1;dl=1;z=8};
chkGsl={cls="checkbox";text="通用";left=456;top=572;right=508;bottom=597;bgcolor=0xFFFFFF;db=1;dl=1;z=18};
chkIelts={cls="checkbox";text="雅思";left=296;top=572;right=348;bottom=597;bgcolor=0xFFFFFF;db=1;dl=1;z=11};
chkKy={cls="checkbox";text="考研";left=402;top=572;right=454;bottom=597;bgcolor=0xFFFFFF;db=1;dl=1;z=13};
chkMeaning={cls="checkbox";text="释义";left=20;top=572;right=72;bottom=597;bgcolor=0xFFFFFF;db=1;dl=1;z=6};
chkNewWords={cls="checkbox";text="生词本";left=509;top=572;right=573;bottom=597;bgcolor=0xFFFFFF;db=1;dl=1;z=16};
chkToefl={cls="checkbox";text="托福";left=349;top=572;right=401;bottom=597;bgcolor=0xFFFFFF;db=1;dl=1;z=12};
chkZk={cls="checkbox";text="中考";left=82;top=572;right=134;bottom=597;bgcolor=0xFFFFFF;db=1;dl=1;z=7};
custom={cls="custom";text="自定义控件";left=572;top=20;right=958;bottom=562;db=1;dr=1;dt=1;z=2};
editKeyword={cls="plus";left=706;top=570;right=851;bottom=596;align="right";border={bottom=1;color=0xFF969696};db=1;dl=1;dr=1;editable="edit";font=LOGFONT(h=-13);notify=1;textPadding={top=3;bottom=3};z=15};
listview={cls="vlistview";left=20;top=20;right=567;bottom=562;db=1;dl=1;dt=1;edge=1;fullRow=1;z=1};
splitter={cls="splitter";left=567;top=20;right=572;bottom=562;db=1;dr=1;dt=1;frame=1;z=3}
)
/*}}*/
import table.coca20000;
winform.listview.columns = [["词频",50],["单词",100],["音标",100],["释义",0],["分类",-1]]
var fields = ["word","phonetic","meaning","tag"]
//虚表
var dataset = table.coca20000;
winform.listview.onGetDispItem = function(item,row,col){
if(col==1) return {text = tostring(row)};
return{ text=dataset[row][fields[col-1]]};
}
import win.ui.grid;
win.ui.grid(winform.listview);//双击显示文本框
import web.form.chat;
var chatUi = web.form.chat(winform.custom);
chatUi.doScript("
document.onmouseup = document.onselectionchange = function() {
var text = '';
if (window.getSelection) {
var selection = window.getSelection();
if (selection.rangeCount === 0) {
return null;
}
text = selection.toString();
} else if (document.selection && document.selection.type != 'Control') {
text = document.selection.createRange().text;
}
if(text) external.onSelectedText(text)
};")
winform.btnAskAi.skin({
color={
active=0xFF00FF00;
default=0xFF3C3C3C;
disabled=0xFF999999;
hover=0xFFFF0000
}
})
winform.btnAskAi.oncommand = function(id,event){
var word = winform.listview.selectedWord;
if(!#word) return winform.msgboxErr("请先点选单词");
import win.dlg.flashDict;
win.dlg.flashDict(winform,word).doModal();
}
import com.wmPlayer;
var soundUrlCache = table.cache();
var pronounce = function(word,site){
var url;
if(site=="youdao"){
url = "https://dict.youdao.com/dictvoice?audio="+word+"&type=2"
}
else{
url = soundUrlCache[word] || ..thread.invokeAndWait(
function(word){
import web.rest.htmlClient;
var http = web.rest.htmlClient();
var webster = http.api("https://www.merriam-webster.com/dictionary/","GET");
var htmlDoc = webster[word].get();//抓取韦氏词典网页
var ele = htmlDoc.queryEle({"class":"play-pron-v2"});//获取指定 HTML 元素
var url;
if(ele && ele["data-dir"] && ele["data-file"]){
//合成韦氏词典美式发音链接
url = "https://media.merriam-webster.com/audio/prons/en/us/mp3/" + ele["data-dir"] + "/" + ele["data-file"] + ".mp3"
}
else{
//合成柯林斯词典美式发音链接
url = "https://www.collinsdictionary.com/sounds/hwd_sounds/en_us_"+string.lower(word)+".mp3"
}
return url;
} ,word
)
soundUrlCache[word] = url;
if(winform.btnVoice.disabledText) winform.btnVoice.disabledText = ['\uF026','\uF027','\uF028'];
}
com.wmPlayer.url = url;
}
import fsys.table;
var config = fsys.table(io.appData("aardio/std/tools/coca2000.table"),{newWords={}});
import string.words;
import string.fuzzyMatching;
winform.listview.onSelChanged = function(selected,item,subItem,nmListView){
chatUi.cocaSentence = null;
fsys.delete("\coca20000-sentence-tts.mp3");
var word = winform.listview.getItemText(item,2);
var meaning = winform.listview.getItemText(item,4);
if((winform.listview.selectedWord == winform.editKeyword.text)
|| !#winform.editKeyword.text){
winform.editKeyword.text = word;
}
winform.listview.selectedWord = word;
winform.listview.selectedWordMeaning = '##### '+word + ' ' + winform.listview.getItemText(item,3)
+ '\r\n\r\n##### ' + meaning
var meaning2 = string.words(word);
if(meaning2) {
meaning2 = string.replace(meaning2,"[,;]","\0 ");
var fuzzyMatching = string.fuzzyMatching(meaning)
if( fuzzyMatching.match(meaning2) < 0.5 ){
winform.listview.selectedWordMeaning = winform.listview.selectedWordMeaning
+ '\r\n\r\n##### ' + meaning2;
}
}
var wordInfo = dataset[item]
if(wordInfo && wordInfo.sentence){
winform.listview.selectedWordMeaning = winform.listview.selectedWordMeaning
+ '\r\n\r\n<br>例句:\r\n\r\n ' + string.replace(wordInfo.sentence,'\n',' <a style="cursor:pointer;font-size:16px;" href="javascript:void(0)" onclick="javascript:external.tts()">🔊</a>\n<br>');
chatUi.cocaSentence = string.match(wordInfo.sentence,"(.+?)<::>?=");
}
if(!winform.btnAskAi.disabled){
var card = winform.listview.selectedWordMeaning
++ ( config.newWords[word] ? "":'\r\n\r\n---\r\n<a href="javascript:void(0)" onclick="javascript:external.newWords();this.innerText=\'已添加到生词本\'">添加到生词本</a>')
chatUi.write(card)
}
pronounce(word,"youdao")
}
winform.splitter.split(winform.listview,winform.custom);
winform.btnVoice.skin({
color={
active=0xFF00FF00;
default=0xFF3C3C3C;
disabled=0xFF999999;
hover=0xFFFF0000
}
})
import web.edgeTextToSpeech;
import bass.channel;
winform.btnVoice.oncommand = function(id,event){
var word = winform.listview.selectedWord;
if(!word) return winform.msgboxErr("请先点选单词");
winform.btnVoice.disabledText = ['\uF254','\uF251','\uF252','\uF253','\uF250'];
pronounce(word,"webster");
thread.delay(1500);
winform.btnVoice.disabledText = null;
}
winform.chkMeaning.oncommand = function(){
winform.listview.setRedraw(false);
if(owner.checked){
winform.listview.setColumnWidth(0,5);
winform.listview.fillParent(4);
}
else{
winform.listview.setColumnWidth(0,4);
winform.listview.fillParent(5);
}
winform.listview.setRedraw(true);
}
var tip = /*
- COCA(Corpus of Contemporary American English, 美国当代英语语料库)20000 词汇。
原表有 22000 个词,合并词性不同的重复条目并添加 NGSL 词汇后共计 17649 个词(区分大小写)。
按词频排序,单词使用频率越高则排序越是靠前。
- 点选单词调用有道词典发音,点选「朗读」按钮则调用韦氏词典加载真人发音。
- 点单词显示例句,点例句后的「🔊」可以仿真人语音朗读例句。
每个例句首次朗读时要略等一会,按住 <kbd>Shift</kbd> 键点「🔊」可以较慢速度朗读。
在 「🔊」链接获得焦点时也可以按 <kbd>Enter</kbd> 键朗读例句。
- 在释义与例句页面内双击选中单词可显示中文释义。
- 双击列表项可切换到编辑框模式。
- 列表项右键菜单 ☑ 勾选「生词本」可添加单词到生词本,也可点击「根据生词本生成例句」菜单项。
- 可勾选下方中考、高考、CET4、CET6、雅思、托福、考研等分类标签。
不勾选任何分类标签则显示全部词汇。
*/
chatUi.write(tip);
import win.ui.menu;
winform.listview.onRightClick = function(item,subItem,nmListView){
var popmenu = win.ui.popmenu(winform);
if(item){
var word = winform.listview.getItemText(item,2);
var id = popmenu.add('生词本',function(id){
config.newWords[word] = !popmenu.checked(1) ? true : null;
config.save();
winform.listview.redraw();
});
popmenu.check(1,!!config.newWords[word]);
}
popmenu.add();
popmenu.add('清空生词本',function(id){
config.newWords = {};
config.save();
winform.chkNewWords.oncommand();
});
popmenu.add('复制生词本',function(id){
var newWords = config.newWords;
var words = []
for(i=1;#dataset;1){
if(newWords[dataset[i].word]){
table.push(words,i + " " +dataset[i].word);
}
}
import win.clip;
win.clip.write( string.join(words,'\r\n') )
});
popmenu.add();
popmenu.add('生词本练习',function(id){
winform.loadForm("/coca2000.practice.aardio")
});
popmenu.popup();
}
var filter = function(){
var p = []
if(winform.chkZk.checked) table.push(p,"<zk>");
if(winform.chkGk.checked) table.push(p,"<gk>");
if(winform.chkCet4.checked) table.push(p,"<cet4>");
if(winform.chkCet6.checked) table.push(p,"<cet6>");
if(winform.chkIelts.checked) table.push(p,"<ielts>");
if(winform.chkToefl.checked) table.push(p,"<toefl>");
if(winform.chkKy.checked) table.push(p,"<ky>");
if(winform.chkGsl.checked) table.push(p,"<gl>");
if(!#p){
dataset = table.coca20000;
}
else{
p = "!\w"+string.join(p,"|");
dataset = []
for(i,wordInfo in table.coca20000){
if(wordInfo.tag && string.find(wordInfo.tag,p)){
table.push(dataset,wordInfo);
}
}
}
if(winform.chkNewWords.checked){
var newWords = config.newWords;
var dataset2 = []
for(i,v in dataset){
if(newWords[v.word]){
table.push(dataset2,v);
}
}
dataset = dataset2;
}
winform.listview.count = #dataset;
winform.listview.redraw();
}
winform.chkZk.oncommand = filter;
winform.chkGk.oncommand = filter;
winform.chkCet4.oncommand = filter;
winform.chkCet6.oncommand = filter;
winform.chkIelts.oncommand = filter;
winform.chkToefl.oncommand = filter;
winform.chkKy.oncommand = filter;
winform.chkGsl.oncommand = filter;
winform.chkNewWords.oncommand = filter;
winform.bindConfig( config,{
checkbox = "checked";
} );
winform.chkMeaning.oncommand();
filter();
winform.listview.onnotify = function(id,code,ptr){
if( code == 0xFFFFFFF4/*_NM_CUSTOMDRAW*/ ){
var lvcd = winform.listview.getNotifyCustomDraw(code,ptr);
if( lvcd.nmcd.dwDrawStage == 0x10001/*_CDDS_ITEMPREPAINT*/)
return 0x20/*_CDRF_NOTIFYSUBITEMDRAW*/
elseif( lvcd.nmcd.dwDrawStage == 1/*_CDDS_PREPAINT*/ ){
return 0x20/*_CDRF_NOTIFYITEMDRAW*/;
}
elseif( lvcd.nmcd.dwDrawStage == ( 0x10001/*_CDDS_ITEMPREPAINT*/ | 0x20000/*_CDDS_SUBITEM*/) ){
//注意这里 iSubItem 的索引自0开始( 其他函数通常自1开始 )
lvcd.clrText = 0x000000;
var word = dataset[lvcd.nmcd.dwItemSpec+1][["word"]]
if(word && config.newWords[word]){
lvcd.clrText = 0x0000FF;
}
lvcd.update();
return 0/*_CDRF_DODEFAULT*/
}
}
}
import win.ui.mask;
var mask = win.ui.mask(winform);
mask.add(
plus={cls="plus";marginBottom=20;marginLeft=550;width=370;height=400;color=0x008000;
font=LOGFONT(h=-96;name='FontAwesome');valign="bottom";
})
import win.debounce;
chatUi.external = {
onDragImageStart = function(imageUrl){
winform.setTimeout( function(){
import key;
key.press("ESC");
var frmImage = win.form(text="aardio form";right=359;bottom=359;border="none";max=false;topmost=1)
frmImage.add(
btnClose={cls="close";text="×";left=327;top=5;right=355;bottom=33;bgcolor=0xCC8B94;dr=1;dt=1;font=LOGFONT(h=-21);z=2};
plus={cls="plus";left=0;top=0;right=360;bottom=360;db=1;dl=1;dr=1;dt=1;repeat="scale";z=1}
)
frmImage.btnClose.show(true);
frmImage.btnClose.oncommand = function(id,event){
frmImage.close();
}
frmImage.onMouseDown = function(wParam,lParam){
frmImage.hitCaption();
}
import win.ui.shadow;
win.ui.shadow(frmImage);
import inet.http;
frmImage.plus.background = imageUrl;
frmImage.show();
frmImage.hitCaption();
chatUi.write(winform.listview.selectedWordMeaning);
},1);
};
newWords = function(){
config.newWords[winform.listview.selectedWord] = true;
config.save();
};
onSelectedText = win.debounce(function(text,left,top,right,bottom){
import winex.tooltip;
if(#text){
var meaning,word = string.words(text);
if(meaning){
var x,y = win.getMessagePos();
y = y + winform.dpiScale(25)
winex.tooltip.balloon(meaning,x,y);
if(!winform.btnVoice.disabled){
pronounce(word,"youdao");
}
return;
}
}
winex.tooltip.balloon(false);
},500);
tts = function(){
if(chatUi.cocaSentence){
if(winform.btnVoice.disabledText) return;
import key;
var slower = key.getState("Shift");
var playMp3 = function(){
winform.btnVoice.disabledText = ['\uF026','\uF027','\uF028'];
var audio = bass.channel.open(string.load("\coca20000-sentence-tts.mp3"));
audio.syncCallback(function(data){
audio.free()
winform.btnVoice.disabledText = null;
},2/*_BASS_SYNC_END*/)
if(slower){
audio.setSpeed(0.85);
}
audio.play()
return;
}
if( io.exist("\coca20000-sentence-tts.mp3") ){
return playMp3();
}
mask.show();
mask.plus.disabledText = ['\uF254','\uF251','\uF252','\uF253','\uF250'];
winform.btnVoice.disabledText = ['\uF254','\uF251','\uF252','\uF253','\uF250'];
var tts = web.edgeTextToSpeech(chatUi.cocaSentence,"\coca20000-sentence-tts.mp3")
tts.voiceOptions.name = "en-US-AriaNeural"
tts.voiceOptions.rate = "-10%"
tts.OnResponseEnd = function(path){
mask.plus.disabledText = null;
mask.show(false);
return playMp3();
}
tts.OnError = function(sender, e){
winform.btnVoice.disabledText = null;
mask.plus.disabledText = null;
mask.show(false);
}
//连接服务器,合成语音
tts.ConnectAsync();
return;
}
};
}
winform.btnSearch.skin({
color={
active=0xFF00FF00;
default=0xFF3C3C3C;
disabled=0xFF6D6D6D;
hover=0xFFFF0000
}
})
winform.btnSearch.oncommand = function(id,event){
var p = string.trim(winform.editKeyword.text);
if(!#p) {
winform.msgboxErr("请输入搜索词,支持模式匹配语法!");
winform.editKeyword.setFocus();
return;
}
var count = winform.listview.count;
var selIndex = winform.listview.selIndex;
if(!selIndex || selIndex >= count ){
selIndex = 1;
}
else{
selIndex++;
}
for(i=selIndex;count;1){
var wordInfo = dataset[i]
if(string.find(wordInfo.word,p)){
winform.listview.selIndex = i;
winform.listview.ensureVisible(i);
return;
}
}
if(selIndex>2){
for(i=1;selIndex-2;1){
var wordInfo = dataset[i]
if(string.find(wordInfo.word,p)){
winform.listview.selIndex = i;
winform.listview.ensureVisible(i);
return;
}
}
}
winform.msgboxErr("找不到下一个匹配的单词!");
winform.editKeyword.setFocus();
}
winform.editKeyword.setCueBannerText("请输入搜索词,支持模式匹配语法");
winform.editKeyword.editBox.onOk = function(ctrl,alt,shift){
winform.btnSearch.oncommand();
return true;
}
winform.btnPractice.skin({
color={
active=0xFF00FF00;
default=0xFF3C3C3C;
disabled=0xFF6D6D6D;
hover=0xFFFF0000
}
})
winform.btnPractice.oncommand = function(id,event){
winform.loadForm("/coca2000.practice.aardio")
}
winform.editKeyword.editBox.disableInputMethod();
winform.show(3/*_SW_MAXIMIZE*/);
import com.autoComplete;
var aco = com.autoComplete(winform.editKeyword);
var items = []
for(k,v in table.coca20000){
table.push(items,v.word);
}
aco.setStrings(items);
win.loopMessage();
Markdown 格式