Created
December 30, 2014 16:54
-
-
Save anonymous/f59fb16cb67ba1a19efc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # -*- coding: utf8 -*- | |
| import sys, os | |
| import sqlite3 | |
| import urllib.request | |
| #import requests | |
| import subprocess | |
| from urwid import * | |
| import pdb | |
| # 整體變數部份 #{ | |
| lPartOfSpeech = ( | |
| ('冠詞', 0x0001, 'art.' ), | |
| ('名詞', 0x0002, 'n.' ), | |
| ('形容詞', 0x0004, 'adj.' ), | |
| ('動詞', 0x0008, 'v.' ), | |
| ('副詞', 0x0010, 'adv.' ), | |
| ('介係詞', 0x0020, 'prop.'), | |
| ('助動詞', 0x0040, 'aux.' ), | |
| ('代名詞', 0x0080, 'pron.'), | |
| ('連接詞', 0x0100, 'conj.'), | |
| ('感嘆詞', 0x0200, 'int.' ) | |
| ) | |
| dPStypes = {lPartOfSpeech[i][0]:(1<<i, i) for i in range(len(lPartOfSpeech))} | |
| dPSnum = {1<<i:lPartOfSpeech[i][0] for i in range(len(lPartOfSpeech))} | |
| C_coding = sys.getfilesystemencoding() | |
| C_agent = {'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.165063 Safari/537.36 AppEngine-Google."} | |
| #}----------------------------------------------------------------------------- | |
| def playSound(filename): #{ | |
| if os.path.isfile(filename): | |
| with open(os.devnull, 'w') as f: | |
| subprocess.call(["mplayer", filename], stdout=f, stderr=f) | |
| #}----------------------------------------------------------------------------- | |
| def textToSound(source, filename='/tmp/out.wav'): #{ | |
| #sudo apt-get install libttspico-utils | |
| try: | |
| #cmd = 'pico2wave -w {0} "{1}"'.format(filename, source) | |
| #subprocess.call(cmd, shell=True) | |
| subprocess.call(['pico2wave', '-w', filename, '"{}"'.format(source)]) | |
| playSound(filename) | |
| except Exception as e: | |
| raise e | |
| #} | |
| def translate(source, to_l="zh-TW", from_l="en"): #{ | |
| flag = 'class="t0">' | |
| urlstr = 'http://translate.google.com/m?hl=%s&sl=%s&q=%s \ | |
| ' % (to_l, from_l, source.replace(" ", "%20")) | |
| result = '' | |
| try: | |
| request = urllib.request.Request(urlstr, headers=C_agent) | |
| #page = urllib.request.urlopen(request) | |
| page = str(urllib.request.urlopen(request).read().decode(C_coding)) | |
| result = page[page.find(flag) + len(flag):] | |
| result = result.split("<")[0] | |
| except urllib.error.HTTPError as e: | |
| pass | |
| #with open('{}.html'.format(source), 'w') as f: | |
| # f.write(page) | |
| #soup = _soup(page.read()) | |
| #t = soup.p.findNext() | |
| #result = ','.join([s for s in [str(x) for x in t.contents] if s[0] != '<']) | |
| return result | |
| #}----------------------------------------------------------------------------- | |
| def downloadmp3(source, filename='/tmp/out.mp3', from_l="en"): #{ | |
| #urlstr = 'http://translate.google.com/translate_tts' | |
| #with open(filename, 'wb') as f: | |
| # payload = { | |
| # 'ie' : 'UTF-8', | |
| # 'tl' : from_l, | |
| # 'q' : source } | |
| # try: | |
| # r = requests.get(urlstr, params=payload) | |
| # for chunk in r.iter_content(chunk_size=1024): | |
| # f.write(chunk) | |
| # except Exception as e: | |
| # raise | |
| urlstr = "http://translate.google.com/translate_tts?ie=UTF-8&tl={0:s}&q={1:s}".format(from_l, source.replace(" ", "%20")) | |
| request = urllib.request.Request(urlstr, headers=C_agent) | |
| try: | |
| response = urllib.request.urlopen(request) | |
| with open(filename, 'wb') as f: | |
| f.write(response.read()) | |
| #time.sleep(1) | |
| except urllib.error.HTTPError as e: | |
| pass | |
| if os.path.exists(filename): | |
| playSound(filename) | |
| #}----------------------------------------------------------------------------- | |
| class cEngDict: #{ | |
| # 類別私有變數 #{ | |
| __sPOSstr = '' | |
| __db = None | |
| __cur = None | |
| __sqldbcreate = ''' | |
| CREATE TABLE IF NOT EXISTS DictWord( | |
| SN INTEGER PRIMARY KEY NOT NULL, | |
| WORD CHAR(64) NOT NULL, | |
| PTWORD CHAR(64), | |
| PPWORD CHAR(64), | |
| VOICE BLOB, | |
| UNIQUE(WORD) | |
| ); | |
| CREATE TABLE IF NOT EXISTS DictState( | |
| SN INTEGER PRIMARY KEY NOT NULL, | |
| W_SN INTEGER NOT NULL, | |
| TYPES INTEGER, | |
| CHINA CHAR(64), | |
| SENTENCE CHAR(255), | |
| TRANSLATE CHAR(255) | |
| ); | |
| ''' | |
| #}------------------------------------------------------------------------- | |
| def __init__(self, dbname='./EnglishDict.db'): #{ | |
| for i in range(len(lPartOfSpeech)): | |
| if (i > 0)and(i % 5 == 0): | |
| self.__sPOSstr += '\n' | |
| if len(lPartOfSpeech[i][0]) == 2: | |
| self.__sPOSstr += "{0}: {1} ".format(i, lPartOfSpeech[i][0]) | |
| else: | |
| self.__sPOSstr += "{0}: {1} ".format(i, lPartOfSpeech[i][0]) | |
| self.__sPOSstr += '\n詞性:' | |
| self.dbname = dbname | |
| self.db = sqlite3.connect(dbname) | |
| try: | |
| self.db.executescript(self.__sqldbcreate) | |
| except Exception as e: | |
| self.db.rollback() | |
| raise e | |
| #}------------------------------------------------------------------------- | |
| def __del__(self): #{ | |
| self.db.commit() | |
| #}------------------------------------------------------------------------- | |
| def add(self, word, vptword='', vppword='', **data): #{ | |
| if type(word) is not str and word == '': return | |
| if type(data) is not dict and len(data) == 0: return | |
| WordSN = 1 | |
| sqlstr = '''SELECT SN FROM DictWord ORDER BY SN DESC LIMIT 1;''' | |
| dbRec = self.db.execute(sqlstr).fetchone() | |
| if type(dbRec) is not type(None): | |
| WordSN += dbRec[0] | |
| sqlstr = '''SELECT SN, WORD FROM DictWord WHERE WORD=="{0}";'''.format(word) | |
| dbRec = self.db.execute(sqlstr).fetchone() | |
| if type(dbRec) is not type(None): | |
| WordSN = dbRec[0] | |
| if type(dbRec) is type(None): | |
| hVoice = None | |
| try: | |
| #if not os.path.isfile('/tmp/out.mp3'): return | |
| #with open("/tmp/out.mp3", "rb") as f: | |
| # hVoice = f.read() | |
| if (data['types'] & dPStypes['動詞'][0] == 0) or (vptword == ''): | |
| # self.db.execute('INSERT INTO DictWord(SN, WORD, VOICE) VALUES(?,?,?)', | |
| # [ | |
| # WordSN, | |
| # word, | |
| # sqlite3.Binary(hVoice) | |
| # ]); | |
| sqlstr = '''INSERT INTO DictWord (SN, WORD) \ | |
| VALUES ({0}, "{1}")'''.format(WordSN, word) | |
| else: | |
| # self.db.execute('INSERT INTO DictWord(SN, WORD, PTWORD, PPWORD, VOICE) VALUES(?,?,?,?,?)', | |
| # [ | |
| # WordSN, | |
| # word, | |
| # vptword, | |
| # vppword, | |
| # sqlite3.Binary(hVoice) | |
| # ]); | |
| sqlstr = '''INSERT INTO DictWord (SN, WORD, PTWORD, PPWORD) \ | |
| VALUES ({0}, "{1}", "{2}", "{3}")'''.format(WordSN, word, | |
| vptword, vppword) | |
| self.db.execute(sqlstr) | |
| finally: | |
| del hVoice | |
| #os.remove('/tmp/out.mp3') | |
| sqlstr = '''SELECT SENTENCE FROM DictState WHERE SENTENCE=="{0}";'''.format( | |
| data['sentence']) | |
| dbRec = self.db.execute(sqlstr).fetchone() | |
| if type(dbRec) is not type(None): return | |
| sqlstr = '''INSERT INTO DictState (W_SN, TYPES, CHINA, SENTENCE, TRANSLATE) \ | |
| VALUES ({0}, {1}, "{2}", "{3}", "{4}");'''.format( | |
| WordSN, | |
| data['types'], | |
| data['china'], | |
| data['sentence'], | |
| data['translate'] | |
| ) | |
| self.db.execute(sqlstr) | |
| self.db.commit() | |
| #print('--------------===[ 資料添加成功 ]===--------------') | |
| #}------------------------------------------------------------------------- | |
| def NewWord(self): #{ | |
| sWord = input("\n單 字:").strip() | |
| iTypes = 0 | |
| sPTsWord = '' | |
| sPPsWord = '' | |
| lType = [int(x) for x in input(self.__sPOSstr).split()] | |
| if dPStypes['動詞'][1] in lType: | |
| sIsIrregular = input("不規則動詞?").strip() | |
| if (len(sIsIrregular) > 1) and (sIsIrregular[0] in ['y', 'Y']): | |
| sPTsWord = input('過 去 式:') | |
| sPPsWord = input('過去分詞:') | |
| for i in lType: | |
| iTypes = iTypes | lPartOfSpeech[i][1] | |
| sChina = input('中文解釋:').strip() | |
| sSentence = input('英文範例:').strip() | |
| sTranslate = input('中文解釋:').strip() | |
| print('\n{0}\n{1}\n{2}\n{3}\n{4}'.format(sWord, iTypes, sChina, sSentence, sTranslate)) | |
| sYesOrNo = input('\n資料是否正確?') | |
| if (len(sYesOrNo) > 0) and (sYesOrNo[0] in ['y', 'Y']): | |
| self.add(sWord, types=iTypes, china=sChina, sentence=sSentence, translate=sTranslate) | |
| sYesOrNo = input("\n繼續輸入?") | |
| if (len(sYesOrNo) > 0) and (sYesOrNo[0] in ['n', 'N']): | |
| return False | |
| else: | |
| return True | |
| #}------------------------------------------------------------------------- | |
| #} | |
| class DictInputListBox(ListBox): #{ | |
| # 類別私有變數 #{ | |
| __ltypekeys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', 'backspace', 'enter']; | |
| __yesorno = ['y', 'Y', 'n', 'N', ' ', 'backspace', 'enter']; | |
| __steps = 0; | |
| __word = ''; | |
| __ltypes = [] | |
| __types = 0; | |
| __irreuglar = False; | |
| __ptword = ''; | |
| __ppword = ''; | |
| __china = ''; | |
| __sentence = ''; | |
| __translate = ''; | |
| __current = False; | |
| __qfunc = [] | |
| __stepsfunc = [] | |
| __db = None; | |
| #} | |
| def __init__(self): #{ | |
| body = SimpleFocusListWalker([self.__inputWord()]); | |
| super(DictInputListBox, self).__init__(body); | |
| self.__steps = 0; | |
| sPOSstr = '' | |
| for i in range(len(lPartOfSpeech)): | |
| if (i >0) and (i % 5 == 0): | |
| sPOSstr += '\n' | |
| if len(lPartOfSpeech[i][0]) == 2: | |
| sPOSstr += "{0}: {1} ".format(i, lPartOfSpeech[i][0]) | |
| else: | |
| sPOSstr += "{0}: {1} ".format(i, lPartOfSpeech[i][0]) | |
| sPOSstr += '\n詞 性:' | |
| self.__qfunc = [ | |
| self.__inputWord(), # 0 | |
| Pile([Edit(('Qcolor', sPOSstr))]), # 1 | |
| Pile([Edit(('Qcolor', '不 規 則?'))]), # 2 | |
| Pile([Edit(('Qcolor', '過 去 式:'))]), # 3 | |
| Pile([Edit(('Qcolor', '過去分詞:'))]), # 4 | |
| Pile([Edit(('Qcolor', '中文解釋:'))]), # 5 | |
| Pile([Edit(('Qcolor', '英文範例:'))]), # 6 | |
| Pile([Edit(('Qcolor', '中文翻譯:'))]), # 7 | |
| Pile([Edit(('Qcolor', '是否正確?'))]), # 8 | |
| Pile([Edit(('Qcolor', '是否繼續?'))]) # 9 | |
| ]; | |
| self.__stepsfunc = [ | |
| self.step_00, # 檢查單字 | |
| self.step_01, # 檢查詞性 | |
| self.step_02, # 檢查規則動詞 | |
| self.step_03, # 檢查過去式動詞 | |
| self.step_04, # 檢查過去分詞 | |
| self.step_05, # 檢查中文解釋 | |
| self.step_06, # 檢查英文範例 | |
| self.step_07, # 檢查中文翻譯 | |
| self.step_08, # 檢查資料是否正 | |
| self.step_09 # 判斷是否離開 | |
| ]; | |
| self.__db = cEngDict() | |
| #}------------------------------------------------------------------------- | |
| def __del__(self): #{ | |
| if self.__db is not None: | |
| del self.__db; | |
| self.__db = None; | |
| #}------------------------------------------------------------------------- | |
| def __inputWord(self): #{ | |
| return Pile([Edit(('Qcolor', "單 字:"))]) | |
| #}------------------------------------------------------------------------- | |
| def __switchChina(self): #{ | |
| try: | |
| import virtkey | |
| v = virtkey.virtkey() | |
| v.press_keysym(65505) | |
| v.press_unicode(ord(' ')) | |
| v.release_unicode(ord(' ')) | |
| v.release_keysym(65505) | |
| pass | |
| except Exception as e: | |
| raise e | |
| #}------------------------------------------------------------------------- | |
| def keypress(self, size, key): #{ overload | |
| if key == 'up': | |
| return None; | |
| elif key == 'esc': | |
| if self.__db is not None: | |
| del self.__db; | |
| self.__db = None; | |
| raise ExitMainLoop() | |
| elif self.__steps == 1: | |
| if key not in self.__ltypekeys: | |
| return None; | |
| elif self.__steps in [2, 8, 9]: | |
| if key not in self.__yesorno: | |
| return None; | |
| key = super(DictInputListBox, self).keypress(size, key); | |
| if key != 'enter': | |
| return key; | |
| else: | |
| data = self.focus[0].edit_text; | |
| pos = self.focus_position | |
| if not data: | |
| if self.__steps == 2: | |
| data = 'n' | |
| self.focus[0].set_edit_text(data) | |
| self.__stepsfunc[self.__steps](data, pos); | |
| if self.__steps > 0: | |
| self.focus_position = pos+1 | |
| elif self.__steps in [8, 9]: | |
| data = 'y' | |
| self.focus[0].set_edit_text(data) | |
| self.__stepsfunc[self.__steps](data, pos); | |
| if self.__steps > 0: | |
| self.focus_position = pos+1 | |
| else: | |
| self.body.clear() | |
| self.body.insert(1, self.__qfunc[9]) | |
| self.__steps = 9 | |
| else: | |
| self.__stepsfunc[self.__steps](data, pos); | |
| if self.__steps > 0: | |
| self.focus_position += 1 | |
| self.focus[0].set_edit_text('') | |
| #}------------------------------------------------------------------------- | |
| # 檢查單字 | |
| def step_00(self, data, pos): #{ | |
| self.__word = data.strip() | |
| #textToSound(self.__word) | |
| downloadmp3(self.__word) | |
| self.body.insert(pos+1, self.__qfunc[1]) | |
| self.__steps = 1; | |
| #}------------------------------------------------------------------------- | |
| # 檢查詞性 | |
| def step_01(self, data, pos): #{ | |
| self.__types = 0 | |
| self.__ltypes = [int(x) for x in data.split() if x.isdigit()] | |
| if dPStypes['動詞'][1] in self.__ltypes: | |
| self.body.insert(pos+1, self.__qfunc[2]) | |
| self.__steps = 2 | |
| else: | |
| self.body.insert(pos+1, self.__qfunc[5]) | |
| self.__steps = 5 | |
| self.__switchChina(); | |
| #}------------------------------------------------------------------------- | |
| # 檢查規則動詞 | |
| def step_02(self, data, pos): #{ | |
| if data.strip()[0] in ['n', 'N']: | |
| self.__irreuglar = False; | |
| self.body.insert(pos+1, self.__qfunc[5]) | |
| self.__steps = 5; | |
| self.__switchChina(); | |
| else: | |
| self.__irreuglar = True | |
| self.body.insert(pos+1, self.__qfunc[3]) | |
| self.__steps = 3; | |
| #}------------------------------------------------------------------------- | |
| # 檢查過去式動詞 | |
| def step_03(self, data, pos): #{ | |
| self.__ptword = data.strip() | |
| textToSound(self.__ptword, filename='/tmp/ptout.wav') | |
| #downloadmp3(self.__ptword, filename='/tmp/ptout.mp3') | |
| self.body.insert(pos+1, self.__qfunc[4]) | |
| self.__steps = 4; | |
| #}------------------------------------------------------------------------- | |
| # 檢查過去分詞 | |
| def step_04(self, data, pos): #{ | |
| self.__ppword = data.strip() | |
| testToSound(self.__ppword, filename='/tmp/ppout.wav') | |
| #downloadmp3(self.__ppword, filename='/tmp/ppout.mp3') | |
| self.body.insert(pos+1, self.__qfunc[5]) | |
| self.__steps = 5; | |
| self.__switchChina(); | |
| #}------------------------------------------------------------------------- | |
| # 檢查中文解釋 | |
| def step_05(self, data, pos): #{ | |
| if len(self.__ltypes) > 0: | |
| for i in self.__ltypes: | |
| self.__types |= lPartOfSpeech[i][1] | |
| self.__china = data.strip() | |
| self.body.insert(pos+1, self.__qfunc[6]) | |
| self.__steps = 6; | |
| else: | |
| self.body.insert(pos+1, self.__qfunc[1]) | |
| self.__steps = 1 | |
| self.__switchChina(); | |
| #}------------------------------------------------------------------------- | |
| # 檢查英文範例 | |
| def step_06(self, data, pos): #{ | |
| self.__sentence = data.strip() | |
| #textToSound(self.__sentence, filename='/tmp/sentence.wav') | |
| downloadmp3(self.__sentence, filename='/tmp/sentence.mp3') | |
| self.body.insert(pos+1, self.__qfunc[7]) | |
| self.__steps = 7; | |
| self.__switchChina(); | |
| #}------------------------------------------------------------------------- | |
| # 檢查中文翻譯 | |
| def step_07(self, data, pos): #{ | |
| self.__translate = data.strip(); | |
| if self.__irreuglar: | |
| dataText = Pile([Text(('Acolor', | |
| "\n單字: {0} (原型: {1} 過去式: {2} 過去分詞: {3})\n" | |
| "詞性: {4}\n解釋: {5}\n範例: {6}\n翻譯: {7}\n".format( | |
| self.__word, | |
| self.__word, | |
| self.__ptword, | |
| self.__ppword, | |
| self.__types, | |
| self.__china, | |
| self.__sentence, | |
| self.__translate | |
| ) | |
| ))]); | |
| else: | |
| dataText = Pile([Text(('Acolor', | |
| "\n單字: {0}\n詞性: {1}\n解釋: {2}\n範例: {3}\n翻譯: {4}\n".format( | |
| self.__word, | |
| self.__types, | |
| self.__china, | |
| self.__sentence, | |
| self.__translate, | |
| ) | |
| ))]); | |
| self.body.insert(pos+1, dataText) | |
| self.focus_position = pos+1 | |
| self.body.insert(self.focus_position+1, self.__qfunc[8]) | |
| self.__steps = 8; | |
| self.__switchChina(); | |
| #}------------------------------------------------------------------------- | |
| # 檢查資料是否正 | |
| def step_08(self, data, pos): #{ | |
| if data.strip()[0] in ['n', 'N']: | |
| self.body.clear() | |
| self.body.insert(1, self.__qfunc[0]) | |
| self.__steps = 0 | |
| else: | |
| # 保存資料 並重新設定參數 | |
| self.__db.add( | |
| self.__word, | |
| vptword = self.__ptword, | |
| vppword = self.__ppword, | |
| types = self.__types, | |
| china = self.__china, | |
| sentence = self.__sentence, | |
| translate = self.__translate | |
| ); | |
| self.__current = False; | |
| self.body.insert(pos+1, self.__qfunc[9]) | |
| self.__steps = 9; | |
| #}------------------------------------------------------------------------- | |
| # 判斷是否離開 | |
| def step_09(self, data, pos): #{ | |
| if not data: return | |
| if data.strip()[0] in ['n', 'N']: | |
| if self.__db is not None: | |
| del self.__db; | |
| self.__db = None; | |
| raise ExitMainLoop() | |
| else: | |
| self.body.clear() | |
| self.body.insert(1, self.__qfunc[0]) | |
| self.__steps = 0 | |
| self.focus[0].set_edit_text('') | |
| #}------------------------------------------------------------------------- | |
| #} | |
| def main(): #{ | |
| #try: | |
| # eDict = cEngDict() | |
| # bQuit = True | |
| # while bQuit: | |
| # bQuit = eDict.NewWord() | |
| #finally: | |
| # del eDict | |
| #""" | |
| # 'black', 'dark red', 'dark green', 'brown', 'dark blue', | |
| # 'dark magenta', 'dark cyan', 'light gray', 'dark gray', | |
| # 'light red', 'light green', 'yellow', 'light blue', | |
| # 'light magenta', 'light cyan', 'white' | |
| #""" | |
| palette = [ | |
| ('Qcolor', 'light magenta, bold', 'black'), | |
| ('Acolor', 'light green', 'black'), | |
| ]; | |
| loop = MainLoop(DictInputListBox(), palette); | |
| loop.screen.set_terminal_properties(colors=256) | |
| loop.run() | |
| #} | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment