elleryq
12/30/2014 - 9:11 PM

gistfile1.py

#!/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()