├── .gitignore ├── .travis.yml ├── README.md ├── __init__.py ├── addon ├── UIForm │ ├── README.md │ ├── __init__.py │ ├── delete.png │ ├── done.png │ ├── failed.png │ ├── icons_rc.py │ ├── icons_rc.qrc │ ├── loginDialog.py │ ├── loginDialog.ui │ ├── mainUI.py │ ├── main_ui.ui │ ├── wait.png │ ├── wordGroup.py │ └── word_group.ui ├── __init__.py ├── addonWindow.py ├── constants.py ├── dictionary │ ├── README.md │ ├── __init__.py │ ├── eudict.py │ └── youdao.py ├── logger.py ├── loginDialog.py ├── misc.py ├── noteManager.py ├── queryApi │ ├── README.md │ ├── __init__.py │ ├── bing.py │ ├── eudict.py │ └── youdao.py └── workers.py ├── anki_addon_page.tpl ├── config.json ├── deploy.py ├── requirements.txt ├── screenshots ├── del.gif └── sync.gif └── test ├── __init__.py ├── dummy_anki ├── __init__.py ├── dummy_collection.py ├── dummy_deck.py ├── dummy_models.py └── dummy_notes.py ├── dummy_aqt ├── __init__.py ├── dummyConfig.json └── dummy_addon.py ├── dummy_noteManager.py ├── pytest.ini ├── test_main.py └── test_queryapi.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | meta.json 3 | .DS_Store 4 | __pycache__ 5 | .pytest_cache 6 | *.log 7 | *.zip 8 | venv -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: true 3 | language: python 4 | python: 5 | - '3.6' 6 | services: 7 | - xvfb 8 | install: 9 | - pip install -r requirements.txt 10 | - export PYTHONPATH=$TRAVIS_BUILD_DIR 11 | - export PYTHONDONTWRITEBYTECODE=1 12 | script: xvfb-run --server-args="-screen 0 1024x768x24" pytest -v 13 | env: 14 | global: 15 | - ANKI_ADDON_ID: 1284759083 16 | - secure: ZtwnARLqggwl5aoQIPl8gdE3Y8CkRjSFKkdDtjC+hLqKu3YB5+2JfxqjImID1jFSVjOsAGLtWu1GZpAz93V/lQDiiZdAAVeAbTIBOXXB27Vkl9vsZKHXrC5AYCdc0pRxLswduXjUSCbv32N+JSQZe/GIkEdeiqb72LOTFYjlh99RS3jbYEg4YMq5Ovgj20YRY1vLRS6/0/+iZiVrJZE3alo67+zyI0UkUGZ1k6rp5fhqZA5pKfzURets73L71/FPF2aOJB6SaXAbyWQDdi0uRs8uNGsHYtUNzEQ2OHJjrzp6Ai7g97V905be8dxgVYPPGoQdYBLGhaCicCegjlSsmEjzLbYOlyOF7PVtLUiF/gr7OVLijlNr1HBpbfaSnXzbZ9tdWu6hXxPKnD2sLzjadM+nLLg7Sw2GuSGo5rCr8lTq0G3hoOLadyy5TBHkh0d1X23htuD5B1r24X1Jds7uUyHguUlRP//F2Zl0f4D8rul/2SwKQjQb9QS5gl7DE7/mmN2HmPnIdSVq0iD8HqI1POfAw4O9P6jTcFgOnwnGarE/3ylc++vbvMS5qxsJ3vxs0Yli4F7mT444fU/QG2nAG+8Qfxh6CLmDgpsczJptpaP5ve/bGcr8oNvMYMi3KkX31O/KGoY7BmRFSKRSLX1qDqbu6jIdGdO9a4vcAlcmRDo= 17 | - secure: TxUc+x+HMq7kJKSkpmqciKIW2hf58WHhXStfWvTiScPK+cFGEpYM0rjAPWPM9JLoTcWPsIZIQrfggNLLorFXuALiqrvXw5RJvYIzPv8/sfigdW0OjZqDPLWFun8a34Xa0EGhrqO4Q0UXQodHV+LkDnNozdoofwBkTAAuc4XGxgNga2usDARCnQ8AnxkUJs5Uz+Y605Qk42PzxRh5CLT9QNPyCPa9MMpBl9S9pMmG/4f/1HN7U+aOv908TuWYUx3JwB2j7in/cqXdRvnYHp6RwWth+IC1tXY0maxWXbJ85V9k2sjkRnaDUUwD1KHiDWxtiDsDPtshJyA+S1jMbCETRuueqCTL3JK8rEKx+5FYfrzL7Am/gbJ5Jbg/ESSGiSuf4NOyEkwxM1xTjOnepZd0DN0IQd1ZSWQME+QTPkoBD5i/1hLZz70cpGJLdTIH5NaqW7JcDwhZRVF/q++1JmI1TZxwhbw87vTlTAWODWvHKliETQLer1lONeABvD7x2FVGpG7gFxBBmAeEmPC7mz4XjFJ04YC24LDSP5aEZJVke8LdiyNN4tMsEVyncessh0njYNFfzXlexxdHp7VUkCAbSQyM6Sj65+ELZFvLUvFSOuRtcMfZFgQik6yl7ypbkO/9wu00PUa8T3vZlpOCmieJgfsGHSw8SYuE+zpiv5J8tcM= 18 | 19 | deploy: 20 | - provider: script 21 | script: python deploy.py 22 | on: 23 | branch: master 24 | 25 | - provider: releases 26 | api-key: 27 | secure: dRGQfrEcQJyhKjk7LNv4HHFvUPQWsHDuaAp1oqs0LuxjSz0Mb3LcbMJzEdqqNcnL1DN777Vm82Fwy5zxI23xPVgUdmwlkxualV/gC6mzIBlUHk5CHzV1Rx2uczWWyglRiGKHyOoL6JDIk7FULuPyKUT75uTC5GRS3K1q7u07lsXu8pr9P7+Esv0YuR59cQtMEZ93aiIXnRFoFMqZ5h2hHaifd6GYfn6ojOqJKXOTRbC8sCOx6ZGTB34ZJ9jNPD7fnQjpsh+WyErrW8f9TXwN2eDLUDFpgy54gPx15GzmmbTFZ+zX1YtpPQbtS0YAIAWJZl0WuZ9o2XNUgpVZfWJ7Gy/vLbFn7ZBQZs+vVpp8OiDAgwaq2GciQZhBs/noXe8whRT2v753j0YoaMLcx59viJHfRdMTgGnqeavS5lxzSM5g1oSenRfatDg2bs/FGX1UVpjeY6wOrTt46W6O79nP3YTZmWmRO25TEbPJ3SH8uDj3ofLOcnUngnEeCTfiLED8CIDEY0B/WUyb8KJ5EGrZQHhodGse/YCXNafkviiVNsoNqWgWhWtGhW/AuIeiGUw2KlwQppigyK/162tzYWy5+xvOLqQXPiFbZWMJSHDaxusvoIE5J8CK8tKzXNa3+QCoYnLyQSF2B/P9KepuBzn47VBL25NJAwoMedKprCt1SbY= 28 | file_glob: true 29 | file: Dict2Anki-*.zip 30 | skip_cleanup: false 31 | draft: true 32 | on: 33 | branch: master -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Dict2Anki 3 | [![Build Status](https://travis-ci.org/megachweng/Dict2Anki.svg?branch=master)](https://travis-ci.org/megachweng/Dict2Anki) 4 | 5 | **Dict2Anki** 是一款方便[有道词典](http://cidian.youdao.com/multi.html)、[欧陆词典](https://www.eudic.net/)用户同步生成单词本卡片至[Anki](https://apps.ankiweb.net/#download)的插件 6 | 7 | 8 | ### Change log 9 | **个人精力有限不再维护** 10 | ___ 11 | * v6.1.6 12 | * 修复ARM Mac启动日志出错的问题 THX to @xbot 13 | * v6.1.5 14 | * 更新有道词典API,解决首次登录无法唤出登陆页的问题 15 | * v6.1.4 16 | * 修复Anki 2.1.4版本同步失败的问题 THX to @YLongo 17 | * 修复Anki 2.1.4版本首次同步默认到Default Deck的问题 18 | * v6.1.3 19 | 修复欧陆字典无法登录的问题 THX to @cythb 20 | * v6.1.2 21 | 修复有道单词本分组获取失败的问题 22 | * v6.1.1 23 | 添加欧陆词典查询API THX to @wd 24 | * v6.1.0 25 | * 支持第三方登陆 26 | * 加入模版字段检查 27 | * v6.0.2 28 | 添加英英注释 THX to deluser8 29 | * v6.0.1 30 | 修复菜单栏不雅词汇 31 | * v6.0.0 32 | * 导入指定单词分组 33 | * 添加必应(bing)词典查询API 34 | * 添加待删除单词列表,可选择需要删除的 Anki 卡片 35 | * 恢复卡片 *短语字段* 36 | * 一些UI优化 37 | * 重构代码,解决上版本奔溃问题 38 | * 添加单元测试 39 | 40 | 41 | ### How to install 42 | Anki --> 工具 --> 附加组件 --> 获取插件 43 | 插件代码:1284759083 44 | ### How to use 45 | 同步 46 | 47 | 48 | 同步删除 49 | 50 | 51 | ### Contribute Guide 52 | 非常欢迎你的贡献,请PR前确保通过了全部单元测试 `pytest test` 53 | 54 | ### Development Guide 55 | Python > 3.6 56 | ``` 57 | export PYTHONPATH='xxx/Dict2Anki' 58 | export DEVDICT2ANKI=1 59 | pip install -r requirements.txt 60 | python __init__.py 61 | ``` 62 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | try: 2 | from aqt import mw 3 | from .addon.addonWindow import Windows 4 | from PyQt5.QtWidgets import QAction 5 | 6 | 7 | def showWindow(): 8 | w = Windows() 9 | w.exec() 10 | 11 | 12 | action = QAction("Dict2Anki...", mw) 13 | action.triggered.connect(showWindow) 14 | mw.form.menuTools.addAction(action) 15 | 16 | except ImportError: 17 | import os 18 | from PyQt5.QtWidgets import QApplication 19 | from addon.addonWindow import Windows 20 | import sys 21 | if os.environ.get('DEVDICT2ANKI'): 22 | app = QApplication(sys.argv) 23 | window = Windows() 24 | window.show() 25 | sys.exit(app.exec()) 26 | -------------------------------------------------------------------------------- /addon/UIForm/README.md: -------------------------------------------------------------------------------- 1 | ## Qt designer UI 2 | > 不可更改 `mainUI.py`, `wordGroup.py`, `icon_rc.py` 3 | 4 | -------------------------------------------------------------------------------- /addon/UIForm/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megachweng/Dict2Anki/4fe993d83d73e0a4ed3090330241d0a9de22b009/addon/UIForm/__init__.py -------------------------------------------------------------------------------- /addon/UIForm/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megachweng/Dict2Anki/4fe993d83d73e0a4ed3090330241d0a9de22b009/addon/UIForm/delete.png -------------------------------------------------------------------------------- /addon/UIForm/done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megachweng/Dict2Anki/4fe993d83d73e0a4ed3090330241d0a9de22b009/addon/UIForm/done.png -------------------------------------------------------------------------------- /addon/UIForm/failed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megachweng/Dict2Anki/4fe993d83d73e0a4ed3090330241d0a9de22b009/addon/UIForm/failed.png -------------------------------------------------------------------------------- /addon/UIForm/icons_rc.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Resource object code 4 | # 5 | # Created by: The Resource Compiler for PyQt5 (Qt v5.9.3) 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore 10 | 11 | qt_resource_data = b"\ 12 | \x00\x00\x22\x2a\ 13 | \x89\ 14 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ 15 | \x00\x00\xc8\x00\x00\x00\xc8\x08\x06\x00\x00\x00\xad\x58\xae\x9e\ 16 | \x00\x00\x20\x00\x49\x44\x41\x54\x78\x5e\xed\x7d\x6b\x98\x5d\x45\ 17 | \x95\xf6\x5a\x75\xba\xd3\x4d\x04\x21\x01\x11\x62\x94\xd0\xb4\xe9\ 18 | \xee\xaa\x6a\x6e\x41\x91\xbb\xe2\x05\x71\x46\x18\x11\x44\xc1\x1b\ 19 | \x88\x32\x23\x82\x28\x88\xb7\xf1\x32\x9f\x8c\xc8\x80\xe3\x28\x2a\ 20 | \xf8\x0d\x0e\xf8\xa9\xa0\x0e\x38\x78\x47\x3e\x18\x87\x81\x5c\x40\ 21 | \xc3\xad\xab\xaa\x4f\x67\x3a\x31\x2a\x06\x11\xc5\x00\x81\x34\xe9\ 22 | \xd3\xb5\xe6\xa9\x78\x0e\x34\x6d\xd2\x7b\xd7\x39\xb5\xcf\xae\x7d\ 23 | \x7a\xd7\xf3\xf4\xd3\x3f\xce\xaa\x55\xab\xde\xaa\x77\xd7\xbe\x54\ 24 | \xbd\x0b\xa1\x2c\xd1\x20\xc0\x39\x5f\x08\x00\x47\x30\xc6\x0e\x26\ 25 | \xa2\xbd\x00\x60\x4f\x44\x64\xd3\x03\x24\xa2\xcd\x44\xb4\x12\x00\ 26 | \x7e\x06\x00\x77\x18\x63\xb6\x44\xd3\x81\x0e\x0c\x04\x3b\xb0\x4f\ 27 | \x85\xe9\x92\x94\xf2\xb9\xd6\xda\x23\x11\xf1\x28\x44\x3c\x92\x88\ 28 | \x24\x22\xfa\x8c\xc9\x9f\x00\xe0\x72\x6b\xed\x65\xc6\x98\xdf\x15\ 29 | \xa6\xe3\x05\x0a\xd4\x67\x30\x0a\xd4\xad\x38\x43\x95\x52\x3e\x7f\ 30 | \x3a\x21\x00\x60\x20\x50\xa4\x93\x00\xf0\x05\x6b\xed\x47\xca\x15\ 31 | \x25\x10\xa2\x75\x37\x25\x41\xc2\xe2\xf9\x0c\x6f\x9c\xf3\x7e\xc6\ 32 | \x98\x5b\x19\x8e\x04\x00\xb7\x4a\x2c\xc9\xb0\x39\x20\xa2\xd1\xa9\ 33 | \xa9\xa9\x93\xab\xd5\xea\x48\x96\xed\xcc\x25\xdf\x25\x41\x02\x8e\ 34 | \x36\xe7\x9c\xd7\x09\xe1\xc8\x70\x34\x00\xec\x1e\xd0\x7d\x2a\x57\ 35 | \x44\xb4\x85\x88\xde\x60\x8c\xf9\x5e\xaa\x0a\xa5\xd1\xac\x08\x94\ 36 | \x04\x69\x61\x82\x2c\x5d\xba\x74\xb7\x79\xf3\xe6\x9d\x44\x44\xaf\ 37 | \x00\x80\x97\x22\xa2\x7b\xc8\xce\xbd\x10\x11\x21\xe2\x59\x4a\xa9\ 38 | \xcb\x73\x0f\xa6\xe0\x01\x94\x04\xf1\x1f\x40\x14\x42\xbc\x15\x11\ 39 | \x4f\x23\xa2\x23\x66\xbe\x65\xf2\x77\x97\x5d\x0d\x6b\xed\xc9\xc6\ 40 | \x98\xef\x64\xd7\x42\xe7\x7b\x2e\x09\xe2\x31\xc6\x52\xca\x57\x01\ 41 | \xc0\x67\x01\x40\x7a\x54\xcb\xd3\xf4\x09\x6b\xed\x7e\xc6\x98\xf1\ 42 | \x3c\x83\x28\x72\xdb\x25\x41\x52\x8c\x1e\xe7\x7c\x47\x44\xfc\x1a\ 43 | \x22\x9e\x90\xc2\xbc\x69\x13\x22\x72\xaf\x6a\x6f\x47\xc4\xdb\x01\ 44 | \x60\xb9\x52\xea\x1e\x00\xa0\xe1\xe1\xe1\xbd\x88\xa8\xdf\x5a\x3b\ 45 | \xcc\x18\x7b\x23\x00\x1c\xe4\xd1\xc8\x88\x52\x6a\x7f\x00\xb0\x1e\ 46 | \x75\x4a\xd3\x3a\x02\x25\x41\x12\xa6\xc2\xe0\xe0\xe0\xb2\x4a\xa5\ 47 | \x72\x3d\x22\xba\x0f\x77\xa1\x4b\x95\x88\x1c\x19\xb6\x92\x42\x29\ 48 | \xb5\x36\x4d\x03\x9c\xf3\xe3\x18\x63\xff\x9a\xf6\x25\x80\xb5\xf6\ 49 | \x74\x63\xcc\x55\x69\x7c\x97\x36\xcf\x44\xa0\x24\xc8\x2c\x33\x82\ 50 | \x73\x2e\x10\x71\x25\x22\xee\x14\x60\xe2\xb8\x6f\x15\xab\x1d\x19\ 51 | \xac\xb5\x8e\x14\xb7\x19\x63\x1e\x6e\xd6\x6f\x7f\x7f\xff\x73\x7a\ 52 | \x7a\x7a\x1c\x71\x8f\x48\xe1\xe3\xfe\x9e\x9e\x9e\xbe\xd5\xab\x57\ 53 | \xbb\x18\xca\xe2\x81\x40\x49\x90\xed\x80\x35\x3c\x3c\xdc\x57\xdf\ 54 | \xd2\xd1\xd4\xab\x5a\x22\x7a\x14\x00\x56\xb8\x95\xc1\xfd\x6d\xde\ 55 | \xbc\x79\xd5\xf8\xf8\xf8\x93\x1e\x63\x93\xc6\xb4\x22\x84\xf8\x11\ 56 | \x22\x1e\x93\x64\x4c\x44\xef\xd4\x5a\x5f\x99\x64\x57\xfe\x5e\xae\ 57 | \x20\x69\xe6\x40\x97\x94\xd2\x5d\xed\xf7\x4d\x63\xec\xbe\x3d\x20\ 58 | \xe2\x3a\x00\xb8\xb7\xbe\x3a\xdc\x6e\x8c\xb9\xaf\x1d\xf7\xfd\x43\ 59 | \x43\x43\x7b\x56\x2a\x15\x03\x00\xbb\xcc\x16\x2b\x11\xdd\xa4\xb5\ 60 | \x4e\x24\x52\x9a\xfe\x36\x63\xc3\x39\xdf\x83\x31\x76\xa8\xb5\xf6\ 61 | \x25\x8c\xb1\x03\x88\xc8\xed\x31\xbb\x1f\x00\xdc\x0b\x84\xf1\xfa\ 62 | \x2d\xe6\x6f\x9a\xf1\x9d\x65\x9d\x72\x05\xd9\x06\xba\x52\xca\x4f\ 63 | \x00\xc0\x27\xd3\x00\x4f\x44\x57\xd6\x6a\xb5\xf7\x8f\x8d\x8d\x3d\ 64 | \x96\xc6\x3e\x0b\x1b\xce\xf9\x79\x8c\xb1\x4b\x13\x7c\x4f\x59\x6b\ 65 | \x77\x6f\xe5\xb6\xce\x23\x76\x36\x38\x38\x28\x1c\x21\x18\x63\x87\ 66 | \x01\x80\xfb\xeb\x4b\x8a\x0f\x00\xae\x01\x80\x0f\x28\xa5\x1e\xf4\ 67 | \x68\x2b\x53\xd3\x92\x20\x33\xe0\x1d\x18\x18\x18\xe8\xee\xee\x56\ 68 | \x00\xd0\x95\x80\xbc\xdb\x28\xf8\x46\xa5\xd4\x4d\x99\x8e\x50\x0a\ 69 | \xe7\xfd\xfd\xfd\x3d\xbd\xbd\xbd\x0f\x00\xc0\x82\xd9\xcc\xad\xb5\ 70 | \xa7\x1a\x63\xdc\x24\x0c\x5a\x16\x2d\x5a\x34\x7f\xc1\x82\x05\x07\ 71 | \xd7\x89\xe0\xc8\x70\x28\x22\x3e\xbb\xc9\x46\x36\x5a\x6b\xdf\x66\ 72 | \x8c\xf9\x7e\x93\xf5\x83\x56\x2b\x09\x32\x03\x4e\xce\xf9\x95\x8c\ 73 | \xb1\x77\x24\xa0\xbc\xb1\x56\xab\x1d\x5c\xad\x56\xd7\x04\x1d\x8d\ 74 | \x16\x9c\x71\xce\xbf\xcc\x18\xfb\xbb\x04\x17\x97\x29\xa5\xce\x69\ 75 | \xa1\x99\xad\x55\x07\x06\x06\x16\x55\x2a\x95\xad\x2b\x43\x7d\x85\ 76 | \x38\x00\x00\x2a\xad\xfa\x9d\x56\x7f\x8a\x88\xde\xac\xb5\xfe\x56\ 77 | \x40\x9f\x4d\xb9\x2a\x09\x32\x0d\xb6\x7d\xf6\xd9\x67\xf7\xde\xde\ 78 | \xde\xdf\x20\xe2\xbc\xed\xa1\x49\x44\x76\x6a\x6a\xea\xf0\x6a\xb5\ 79 | \xea\xce\x64\x44\x53\xa4\x94\xaf\x03\x80\xef\xce\x16\x10\x11\xdd\ 80 | \xa9\xb5\x76\x57\x7a\x9f\xc2\x84\x10\xc3\xd3\x56\x87\xc3\x32\x7a\ 81 | \xe5\xfd\x8c\x98\xdc\x73\x9d\xb5\x76\xd9\xe8\xe8\xa8\x5b\xcd\x73\ 82 | \x2b\x25\x41\xa6\x41\x2f\xa5\x3c\x1f\x00\x2e\x49\x18\x8d\x8b\x94\ 83 | \x52\x1f\xc9\x6d\xc4\xb6\xd3\xf0\xe0\xe0\xe0\xae\x5d\x5d\x5d\x7f\ 84 | \x98\xf1\xf3\x24\x11\xdd\xed\x3e\x3a\xba\xbf\x27\x9f\x7c\xf2\xbf\ 85 | \xc7\xc7\xc7\x1f\x9a\x2d\x76\xf7\x51\x14\x00\xb6\xde\x2e\x21\xa2\ 86 | \x5b\x25\x0e\x09\xf4\x9a\xdb\x1b\x32\x22\x32\x5a\x6b\xf7\xa2\x64\ 87 | \xca\xbb\x72\xa0\x0a\x25\x41\xa6\x01\x29\x84\xb8\x71\xb6\x57\xa6\ 88 | \x6e\xf5\xb0\xd6\x2e\x1e\x1d\x1d\x75\xf7\xfb\xd1\x95\xfa\x9b\x37\ 89 | \xf7\x35\x7e\x39\x22\x2e\x7f\xec\xb1\xc7\xee\x58\xbf\x7e\xfd\xc4\ 90 | \x6c\x81\xba\x33\x2a\x44\xd4\x78\x90\x76\xff\xf7\x8b\x69\x7f\x99\ 91 | \xb5\xf6\x6f\x8d\x31\x5f\xc9\x0b\xec\x92\x20\x4f\x23\xdf\x25\x84\ 92 | \xd8\x84\x88\x3d\xb3\x0c\xc6\xcd\x4a\xa9\x57\xe6\x35\x58\x01\xda\ 93 | \xad\x70\xce\xdd\x15\xb9\xb1\x3a\xb8\xd3\x8c\x8b\x02\xf8\xcd\xd2\ 94 | \xc5\x2a\xa5\xd4\x21\x59\x36\x30\x9b\xef\x92\x20\x75\x74\xa4\x94\ 95 | \x6e\xe2\xdc\x3b\x1b\x58\xd6\xda\xf3\x8d\x31\x6e\xb3\x62\x21\xca\ 96 | \xc0\xc0\xc0\x4e\xdd\xdd\xdd\x2f\x99\xfe\x76\x09\x00\xe6\x17\x22\ 97 | \xf8\x7a\x90\x6e\xeb\x3e\x11\xed\xd6\xa6\xd7\xd3\x7f\x01\x4d\x49\ 98 | \x90\xa7\x09\xe2\x56\x86\x59\x5f\xd9\x5a\x6b\x8f\x8f\xe5\xf5\xe3\ 99 | \xb6\x26\xf9\xe0\xe0\xe0\x12\xf7\x56\x09\x11\x0f\xad\x93\x62\x38\ 100 | \xa6\xdb\xa5\x66\x89\x69\xad\xfd\x9b\xbc\x0e\x80\x95\x04\xa9\x8f\ 101 | \x1a\xe7\xfc\xcd\x8c\xb1\xaf\xcf\xba\xdc\x22\xbe\x74\x64\x64\xe4\ 102 | \xd6\x66\x07\x3a\x70\x3d\xf7\xb5\xdf\xed\xd2\xdd\xfa\xfc\x50\x3f\ 103 | \x9b\xb2\x47\xe0\x36\xa2\x70\x67\xad\xbd\xc4\x18\x73\x41\x1e\xc1\ 104 | \x94\x04\x79\x9a\x20\x67\x32\xc6\xae\x48\xb8\xc5\xca\x6d\x05\xe9\ 105 | \xeb\xeb\xdb\xb9\xb7\xb7\xd7\xbd\x51\xda\x4a\x08\x44\x74\xb7\x4e\ 106 | \x3b\xe4\x31\x69\x72\x68\x73\x85\x52\xca\xf5\xbb\xed\xa5\x24\xc8\ 107 | \xd3\x04\x39\x95\x31\xf6\x8d\x84\x11\x70\xdb\x20\x92\xb6\x74\x04\ 108 | \x19\xc4\xfa\x66\xc9\xa7\xde\x2e\x11\x91\xdb\x59\x3c\x57\xc7\xab\ 109 | \xa6\x94\x72\x17\x83\x5a\x10\x70\x3d\x9c\xcc\x55\xc0\xff\x02\x22\ 110 | \xce\xf9\xcb\x19\x63\x37\xcf\x86\x1d\x11\x5d\xab\xb5\x3e\xc5\x03\ 111 | \xdf\x54\xa6\xcb\x96\x2d\xeb\xde\xbc\x79\xf3\x01\xd3\x56\x07\xb7\ 112 | \x85\xbd\xa9\x5d\xc4\xa9\x1a\x2c\xa6\xd1\x61\x4a\xa9\x15\xed\x0e\ 113 | \xbd\x24\x48\x1d\xf1\xfe\xfe\xfe\xc5\xee\x2b\x7a\x02\x41\xd6\x6b\ 114 | \xad\xf7\x6e\x75\x90\x86\x87\x87\x17\xd4\x6a\xb5\x43\x1a\xdb\x35\ 115 | \x88\xe8\x60\x44\xec\x6d\xd5\x6f\x87\xd7\xbf\x40\x29\x95\xf4\x11\ 116 | \x37\x38\x04\x25\x41\xa6\x41\x2a\x84\x78\x24\x69\x93\xdd\x96\x2d\ 117 | \x5b\x9e\xb3\x66\xcd\x9a\x99\x5f\xac\x67\x1d\x18\xa7\x8f\xd5\x58\ 118 | \x1d\xea\xcf\x0f\x3c\xf8\x48\x76\xbe\xc3\x1b\x94\x52\x6e\x3b\x4d\ 119 | \x5b\x4b\x49\x90\x67\x12\xe4\x27\x88\xf8\xea\x19\x23\xb0\xce\x1d\ 120 | \x8b\x25\x22\xb7\x5d\xc3\x9d\xf3\x70\x67\x2f\xb6\x5b\x38\xe7\xf3\ 121 | \xdc\x1e\xa2\xc6\x56\x6f\x27\x1a\x87\x88\xbb\xb6\x75\x54\x3b\xb0\ 122 | \x31\x22\x5a\xa3\xb5\x0e\xa5\x44\x99\x1a\xa1\x92\x20\xd3\xa0\xe2\ 123 | \x9c\x7f\x88\x31\x76\x62\xfd\xd0\x93\xdb\xbb\x74\xeb\xda\xb5\x6b\ 124 | \x7f\x3f\x1b\x9a\x6e\x0f\x54\xa5\x52\x69\x7c\x77\x70\x0f\xd5\x2f\ 125 | \x9e\x6d\xb3\x63\xea\x91\x29\x0d\xa7\x23\xe0\x76\xf7\x7e\x54\x6b\ 126 | \x7d\x71\xbb\x61\x29\x09\xe2\x89\x78\xfd\xbc\xc8\xf4\xbd\x4b\x6d\ 127 | \xbf\xaa\x79\x86\x5c\x44\xf3\xcd\x00\x70\xa7\x3b\xb2\x5c\xdf\x57\ 128 | \xb6\x62\x64\x64\xc4\x9d\xbf\x69\x7b\x29\x09\x32\x0b\xe4\xee\x20\ 129 | \x52\x4f\x4f\x8f\x93\xd8\x69\x10\xe2\xf0\x58\xd4\x13\xdb\x3e\x53\ 130 | \x32\x6c\x90\x88\x36\x34\xc8\x40\x44\x2b\x8c\x31\x77\xe5\xf1\x4a\ 131 | \x77\x5b\x5d\x2c\x09\x32\x0d\x15\xa7\x14\x32\x6f\xde\xbc\xad\xb7\ 132 | \x4b\x6e\xcb\x06\x11\x1d\x54\xde\x2e\x05\x67\x86\xbb\x5d\x72\xe2\ 133 | \xda\x2b\xdc\x73\x9d\xb5\x76\x45\xb5\x5a\x5d\x1f\xbc\x95\x40\x0e\ 134 | \xe7\x32\x41\x50\x4a\x39\x38\x7d\xab\x37\x22\xbe\x30\x10\xae\xa5\ 135 | \x9b\x3a\x02\x44\xf4\x18\x22\xae\xaa\x9f\x49\x59\x61\xad\x5d\x69\ 136 | \x8c\xd9\x54\x14\x80\xe6\x0c\x41\x96\x2c\x59\xd2\x3b\x7f\xfe\xfc\ 137 | \x17\x35\xb6\x7a\xd7\x5f\xbb\xce\x7a\x86\xbb\x28\x83\x18\x59\x9c\ 138 | \xbf\x6c\xdc\x2e\xd5\xd5\x21\xdd\x89\xc0\xc2\xaa\x3a\x76\x2c\x41\ 139 | \x5c\xf6\xa6\xfa\xb3\x43\xe3\x0d\xd3\x32\x00\xe8\x8e\x6c\x32\x15\ 140 | \x3d\x9c\xa7\x4e\x2c\xba\x67\x07\x77\x62\x31\xe9\xad\x5f\xd1\x3a\ 141 | \xdc\x29\x04\xc1\xa1\xa1\x21\xb7\x57\xe9\xa9\xad\xde\x88\xb8\x4f\ 142 | \xd1\x06\x23\xf6\x78\x89\xe8\x8f\x00\xb0\xd2\x91\xc1\x3d\x3f\x4c\ 143 | \x4e\x4e\xde\x91\x81\x18\x5e\x54\x30\x14\x92\x20\x4e\x66\x66\xe1\ 144 | \xc2\x85\x2f\xae\x6f\xf3\x6e\xec\x6e\x6d\x56\x66\x26\xaa\x01\x89\ 145 | \x2c\x98\xb1\xc6\x79\x76\x44\x74\xaf\x5a\xab\x91\xc5\x97\x79\x38\ 146 | \x85\x20\x48\x5d\x66\xc6\x69\x2d\x35\xc8\x70\x60\x60\x99\x99\xcc\ 147 | \x81\x8e\xbd\x01\x22\x72\x67\xd7\x7f\xde\x78\x98\x76\x2b\x44\x5e\ 148 | \xa7\xf8\x62\xc2\x2a\x46\x82\x30\x29\xa5\xcb\xbf\xd1\x38\x08\xe4\ 149 | \x6e\x9b\x32\xcd\xed\x17\xd3\x80\xb4\x2b\x96\x7a\xaa\x85\xe5\xee\ 150 | \x76\xc9\x91\x62\x87\x1d\x76\xb8\xab\x14\xb7\xfe\x4b\xf4\xa3\x21\ 151 | \x08\xe7\xfc\x70\xc6\xd8\x7b\x00\xc0\xed\x85\xda\xb9\x5d\x13\x65\ 152 | \x2e\xb4\xe3\xd4\x58\x10\x51\x59\x6b\xdd\x7e\xb2\x15\x53\x53\x53\ 153 | \xcb\xc7\xc6\xc6\xdc\xdb\xa6\xb2\x24\x20\x90\x3b\x41\x9c\x0e\x93\ 154 | \xd3\x95\x25\xa2\x77\xcd\xe1\x03\x41\x41\x27\x2a\x11\x39\x75\x96\ 155 | \x55\x6e\x75\x70\xf2\x3f\x93\x93\x93\x2b\xf3\xd4\x0e\x0e\xda\xb9\ 156 | \x36\x3b\xcb\x95\x20\x43\x43\x43\x92\x31\xf6\xc3\x76\x28\xf5\xb5\ 157 | \x19\xd7\xb6\x36\x47\x44\xbf\x9a\xf1\xec\xd0\x16\x65\xf9\xb6\x76\ 158 | \x32\xa7\xc6\x72\x23\x88\x94\xd2\xbd\x86\x75\xf2\x9d\xcf\xc9\xa9\ 159 | \xef\x45\x6d\xb6\xe6\xd4\x12\x1b\xcf\x0e\xf5\x44\x3c\x4e\x2c\xae\ 160 | \x2c\x19\x20\x90\x17\x41\x5c\xa6\xd8\xbb\x11\x71\xbf\x0c\xfa\xd4\ 161 | \x69\x2e\xdd\x2e\x56\x77\x21\xd9\xfa\xfc\xb0\x69\xd3\xa6\x55\x49\ 162 | \x6a\x89\x9d\x06\x40\x9e\xfd\xc9\x85\x20\x52\xca\xd3\x01\xe0\xab\ 163 | \x79\x76\x3c\xd6\xb6\xdd\xc1\xa0\x69\xdb\xbc\x5d\x22\xcf\xd1\x58\ 164 | \x63\x9d\x0b\x71\xe5\x42\x10\x21\x84\x46\xc4\x39\x7f\xec\x94\x88\ 165 | \x5c\x4a\xb6\x5f\xb8\xd5\xa1\x7e\xcb\xd4\x52\xde\xc2\xb9\x30\x61\ 166 | \xdb\xdd\xc7\xb6\x13\xc4\x9d\xcf\x66\x8c\xfd\x4f\xbb\x3b\x1a\x49\ 167 | \x7b\x2e\x73\x92\xfb\xee\xb0\xa2\x56\xab\x2d\x67\x8c\xad\x36\xc6\ 168 | \x6c\x89\x24\xb6\x32\x8c\x6d\x20\xd0\x76\x82\x48\x29\x5d\x72\x9a\ 169 | \x8e\x4f\x26\x59\xff\xf6\xa0\xa7\xed\x6c\x75\xe2\x67\xa9\xd2\x3c\ 170 | \x97\x33\x35\x1e\x04\xda\x4e\x10\x21\xc4\x45\x88\xf8\xa1\x78\x20\ 171 | \x08\x16\xc9\xe3\x44\x74\x47\xe3\x76\x69\xcb\x96\x2d\x2b\xc6\xc7\ 172 | \xc7\x5d\xa6\xdb\xb2\x14\x18\x81\x3c\x08\xf2\x15\x44\x7c\x57\x81\ 173 | \x31\xdb\x1a\x3a\x11\xfd\xba\x71\x2a\xce\x3d\x3f\x8c\x8e\x8e\x3a\ 174 | \x65\xf8\xdc\x12\xbd\x14\x1d\xcf\x58\xe3\xcf\x83\x20\x9f\x43\xc4\ 175 | \x73\x63\x05\x64\x3b\x71\x39\xc9\x4b\x47\x80\xad\xaf\x5a\x27\x27\ 176 | \x27\x6f\x1b\x1b\x1b\x73\xe7\xa8\xcb\xd2\xe1\x08\xb4\x9d\x20\x9c\ 177 | \xf3\xb3\x19\x63\x5f\x88\x1c\xd7\x8d\x44\xe4\xbe\x3d\x6c\xdd\xc8\ 178 | \xf7\xc8\x23\x8f\xac\xba\xff\xfe\xfb\x9d\xd2\x46\x59\xe6\x18\x02\ 179 | \x79\x10\xc4\x6d\x4a\xbc\x2d\x26\x9c\x89\xc8\x25\xb3\x7f\x6a\x67\ 180 | \x6b\x5d\x1c\x8e\x62\x8a\xb1\x8c\x25\x1f\x04\xda\x4e\x10\x97\x7f\ 181 | \x5c\x4a\xe9\xae\xc6\x49\x79\xc8\x33\x41\xc4\x7d\x7b\x40\xc4\xd5\ 182 | \x8d\x5d\xad\x44\x74\x5b\xb5\x5a\x75\x27\xe5\xca\x52\x22\xf0\x17\ 183 | \x08\xe4\x41\x10\x90\x52\xba\xdb\x17\x97\xdf\xa2\x1d\xe5\xa1\xc6\ 184 | \xae\xd6\xfa\x51\xd1\x9f\x97\xdf\x1e\xda\x01\x7b\x67\xb4\x91\x17\ 185 | \x41\x5c\x8e\x8d\xf3\x42\x43\xe8\x92\xd9\x01\x80\xd3\xce\xdd\xfa\ 186 | \xec\xe0\x34\x97\x46\x47\x47\xe7\xea\x47\xc9\xd0\xf0\xce\x49\x7f\ 187 | \x79\x11\xe4\x04\x00\xb8\x3e\x00\xe2\x4f\xb8\x6f\x0f\x8d\x9d\xad\ 188 | \x13\x13\x13\x2b\xd6\xad\x5b\xf7\x48\x00\xbf\xa5\x8b\x12\x81\xad\ 189 | \x08\xe4\x42\x90\xed\x24\xbd\x4f\x33\x24\xf7\xcf\xf8\x32\x7d\x77\ 190 | \xf9\xed\x21\x0d\x6c\xa5\x4d\xb3\x08\xe4\x42\x10\x17\xac\x10\x62\ 191 | \x3c\x41\x9a\xc7\x7d\x74\xbb\xb7\xb1\x3a\xd4\x35\x5b\xdd\xc7\xb9\ 192 | \xb2\x94\x08\xb4\x0d\x81\xdc\x08\x22\xa5\xfc\x3c\x00\x9c\x33\xad\ 193 | \xa7\x8f\x10\xd1\x56\x89\x4a\x47\x86\x8d\x1b\x37\xae\xdc\xb0\x61\ 194 | \xc3\x13\x6d\x43\xa2\x6c\xa8\x44\x60\x1b\x08\xe4\x46\x90\x7a\x92\ 195 | \xfb\xb3\xad\xb5\x7f\xac\x0b\x18\x3b\x89\xca\xf2\xdb\x43\x39\x4d\ 196 | \xa3\x42\x20\x37\x82\x44\x85\x42\x19\x4c\x89\xc0\x76\x10\x28\x09\ 197 | \x52\x4e\x8d\x12\x81\x59\x10\x28\x09\x52\x4e\x8f\x12\x81\x02\x12\ 198 | \xc4\xa9\x2b\x7e\x09\x00\x86\xca\xd1\x9b\xbb\x08\x10\xd1\x2d\x5a\ 199 | \xeb\x4f\xe5\x89\x40\x94\x2b\x88\x10\xc2\xc9\x8d\xde\x9e\x27\x30\ 200 | \x65\xdb\x51\x20\x30\xa5\x94\xca\x65\xcf\x5e\xa3\xf7\x51\x12\x84\ 201 | \x73\x2e\x18\x63\xee\xad\x56\x59\xe6\x36\x02\x0f\x2a\xa5\xf6\xc8\ 202 | \x13\x82\x28\x09\xd2\xc2\x97\xf6\x3c\xb1\x2c\xdb\x0e\x8c\x00\x11\ 203 | \xdd\xab\xb5\xde\x3f\xb0\x5b\x2f\x77\x51\x12\xc4\xf5\x40\x4a\xe9\ 204 | \xd4\x3e\xca\x8c\x50\x5e\xc3\xd9\x59\xc6\x44\x74\xa3\xd6\xfa\xd8\ 205 | \x3c\x7b\x15\x33\x41\xdc\xb6\x92\xe7\xe7\x09\x4e\xd9\x76\xbe\x08\ 206 | \x10\xd1\xd5\x5a\xeb\xd3\xf2\x8c\x22\x5a\x82\x08\x21\xee\x40\x44\ 207 | \x97\x45\xaa\x2c\x73\x17\x81\x8b\x94\x52\x1f\xc9\xb3\xfb\x31\x13\ 208 | \xe4\x7b\x88\x78\x5c\x9e\xe0\x94\x6d\xe7\x8e\xc0\x7b\x95\x52\xb9\ 209 | \xea\x17\xc4\x4c\x90\x8e\x90\x07\xca\x7d\x8a\x15\x38\x00\x6b\xed\ 210 | \xc9\xc6\x98\xef\xe4\xd9\x85\x68\x09\x22\xa5\xfc\x24\x00\x7c\x22\ 211 | \x4f\x70\xca\xb6\xf3\x45\xc0\x5a\x7b\xa4\x31\x26\x57\x81\x8f\x98\ 212 | \x09\xf2\xb7\x00\x70\x79\xbe\x43\x54\xb6\x9e\x27\x02\x53\x53\x53\ 213 | \x4b\xf3\x3e\x32\x1d\x2d\x41\x38\xe7\xc7\x33\xc6\x6e\xc8\x73\x80\ 214 | \xca\xb6\xf3\x45\xc0\x5a\xbb\x93\x31\x66\x53\x9e\x51\xc4\x4c\x90\ 215 | \x83\x19\x63\xee\x00\x55\x59\xe6\x26\x02\x93\x4a\xa9\x79\x79\x77\ 216 | \x3d\x66\x82\xbc\x80\x31\xe6\x72\xef\x95\x65\x0e\x22\xe0\xc4\xfc\ 217 | \xb4\xd6\x2f\xcc\xbb\xeb\xd1\x12\x64\xd9\xb2\x65\xdd\x4f\x3e\xf9\ 218 | \x64\x99\x3b\x23\xef\x19\x92\x53\xfb\x44\x74\xbb\xd6\xfa\x88\x9c\ 219 | \x9a\x7f\xaa\xd9\x68\x09\xe2\x22\x94\x52\x3e\x0c\x00\x0b\xf2\x06\ 220 | \xa9\x6c\xbf\xfd\x08\x10\xd1\x75\x5a\xeb\x93\xda\xdf\xf2\x33\x5b\ 221 | \x8c\x9a\x20\x65\xaa\xb6\xbc\xa7\x47\xae\xed\x5f\xa6\x94\x9a\x2e\ 222 | \xea\x91\x4b\x30\xb1\x13\xe4\x16\x44\x3c\x3a\x17\x64\xca\x46\xf3\ 223 | \x46\xe0\xa3\x4a\xa9\x4f\xe7\x1d\x44\xd4\x04\x91\x52\x7e\x03\x00\ 224 | \x4e\xcd\x1b\xa4\xb2\xfd\xf6\x23\x60\xad\x3d\xdd\x18\x73\x55\xfb\ 225 | \x5b\x2e\xd0\x2d\x96\x94\x32\x13\x0d\xdf\xbc\x41\x2f\xdb\x4f\x46\ 226 | \xc0\x5a\xfb\x1a\x63\xcc\x4f\x92\x2d\xb3\xb5\x88\x7a\x05\xe1\x9c\ 227 | \x9f\xc7\x18\x73\x24\x29\xcb\x1c\x43\xc0\x5a\x7b\x80\x31\xe6\x9e\ 228 | \xbc\xbb\x1d\x3b\x41\x4e\x65\x8c\xb9\xdb\xac\xb2\xcc\x31\x04\xac\ 229 | \xb5\x7b\x1a\x63\x7e\x97\x77\xb7\x63\x27\xc8\xcb\x19\x63\x37\xe7\ 230 | \x0d\x52\xd9\x7e\x7b\x11\x70\x69\x2c\xb4\xd6\x95\x18\x94\x36\x63\ 231 | \x27\x08\x67\x8c\xb9\x5c\xe3\x65\x99\x43\x08\x10\xd1\xef\xb4\xd6\ 232 | \x7b\xc6\xd0\xe5\xd8\x09\xb2\x90\x31\x56\xa6\x47\x8b\x61\xa6\xb4\ 233 | \x31\x06\x22\xba\x47\x6b\x7d\x40\x1b\x9b\xdc\x6e\x53\x51\x13\xc4\ 234 | \x45\x5d\x8a\x37\xc4\x30\x4d\xda\x1b\x03\x11\xfd\x44\x6b\xfd\x9a\ 235 | \xf6\xb6\xba\xed\xd6\xa2\x27\x88\x10\xe2\x57\x88\xf8\x82\x2c\xc1\ 236 | \x72\xb7\xbc\x00\xf0\x6d\x6b\xed\xca\x4a\xa5\xe2\x72\xa2\x3f\x55\ 237 | \xac\xb5\x8b\x19\x63\x1f\x74\x5c\xcd\x38\x06\x0b\x00\xdf\x25\xa2\ 238 | \x1f\x33\xc6\x7e\x39\x23\x06\x86\x88\x47\x21\xe2\x07\x00\x60\x87\ 239 | \x8c\xe3\xf8\x23\x22\x5e\x63\xad\xbd\x85\x31\x36\x33\x5b\xd7\xb3\ 240 | \x00\xe0\x64\x00\x78\x4b\x96\x31\x00\xc0\x55\x4a\xa9\xd3\x33\x6e\ 241 | \x23\x95\xfb\x22\x10\x24\x53\xf1\x06\x22\xfa\x98\xd6\xda\x7d\xb1\ 242 | \x75\x13\x74\x7b\xa5\x8b\x73\x7e\x05\x63\xec\x1d\xa9\x50\xf5\x37\ 243 | \xfa\x4d\xad\x56\x7b\x5d\xb5\x5a\x75\xd9\x77\xb7\x5b\xa4\x94\xfb\ 244 | \x00\xc0\xcf\x32\x54\x7b\xb9\x79\xcb\x96\x2d\x6f\x5a\xb3\x66\xcd\ 245 | \x1f\x66\x8b\x83\x73\x7e\x22\x22\x7e\x1b\x11\x99\x7f\x57\x53\xd5\ 246 | \xc8\x5d\xac\xa1\x11\x65\x11\x08\x72\x03\x22\x1e\x9f\x0a\x56\x4f\ 247 | \x23\x6b\xed\xe5\xc6\x98\x77\xa7\xac\xd6\x25\x84\xb8\x07\x11\x45\ 248 | \x4a\xfb\xb4\x66\x53\xd6\xda\x83\xd2\xbe\xf3\x1f\x1a\x1a\x3a\xb2\ 249 | \x52\xa9\xdc\x9a\xd6\x79\x5a\x3b\x22\xfa\x9f\xc7\x1f\x7f\x7c\xdf\ 250 | \xf5\xeb\xd7\x4f\xa4\xa9\x93\xe5\x47\x5c\x6b\xed\x39\xc6\x98\xcb\ 251 | \xd2\xc4\x91\xb5\x4d\xf4\x04\x91\x52\x5e\x01\x00\x67\x66\x00\xc4\ 252 | \x64\xad\x56\xdb\xd3\x27\x47\x3a\xe7\xfc\x6c\xc6\x58\x50\x95\x0d\ 253 | \x22\xba\x56\x6b\x7d\x8a\x4f\xff\x84\x10\x06\x11\x83\x0a\x7b\x5b\ 254 | \x6b\xdf\x62\x8c\x49\xfd\xcd\x89\x73\x9e\xd9\x79\x1d\x6b\xed\x1b\ 255 | \x8c\x31\xff\xee\x83\x49\x56\xb6\x45\x20\x88\x13\x6e\x70\x02\x0e\ 256 | \xa1\x8b\x52\x4a\x0d\xfb\x38\x1d\x1e\x1e\x3e\x8a\x88\xfe\xcb\xa7\ 257 | \x4e\x92\x2d\x11\xbd\x47\x6b\xed\x94\xec\x53\x17\x29\xe5\xb7\xea\ 258 | \xcf\x02\xa9\xeb\x24\x19\x4e\x4e\x4e\xf6\x8d\x8d\x8d\x3d\xe3\xd9\ 259 | \x27\xa9\x8e\x10\xe2\x51\x44\xdc\x29\xc9\xce\xf7\x77\x6b\xed\x11\ 260 | \xc6\x98\x28\xc4\xcb\xa3\x27\x08\xe7\xfc\x4c\xc6\x98\x5b\x45\x82\ 261 | \x16\x22\xba\x5b\x6b\x7d\xa0\x8f\x53\xce\x79\xf0\xef\x32\x44\xf4\ 262 | \x36\xad\xf5\xff\xf3\x8c\xe3\xca\xd0\xcf\x43\x8c\xb1\x1d\xef\xbb\ 263 | \xef\xbe\xc7\x7d\xe2\xc8\xea\xbc\x8e\xb5\xf6\x85\xc6\x98\x71\x9f\ 264 | \x58\xb2\xb2\x2d\x02\x41\x8e\x63\x8c\x7d\x2f\x03\x00\x7e\xa9\x94\ 265 | \xea\xf3\xf1\x3b\x30\x30\xb0\xa8\xbb\xbb\xfb\xb7\x3e\x75\x92\x6c\ 266 | \x63\x20\x48\xfd\xcb\xb5\xf7\x03\xb7\x10\xc2\x22\x62\xf0\x39\xd4\ 267 | \x0c\x59\x93\x70\x6e\xf6\xf7\xe0\x9d\x6b\x36\x90\xed\xd5\xe3\x9c\ 268 | \xbf\x98\x31\x76\x47\x68\xbf\x00\xb0\x51\x29\xe5\x75\x5a\x71\xf1\ 269 | \xe2\xc5\x3b\xec\xb2\xcb\x2e\x41\x33\xef\xc6\x40\x10\x00\x78\x48\ 270 | \x29\xb5\xbb\x0f\xc6\x7d\x7d\x7d\x3b\xcf\x9f\x3f\x7f\xa3\x4f\x9d\ 271 | \x34\xb6\x44\xb4\x49\x6b\x1d\xfc\xb6\x2d\x4d\xdb\xdb\xb2\x29\x02\ 272 | \x41\x32\x79\x18\x8c\xe5\xaa\x19\x03\x41\xdc\x1b\x2c\xad\xf5\x52\ 273 | \x9f\x49\x34\x34\x34\xb4\x57\xa5\x52\x59\xef\x53\x27\x8d\x6d\x2c\ 274 | \x62\x0d\x8d\x58\xa3\x27\x48\x96\xe2\x0d\x9b\x36\x6d\x5a\xb0\x7e\ 275 | \xfd\x7a\xaf\xab\xa0\x94\xd2\xed\x30\x7d\x6e\x9a\xc1\x4e\x63\x13\ 276 | \x09\x41\xee\xd4\x5a\x1f\x9c\x26\xde\x86\x0d\xe7\x7c\x7f\xc6\xd8\ 277 | \xdd\x3e\x75\xd2\xd8\x12\xd1\x6d\x5a\xeb\x23\xd3\xd8\xb6\xc3\x26\ 278 | \x7a\x82\x38\x10\x84\x10\xee\xeb\xee\xc2\xd0\x80\xd4\x6a\xb5\xbd\ 279 | \xab\xd5\xaa\xd7\x55\x50\x4a\x59\x05\x80\x81\x50\xb1\x44\x42\x90\ 280 | \x9b\xb4\xd6\xc7\xf8\xf4\x49\x4a\xf9\xd2\xfa\x47\x4b\x9f\x6a\x69\ 281 | \x6c\xff\x5d\x29\xf5\x86\x34\x86\xed\xb0\x29\x0a\x41\x54\x06\x1f\ 282 | \xe8\xc0\x5a\x7b\xa0\x31\xc6\xeb\x2a\x28\xa5\x5c\x09\x00\x2f\x09\ 283 | \x35\x38\x31\x10\xc4\x6d\xb3\x51\x4a\xbd\xd1\xa7\x4f\x52\xca\xd7\ 284 | \xb9\xad\x31\x3e\x75\x52\xda\x7e\x41\x29\xf5\xde\x94\xb6\x99\x9b\ 285 | \x15\x85\x20\x37\x23\xe2\xcb\x43\xa3\x41\x44\x47\x6b\xad\xdd\xd6\ 286 | \x8d\xd4\x45\x08\xf1\x13\x44\x7c\x75\xea\x0a\x09\x86\x91\x10\xe4\ 287 | \x0a\xa5\xd4\xdf\xf9\xf4\x49\x4a\xe9\xf6\x4a\x7d\xd5\xa7\x4e\x1a\ 288 | \x5b\x6b\xed\x47\x8c\x31\x17\xa5\xb1\x6d\x87\x4d\x21\x08\x22\xa5\ 289 | \xfc\x3a\x00\xbc\x39\x03\x40\x5e\xaf\x94\xf2\xba\x0a\x0a\x21\xae\ 290 | \x41\xc4\x37\x85\x8a\x25\x06\x82\x10\xd1\x67\xb4\xd6\x1f\xf6\xe9\ 291 | \x13\xe7\xfc\xfd\x8c\xb1\xcf\xfa\xd4\x49\x63\x6b\xad\x3d\xcd\x18\ 292 | \x73\x75\x1a\xdb\x76\xd8\x14\x85\x20\x97\x00\xc0\xf9\x19\x00\xf2\ 293 | \x0e\xa5\xd4\xbf\xf9\xf8\xe5\x9c\x7f\x99\x31\xe6\x75\xb5\x9d\xcd\ 294 | \x7f\x24\x04\xf9\xa0\xd6\xfa\x9f\x7c\x70\x10\x42\x7c\x0a\x11\xff\ 295 | \xde\xa7\x4e\x1a\x5b\x6b\xed\xb1\xc6\x98\x1b\xd3\xd8\xb6\xc3\xa6\ 296 | \x10\x04\xc9\x4a\xbc\xc1\x5a\x7b\xbe\x31\xc6\xeb\x2a\x28\xa5\xfc\ 297 | \x47\x00\x08\x96\x16\x2c\x06\x82\x58\x6b\xcf\x34\xc6\xfc\x5f\x9f\ 298 | \x09\x27\x84\xb8\x0c\x11\xdf\xe3\x53\x27\x8d\x6d\x2c\x62\x0d\x8d\ 299 | \x58\x8b\x42\x90\x53\x18\x63\xdf\x4c\x03\xb0\x8f\x0d\x11\x5d\xa8\ 300 | \xb5\xfe\x98\x4f\x1d\x29\xa5\x3b\x93\xe1\x75\xb5\x8d\x7d\x05\x69\ 301 | \x66\x73\x60\x86\x9a\x65\x7b\x28\xa5\x1e\xf4\x19\x93\x2c\x6d\x8b\ 302 | \x42\x90\xa3\x19\x63\xb7\x84\x06\x82\x88\xbe\xa4\xb5\xf6\xba\x0a\ 303 | \x0a\x21\xce\x40\xc4\x7f\x0d\x15\x4b\x0c\x2b\x08\x00\xbc\x4a\x29\ 304 | \xf5\xff\x7d\xfa\x24\xa5\xfc\x21\x00\xfc\x95\x4f\x9d\x24\xdb\x98\ 305 | \xc4\x1a\x0a\xb5\x82\x48\x29\xdd\xd6\x6e\x93\x04\x70\x13\xbf\x7f\ 306 | \x53\x29\xe5\xf5\xf0\xef\x0e\x0b\x31\xc6\x82\x6d\xc5\x8e\x84\x20\ 307 | \x2f\x52\x4a\xfd\xc2\x07\x3f\x29\xe5\x72\x00\x38\xd4\xa7\x4e\x92\ 308 | \x2d\x11\x3d\xa0\xb5\x5e\x94\x64\xd7\xce\xdf\x0b\xb1\x82\x0c\x0f\ 309 | \x0f\x2f\x20\x22\xa7\xf4\x1e\xba\xfc\x58\x29\xe5\x75\x15\xe4\x9c\ 310 | \x07\x95\x22\x8a\x81\x20\xcd\xec\x9e\xcd\x42\x58\xbc\x99\x1d\xd6\ 311 | \xa1\x27\xc4\x4c\x7f\x85\x20\x88\x0b\x3a\x23\xf1\x86\x15\x4a\xa9\ 312 | \xc3\x7c\x40\x1e\x1c\x1c\x5c\xd6\xd5\xd5\xe5\x75\xb5\x8d\xfd\x19\ 313 | \xa4\x56\xab\xed\xe6\x73\x70\xcc\xf5\x47\x08\xb1\x01\x11\x83\x4a\ 314 | \xf3\xc4\x24\xd6\x50\xa8\x5b\xac\xfa\x80\xac\x47\xc4\xbd\x7c\x26\ 315 | \x73\x92\x2d\x11\x8d\x6a\xad\x79\x92\xdd\xf4\xdf\x87\x87\x87\xfb\ 316 | \x88\x68\xad\x4f\x9d\xd8\x09\xa2\x94\x72\x5b\xdd\xc9\xa7\x4f\x52\ 317 | \x4a\xb7\xab\x39\xb4\x80\xc4\xbf\x29\xa5\xb2\x3a\xf7\xef\xd3\xbd\ 318 | \xa7\x6c\x0b\xb3\x82\x08\x21\x56\x21\xa2\xd7\x86\xba\x24\x44\x9a\ 319 | \xb9\xe7\xe5\x9c\x07\xd5\xea\xca\xfb\x16\x8b\x88\x1e\xd3\x5a\x3f\ 320 | \x3b\x09\xab\x19\xbf\xa3\x94\x72\x36\x91\x0b\x4f\x77\x4f\x99\x7f\ 321 | \x5a\x29\xf5\xd1\x66\x2b\x67\x51\xaf\x30\x04\x91\x52\xfe\x07\x00\ 322 | \xfc\x4d\x48\x10\x88\x68\x42\x6b\xed\x7b\x15\x0c\x3a\x39\x22\x20\ 323 | \xc8\xaf\xb5\xd6\x5e\x2b\x33\xe7\x7c\x0f\xc6\xd8\x03\x21\xc7\xc2\ 324 | \xf9\xb2\xd6\x9e\x6d\x8c\xf9\x62\x68\xbf\xad\xf8\x2b\x12\x41\x5c\ 325 | \xce\x74\x97\x3b\x3d\x68\x69\xe6\xf6\x42\x08\xf1\x08\x22\xfa\x5e\ 326 | \x75\xb7\x19\x77\xde\x04\x01\x80\xfb\x94\x52\xfb\xf9\x80\x3a\x3c\ 327 | \x3c\x3c\xe8\x6e\x4f\x7d\xea\xa4\xb1\xb5\xd6\x9e\x64\x8c\xb9\x2e\ 328 | \x8d\x6d\xbb\x6c\x0a\x43\x10\xce\xf9\xc7\x19\x63\xff\x10\x1a\x98\ 329 | \x66\x54\xc4\x85\x10\xc1\x9e\x87\x22\x20\xc8\xad\x4a\x29\xb7\x75\ 330 | \x3d\x75\x19\x1c\x1c\x3c\xa4\xab\xab\x6b\x45\xea\x0a\x29\x0d\x89\ 331 | \xe8\x70\xad\xb5\x7b\x7d\x1c\x4d\x29\x12\x41\xde\xc5\x18\xfb\x4a\ 332 | \x68\xe4\x9c\x7c\xce\xc8\xc8\x88\x3b\xe3\x91\xba\xd4\xf5\xb1\xbc\ 333 | \xae\xba\xdb\x73\x9e\x37\x41\x88\xe8\x7b\x5a\x6b\xaf\x5b\x57\xce\ 334 | \xf9\xb1\x8c\xb1\x1f\xa7\x06\x2c\xbd\x61\xbf\x52\x2a\xd8\x0b\x90\ 335 | \xf4\xcd\x6e\xdf\xb2\x48\x04\xc9\x44\xbc\x61\x6a\x6a\xea\x90\xd1\ 336 | \xd1\xd1\x55\x3e\x60\x4a\x29\x9d\xf4\xcf\x51\x3e\x75\x22\x26\xc8\ 337 | \xd5\x5a\xeb\xd3\x7c\xfa\xc2\x39\xcf\x64\xeb\x4f\x4f\x4f\xcf\xbc\ 338 | \xd5\xab\x57\x4f\xfa\xc4\x92\xb5\x6d\x61\x08\x22\x84\x78\x11\x22\ 339 | \xde\x19\x1a\x90\x66\x52\x7d\x85\x7c\x61\x10\xc1\x0a\xf2\x2f\x5a\ 340 | \xeb\xf7\xf9\xe0\x2a\x84\x78\x37\x22\x7a\x69\x79\x25\xf9\x6f\xf2\ 341 | \x6d\x5a\x92\xdb\x96\x7f\x2f\x0c\x41\xa4\x94\xcf\x07\x80\x5f\xb7\ 342 | \xdc\xe3\x19\x0e\x88\xe8\x14\xad\xf5\xb5\x3e\x7e\x85\x10\x57\x21\ 343 | \xe2\xdb\x7d\xea\xc4\xba\x82\x58\x6b\x3f\x61\x8c\xf9\x3f\x3e\x7d\ 344 | \x91\x52\xba\x57\xb1\x17\xfa\xd4\x49\xb2\x6d\x46\x38\x22\xc9\x67\ 345 | \x88\xdf\x0b\x43\x90\xac\xc4\x1b\x88\xe8\x2c\xad\xf5\x97\x7d\xc0\ 346 | \x14\x42\xfc\x33\x22\x7a\x5d\x75\x63\x25\x08\x00\xbc\x57\x29\xe5\ 347 | \x25\xa7\x2a\xa5\xcc\xe2\x7c\xce\x7f\x2b\xa5\x82\xdc\xb6\xfa\x8c\ 348 | \x65\x92\x6d\x61\x08\xe2\x3a\x22\x84\xf8\x03\x22\xee\x9a\xd4\x29\ 349 | \xcf\xdf\xbd\xf3\x71\x87\x7c\xa3\x96\xf7\x2d\x16\x00\xbc\x55\x29\ 350 | \xe5\x4e\x6c\xa6\x2e\x9c\xf3\xe0\xca\x8e\x00\xf0\x1d\xa5\x94\x4b\ 351 | \xad\x10\x55\x29\x14\x41\xa4\x94\x23\x19\xe4\xe9\xb8\x54\x29\xe5\ 352 | \xce\x78\xa4\x2e\x21\x45\xac\xf3\x26\x08\x11\x1d\xa7\xb5\xfe\x41\ 353 | \xea\xce\xff\xf9\x42\x75\x1d\x22\xbe\xde\xa7\x4e\x92\xad\xb5\xf6\ 354 | \xf3\xc6\x98\x73\x93\xec\xda\xfd\x7b\xd1\x08\xe2\xce\x2c\xbc\x22\ 355 | \x24\x48\x44\x74\xa5\xd6\xfa\x9d\x3e\x3e\xa5\x94\x2e\x81\x8c\x97\ 356 | \x9e\x6e\xac\xb7\x58\xcd\x08\x45\x0b\x21\x6e\x41\xc4\xa3\x7d\x30\ 357 | \x4b\xb2\xb5\xd6\x7e\xd8\x18\xf3\x99\x24\xbb\x76\xff\x5e\x34\x82\ 358 | \x04\x17\x6f\x20\xa2\xeb\xb5\xd6\x27\xfa\x00\x2f\xa5\xfc\x6b\x00\ 359 | \xf0\xba\xea\x46\x4c\x10\x69\x8c\xf1\x4a\x94\x2a\x84\xb8\x0b\x11\ 360 | \x83\xe6\x10\x8c\x4d\xac\xa1\x31\x5e\x85\x22\x08\xe7\xfc\x9f\x18\ 361 | \x63\x5e\xb7\x43\x49\x13\x9f\x88\x6e\xd1\x5a\x7b\xad\x4a\x9c\xf3\ 362 | \xc3\x19\x63\xb7\x25\xf9\x4e\xf3\x7b\xde\xb7\x58\x5b\xb6\x6c\x59\ 363 | \xbc\x66\xcd\x1a\x2f\x41\x6e\x29\xe5\x3a\x00\xd8\x3b\x4d\xff\xd2\ 364 | \xda\x10\xd1\xab\xb5\xd6\x3f\x4d\x6b\xdf\x2e\xbb\xa2\x11\x24\x0b\ 365 | \xa9\x99\xbb\x94\x52\xcb\x7c\x00\xe7\x9c\x0b\xc6\x98\xf2\xa9\x13\ 366 | \xeb\x0a\xf2\xf0\xc3\x0f\x3f\x6b\xc3\x86\x0d\x5e\x82\xdc\x52\xca\ 367 | \x3f\x01\xc0\x2e\x21\xfa\xdf\xf0\x41\x44\xfb\x6b\xad\xef\x0d\xe9\ 368 | \x33\x84\xaf\x42\x11\x44\x08\xf1\x26\x97\x60\x32\x44\xc7\xa7\xf9\ 369 | \x58\xa7\x94\x72\xb9\xff\x52\x97\xa5\x4b\x97\x3e\x6f\xde\xbc\x79\ 370 | \xf7\xa7\xae\x30\x8b\x61\x9e\x2b\x48\x2c\x02\xde\x0e\x9e\xcd\x9b\ 371 | \x37\x3f\x77\xed\xda\xb5\xbf\x0f\x81\x69\x48\x1f\x45\x23\xc8\xcb\ 372 | \x10\xf1\x3f\x43\x02\x00\x00\x7f\x52\x4a\x79\xe9\xfe\x2e\x5a\xb4\ 373 | \x68\xfe\xc2\x85\x0b\xbd\x92\xcd\x44\xba\x82\xfc\x5e\x29\xe5\x25\ 374 | \xc4\xbd\x64\xc9\x92\x5d\x76\xdc\x71\x47\xb7\x82\x04\x2b\x31\x8a\ 375 | \x35\x14\xf2\x19\x24\x0b\xf1\x86\xbc\xaf\xa2\x39\xaf\x20\x6b\xb4\ 376 | \xd6\x5e\x42\xdc\x83\x83\x83\x4b\xba\xba\xba\xbc\x52\xb5\x25\x31\ 377 | \xa9\x99\x83\x6b\x49\x3e\x43\xfd\x5e\xa8\x15\x24\x8b\xab\x97\x03\ 378 | \xf2\x89\x27\x9e\xd8\x65\xdd\xba\x75\x33\x73\x82\xcf\x8a\xb1\x94\ 379 | \xd2\x69\x37\x79\x25\x9d\xd9\x96\xc3\x9c\x09\x72\x87\xd6\xda\x4b\ 380 | \x88\x9b\x73\x7e\x00\x63\xec\xae\x50\x13\xb0\xee\xc7\xfb\x39\x30\ 381 | \x70\xfb\xdb\x75\x57\x28\x82\xb8\x5e\x64\x21\xde\x30\x35\x35\xb5\ 382 | \x64\x74\x74\xf4\x57\x3e\xa0\x0b\x21\xc6\x10\xd1\x2b\xe9\x4c\x84\ 383 | \x04\xf9\xa9\xd6\xda\x4b\x88\x5b\x08\x91\xc5\x6d\xae\xb7\xba\x8c\ 384 | \xcf\x58\xb5\x62\x5b\x38\x82\x08\x21\x7e\x89\x88\x4b\x5a\xe9\xf4\ 385 | \xcc\xba\xcd\xc8\x5d\x86\x3a\x23\x9f\xf3\x0a\xf2\x2d\xad\xb5\x97\ 386 | \x10\xb7\x94\xf2\x04\x00\xb8\x3e\x30\xfe\x5f\x35\xc6\x9c\x11\xd2\ 387 | \x67\x28\x5f\x85\x23\x48\xe8\xfc\x1c\x75\x20\x5f\xa6\x94\xf2\x4a\ 388 | \xef\x2c\x84\xb8\x11\x11\xbd\x92\xce\xc4\xb6\x82\x00\x40\x14\x69\ 389 | \x0f\xac\xb5\xff\x68\x8c\x09\x2e\x84\x1d\x82\x24\x45\x24\x88\x4b\ 390 | \x57\xe0\x92\xb7\x84\x2c\x27\x28\xa5\x9c\x28\x44\xea\x22\x84\xb8\ 391 | \x16\x11\xbd\x92\xce\x44\x48\x90\x8b\x94\x52\x5e\x42\xdc\x59\x08\ 392 | \x89\x37\x93\x2b\x3e\xf5\x40\xb5\x68\x58\x38\x82\x84\x4e\x3f\xe0\ 393 | \xf0\xb3\xd6\x9e\x6e\x8c\xb9\xca\x07\x4b\x29\x65\x10\x11\x89\x9c\ 394 | \x6f\xb1\xa2\x48\x7b\x40\x44\x27\x6a\xad\x83\xde\xb6\xf9\x8c\xe5\ 395 | \x6c\xb6\x45\x24\x48\x70\xf1\x06\x6b\xed\x79\xc6\x98\x7f\xf6\x01\ 396 | \x55\x4a\xf9\x69\x00\xf0\x4a\x3a\x13\xdb\x0a\x42\x44\xef\xd2\x5a\ 397 | \x7b\x09\x71\x0b\x21\xbe\x88\x88\x67\xf9\x60\x95\x64\x1b\xa3\x58\ 398 | \x43\x23\xe6\xc2\x11\x44\x08\xf1\x4e\x44\xf4\xca\x65\x91\x62\x80\ 399 | \x3e\xa5\xb5\xfe\x78\x92\xdd\xf4\xdf\x85\x10\x17\x20\xe2\xc5\x3e\ 400 | \x75\x62\x23\x48\x33\x32\x3b\x42\x88\x6f\x22\xe2\x29\xad\xf6\x7b\ 401 | \x7a\x7d\x44\xdc\x67\x64\x64\xc4\xed\xef\x8a\xae\x14\x91\x20\xaf\ 402 | \x45\xc4\xef\x87\x44\x92\x88\xbe\xa8\xb5\x3e\xdb\xc7\x67\x28\xa2\ 403 | \xe6\x79\x8b\x35\x35\x35\xf5\xca\xd1\xd1\xd1\x9b\x7d\xfa\x2d\xa5\ 404 | \xfc\x11\x00\xbc\xc6\xa7\x4e\x92\x6d\x8c\x62\x0d\x85\x5d\x41\xa4\ 405 | \x94\x07\x01\xc0\xcf\x93\x40\xf7\xfc\xfd\x1b\x4a\x29\x77\xc6\x23\ 406 | \x75\xe1\x9c\x9f\xc4\x18\xfb\x4e\xea\x0a\xdb\x31\xcc\x93\x20\xb5\ 407 | \x5a\xed\xa0\x6a\xb5\xba\xda\xa7\x0f\x52\x4a\xa7\x87\x75\x88\x4f\ 408 | \x9d\xd9\x6c\x89\xe8\x51\xad\xf5\xce\xa1\xfc\x85\xf6\x53\xb8\x15\ 409 | \xa4\xbf\xbf\x7f\x71\x6f\x6f\xef\x6f\x02\x03\xf1\x23\xa5\x94\x3b\ 410 | \xe3\x91\xba\x0c\x0d\x0d\xbd\xa2\x52\xa9\x78\x25\x9d\x89\xed\x16\ 411 | \x0b\x00\xbc\x75\xa8\x84\x10\xc6\x69\x89\xa5\x06\x2a\xc1\x90\x88\ 412 | \xbc\xb7\xbb\x84\x6a\x3b\x8d\x9f\xc2\x11\xc4\x89\x37\x4c\x4c\x4c\ 413 | \x3c\x89\x88\xc1\x62\x27\xa2\xe5\x5a\xeb\xc3\xd3\x00\xd6\xb0\x09\ 414 | \xb5\x92\xe5\xb9\x82\x58\x6b\x77\x35\xc6\x78\xe5\x5d\x11\x42\x3c\ 415 | \x80\x88\x7b\xf8\x60\x95\x60\xeb\xad\xec\x18\xb0\xed\x44\x57\xc1\ 416 | \x26\x59\x62\x4b\x01\x0d\x84\x10\x0f\x21\xe2\x6e\xa1\x5c\x12\x91\ 417 | \xd1\x5a\x0b\x1f\x7f\x52\x4a\xb7\x45\x7e\xdc\xa7\x4e\x6c\x2b\x48\ 418 | \x93\xba\xc4\x13\x88\xd8\xd3\x6a\xbf\xa7\xd5\xff\xb6\x52\xaa\xe5\ 419 | \xef\x49\x01\xe3\x79\x86\xab\x42\x12\x24\xb4\x78\x03\x11\x6d\xd0\ 420 | \x5a\x3f\xcf\x07\xe4\xc1\xc1\xc1\x5d\xbb\xba\xba\xfe\xe0\x53\x27\ 421 | \x26\x82\x34\x73\xef\xbf\x64\xc9\x92\xde\x1d\x77\xdc\x71\x73\xab\ 422 | \x7d\x9e\x5e\x3f\x56\xb1\x86\x46\x8c\x45\x25\xc8\x4d\x00\xf0\xca\ 423 | \x80\x03\xb5\x59\x29\x35\xdf\xd3\x5f\x90\x34\x08\x79\xdd\x62\x11\ 424 | \x51\x14\x69\x0f\x88\xe8\x43\x5a\xeb\x96\x5f\x97\x7b\x8e\x5d\x6a\ 425 | \xf3\xa2\x12\xc4\x29\x8a\x78\xbd\x75\x4a\x42\xa4\xc9\xdb\x8d\x47\ 426 | \x11\x71\xa7\x24\xdf\xb3\xfd\x9e\x23\x41\xee\xd5\x5a\xef\xef\x13\ 427 | \x7b\x46\xe7\x71\xde\xae\xb5\xfe\x9a\x4f\x1c\xed\xb4\x2d\x24\x41\ 428 | \x84\x10\x17\x23\xe2\x05\x81\x81\xf2\xce\xcf\x2d\x84\xf8\x15\x22\ 429 | \xbe\xa0\x95\x38\xf2\x22\x08\x00\x78\x3f\x1c\x67\x94\xf6\xe0\x18\ 430 | \xa5\x94\xbb\x23\x88\xb2\x14\x95\x20\xef\x43\x44\xaf\xad\x21\x49\ 431 | \xe8\x4f\x4e\x4e\x0e\x8e\x8d\x8d\x8d\x25\xd9\x4d\xff\x5d\x4a\xe9\ 432 | \x44\x06\xf6\xf5\xa9\x33\xd3\x36\x47\x82\xdc\xa0\x94\xf2\xda\xf4\ 433 | \x39\x34\x34\xf4\x9a\x4a\xa5\xe2\x3e\x14\x86\x2c\xfb\x29\xa5\xee\ 434 | \x0b\xe9\x30\xa4\xaf\xa2\x12\xe4\x8d\x88\xe8\x25\x38\x9d\x04\x5a\ 435 | \x5e\x69\x10\x72\x24\xc8\x55\x4a\xa9\xd3\x93\x70\x99\xfe\x3b\xe7\ 436 | \xfc\x54\xc6\xd8\x37\x7c\xea\x24\xd9\x4e\x4c\x4c\xec\x3e\x3e\x3e\ 437 | \xfe\x50\x92\x5d\x5e\xbf\x17\x92\x20\x52\x4a\x97\x11\xe9\x67\x21\ 438 | \x41\xb3\xd6\x1e\x6b\x8c\xb9\xd1\xc7\xa7\x10\xe2\x06\x44\x3c\xde\ 439 | \xa7\x4e\x2c\x2b\x08\x11\x7d\x4e\x6b\xfd\x7e\x9f\xd8\x85\x10\x67\ 440 | \x21\x62\xb0\x1c\x82\x31\x8b\x35\x34\x70\x29\x24\x41\xb2\xc8\x91\ 441 | \x97\x57\x1a\x84\xbc\x56\x10\x22\xfa\xb8\xd6\xfa\x53\x9e\x04\xf9\ 442 | \x7b\x44\xf4\xaa\x33\x9b\xff\x66\x5e\xaf\xfb\xc4\x1b\xc2\xb6\x90\ 443 | \x04\xe9\xeb\xeb\xdb\x79\xfe\xfc\xf9\x1b\x43\x00\x30\xcd\xc7\xbb\ 444 | \x95\x52\xee\x8c\x47\xea\x22\x84\xf8\x1c\x22\xb6\x24\xb8\x9c\x17\ 445 | \x41\xac\xb5\xe7\x18\x63\x2e\x4b\xdd\xd9\x3f\xeb\x01\x5c\x0a\x00\ 446 | \xe7\xf9\xd4\x49\xb0\x5d\xad\x94\x72\x7b\xeb\xa2\x2d\x85\x24\x88\ 447 | \x43\x33\x03\xf1\x86\x5c\xd2\x20\xe4\x48\x90\xb7\x18\x63\xbc\x9e\ 448 | \x27\xa4\x94\x5f\x05\x00\xaf\xe7\x96\x84\x99\xef\xbd\x07\xae\xdd\ 449 | \x4c\x2a\x32\x41\x82\xea\xc3\x5a\x6b\x2f\x31\xc6\x78\xbd\x3a\x96\ 450 | \x52\x9e\x03\x00\x9f\x6f\x65\xd0\xf2\x22\x08\x00\xbc\x56\x29\xf5\ 451 | \x43\x9f\xd8\x85\x10\xd7\x23\xa2\x13\x6d\x08\x52\x9a\x51\xd6\x0f\ 452 | \xd2\xb0\x87\x93\x22\x13\x24\xf4\xb6\xeb\x5c\xd2\x20\xe4\x45\x90\ 453 | \x66\x4e\xf1\x09\x21\xfe\x13\x11\x5f\xe6\x31\xbf\x66\x35\x25\xa2\ 454 | \x0b\xb5\xd6\x1f\x0b\xe5\x2f\x0b\x3f\x45\x26\x48\x50\xf1\x06\x22\ 455 | \xba\x4e\x6b\x7d\x92\x0f\xc8\x42\x88\x96\x0f\x6f\xe5\x45\x10\x6b\ 456 | \x6d\xee\x69\x0f\x62\x16\x6b\x68\xcc\x83\xc2\x12\x44\x08\xf1\x25\ 457 | \x44\x7c\xb7\xcf\x84\x9e\xcd\x36\xaf\x34\x08\x79\x11\x64\x72\x72\ 458 | \xf2\x79\x63\x63\x63\x1b\x7c\xf0\xcb\x40\x93\xec\xf5\x4a\x29\x77\ 459 | \xa1\x8b\xb6\x14\x99\x20\x1f\x43\x44\xaf\xec\xac\xa1\xdf\xa8\x0c\ 460 | \x0d\x0d\xc9\x4a\xa5\xe2\xd2\xc2\x35\x5d\xf2\x22\x48\x24\x69\x0f\ 461 | \x0e\x53\x4a\xb9\x5b\xe5\x68\x4b\x91\x09\x72\x06\x22\x7a\x29\x72\ 462 | \x24\x8c\x42\x2e\x69\x10\xf2\x20\x48\x93\x82\xdd\x41\x76\x2f\x4f\ 463 | \x1f\x83\xc9\xc9\xc9\xbe\xb1\xb1\xb1\xa0\x42\xd8\xa1\x99\x56\x58\ 464 | \x82\x84\x4c\x83\xe6\x40\x25\xa2\x87\xb5\xd6\x5e\x19\x74\xf7\xdd\ 465 | \x77\xdf\x67\x59\x6b\x37\xb5\x32\x28\x79\x10\x04\x00\x1e\x54\x4a\ 466 | \x79\x9d\x0a\x1c\x1e\x1e\x5e\xe0\x30\x6a\xa5\xaf\x33\xeb\xc6\x2c\ 467 | \xd6\x50\xf8\x67\x90\xc1\xc1\xc1\x65\x5d\x5d\x5d\xbf\x08\x35\x60\ 468 | \x4d\x5e\x55\x5d\xc6\x57\xdb\xca\xf1\xdf\x9c\x08\x32\xa6\x94\x1a\ 469 | \xf4\xc1\x6e\x60\x60\x60\xef\xee\xee\xee\x90\xd2\x3c\x8f\x28\xa5\ 470 | \x82\x66\xa9\xf2\xe9\x4f\x5a\xdb\xc2\xae\x20\x21\xb3\x3c\x35\xc0\ 471 | \x9a\x98\x98\xd8\x79\x7c\x7c\xfc\xd1\xb4\xe0\x39\x3b\x29\xa5\xcb\ 472 | \x8a\xf4\x1c\x9f\x3a\xd3\x6d\x73\x22\xc8\x2a\xa5\x94\x97\x32\xc9\ 473 | \xd0\xd0\xd0\x81\x95\x4a\xc5\x4b\x01\x25\x01\x13\x6f\x92\x36\x8b\ 474 | \x71\x2b\xf5\x0a\x4b\x10\x00\x40\x21\xc4\x54\x2b\x57\xef\x99\xc0\ 475 | \x59\x6b\xf7\x32\xc6\xfc\xda\x07\x50\x21\xc4\x1a\x44\x7c\xa1\x4f\ 476 | \x9d\xbc\x09\x42\x44\x37\x6a\xad\x8f\xf5\x89\x99\x73\x7e\x34\x63\ 477 | \xec\x16\x9f\x3a\x09\xb6\xde\xe7\x51\x02\xb6\x9d\xda\x55\x91\x09\ 478 | \xd2\xf2\xd5\x7b\x26\x4a\xcd\x24\x92\x14\x42\xdc\x81\x88\x2f\x4e\ 479 | \x8d\xf8\x0c\xc3\x3c\x56\x10\x22\xba\x56\x6b\xed\xa5\x8e\x28\x84\ 480 | \x78\x3d\x22\x5e\xd7\x6c\x3f\xb7\x81\xb5\x77\xea\x85\x50\x6d\xfb\ 481 | \xf8\x29\x3a\x41\xdc\x41\x9b\x61\x9f\x0e\xcf\x66\x8b\x88\x2f\x1d\ 482 | \x19\x19\xb9\xd5\xc7\x9f\x10\xe2\xa7\x88\xf8\x2a\x9f\x3a\x79\xaf\ 483 | \x20\xd6\xda\xcb\x8d\x31\x5e\xdf\x90\xa4\x94\xef\x00\x80\x2b\x9b\ 484 | \xed\xe7\x36\x08\xf2\x2f\x5a\xeb\xf7\x85\xf2\x97\x95\x9f\x42\x13\ 485 | \xa4\xd5\xc9\x39\x13\xd4\xa9\xa9\xa9\xd7\x8d\x8e\x8e\xde\xe0\x03\ 486 | \xb6\x94\xf2\x5b\x00\x70\xb2\x4f\x9d\xbc\x09\x02\x00\x9f\x56\x4a\ 487 | \x7d\xd4\x27\x66\x29\xe5\xf9\x00\x70\x89\x4f\x9d\xd9\x6c\x89\xc8\ 488 | \x5b\x59\x3e\x54\xdb\x3e\x7e\x8a\x4e\x90\xaf\x21\xe2\x5b\x7d\x3a\ 489 | \x3c\x9b\xad\xb5\xf6\x34\x63\xcc\xd5\x3e\xfe\xa4\x94\x57\x00\xc0\ 490 | \x99\x3e\x75\x22\x20\xc8\x05\x4a\x29\xaf\xc9\xce\x39\xbf\x90\x31\ 491 | \xe6\x45\xaa\x04\x82\xbc\x4d\x6b\xed\xc4\x37\xa2\x2e\x45\x27\xc8\ 492 | \x67\x10\xf1\x83\xa1\x10\x26\xa2\xf7\x6b\xad\x3f\xe7\xe3\x4f\x08\ 493 | \x71\x11\x22\x7e\xc8\xa7\x4e\xde\x04\x21\xa2\x77\x6a\xad\xbd\x6e\ 494 | \x97\x42\x6f\xed\x01\x80\x57\x29\xa5\x5a\x96\x6e\x6d\x16\xf7\xb4\ 495 | \xf5\x8a\x4e\x90\x73\x11\xd1\x6b\x42\x27\x00\xe3\x9d\x71\x49\x4a\ 496 | \xe9\xae\xaa\x17\xa6\x05\x7c\x1b\x76\x67\x28\xa5\xdc\x39\x8b\xd4\ 497 | \x45\x08\x71\x15\x22\xbe\x3d\x75\x85\x19\x86\xd6\x5a\xef\xb3\x20\ 498 | \x42\x88\x6b\x10\xd1\x2b\x9f\xe1\x6c\xf1\xd5\x6a\xb5\x7d\xab\xd5\ 499 | \x6a\x4b\xdb\x74\x9a\xed\xbf\x4f\xbd\xa2\x13\x24\xa8\x78\x03\x11\ 500 | \xfd\x40\x6b\x7d\x9c\x0f\x80\x01\x32\x5e\x5d\xaa\x94\xfa\x80\x4f\ 501 | \x9b\x42\x88\x5b\x10\xf1\x68\x9f\x3a\x33\x56\x2d\xef\x7c\x28\xa1\ 502 | \x55\xdd\x63\x17\x6b\x68\xe0\x55\x68\x82\x0c\x0f\x0f\x1f\x45\x44\ 503 | \x5e\xc9\x37\x13\x26\xd5\x13\x13\x13\x13\x4b\xd2\xaa\x6c\x0c\x0c\ 504 | \x0c\xec\xd4\xd5\xd5\xe5\xb2\xee\x7a\x6d\x51\x99\x31\x59\xd7\xf7\ 505 | \xf6\xf6\x2e\x5d\xbd\x7a\xf5\x64\x9a\x09\x3f\x3c\x3c\xdc\xe7\x14\ 506 | \xd1\x01\xa0\x92\xc6\x7e\x5b\x36\x75\x45\x75\x0e\x00\x53\x69\x7c\ 507 | \x70\xce\x39\x22\xaa\x50\xdf\x9c\x8a\x20\xd6\xd0\x11\x04\x19\x18\ 508 | \x18\x18\xe8\xee\xee\xae\xa6\x19\xe4\xb4\x36\x44\xf4\x7d\xad\xb5\ 509 | \x3b\x35\x97\x34\x79\xdc\xe6\x3d\xa7\x08\xd8\xb2\xc2\x23\x11\xa5\ 510 | \x7a\xe5\xd9\xdf\xdf\xdf\xd3\xd3\xd3\x73\x33\x22\x7a\x29\xd1\x6f\ 511 | \xa7\xef\xa9\xde\x64\xd5\xf5\x78\x97\x03\xc0\x81\x69\x31\x4c\x61\ 512 | \xf7\x5b\xa5\xd4\xe2\x14\x76\xb9\x9b\x14\x7a\x05\xe9\xef\xef\x7f\ 513 | \x76\x6f\x6f\xef\x23\xa1\x51\x24\xa2\x3b\xa7\xa6\xa6\xce\xad\x56\ 514 | \xab\xab\xdc\x3e\xc6\x99\xfe\xeb\xfb\xc0\x3e\x0b\x00\x47\x85\x6a\ 515 | \x9b\x88\x7e\xe8\x74\x6a\x8d\x31\x7a\x1b\x3e\x19\xe7\xfc\x65\x88\ 516 | \xf8\x79\x44\xf4\x52\xa1\x9f\x2d\x3e\x22\xfa\xae\x7b\x33\x35\x32\ 517 | \x32\xb2\xad\x8b\x4c\x45\x08\xf1\x0a\xd7\x26\x00\x0c\x84\xea\x67\ 518 | \xdd\xcf\x2f\x94\x52\x2f\x0a\xec\x33\x13\x77\x85\x26\x88\x43\x24\ 519 | \x03\xf1\x86\x4c\x80\x2e\x9d\x3e\x8d\x80\xbb\x18\x68\xad\x5f\x5b\ 520 | \x04\x4c\x3a\x81\x20\x41\xc5\x1b\x8a\x30\x68\x45\x8f\xb1\x08\x62\ 521 | \x0d\x1d\xf1\x0c\x52\x5f\x41\xdc\xfd\xf1\xa1\x45\x9f\x34\x73\x29\ 522 | \x7e\x22\xf2\x7e\x8b\x96\x17\x3e\x85\x5f\x41\x42\x4b\xd1\xe4\x35\ 523 | \x10\x73\xa9\x5d\x22\x3a\x4b\x6b\xfd\xe5\x22\xf4\xb9\x13\x08\x12\ 524 | \x3c\xb1\x7d\x11\x06\xae\xe0\x31\x9e\xa0\x94\xfa\x8f\x22\xf4\xa1\ 525 | \x13\x08\x12\x54\x2f\xb6\x08\x83\x56\xf4\x18\x6b\xb5\xda\xa1\xd5\ 526 | \x6a\x75\x65\x11\xfa\x51\x78\x82\x84\xde\x86\x5d\x84\x41\x2b\x7a\ 527 | \x8c\xb5\x5a\x6d\xef\x6a\xb5\xba\xbe\x08\xfd\xe8\x04\x82\xfc\x15\ 528 | \x00\x78\x49\x68\x16\x61\x60\x3a\x7a\x13\x3c\x1f\x00\x00\x01\xe5\ 529 | \x49\x44\x41\x54\x39\xc6\x22\x88\x35\x74\xcc\x5b\xac\xd0\xe2\x0d\ 530 | \x9d\x3c\x31\x23\xe9\x5b\x21\xc4\x1a\x3a\x86\x20\x03\x03\x03\x8b\ 531 | \xba\xbb\xbb\x7f\x1b\xc9\xe0\x97\x61\x24\x23\x50\x55\x4a\x0d\x25\ 532 | \x9b\xc5\x61\x51\xf8\x5b\xac\x2c\xc4\x1b\xe2\x18\x9a\x8e\x8d\xe2\ 533 | \xbf\x94\x52\xc1\x04\xb0\xb3\x46\xa9\x13\x08\xe2\xb6\x9b\x3c\x08\ 534 | \x00\xbb\x67\x0d\x56\xe9\xbf\x75\x04\x9a\x11\x8c\x68\xbd\xd5\xe6\ 535 | \x3d\x74\x0a\x41\x5a\xce\x36\xdb\x3c\x84\x65\x4d\x1f\x04\x9a\xc9\ 536 | \x8d\xe8\xe3\x3f\xb4\x6d\x47\x10\x44\x08\x71\x23\x22\x1e\x13\x1a\ 537 | \x9c\xd2\x5f\x26\x08\x78\x9f\x87\xcf\x24\x8a\x94\x4e\x3b\x85\x20\ 538 | \x57\x23\xe2\xdb\x52\xf6\xb9\x34\xcb\x17\x81\xb7\x2a\xa5\xbe\x9e\ 539 | \x6f\x08\xe9\x5b\xef\x14\x82\xb4\x24\x9c\x90\x1e\xae\xd2\x32\x00\ 540 | \x02\xc7\x28\xa5\x6e\x0a\xe0\xa7\x2d\x2e\x3a\x82\x20\x21\x72\x05\ 541 | \xb6\x05\xed\xb2\x11\x28\x8a\x58\x43\x63\xa8\x3a\x85\x20\x7f\x0d\ 542 | \x00\x3f\x28\xe7\x5f\xfc\x08\xd4\x6a\xb5\xdd\xaa\xd5\xea\x1f\xe3\ 543 | \x8f\xf4\xcf\x11\x76\x04\x41\x16\x2d\x5a\x34\x7f\xe1\xc2\x85\x4e\ 544 | \x95\xbd\x69\x21\x83\xa2\x0c\x58\x91\xe3\x24\x22\xa3\xb5\x0e\x76\ 545 | \x64\xb8\x1d\x58\x74\x04\x41\x1c\x50\x42\x88\x1b\x10\xf1\xf8\x76\ 546 | \x80\x56\xb6\xd1\x1c\x02\x44\xf4\x19\xad\xf5\x87\x9b\xab\x9d\x4f\ 547 | \xad\x8e\x21\xc8\xe0\xe0\xe0\x70\xa5\x52\xb9\x07\x11\x59\x3e\x50\ 548 | \x96\xad\x26\x20\xf0\xf8\xe6\xcd\x9b\xfb\xd6\xae\x5d\xeb\xf2\xa9\ 549 | \x14\xa6\x74\x0c\x41\xea\xab\xc8\xc5\x88\x78\x41\x61\xd0\x9f\x43\ 550 | \x81\x3a\xc5\x16\xad\xf5\xc5\x45\xeb\x72\x47\x11\x04\x00\x98\x10\ 551 | \xe2\xbb\xe5\xad\x56\x5c\xd3\x90\x88\xae\xd7\x5a\x9f\x18\x57\x54\ 552 | \xe9\xa2\xe9\x34\x82\xb8\x5e\x3b\x3d\xa7\x4b\x11\xf1\xdc\x74\x10\ 553 | \x94\x56\x19\x23\xf0\x75\xa5\xd4\xe9\x00\x50\xcb\xb8\x9d\x4c\xdc\ 554 | \x77\x22\x41\xb6\x02\xe5\x64\x49\xad\xb5\x5f\x0a\x29\xb4\x96\xc9\ 555 | \x08\x74\xa8\x53\x22\x7a\x80\x88\xce\x37\xc6\x5c\x53\xe4\x2e\x76\ 556 | \x2c\x41\xea\x83\x82\x43\x43\x43\x2f\xaf\x54\x2a\x67\x10\xd1\xbe\ 557 | \x00\xd0\x87\x88\x3d\x45\x1e\xb0\x58\x63\x77\x29\xa2\x11\xd1\x69\ 558 | \x94\x8d\x58\x6b\x6f\xde\xb8\x71\xe3\x0d\x1b\x36\x6c\x78\x22\xd6\ 559 | \x78\xd3\xc6\xf5\xbf\xbf\xb3\x69\xaa\x3d\x0b\xe5\x79\x00\x00\x00\ 560 | \x00\x49\x45\x4e\x44\xae\x42\x60\x82\ 561 | \x00\x00\x0a\x3a\ 562 | \x89\ 563 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ 564 | \x00\x00\xc8\x00\x00\x00\xc8\x08\x06\x00\x00\x00\xad\x58\xae\x9e\ 565 | \x00\x00\x0a\x01\x49\x44\x41\x54\x78\x5e\xed\xdd\x41\x6f\x55\x45\ 566 | \x18\xc6\xf1\x33\x2d\xc9\x95\x94\x84\x2f\xc0\xa2\x0b\x16\x04\x0a\ 567 | \x2b\x8d\xd1\x98\x18\x44\x41\x59\xd5\x8f\xe3\x27\xf0\xe3\xc8\xc2\ 568 | \xa8\x18\xd1\x90\x98\x18\xa3\x2b\x28\x84\x45\x17\x5d\x10\x96\x24\ 569 | \x4d\xa8\x70\x12\xca\x31\x47\x7a\xa5\x94\x7b\xef\x99\x79\xcf\xbc\ 570 | \x73\x66\xde\xf9\xb3\xed\xcc\x9c\x99\xe7\x99\x1f\xb7\xb5\x78\xaf\ 571 | \x6b\xf8\x43\x02\x24\xb0\x34\x01\x47\x36\x24\x40\x02\xcb\x13\x00\ 572 | \x08\xb7\x83\x04\x56\x24\x00\x10\xae\x07\x09\x00\x84\x3b\x40\x02\ 573 | \xb2\x04\x78\x05\x91\xe5\xc6\xac\x4a\x12\x00\x48\x25\x45\x73\x4c\ 574 | \x59\x02\x00\x91\xe5\xc6\xac\x4a\x12\x00\x48\x25\x45\x73\x4c\x59\ 575 | \x02\x00\x91\xe5\xc6\xac\x4a\x12\x00\x48\x25\x45\x73\x4c\x59\x02\ 576 | \x00\x91\xe5\xc6\xac\x4a\x12\x00\x48\x25\x45\x73\x4c\x59\x02\x00\ 577 | \x91\xe5\xc6\xac\x4a\x12\x00\x48\x25\x45\x73\x4c\x59\x02\x00\x91\ 578 | \xe5\xc6\xac\x4a\x12\x00\x48\x25\x45\x73\x4c\x59\x02\x00\x91\xe5\ 579 | \xc6\xac\x4a\x12\x00\x48\x25\x45\x73\x4c\x59\x02\x00\x91\xe5\xc6\ 580 | \xac\x4a\x12\x00\x48\x25\x45\x73\x4c\x59\x02\x00\x91\xe5\xc6\xac\ 581 | \x4a\x12\x00\x48\x25\x45\x73\x4c\x59\x02\x00\x91\xe5\xc6\xac\x4a\ 582 | \x12\x00\x48\x25\x45\x73\x4c\x59\x02\x00\x91\xe5\xc6\xac\x4a\x12\ 583 | \x00\x48\x25\x45\x73\x4c\x59\x02\x00\x91\xe5\xc6\xac\x4a\x12\x00\ 584 | \x48\x25\x45\x73\x4c\x59\x02\x00\x91\xe5\xc6\xac\x4a\x12\x00\x48\ 585 | \x25\x45\x97\x7e\xcc\x8b\x17\x2f\x9e\x71\xce\xdd\x6a\x9a\xe6\x9b\ 586 | \x07\x0f\x1e\xfc\x95\xea\x3c\x00\x49\x95\x34\xcf\x11\x27\x70\xe5\ 587 | \xca\x95\x8d\xc3\xc3\xc3\x3b\xce\xb9\x0f\xbb\xae\x7b\xe6\x9c\xbb\ 588 | \xba\xb3\xb3\xf3\xb7\x78\xc1\x80\x89\x00\x09\x08\x8b\xa1\xe9\x13\ 589 | \x38\x8e\x63\xfe\xf4\x94\x48\x00\x92\xbe\x73\x9e\xe8\x99\xc0\x22\ 590 | \x1c\xa9\x91\x00\xc4\xb3\x2c\x86\xa5\x4d\x60\x15\x8e\x94\x48\x00\ 591 | \x92\xb6\x77\x9e\xe6\x91\x80\x0f\x8e\xe3\x48\x0e\x0f\x0f\xaf\x3f\ 592 | \x7a\xf4\xe8\x0f\x8f\xa5\x83\x87\x00\x24\x38\x32\x26\x68\x26\x10\ 593 | \x82\xe3\xd8\x3e\x9e\xbf\x7c\xf9\xf2\x9a\x06\x12\x80\x68\xb6\xcd\ 594 | \xda\x41\x09\x08\x71\xcc\x9f\xa1\x82\x04\x20\x41\x15\x32\x58\x2b\ 595 | \x81\x91\x38\xd4\x90\x00\x44\xab\x71\xd6\xf5\x4e\x20\x12\x0e\x15\ 596 | \x24\x00\xf1\xae\x91\x81\x1a\x09\x44\xc6\x11\x1d\x09\x40\x34\x5a\ 597 | \x67\x4d\xaf\x04\x94\x70\x44\x45\x02\x10\xaf\x2a\x19\x14\x3b\x01\ 598 | \x65\x1c\xd1\x90\x00\x24\x76\xf3\xac\x37\x98\x40\x22\x1c\x51\x90\ 599 | \x00\x64\xb0\x4e\x06\xc4\x4c\x20\x31\x8e\xd1\x48\x00\x12\xb3\x7d\ 600 | \xd6\x5a\x99\xc0\x44\x38\xfe\x47\xe2\x9c\xfb\xea\xfe\xfd\xfb\x77\ 601 | \x43\x6a\x02\x48\x48\x5a\x8c\x15\x27\x30\x31\x8e\xff\xf6\xdd\x75\ 602 | \x5d\xbb\xb6\xb6\x76\x23\x04\x09\x40\xc4\x95\x33\xd1\x37\x81\x1c\ 603 | \x70\xcc\xf7\x1a\x8a\x04\x20\xbe\x2d\x33\x4e\x94\x40\x4e\x38\x24\ 604 | \x48\x00\x22\xaa\x9d\x49\x3e\x09\xe4\x88\x23\x14\x09\x40\x7c\x9a\ 605 | \x66\x4c\x70\x02\x39\xe3\x08\x41\x02\x90\xe0\xea\x99\x30\x94\x40\ 606 | \x09\x38\x7c\x91\x00\x64\xa8\x6d\xbe\x1e\x94\x40\x49\x38\x7c\x90\ 607 | \x00\x24\xa8\x7e\x06\xaf\x4a\xa0\x7f\x6b\x9e\xb5\xb5\xb5\xdb\x4d\ 608 | \xd3\x7c\x5c\x60\x52\xb7\x76\x76\x76\xbe\x3e\xb9\x6f\x80\x14\xd8\ 609 | \x64\x8e\x5b\x3e\x77\xee\xdc\xe9\xb3\x67\xcf\xfe\xd6\xbf\x35\x4f\ 610 | \x8e\xfb\x5b\xb5\xa7\xae\xeb\x7e\x6a\xdb\x76\x7b\x77\x77\xb7\x05\ 611 | \x48\x69\xed\x15\xb0\xdf\x23\x1c\x3f\x3b\xe7\x3e\x29\x60\xbb\x6f\ 612 | \x6d\x71\x15\x8e\x7e\x20\xaf\x20\xa5\x35\x9a\xd9\x7e\x2d\xe3\x00\ 613 | \x48\x66\x97\xad\xb4\xed\x58\xc7\x01\x90\xd2\x6e\x64\x46\xfb\xad\ 614 | \x01\x07\x40\x32\xba\x70\x25\x6d\xa5\x16\x1c\x00\x29\xe9\x56\x66\ 615 | \xb2\xd7\x9a\x70\x00\x24\x93\x4b\x57\xca\x36\x6a\xc3\x01\x90\x52\ 616 | \x6e\x66\x06\xfb\xac\x11\x07\x40\x32\xb8\x78\x25\x6c\xa1\x56\x1c\ 617 | \x00\x29\xe1\x76\x4e\xbc\xc7\x9a\x71\x00\x64\xe2\xcb\x97\xfb\xe3\ 618 | \x6b\xc7\x01\x90\xdc\x6f\xe8\x84\xfb\x03\xc7\xeb\xf0\xf9\xa7\x26\ 619 | \x13\x5e\xc2\x5c\x1f\x0d\x8e\x37\xcd\x00\x24\xd7\x5b\x3a\xd1\xbe\ 620 | \xc0\xf1\x76\xf0\x00\x99\xe8\x22\xe6\xf8\x58\x70\xbc\xdb\x0a\x40\ 621 | \x72\xbc\xa9\x13\xec\x09\x1c\x8b\x43\x07\xc8\x04\x97\x31\xb7\x47\ 622 | \x82\x63\x79\x23\x00\xc9\xed\xb6\x26\xde\x0f\x38\x56\x07\x0e\x90\ 623 | \xc4\x17\x32\xa7\xc7\x81\x63\xb8\x0d\x80\x0c\x67\x64\x72\x04\x38\ 624 | \xfc\x6a\x05\x88\x5f\x4e\xa6\x46\x81\xc3\xbf\x4e\x80\xf8\x67\x65\ 625 | \x62\x24\x38\xc2\x6a\x04\x48\x58\x5e\x45\x8f\x06\x47\x78\x7d\x00\ 626 | \x09\xcf\xac\xc8\x19\xe0\x90\xd5\x06\x10\x59\x6e\x45\xcd\x02\x87\ 627 | \xbc\xae\xa4\x40\x2e\x5d\xba\xf4\x41\xd3\x34\xdf\x76\x5d\xb7\xfd\ 628 | \xf0\xe1\xc3\x67\xf2\x6d\x33\xd3\x37\x01\x70\xf8\x26\x35\xf1\x6f\ 629 | \xd2\xb7\xb6\xb6\xde\xef\xba\xae\x7f\x6b\xca\x33\x5d\xd7\xfd\xb9\ 630 | \xbe\xbe\x7e\xed\xde\xbd\x7b\x07\xe3\xb6\xcf\xec\x55\x09\x80\x63\ 631 | \xfc\xfd\x48\xf2\x0a\x72\x1c\xc7\x7c\xcb\x20\x19\x5f\x1e\x38\x74\ 632 | \x33\xec\x57\x57\x07\xb2\x08\x07\x48\x74\x8b\xe5\x95\x23\x5e\xbe\ 633 | \xaa\x40\x2e\x5c\xb8\xf0\xd1\xfa\xfa\x7a\xff\xa6\xc6\x67\x96\x6d\ 634 | \x99\x57\x92\x78\x65\xf6\x2b\x81\x23\x6e\x9e\x6a\x40\x7a\x1c\xa7\ 635 | \x4e\x9d\xba\xd3\x34\xcd\xe9\xa1\x2d\x83\x64\x28\x21\xbf\xaf\x83\ 636 | \xc3\x2f\xa7\x90\x51\x2a\x40\x42\x70\xf0\xed\x56\x48\x5d\xcb\xc7\ 637 | \x82\x23\x4e\x8e\x27\x57\x89\x0e\x44\x82\x03\x24\xe3\xca\x05\xc7\ 638 | \xb8\xfc\x56\xcd\x8e\x0a\x64\x0c\x0e\x90\xc8\x4a\x06\x87\x2c\x37\ 639 | \xdf\x59\xd1\x80\xc4\xc0\x71\x1c\xc9\xfe\xfe\xfe\xd5\xc7\x8f\x1f\ 640 | \x3f\xf7\x3d\x48\x8d\xe3\xc0\xa1\xdf\x7a\x14\x20\x31\x71\x1c\x43\ 641 | \xf2\xfb\xfe\xfe\xfe\x75\x90\x2c\xbe\x04\xe0\xd0\xc7\xd1\x3f\x61\ 642 | \x34\x10\x0d\x1c\x20\x59\x5d\x3e\x38\xd2\xe0\x18\x0d\x44\x13\x07\ 643 | \x48\x16\x5f\x82\xf3\xe7\xcf\xcf\x66\xb3\xd9\x2f\x16\x3f\x30\x33\ 644 | \xdd\xb5\xf7\x7f\x92\xf8\x15\xe4\xf2\xe5\xcb\x9f\x76\x5d\xf7\xa3\ 645 | \xcf\xef\x39\xfc\xb7\xb3\x78\x64\xd7\x75\x7c\xbb\xd5\x34\xcd\x11\ 646 | \x8e\x1f\x9c\x73\x9f\x8d\xcd\x34\xf5\xfc\xa1\x4f\x93\x4d\xbd\x1f\ 647 | \xdf\xe7\x89\x80\xf4\x38\x5e\xbd\x7a\x75\xdb\x39\x37\xf3\x7d\xd0\ 648 | \xd8\x71\xb5\x23\x01\xc7\xd8\x1b\x24\x9b\x1f\x0c\x64\x0a\x1c\xb5\ 649 | \x7f\xbb\x05\x0e\xd9\xe5\x8e\x31\x2b\x08\xc8\x94\x38\x6a\x45\x02\ 650 | \x8e\x18\xd7\x5c\xbe\x86\x37\x90\x1c\x70\xd4\x86\x04\x1c\xf2\x8b\ 651 | \x1d\x6b\xa6\x17\x90\x9c\x70\xd4\x82\x04\x1c\xb1\xae\xf8\xb8\x75\ 652 | \x06\x81\xe4\x88\xc3\x3a\x12\x70\x8c\xbb\xd4\x31\x67\xaf\x04\x92\ 653 | \x33\x0e\xab\x48\xc0\x11\xf3\x7a\x8f\x5f\x6b\x29\x90\x12\x70\x58\ 654 | \x43\x02\x8e\xf1\x17\x3a\xf6\x0a\x0b\x81\x94\x84\xc3\x0a\x12\x70\ 655 | \xc4\xbe\xda\x71\xd6\x5b\x08\x64\x6b\x6b\xeb\xbb\xa6\x69\xb6\xe3\ 656 | \x3c\x22\xe9\x2a\x77\x9f\x3e\x7d\x7a\xf3\xc9\x93\x27\xff\x24\x7d\ 657 | \xea\xc8\x87\x6d\x6e\x6e\xbe\xb7\xb1\xb1\xf1\xbd\x73\xee\xda\xc8\ 658 | \xa5\x92\x4f\xef\xba\xee\xf6\xc1\xc1\xc1\xf6\xde\xde\xde\x8b\xe4\ 659 | \x0f\x4f\xf0\xc0\x85\x40\x8e\xfe\x36\xbb\xe5\x9c\xfb\x32\xc1\x1e\ 660 | \xa2\x3e\xa2\xb4\xdf\xb8\xf3\xca\x11\xb5\xfe\xe8\x8b\x2d\xfd\x19\ 661 | \x04\x24\xd1\xb3\x7e\x67\x41\x70\xe8\x67\x3c\xf6\x09\x2b\xff\x2b\ 662 | \x16\x48\xc6\xc6\xbb\x7c\x3e\x38\xf4\xb2\x8d\xb9\xf2\xe0\xef\x41\ 663 | \x4a\x47\xd2\xb6\xed\xe7\xbb\xbb\xbb\x6d\xcc\xd0\xc6\xae\x05\x8e\ 664 | \xb1\x09\xa6\x9b\x3f\x08\xa4\xdf\x4a\xe1\x48\x7e\x6d\xdb\xf6\x66\ 665 | \x2e\x48\xc0\x91\xee\x72\xc7\x78\x92\x17\x10\x90\xc4\x88\x9a\xff\ 666 | \x9f\x23\x4e\x8a\x69\x57\xf1\x06\x02\x92\x71\xc5\xf0\xca\x31\x2e\ 667 | \xbf\xa9\x66\x07\x01\x01\x89\xac\x26\x70\xc8\x72\xcb\x61\x56\x30\ 668 | \x10\x90\x84\xd5\x06\x8e\xb0\xbc\x72\x1b\x2d\x02\x02\x12\xbf\x1a\ 669 | \xc1\xe1\x97\x53\xce\xa3\xc4\x40\x40\xb2\xba\x56\x70\xe4\x7c\xed\ 670 | \xfd\xf7\x36\x0a\x08\x48\x16\x07\x0d\x0e\xff\x0b\x98\xfb\xc8\xd1\ 671 | \x40\x40\xf2\x76\xc5\xe0\xc8\xfd\xca\x87\xed\x2f\x0a\x10\x90\xbc\ 672 | \x0e\x1d\x1c\x61\x97\xaf\x84\xd1\xd1\x80\xd4\x8e\x04\x1c\x25\x5c\ 673 | \xf7\xf0\x3d\x46\x05\x52\x2b\x12\x70\x84\x5f\xbc\x52\x66\x44\x07\ 674 | \x52\x1b\x12\x70\x94\x72\xd5\x65\xfb\x54\x01\x52\x0b\x12\x70\xc8\ 675 | \x2e\x5d\x49\xb3\xd4\x80\x58\x47\x02\x8e\x92\xae\xb9\x7c\xaf\xaa\ 676 | \x40\xac\x22\x01\x87\xfc\xc2\x95\x36\x53\x1d\x88\x35\x24\xe0\x28\ 677 | \xed\x8a\x8f\xdb\x6f\x12\x20\x56\x90\xf4\xe7\x98\xcd\x66\x7c\x3e\ 678 | \xc7\xb8\x3b\x57\xd4\xec\x64\x40\xfa\x54\x8e\xde\xde\xa6\x7f\xb7\ 679 | \x94\x1b\x45\xa5\xd4\x34\x4d\xff\x01\x30\xce\xb9\xf5\xa6\x69\xbe\ 680 | \x28\x70\xef\xa6\xdf\x9a\x47\xb3\x8f\xa4\x40\x4a\x7f\x25\xd1\x2c\ 681 | \x42\x6b\xed\x52\x3f\xd9\x49\x2b\x8f\xd0\x75\x93\x03\x01\x49\x68\ 682 | \x45\xf2\xf1\xe0\x90\x67\x37\x9f\x39\x09\x10\x90\x8c\x2f\x6e\x68\ 683 | \x05\x70\x0c\x25\xe4\xf7\xf5\xc9\x80\x80\xc4\xaf\x20\xc9\x28\x70\ 684 | \x48\x52\x5b\x3c\x67\x52\x20\x20\x89\x57\xe4\x7c\x25\x70\xc4\xcd\ 685 | \x74\x72\x20\x20\x89\x57\x28\x38\xe2\x65\x39\xf9\xcf\x20\x27\x8f\ 686 | \x52\xf2\x9b\xd3\xc5\xaf\x25\x7c\x45\x70\x84\x67\xe6\x33\x23\x8b\ 687 | \x57\x90\xf9\x46\x41\xe2\x53\xd9\xbb\x63\xc0\x21\xcb\xcd\x67\x56\ 688 | \x56\x40\xf8\x76\xcb\xa7\xb2\xb7\xc7\x80\x23\x3c\xb3\x90\x19\xd9\ 689 | \x01\x01\x89\x7f\x7d\xe0\xf0\xcf\x4a\x3a\x32\x4b\x20\x20\x19\xae\ 690 | \x13\x1c\xc3\x19\xc5\x18\x91\x2d\x10\x90\x2c\xaf\x17\x1c\x31\xae\ 691 | \xbe\xdf\x1a\x59\x03\x01\x09\x3f\x90\xfb\x5d\x63\xbd\x51\xd9\x03\ 692 | \x01\xc9\x9b\xf2\x79\xe5\xd0\x83\xb0\x6c\xe5\x22\x80\x80\xe4\xf5\ 693 | \x3f\xb7\x6f\xdb\x76\x3b\x97\x0f\x02\x4a\x7f\x55\xa7\x79\x62\x31\ 694 | \x40\x6a\x46\x02\x8e\x69\x70\xf4\x4f\x2d\x0a\x48\x8d\x48\xc0\x31\ 695 | \x1d\x8e\x22\x81\xd4\x84\x04\x1c\xd3\xe2\x28\x16\x48\x0d\x48\xc0\ 696 | \x31\x3d\x8e\xa2\x81\x58\x46\x02\x8e\x3c\x70\x14\x0f\xc4\x22\x12\ 697 | \x70\xe4\x83\xc3\x04\x10\x4b\x48\xc0\x91\x17\x0e\x33\x40\x2c\x20\ 698 | \x01\x47\x7e\x38\x4c\x01\x29\x19\x09\x38\xf2\xc4\x61\x0e\x48\x89\ 699 | \x48\xc0\x91\x2f\x0e\x93\x40\x4a\x42\x02\x8e\xbc\x71\x98\x05\x52\ 700 | \x02\x12\x70\xe4\x8f\xc3\x34\x90\x9c\x91\x80\xa3\x0c\x1c\xe6\x81\ 701 | \xe4\x88\x04\x1c\xe5\xe0\xa8\x02\x48\x4e\x48\xc0\x51\x16\x8e\x6a\ 702 | \x80\xe4\x80\x04\x1c\xe5\xe1\xa8\x0a\xc8\x94\x48\xc0\x51\x26\x8e\ 703 | \xea\x80\x4c\x81\x04\x1c\xe5\xe2\xa8\x12\x48\x4a\x24\xe0\x28\x1b\ 704 | \x47\xb5\x40\x52\x20\x01\x47\xf9\x38\xaa\x06\xa2\x89\x04\x1c\x36\ 705 | \x70\x54\x0f\x44\x03\x09\x38\xec\xe0\x00\xc8\x51\x97\xb1\xde\x55\ 706 | \x1e\x1c\xb6\x70\x00\xe4\x58\x9f\x63\x91\x80\xc3\x1e\x0e\x80\x9c\ 707 | \xe8\x54\x8a\x04\x1c\x36\x71\x00\x64\x41\xaf\xa1\x48\xc0\x61\x17\ 708 | \x07\x40\x96\x74\xeb\x8b\x04\x1c\xb6\x71\x00\x64\x45\xbf\x43\x48\ 709 | \xc0\x61\x1f\x07\x40\x06\x3a\x5e\x86\x04\x1c\x75\xe0\x00\x88\x47\ 710 | \xcf\x27\x91\x80\xc3\x23\x34\x43\x43\x8a\x7b\xf3\xea\x29\xb2\x9f\ 711 | \x23\xe9\x9f\xcd\x47\x10\x4c\xd1\xc0\x74\xcf\x04\x88\x67\xf6\x9b\ 712 | \x9b\x9b\xef\xf5\x43\xf7\xf6\xf6\x5e\x78\x4e\x61\x98\x81\x04\x00\ 713 | \x62\xa0\x44\x8e\xa0\x97\x00\x40\xf4\xb2\x65\x65\x03\x09\x00\xc4\ 714 | \x40\x89\x1c\x41\x2f\x01\x80\xe8\x65\xcb\xca\x06\x12\x00\x88\x81\ 715 | \x12\x39\x82\x5e\x02\x00\xd1\xcb\x96\x95\x0d\x24\x00\x10\x03\x25\ 716 | \x72\x04\xbd\x04\x00\xa2\x97\x2d\x2b\x1b\x48\x00\x20\x06\x4a\xe4\ 717 | \x08\x7a\x09\x00\x44\x2f\x5b\x56\x36\x90\x00\x40\x0c\x94\xc8\x11\ 718 | \xf4\x12\x00\x88\x5e\xb6\xac\x6c\x20\x01\x80\x18\x28\x91\x23\xe8\ 719 | \x25\x00\x10\xbd\x6c\x59\xd9\x40\x02\x00\x31\x50\x22\x47\xd0\x4b\ 720 | \x00\x20\x7a\xd9\xb2\xb2\x81\x04\x00\x62\xa0\x44\x8e\xa0\x97\x00\ 721 | \x40\xf4\xb2\x65\x65\x03\x09\x00\xc4\x40\x89\x1c\x41\x2f\x01\x80\ 722 | \xe8\x65\xcb\xca\x06\x12\x00\x88\x81\x12\x39\x82\x5e\x02\x00\xd1\ 723 | \xcb\x96\x95\x0d\x24\x00\x10\x03\x25\x72\x04\xbd\x04\x00\xa2\x97\ 724 | \x2d\x2b\x1b\x48\x00\x20\x06\x4a\xe4\x08\x7a\x09\x00\x44\x2f\x5b\ 725 | \x56\x36\x90\xc0\xbf\x8a\xe6\xd7\x41\x2e\x18\x67\x0e\x00\x00\x00\ 726 | \x00\x49\x45\x4e\x44\xae\x42\x60\x82\ 727 | \x00\x00\x0f\x11\ 728 | \x89\ 729 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ 730 | \x00\x00\xc8\x00\x00\x00\xc8\x08\x06\x00\x00\x00\xad\x58\xae\x9e\ 731 | \x00\x00\x0e\xd8\x49\x44\x41\x54\x78\x5e\xed\xdd\x5f\x88\x1d\xd5\ 732 | \x1d\x07\xf0\xdf\x99\xec\xdd\x7b\x25\x21\x5d\x5b\xa1\x05\x43\x1b\ 733 | \xc2\x75\x37\x7b\x67\x02\x81\xb5\x0f\x0d\x18\x43\x50\x22\x8a\xa0\ 734 | \x0f\x8a\x50\x29\xbe\x14\x41\xf4\xa5\xd5\xea\x5b\xdb\xb7\x4a\x2d\ 735 | \x08\x4a\x4b\xf1\xa5\x88\x05\x69\x1f\x14\xc4\x12\x9b\x92\xa6\x0a\ 736 | \xe9\x43\xba\x20\x64\xe6\x26\x59\x2f\x61\x2b\xf1\x21\x90\x62\x9a\ 737 | \x66\xe9\xec\xde\xed\x9c\x72\xae\x7b\xf5\x1a\xf7\xe6\xde\x99\x39\ 738 | \xff\xcf\x77\xde\x42\x66\xe6\x9c\xf3\xfb\xfd\x3e\x7b\xe6\xcc\xbd\ 739 | \x77\x86\x11\x36\x44\x00\x11\x18\x1b\x01\x86\xd8\x20\x02\x88\xc0\ 740 | \xf8\x08\x00\x08\xaa\x03\x11\xb8\x49\x04\x00\x04\xe5\x81\x08\x00\ 741 | \x08\x6a\x00\x11\xa8\x16\x01\xcc\x20\xd5\xe2\x86\xa3\x02\x89\x00\ 742 | \x80\x04\x92\x68\x0c\xb3\x5a\x04\x00\xa4\x5a\xdc\x70\x54\x20\x11\ 743 | \x00\x90\x40\x12\x8d\x61\x56\x8b\x00\x80\x54\x8b\x1b\x8e\x0a\x24\ 744 | \x02\x00\x12\x48\xa2\x31\xcc\x6a\x11\x00\x90\x6a\x71\xc3\x51\x81\ 745 | \x44\xc0\x09\x20\xfb\xf6\xed\xfb\x5a\xab\xd5\x5a\xc8\xf3\xfc\xc2\ 746 | \xc5\x8b\x17\xff\x1d\x48\x6e\xbc\x1c\xa6\x6b\xb9\xb4\x1a\xc8\xde\ 747 | \xbd\x7b\x5b\x3b\x77\xee\x7c\x89\x88\x9e\x62\x8c\x31\xce\x39\x27\ 748 | \xa2\xdf\xac\xad\xad\xfd\x78\x75\x75\x35\xf7\xb2\x82\x3c\x1d\x94\ 749 | \xab\xb9\xb4\x16\xc8\x56\x40\xdf\x66\x8c\x1d\xdb\xa6\x66\x4e\xe5\ 750 | \x79\x7e\x5f\xaf\xd7\x5b\xf7\xb4\x9e\xbc\x1a\x56\xbb\xdd\x6e\xb6\ 751 | \x5a\xad\xe3\x44\x74\xe4\xc6\x81\x71\xce\xdf\x5b\x5b\x5b\x7b\xc8\ 752 | \xd6\x3f\x78\x56\x02\x99\x80\x63\x18\xe3\x53\x57\xaf\x5e\xbd\xff\ 753 | \xd2\xa5\x4b\xff\xf5\xaa\x9a\x3c\x1b\xcc\x9e\x3d\x7b\x6e\x99\x9b\ 754 | \x9b\xfb\xd3\x76\x38\x86\x43\xb5\x19\x89\x75\x40\xa6\xc4\x31\x8c\ 755 | \xed\xe9\xa2\x28\x8e\x75\xbb\xdd\xeb\x9e\xd5\x95\x17\xc3\xe9\x74\ 756 | \x3a\xbb\xa2\x28\x7a\x8f\x88\x0e\x4d\x1a\x90\xad\x48\xac\x02\x52\ 757 | \x12\xc7\x20\xe6\x9c\xf3\x33\xeb\xeb\xeb\xf7\xf4\x7a\xbd\x6b\x93\ 758 | \x92\x80\xff\xd7\x17\x81\x76\xbb\xbd\xbb\xd9\x6c\xfe\x85\x31\xf6\ 759 | \xdd\x69\x5b\xb5\x11\x89\x35\x40\xaa\xe0\x18\x99\xa2\x3f\x8c\xa2\ 760 | \xe8\xe8\xd9\xb3\x67\x3f\x9d\x36\x19\xd8\x4f\x5d\x04\x0e\x1c\x38\ 761 | \x70\x6b\x51\x14\x27\x19\x63\x07\xcb\xb6\x62\x1b\x12\x2b\x80\xd4\ 762 | \xc1\x31\x82\x24\x8b\xa2\xe8\x2e\x20\x29\x5b\x92\x72\xf7\xdf\xc2\ 763 | \xf1\x01\x63\x2c\xae\x7a\x66\x9b\x90\x18\x07\x22\x03\xc7\x28\x92\ 764 | \x7e\xbf\x7f\x64\x65\x65\xe5\x4a\xd5\xe4\xe0\xb8\xea\x11\x98\x9f\ 765 | \x9f\xbf\xad\xd1\x68\x9c\xaa\x83\xc3\xb6\x85\xbb\x51\x20\x32\x71\ 766 | \x8c\xa4\xf5\x02\x11\xdd\x9d\xa6\xe9\xe5\xea\xa9\xc6\x91\x65\x23\ 767 | \x90\x24\xc9\x37\x89\xe8\x6f\x44\xb4\x50\xf6\xd8\x71\xfb\xdb\x30\ 768 | \x93\x18\x03\xa2\x08\xc7\x30\xd6\x17\x37\x36\x36\x0e\xaf\xac\xac\ 769 | \x7c\x22\x2b\x59\x38\xcf\xf8\x08\xcc\xcf\xcf\xdf\x3e\x3b\x3b\xfb\ 770 | \x3e\x11\xed\x93\x1d\x27\xd3\x48\x8c\x00\x51\x8c\x63\x78\x77\xeb\ 771 | \xe3\x7e\xbf\x7f\x08\x48\x64\x97\xec\x97\xcf\x27\x70\x34\x1a\x8d\ 772 | \xd3\x8c\xb1\x6f\xab\x6a\xc9\x24\x12\xed\x40\x74\xe0\x18\xb9\x8e\ 773 | \xfd\xb8\x28\x8a\xc3\xe7\xce\x9d\xfb\xa7\xaa\xe4\x85\x7c\xde\xc5\ 774 | \xc5\xc5\xef\x44\x51\xf4\xbe\x4a\x1c\xa6\xd7\x24\x5a\x81\xe8\xc4\ 775 | \x31\x52\xb8\x9f\x30\xc6\x0e\x9f\x3d\x7b\xf6\x62\xc8\xc5\x2c\x7b\ 776 | \xec\x07\x0e\x1c\xd8\xc7\x39\x17\x97\x55\xb7\xcb\x3e\xb7\x4d\x6b\ 777 | \x12\x6d\x40\x0c\xe1\x18\xc6\xfa\x72\xbf\xdf\xbf\xfb\xc2\x85\x0b\ 778 | \x62\x01\x8f\xad\x66\x04\x16\x16\x16\x16\x1a\x8d\x86\x58\x90\x8b\ 779 | \x85\xb9\xd6\x4d\xf7\xe5\x96\x16\x20\x86\x71\x0c\xd7\x24\x57\x38\ 780 | \xe7\x47\xba\xdd\x6e\xa6\x35\xa3\x9e\x35\xd6\xe9\x74\x62\xc6\x98\ 781 | \xb8\x95\x7b\x9b\xa9\xa1\xe9\x44\xa2\x1c\x88\x0d\x38\x46\x12\xf9\ 782 | \x69\x51\x14\x77\x01\x49\xb5\xd2\x16\x38\xa2\x28\xfa\x80\x88\x6e\ 783 | \xad\x76\x06\x79\x47\xe9\x42\xa2\x14\x88\x65\x38\x86\xd9\x11\x48\ 784 | \x8e\x76\xbb\xdd\x0f\xe5\xa5\xcb\xff\x33\x75\x3a\x9d\x83\x51\x14\ 785 | \x9d\xb4\x01\x87\xce\x85\xbb\x32\x20\x96\xe2\x18\x5e\x6e\x89\x2f\ 786 | \x36\xde\x93\x65\xd9\x19\xff\x4b\xbb\xfe\x08\xe3\x38\x16\x5f\x38\ 787 | \x14\x5f\x3c\xdc\x5d\xff\x6c\x72\xcf\xa0\x7a\x26\x51\x02\xc4\x66\ 788 | \x1c\x23\x7f\x7d\xae\x8b\x1f\x63\xa5\x69\x7a\x5a\x6e\xca\xfc\x3a\ 789 | \x5b\x92\x24\x87\x44\x11\x32\xc6\x76\xd9\x3a\x32\x95\x48\xa4\x03\ 790 | \x71\x01\xc7\x48\xa2\xc5\x8f\xad\xee\x4f\xd3\xf4\x94\xad\xc9\x37\ 791 | \xd9\xaf\x24\x49\xc4\x2f\x00\xc5\x8f\x9d\x6e\x31\xd9\x8f\x69\xda\ 792 | \x56\x85\x44\x2a\x10\xc7\x70\x0c\x2f\xb7\xd6\x19\x63\xf7\x01\xc9\ 793 | \x97\xcb\x50\xe0\xe0\x9c\x1f\x67\x8c\x35\xa7\x29\x50\x1b\xf6\x51\ 794 | \x81\x44\x1a\x10\x17\x71\x8c\x5c\x6e\x09\x24\x0f\xa6\x69\x7a\xc2\ 795 | \x86\x44\x9b\xee\x43\x92\x24\xf7\x72\xce\xdf\x71\x09\x87\xaa\x85\ 796 | \xbb\x14\x20\x2e\xe3\x18\x29\xc6\x3e\x11\x3d\x9c\xa6\xe9\xbb\xa6\ 797 | \x0b\xd4\x64\xfb\x49\x92\x3c\x40\x44\x6f\x11\x51\xc3\x64\x3f\xea\ 798 | \xb4\x2d\x73\x26\xa9\x0d\xc4\x13\x1c\xc3\x7c\x6c\x12\xd1\xa3\x69\ 799 | \x9a\x8a\x02\x09\x6e\x4b\x92\xe4\x61\x22\xfa\x03\x11\xcd\xb8\x3e\ 800 | \x78\x59\x48\x6a\x01\xf1\x0c\xc7\xb0\x26\xfe\x47\x44\x8f\x84\x86\ 801 | \x64\x0b\xc7\x1f\x89\x68\x87\xeb\x38\x64\x5e\x6e\x55\x06\xe2\x29\ 802 | \x8e\xcf\x91\x70\xce\x1f\xcf\xb2\xec\x4d\x5f\x8a\xe5\x66\xe3\x88\ 803 | \xe3\xf8\x31\xc6\xd8\x1b\x3e\xe1\x90\x85\xa4\x12\x10\xcf\x71\x0c\ 804 | \xef\x6e\x89\xa7\x38\x3e\x91\x65\xd9\xeb\x3e\x23\x89\xe3\xf8\x07\ 805 | \x44\xf4\x3b\xf1\xe4\x4a\x5f\xc7\x59\xe7\x72\xab\x52\x50\xe2\x38\ 806 | \xfe\x05\x63\xec\x79\x5f\x03\x3a\xf2\xd7\x47\x20\x79\x32\xcb\xb2\ 807 | \xd7\x7c\x1c\x6b\x1c\xc7\x3f\x24\xa2\xdf\xfa\x8c\x63\x24\x97\x2f\ 808 | \x66\x59\xf6\x42\xd9\x3c\x96\x06\xb2\xb4\xb4\xd4\xc8\xf3\xfc\x1a\ 809 | \x63\xac\x55\xb6\x31\x57\xf7\x2f\x8a\xe2\x99\x6e\xb7\xfb\xaa\xab\ 810 | \xfd\xdf\xae\xdf\x9d\x4e\xe7\xe9\x28\x8a\x5e\xf1\x69\x4c\x37\x1b\ 811 | \x0b\xe7\x3c\x6f\xb5\x5a\xbb\x97\x97\x97\xc5\xdd\xca\xa9\xb7\xd2\ 812 | \x40\x3a\x9d\x4e\x3b\x8a\xa2\x8f\xa6\x6e\xc1\x93\x1d\x7d\x42\x12\ 813 | \x1a\x8e\x61\x09\x16\x45\x71\x47\xb7\xdb\xed\x95\x29\xc9\xd2\x40\ 814 | \x42\x9c\x41\x46\x02\xfa\x5c\x9a\xa6\xe2\x69\xf3\xce\x6e\x49\x92\ 815 | \x3c\x4b\x44\xbf\x74\x76\x00\x15\x3b\xae\x6d\x06\x11\xfd\x0b\x65\ 816 | \x0d\x32\x26\x17\x3f\x4f\xd3\xf4\x67\x15\xf3\x64\xf4\xb0\x24\x49\ 817 | \x7e\x4a\x44\x4e\xf6\xbd\x6e\xe0\x38\xe7\x7a\xd6\x20\xa2\xa3\x21\ 818 | \xdc\xc5\x9a\x90\x90\x97\xd2\x34\x7d\xae\x6e\xd2\x74\x1e\x9f\x24\ 819 | \x89\x98\x35\xc4\xec\x11\xdc\xa6\xfd\x2e\x16\x90\x0c\x1e\x9a\xfd\ 820 | \x6a\x96\x65\xcf\xb8\x50\x6d\x71\x1c\xbf\xc2\x18\x7b\xda\x85\xbe\ 821 | \xca\xee\x63\x1d\x1c\xa2\x2f\xa5\xd7\x20\xa3\x03\x08\x7d\x26\x71\ 822 | \x01\x09\x70\xd4\x7b\x39\x4f\x2d\x20\x98\x49\x06\x33\xc9\x6b\x59\ 823 | \x96\x3d\x29\xde\xc4\x20\xfb\xaf\x5f\xcd\xf3\xb1\x38\x8e\xc5\x67\ 824 | \x1c\xe2\xb3\x8e\xe0\xb6\xba\x33\xc7\x30\x60\xb5\x81\x00\xc9\x00\ 825 | \xc9\xeb\x59\x96\x3d\x61\x11\x12\x81\x43\x7c\x3a\x2e\x3e\x25\x0f\ 826 | \x6e\x93\x85\xa3\xf6\x25\x16\x2e\xb7\xbe\x88\x00\xe7\xfc\xcd\x2c\ 827 | \xcb\x1e\x27\x22\xf1\x65\x47\x93\xdb\x8e\x38\x8e\xdf\x60\x8c\x3d\ 828 | \x66\xb2\x13\xa6\xda\x96\x89\x43\x2a\x10\xcc\x24\x83\x92\x78\x2b\ 829 | \x4d\xd3\x47\x0c\x22\xd9\x91\x24\x89\xf8\x46\xae\xf8\xda\x7a\x70\ 830 | \x9b\x6c\x1c\xd2\x81\x00\xc9\xe7\x48\x1e\x25\x22\xf1\xdb\x12\x9d\ 831 | \xdb\x4c\x92\x24\xe2\xb7\x1c\xc0\x21\x31\xea\x52\xd6\x20\x37\xf6\ 832 | \x27\xf4\xbb\x5b\x44\xf4\x6e\xb3\xd9\x7c\xb8\xec\xf7\x7e\xaa\xe6\ 833 | \x55\x7c\xbb\x61\x7d\x7d\x5d\xfc\xc8\x4b\xfc\x1a\x30\xb8\x4d\xc5\ 834 | \xcc\x31\x0c\xa2\x12\x20\x98\x49\x06\xe1\x3d\x91\xe7\xf9\x83\xaa\ 835 | \xdf\xe5\xbe\xf5\x0e\xf2\x77\x88\xe8\xde\xe0\x64\x7c\xf6\x12\x57\ 836 | \xa5\xef\x59\x57\x06\x04\x48\x06\xe5\x7a\x2a\xcf\xf3\xfb\x54\x21\ 837 | \xd9\xc2\x71\xfc\x66\xef\x20\xf7\x19\x8d\x6a\x1c\x4a\xd6\x20\xb8\ 838 | \xdc\xfa\x4a\x49\x9e\xba\x7a\xf5\xea\xfd\x97\x2e\x5d\x12\xcf\xe0\ 839 | \x92\xb6\xed\xd9\xb3\xe7\x96\xb9\xb9\x39\xf1\xcc\x2a\xf1\xec\xaa\ 840 | \xe0\x36\x1d\x38\xb4\x00\xc1\x4c\x32\xa8\xdd\xd3\x45\x51\x1c\xeb\ 841 | \x76\xbb\xd7\x65\x54\x72\xa7\xd3\xd9\x15\x45\xd1\x7b\x44\x74\x48\ 842 | \xc6\xf9\x5c\x3b\x87\x2e\x1c\xda\x80\x00\xc9\xe0\x5a\xf9\xcc\xfa\ 843 | \xfa\xfa\x3d\xbd\x5e\x4f\x3c\x17\xb8\xf2\xd6\x6e\xb7\x77\x37\x9b\ 844 | \x4d\xf1\x9c\x5c\xf1\xbc\xdc\xe0\x36\x9d\x38\xb4\x02\x01\x92\x01\ 845 | \x92\x0f\xa3\x28\x3a\x5a\xf5\x5d\xee\x5b\xef\x20\x3f\xc9\x18\x3b\ 846 | \x18\x9c\x0c\x0d\x0b\xf2\xed\x62\xaa\x74\x91\xbe\x5d\x83\xa1\xdf\ 847 | \x02\xe6\x9c\x67\x51\x14\xdd\x55\x16\xc9\x16\x8e\x0f\x64\xbc\x83\ 848 | \xdc\x45\x5c\xba\x67\x8e\x61\x8c\xb4\x03\xc1\x4c\x32\x98\x49\xb2\ 849 | \x7e\xbf\x7f\x64\x65\x65\xe5\xca\x34\xc5\x3a\x3f\x3f\x7f\x5b\xa3\ 850 | \xd1\x10\x6f\x75\x8a\xa7\xd9\xdf\xb7\x7d\x4c\xe1\xd0\x7e\x89\x35\ 851 | \x9a\xb8\xd0\x67\x12\x22\x12\xef\x4b\xbc\x3b\x4d\xd3\xcb\x37\x2b\ 852 | \xe8\x24\x49\xc4\x7b\x00\xc5\xfb\x00\x17\x7c\x2b\xfc\x69\xc6\x63\ 853 | \x12\x87\x51\x20\x98\x49\x06\xe5\x71\x71\x63\x63\xe3\xf0\xb8\x77\ 854 | \xb9\x8b\x77\x90\xcf\xce\xce\x8a\x37\xc9\xee\x9b\xa6\x98\x7c\xdb\ 855 | \xc7\x34\x0e\xe3\x40\x80\x64\x70\xb9\xf5\x71\xbf\xdf\x3f\x74\x23\ 856 | \x12\x81\xa3\xd1\x68\x9c\xd6\xf1\x0e\x72\x1b\x61\xd9\x80\xc3\x0a\ 857 | \x20\x40\x32\x40\x72\x85\x31\xf6\x23\x22\xfa\xb3\x88\x47\x51\x14\ 858 | \xf7\x32\xc6\x5e\x66\x8c\x7d\xc3\xc6\xe2\x55\xdd\x27\x5b\x70\x58\ 859 | \x03\x04\x48\x54\x97\x9c\x3b\xe7\xb7\x09\x87\x55\x40\x80\xc4\x9d\ 860 | \x22\x56\xd5\x53\xdb\x70\x58\x07\x04\x48\x54\x95\x9e\xfd\xe7\xb5\ 861 | \x11\x87\x95\x40\x80\xc4\xfe\x62\x96\xdd\x43\x5b\x71\x58\x0b\x04\ 862 | \x48\x64\x97\xa0\xbd\xe7\xb3\x19\x87\xd5\x40\x80\xc4\xde\xa2\x96\ 863 | \xd5\x33\xdb\x71\x58\x0f\x04\x48\x64\x95\xa2\x7d\xe7\x71\x01\x87\ 864 | \x13\x40\x80\xc4\xbe\xe2\xae\xdb\x23\x57\x70\x38\x03\x04\x48\xea\ 865 | \x96\xa4\x3d\xc7\xbb\x84\xc3\x29\x20\x40\x62\x4f\x91\x57\xed\x89\ 866 | \x6b\x38\x9c\x03\x02\x24\x55\x4b\xd3\xfc\x71\x2e\xe2\x70\x12\x08\ 867 | \x90\x98\x2f\xf6\xb2\x3d\x70\x15\x87\xb3\x40\x80\xa4\x6c\x89\x9a\ 868 | \xdb\xdf\x65\x1c\x4e\x03\x01\x12\x73\x45\x3f\x6d\xcb\xae\xe3\x70\ 869 | \x1e\x08\x90\x4c\x5b\xaa\xfa\xf7\xf3\x01\x87\x17\x40\x80\x44\x7f\ 870 | \xf1\x4f\x6a\xd1\x17\x1c\xde\x00\x01\x92\x49\x25\xab\xef\xff\x7d\ 871 | \xc2\xe1\x15\x10\x20\xd1\x87\x60\x5c\x4b\xbe\xe1\xf0\x0e\x08\x90\ 872 | \x98\x43\xe2\x23\x0e\x2f\x81\x00\x89\x7e\x24\xbe\xe2\xf0\x16\x08\ 873 | \x90\xe8\x43\xe2\x33\x0e\xaf\x81\x00\x89\x7a\x24\xbe\xe3\xf0\x1e\ 874 | \x08\x90\xa8\x43\x12\x02\x8e\x20\x80\x00\x89\x7c\x24\xa1\xe0\x08\ 875 | \x06\x08\x90\xc8\x43\x12\x12\x8e\xa0\x80\x00\x49\x7d\x24\xa1\xe1\ 876 | \x08\x0e\x08\x90\x54\x47\x12\x22\x8e\x20\x81\x00\x49\x79\x24\xa1\ 877 | \xe2\x08\x16\x08\x90\x4c\x8f\x24\x64\x1c\x41\x03\x01\x92\xc9\x48\ 878 | \x42\xc7\x11\x3c\x10\x20\x19\x8f\x04\x38\x3e\x8b\x8d\x91\x77\x14\ 879 | \x4e\xfe\xdb\xa5\x77\x0f\xf1\x3a\xb8\x5d\xbb\x76\x9d\x24\xa2\xef\ 880 | \xe9\x6d\xd9\xda\xd6\xfe\x7e\xfd\xfa\xf5\xa3\xab\xab\xab\xb9\xb5\ 881 | \x3d\xd4\xd4\x31\x00\xd9\x0a\x74\x92\x24\x77\x12\xd1\x19\x4d\x71\ 882 | \xb7\xba\x99\xcd\xcd\xcd\x3b\xcf\x9f\x3f\xbf\x6c\x75\x27\x35\x75\ 883 | \x0e\x40\x46\x02\x1d\xc7\xf1\xbf\x18\x63\x5f\xd7\x14\x7b\x5b\x9b\ 884 | \xb9\x9c\xa6\xe9\xb7\x6c\xed\x9c\xee\x7e\x01\xc8\x48\xc4\x93\x24\ 885 | \xf9\x94\x88\xe6\x74\x27\xc1\xb2\xf6\x00\x64\x24\x21\x00\xb2\x15\ 886 | \x8c\xfd\xfb\xf7\x2f\xcd\xcc\xcc\xfc\xc3\xb2\x62\x35\xd2\x1d\x5c\ 887 | \x62\x7d\x11\x76\x00\x21\xa2\x76\xbb\xdd\x6c\xb5\x5a\x7f\xc5\x22\ 888 | \xfd\xf3\xc2\xc0\x22\x7d\x2b\x14\xc1\x03\xd9\xc2\x71\x9c\x88\x8e\ 889 | \x18\xf9\x73\x6d\x69\xa3\xb8\xcd\x8b\xdb\xbc\xc3\x99\x03\x38\xc6\ 890 | \x20\x05\x92\x80\x3f\x07\xc1\xcc\x31\xdd\xd4\x15\x3a\x92\x20\x2f\ 891 | \xb1\x80\x63\x3a\x1c\xc3\xbd\x42\x46\x12\x1c\x10\xe0\x28\x87\x23\ 892 | \x74\x24\x41\x01\x01\x8e\x6a\x38\x42\x46\x12\x0c\x10\xe0\xa8\x87\ 893 | \x23\x54\x24\x41\x00\x01\x0e\x39\x38\x42\x44\xe2\x3d\x10\xe0\x90\ 894 | \x8b\x23\x34\x24\x5e\x03\x01\x0e\x35\x38\x42\x42\xe2\x2d\x10\xe0\ 895 | \x50\x8b\x23\x14\x24\x5e\x02\x01\x0e\x3d\x38\x42\x40\xe2\x1d\x10\ 896 | \xe0\xd0\x8b\xc3\x77\x24\x5e\x01\x01\x0e\x33\x38\x7c\x46\xe2\x0d\ 897 | \x10\xe0\x30\x8b\xc3\x57\x24\x5e\x00\x01\x0e\x3b\x70\xf8\x88\xc4\ 898 | \x79\x20\xc0\x61\x17\x0e\xdf\x90\x38\x0d\x04\x38\xec\xc4\xe1\x13\ 899 | \x12\x67\x81\x00\x87\xdd\x38\x7c\x41\xe2\x24\x10\xe0\x70\x03\x87\ 900 | \x0f\x48\x9c\x03\x02\x1c\x6e\xe1\x70\x1d\x89\x53\x40\x80\xc3\x4d\ 901 | \x1c\x2e\x23\x71\x06\x08\x70\xb8\x8d\xc3\x55\x24\x4e\x00\x01\x0e\ 902 | \x3f\x70\xb8\x88\xc4\x7a\x20\xc0\xe1\x17\x0e\xd7\x90\x58\x0d\x04\ 903 | \x38\xfc\xc4\xe1\x12\x12\x6b\x81\x00\x87\xdf\x38\x5c\x41\x62\x25\ 904 | \x10\xe0\x08\x03\x87\x0b\x48\xac\x03\x02\x1c\x61\xe1\xb0\x1d\x89\ 905 | \x55\x40\x42\xc6\xc1\x39\x2f\x18\x63\x19\x11\x35\x38\xe7\xf3\x8c\ 906 | \xb1\x28\x34\x2a\x36\x3e\xc1\xd1\x1a\x20\x21\xe3\x20\xa2\xd3\x9b\ 907 | \x9b\x9b\xdf\x3f\x7f\xfe\xfc\xaa\x40\xb1\x7f\xff\xfe\xbd\x33\x33\ 908 | \x33\xbf\x27\xa2\x43\x40\x62\x36\x02\x56\x00\x09\x19\xc7\xb8\xbf\ 909 | \x9a\xe2\xc5\xa2\x3b\x77\xee\x7c\x9b\x31\x76\xcc\x6c\x89\xe8\x6f\ 910 | \xdd\xa6\x99\xc4\x38\x10\xe0\x58\x7b\x68\xdc\xdb\x64\x81\x64\x7c\ 911 | \x6c\x74\xb1\x35\x0a\x04\x38\x26\x17\x00\x90\x4c\x8e\x91\x4a\x2c\ 912 | \xc6\x80\x00\xc7\xf4\x89\x07\x92\xe9\x63\x25\x1b\x8b\x11\x20\xc0\ 913 | \x51\x3e\xe1\x40\x52\x3e\x66\x32\xb0\x68\x07\x02\x1c\xd5\x13\x0d\ 914 | \x24\xd5\x63\x57\x15\x8b\x56\x20\xc0\x51\x3f\xc1\x40\x52\x3f\x86\ 915 | \x65\xb0\x68\x03\x02\x1c\xf2\x12\x0b\x24\xf2\x62\x39\x09\x8b\x16\ 916 | \x20\xc0\x21\x3f\xa1\x40\x22\x3f\xa6\xdb\x61\x51\x0e\x04\x38\xd4\ 917 | \x25\x12\x48\xd4\xc5\x76\x88\x45\x29\x10\xe0\x50\x9f\x40\x20\x51\ 918 | \x1b\x63\x65\x40\x80\x43\x6d\xe2\x46\x2f\x07\x80\x44\x5d\xac\x95\ 919 | \x00\x01\x0e\x75\x09\x1b\xb7\xa8\x04\x12\x35\x31\x97\x0e\x04\x38\ 920 | \xd4\x24\x6a\xd2\xdd\x16\xf1\xff\x40\x22\x3f\xf6\x52\x81\x00\x87\ 921 | \xfc\x04\x4d\x03\x03\x97\x5b\x9f\x45\x40\xc5\xb7\x80\xa5\x01\x01\ 922 | \x0e\xf3\x38\x86\x50\x30\x93\xc8\xcb\x85\x14\x20\xc0\x21\x2f\x21\ 923 | \x65\x67\x0c\xac\x49\xbe\x1a\x01\x99\x33\x49\x6d\x20\xc0\x61\x1f\ 924 | \x0e\xcc\x24\xf2\x2e\xb7\x6a\x01\x01\x0e\x7b\x71\x00\x89\x1c\x24\ 925 | \x95\x81\x00\x87\xfd\x38\x80\xa4\x3e\x92\x4a\x40\x80\xc3\x1d\x1c\ 926 | \x40\x52\x0f\x49\x25\x20\x71\x1c\xbf\xc8\x18\xfb\x89\xac\x05\xa5\ 927 | \x2b\xe7\x91\xb9\xf8\x33\x31\xe6\xc0\xef\x6e\xbd\x98\x65\xd9\x0b\ 928 | \x65\xe3\x5e\x1a\xc8\xd2\xd2\x52\x23\xcf\xf3\xff\x30\xc6\x9a\x65\ 929 | \x1b\x73\x79\x7f\xd7\x71\x84\x3e\x93\x70\xce\xf3\x56\xab\xb5\x7b\ 930 | \x79\x79\xb9\x5f\xa6\x0e\x4b\x03\x59\x5c\x5c\xbc\x63\xc7\x8e\x1d\ 931 | \x2b\x65\x1a\x71\x7d\x5f\x5f\x70\x84\x8e\xa4\x28\x8a\x3b\xba\xdd\ 932 | \x6e\xaf\x4c\x3d\x96\x06\x12\xda\x0c\xe2\x1b\x8e\x50\x91\x68\x9b\ 933 | \x41\x44\x80\x43\x59\x83\xf8\x8a\x23\x44\x24\x9c\x73\x3d\x6b\x90\ 934 | \x91\x2f\xc5\xbd\xcb\x18\x3b\x5a\x66\xba\x72\x69\x5f\xdf\x71\x04\ 935 | \x86\xe4\x44\x9e\xe7\x0f\xf6\x7a\xbd\xf5\xb2\x35\x58\xfa\x12\xeb\ 936 | \x86\xc0\x7a\x89\x24\x14\x1c\x81\x20\x39\xd1\x6c\x36\x1f\x28\xbb\ 937 | \x38\x1f\xc6\xa6\x32\x10\x5f\x67\x92\xd0\x70\x78\x8e\xa4\x16\x0e\ 938 | \x11\x9b\x5a\x40\x7c\x43\x12\x2a\x0e\x4f\x91\xd4\xc6\x21\x05\x88\ 939 | \x2f\x48\x42\xc7\xe1\x19\x12\x29\x38\xa4\x01\x71\x1d\x09\x70\x7c\ 940 | \x79\xe9\xea\xf8\x27\xee\xd2\x70\x48\x05\xe2\x2a\x12\xe0\xd8\xfe\ 941 | \xbe\x8e\xa3\x48\xa4\xe2\x90\x0e\xc4\x35\x24\xc0\x71\xf3\x9b\x9e\ 942 | \x8e\x21\x91\x8e\x43\x09\x10\x57\x90\x00\xc7\x74\x9f\x08\x38\x82\ 943 | \x44\x09\x0e\x65\x40\x6c\x47\x02\x1c\xd3\xe1\x70\x64\xe1\xae\x0c\ 944 | \x87\x52\x20\xb6\x22\x01\x8e\x72\x38\x2c\x47\xa2\x14\x87\x72\x20\ 945 | \xb6\x21\x01\x8e\x6a\x38\x2c\x45\xa2\x1c\x87\x16\x20\xb6\x20\x01\ 946 | \x8e\x7a\x38\x2c\x43\xa2\x05\x87\x36\x20\xa6\x91\x00\x87\x1c\x1c\ 947 | \x96\x20\xd1\x86\x43\x2b\x10\x53\x48\x80\x43\x2e\x0e\xc3\x48\xb4\ 948 | \xe2\xd0\x0e\x44\x37\x12\xe0\x50\x83\xc3\x10\x12\xed\x38\x8c\x00\ 949 | \xd1\x85\x04\x38\xd4\xe2\xd0\x8c\xc4\x08\x0e\x63\x40\x54\x23\x01\ 950 | \x0e\x3d\x38\x34\x21\x31\x86\xc3\x28\x10\x55\x48\x80\x43\x2f\x0e\ 951 | \xc5\x48\x8c\xe2\x30\x0e\x44\x36\x12\xe0\x30\x83\x43\x11\x12\xe3\ 952 | \x38\xac\x00\x22\x0b\x09\x70\x98\xc5\x21\x19\x89\x15\x38\xac\x01\ 953 | \x52\x17\x09\x70\xd8\x81\x43\x12\x12\x6b\x70\x58\x05\xa4\x2a\x12\ 954 | \xe0\xb0\x0b\x47\x4d\x24\x56\xe1\xb0\x0e\x48\x59\x24\xc0\x61\x27\ 955 | \x8e\x8a\x48\xac\xc3\x61\x25\x90\x69\x91\x00\x87\xdd\x38\x4a\x22\ 956 | \xb1\x12\x87\xb5\x40\x26\x21\x01\x0e\x37\x70\x4c\x89\xc4\x5a\x1c\ 957 | \x56\x03\x19\x41\xf2\x2b\xc6\xd8\x53\xe2\xdf\x9c\x73\x4e\x44\xbf\ 958 | \x5e\x5b\x5b\x7b\x76\x75\x75\x35\x77\xab\x4c\xc2\xee\xed\xd6\x2f\ 959 | \x13\x5f\x22\xa2\xa7\x18\x63\x6c\x2b\x97\x2f\xb7\x5a\xad\xe7\xab\ 960 | \x3e\xd4\x4d\x47\x44\x6b\x3f\x17\x4b\x47\x27\xdb\xed\xf6\xee\xd9\ 961 | \xd9\xd9\xc5\x8d\x8d\x8d\x73\xbd\x5e\xef\x9a\x8e\x36\xd1\x86\x9a\ 962 | \x08\xb8\x96\x4b\x27\x80\xa8\x49\x15\xce\x8a\x08\x4c\x8e\x00\x80\ 963 | \x4c\x8e\x11\xf6\x08\x38\x02\x00\x12\x70\xf2\x31\xf4\xc9\x11\x00\ 964 | \x90\xc9\x31\xc2\x1e\x01\x47\x00\x40\x02\x4e\x3e\x86\x3e\x39\x02\ 965 | \x00\x32\x39\x46\xd8\x23\xe0\x08\x00\x48\xc0\xc9\xc7\xd0\x27\x47\ 966 | \x00\x40\x26\xc7\x08\x7b\x04\x1c\x01\x00\x09\x38\xf9\x18\xfa\xe4\ 967 | \x08\x00\xc8\xe4\x18\x61\x8f\x80\x23\x00\x20\x01\x27\x1f\x43\x9f\ 968 | \x1c\x01\x00\x99\x1c\x23\xec\x11\x70\x04\xfe\x0f\x14\xcd\xef\x6e\ 969 | \xa2\x15\xe6\x28\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ 970 | \ 971 | \x00\x00\x13\xaf\ 972 | \x89\ 973 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ 974 | \x00\x00\xc8\x00\x00\x00\xc8\x08\x06\x00\x00\x00\xad\x58\xae\x9e\ 975 | \x00\x00\x13\x76\x49\x44\x41\x54\x78\x5e\xed\x9d\x7f\x90\x5d\x55\ 976 | \x7d\xc0\xcf\xf7\xbe\x6c\xf2\x36\x09\x24\x2b\xc3\x14\x16\xb4\xdb\ 977 | \xcc\x92\xcd\xde\x73\x13\x6b\x41\xb0\x1d\x4d\x07\x90\x46\xaa\x93\ 978 | \x22\xc5\x19\x8b\x08\xd5\x11\xa4\x10\x2c\x05\xb4\xad\xb6\x82\xda\ 979 | \xa2\x8e\x20\xca\x4f\x91\xd2\x51\x14\xc7\x3f\x0c\xb5\x19\x1d\x88\ 980 | \xd0\xc0\x20\x5a\xf9\x55\x1c\x72\xcf\xd9\xec\x9a\xa6\x69\x59\x02\ 981 | \xad\xed\x2e\x29\x6c\x76\xd9\xcd\x3b\xdf\xce\x21\x6f\x3b\xcf\xb0\ 982 | \xd9\x77\xcf\x3d\xf7\xdd\x73\xce\xbb\xdf\xf7\xe7\xee\xf9\x9e\xef\ 983 | \x39\x9f\xef\xf9\xbc\x7b\xdf\xbb\xef\x9e\x0b\x8c\x5e\x44\x80\x08\ 984 | \x1c\x91\x00\x10\x1b\x22\x40\x04\x8e\x4c\x80\x04\xa1\xd5\x41\x04\ 985 | \x16\x21\x40\x82\xd0\xf2\x20\x02\x24\x08\xad\x01\x22\x90\x8f\x00\ 986 | \x1d\x41\xf2\x71\xa3\xa8\x8a\x10\x20\x41\x2a\x52\x68\x9a\x66\x3e\ 987 | \x02\x24\x48\x3e\x6e\x14\x55\x11\x02\x24\x48\x45\x0a\x4d\xd3\xcc\ 988 | \x47\x80\x04\xc9\xc7\x8d\xa2\x2a\x42\x80\x04\xa9\x48\xa1\x69\x9a\ 989 | \xf9\x08\x90\x20\xf9\xb8\x51\x54\x45\x08\x90\x20\x15\x29\x34\x4d\ 990 | \x33\x1f\x01\x12\x24\x1f\x37\x8a\xaa\x08\x01\x12\xa4\x22\x85\xa6\ 991 | \x69\xe6\x23\x40\x82\xe4\xe3\x46\x51\x15\x21\x40\x82\x54\xa4\xd0\ 992 | \x34\xcd\x7c\x04\x48\x90\x7c\xdc\x28\xaa\x22\x04\x48\x90\x8a\x14\ 993 | \x9a\xa6\x99\x8f\x00\x09\x92\x8f\x1b\x45\x55\x84\x00\x09\x52\x91\ 994 | \x42\xd3\x34\xf3\x11\x20\x41\xf2\x71\xa3\xa8\x8a\x10\x20\x41\x2a\ 995 | \x52\x68\x9a\x66\x3e\x02\x24\x48\x3e\x6e\x14\x55\x11\x02\x24\x48\ 996 | \x45\x0a\x4d\xd3\xcc\x47\x80\x04\xc9\xc7\x8d\xa2\x2a\x42\x80\x04\ 997 | \xa9\x48\xa1\x69\x9a\xf9\x08\x90\x20\xf9\xb8\x15\x1a\x15\xc7\xf1\ 998 | \x52\x44\xfc\xad\x5a\xad\xf6\x9b\x8c\xb1\xe3\x94\x52\x2f\x34\x1a\ 999 | \x8d\xef\x8c\x8e\x8e\xbe\x5c\x68\x22\xea\xcc\x98\x00\x09\x62\x8c\ 1000 | \xac\xd8\x80\x38\x8e\xcf\x03\x80\x3b\x01\xe0\x0d\xad\x3d\x23\xe2\ 1001 | \x2b\x8c\xb1\x5b\x85\x10\x9f\x64\x8c\x61\xb1\x59\xa9\xb7\xac\x04\ 1002 | \x48\x90\xac\xa4\x3a\xd0\x2e\x49\x92\xaf\x31\xc6\x3e\xba\x58\xd7\ 1003 | \x88\x78\x8f\x10\xe2\xa2\x0e\xa4\xa7\x2e\x33\x10\x20\x41\x32\x40\ 1004 | \xea\x44\x93\x38\x8e\xaf\x8e\xa2\xe8\x86\x2c\x7d\x2b\xa5\xae\x96\ 1005 | \x52\x7e\x39\x4b\x5b\x6a\x53\x2c\x01\x12\xa4\x58\x9e\x99\x7a\xdb\ 1006 | \xb0\x61\xc3\x0a\xa5\xd4\x38\x63\x6c\x75\xa6\x00\xc6\x5e\x9a\x98\ 1007 | \x98\x38\x61\xdf\xbe\x7d\x07\x32\xb6\xa7\x66\x05\x11\x20\x41\x0a\ 1008 | \x02\x69\xd2\x4d\x92\x24\xe7\x32\xc6\xb6\x9a\xc4\x28\xa5\x3e\x28\ 1009 | \xa5\xfc\xb6\x49\x0c\xb5\xb5\x27\x40\x82\xd8\x33\x34\xee\x81\x73\ 1010 | \xfe\x39\x00\xf8\x2b\x93\x40\xa5\xd4\xdf\x4a\x29\x8d\x62\x4c\xfa\ 1011 | \xa7\xb6\x0b\x13\x20\x41\x1c\xac\x0c\xce\xf9\x6d\x00\x70\x99\x49\ 1012 | \x6a\x44\xd4\xdf\x68\x5d\x61\x12\x43\x6d\xed\x09\x90\x20\xf6\x0c\ 1013 | \x8d\x7b\x48\x92\xe4\x0e\xc6\xd8\xa5\x26\x81\x88\x78\xbb\x10\xe2\ 1014 | \x72\x93\x18\x6a\x6b\x4f\x80\x04\xb1\x67\x68\xdc\x03\x09\x62\x8c\ 1015 | \xcc\x59\x00\x09\xe2\x00\x3d\x09\xe2\x00\x7a\xce\x94\x24\x48\x4e\ 1016 | \x70\x36\x61\x24\x88\x0d\xbd\x72\x63\x49\x90\x72\x79\xbf\x96\x8d\ 1017 | \x04\x71\x00\x3d\x67\x4a\x12\x24\x27\x38\x9b\x30\x12\xc4\x86\x5e\ 1018 | \xb9\xb1\x24\x48\xb9\xbc\xe9\x08\xe2\x80\xb7\x4d\x4a\x12\xc4\x86\ 1019 | \x5e\xce\x58\x3a\x82\xe4\x04\xe7\x20\x8c\x04\x71\x00\x9d\x04\x71\ 1020 | \x00\x3d\x67\x4a\x12\x24\x27\x38\x9b\x30\x12\xc4\x86\x5e\xb9\xb1\ 1021 | \x24\x48\xb9\xbc\xe9\x33\x88\x03\xde\x36\x29\xbb\x4e\x90\xf5\xeb\ 1022 | \xd7\xf7\x29\xa5\x62\x44\xd4\x73\x7b\x42\x4a\x39\x6b\x03\xa8\x13\ 1023 | \xb1\xdd\x76\x04\xd1\x3f\xdf\x3f\x78\xf0\x60\x52\xab\xd5\xea\x00\ 1024 | \xf0\xd4\xb3\xcf\x3e\x3b\xd5\x09\x6e\x2e\xfa\xec\x16\x41\xa2\x24\ 1025 | \x49\xfe\x92\x31\xf6\x61\xc6\xd8\x9a\x16\x90\xff\xc5\x18\xbb\x43\ 1026 | \x29\x75\x83\x94\x52\xdf\xc2\xea\xc5\xab\x5b\x04\x89\xe3\xf8\x82\ 1027 | \x28\x8a\xfe\x1c\x11\x39\x00\xbc\xb6\x96\x9a\xb7\x0a\xdf\x03\x00\ 1028 | \x9f\x4d\xd3\xf4\x3f\xbd\x00\x6e\x31\x88\xe0\x05\x19\x1c\x1c\x3c\ 1029 | \x76\xd9\xb2\x65\xf7\x01\xc0\xdb\x8f\xc4\x01\x11\x9f\x3c\x78\xf0\ 1030 | \xe0\x99\xbe\x6c\x82\x10\xba\x20\x43\x43\x43\x47\xf5\xf4\xf4\xdc\ 1031 | \xc3\x18\x3b\x67\x91\xb5\xb7\x67\x76\x76\x76\xe3\xd8\xd8\xd8\xf3\ 1032 | \x16\xeb\xd3\x79\x68\xd0\x82\xe8\xdd\x40\xa2\x28\x7a\x92\x31\xb6\ 1033 | \xa1\x1d\x49\x44\x7c\x1c\x11\xdf\xe9\xc3\x91\x24\x64\x41\xe2\x38\ 1034 | \x5e\x09\x00\x0f\x01\xc0\x69\x19\x98\x8f\x4c\x4e\x4e\x9e\x12\xf2\ 1035 | \x9d\x90\xa1\x0b\x72\x49\x14\x45\x77\xb6\x2b\xd4\xfc\xff\x7d\x91\ 1036 | \x24\x54\x41\x4c\xe4\x68\x61\x7e\x95\x10\xe2\xa6\xac\x35\xf2\xad\ 1037 | \x5d\xd0\x82\x70\xce\x9f\x00\x80\xb7\x9a\x40\xd5\x92\x4c\x4e\x4e\ 1038 | \x9e\xe1\xf2\x5d\x2d\x44\x41\xfa\xfb\xfb\x97\xf7\xf5\xf5\xed\xc8\ 1039 | \x72\xe4\x38\xac\x1e\xe3\x69\x9a\xbe\xd1\xa4\x46\x3e\xb5\x0d\x56\ 1040 | \x90\xc1\xc1\xc1\x65\xcb\x96\x2d\x9b\x9e\xff\x70\x68\x02\x15\x11\ 1041 | \x1f\x9b\x9c\x9c\xdc\xe4\x4a\x92\xd0\x04\x69\xca\xb1\x7d\xb1\xcf\ 1042 | \x79\x8b\xf1\x57\x4a\x1d\x2f\xa5\x7c\xd1\xa4\x46\xbe\xb4\x0d\x56\ 1043 | \x90\xe1\xe1\xe1\xe3\x6b\xb5\xda\xbe\xbc\x20\x5d\x4a\x12\x92\x20\ 1044 | \xb6\x72\xe8\xfa\xcc\xcd\xcd\xad\x1b\x1d\x1d\x1d\xcd\x5b\x2b\x97\ 1045 | \x71\xc1\x0a\xa2\x8f\x20\xf5\x7a\x7d\xc6\x06\x9e\x2b\x49\x42\x11\ 1046 | \xa4\x08\x39\x74\x7d\x94\x52\xc7\x48\x29\x27\x6c\x6a\xe5\x2a\x36\ 1047 | \x58\x41\x34\xb0\x24\x49\xf4\x37\x58\xa7\xd8\xc0\x73\x21\x49\x08\ 1048 | \x82\x14\x25\x07\x22\x4a\x21\x04\xb7\xa9\x91\xcb\xd8\xa0\x05\x89\ 1049 | \xe3\xf8\x03\x51\x14\x59\xef\x15\xa5\x25\x99\x9a\x9a\x3a\x6b\xef\ 1050 | \xde\xbd\x56\x47\xa4\xac\x85\xf4\x5d\x90\x81\x81\x81\xfa\x8a\x15\ 1051 | \x2b\x1e\xcc\xfb\x99\xa3\x95\x83\x52\xea\x1a\x29\xe5\x8d\x59\xd9\ 1052 | \xf8\xd6\x2e\x68\x41\x34\x4c\xce\xf9\xbd\x00\x70\xbe\x2d\x58\x44\ 1053 | \xdc\x31\x35\x35\xf5\xee\x32\x24\xf1\x59\x90\xa6\x1c\x3f\x04\x80\ 1054 | \x33\x0a\x60\xfa\xd8\xfe\xfd\xfb\x7f\x6f\x7c\x7c\x7c\xda\xb6\x2f\ 1055 | \x57\xf1\xc1\x0b\xa2\x2f\x16\x02\xc0\x36\x00\xd8\x64\x0b\xb1\x2c\ 1056 | \x49\x7c\x15\xa4\x60\x39\xb6\x23\xe2\x66\x1f\x7f\x0b\x67\xb2\x4e\ 1057 | \x82\x17\x44\x4f\x36\x34\x49\x7c\x14\x84\xe4\x58\x58\x9b\xae\x10\ 1058 | \xa4\x45\x92\xfb\x0b\x3a\x35\xd8\x81\x88\x67\x77\xea\xdd\x8f\x73\ 1059 | \x7e\x2b\x00\x98\x6e\x02\x77\x4b\x9a\xa6\x1f\x33\x79\xf7\xcb\xda\ 1060 | \xb6\x60\x39\x3a\xca\x2e\xeb\x9c\x8a\x6a\xd7\x35\x82\x68\x20\x05\ 1061 | \x17\xba\x63\xa7\x08\x9c\xf3\xcf\x00\xc0\xa7\x0d\x8b\xf8\xa9\x34\ 1062 | \x4d\xaf\x37\x8c\x69\xdb\xbc\x79\xf4\x2d\xec\x8d\xa5\xac\xcf\x71\ 1063 | \x6d\x27\x56\x50\x83\xae\x12\x24\x14\x49\x38\xe7\x9b\x00\xe0\x01\ 1064 | \x93\x1a\x2a\xa5\xde\x21\xa5\x7c\xcc\x24\xa6\x5d\xdb\xd0\x4e\x4d\ 1065 | \xdb\xcd\xa7\x13\xff\xef\x3a\x41\x02\x91\x24\xe2\x9c\xef\x02\x80\ 1066 | \x93\xb2\x14\x15\x11\xff\x55\x08\xb1\x56\x5f\x73\xcb\xd2\x3e\x4b\ 1067 | \x1b\x92\x23\x0b\x25\xc6\xba\x52\x90\x4e\x48\x22\x84\x78\x0f\x63\ 1068 | \xec\x60\x36\xac\xed\x5b\xc5\x71\xfc\x2e\x00\xd0\x5f\xa7\x46\x8b\ 1069 | \xb5\x46\x44\xa5\x94\xda\x34\x32\x32\xf2\x50\xfb\x5e\xb3\xb5\x20\ 1070 | \x39\xb2\x71\xd2\xad\xba\x56\x90\x16\x49\x0a\xb9\xe0\x85\x88\xdb\ 1071 | \x84\x10\x7f\x58\xa4\x24\x9c\xf3\xf7\x03\xc0\xdd\x8c\xb1\xe5\x0b\ 1072 | \x95\xac\x79\x77\xde\xc5\x42\x88\xef\x66\x2f\x69\xdb\x96\x4b\x38\ 1073 | \xe7\x3f\x28\xe8\x6b\xf1\x52\x2f\xb0\xb6\x9d\x59\x07\x1a\x74\xb5\ 1074 | \x20\x9a\x57\x51\x3f\x99\xd0\x7d\x75\x42\x12\x7d\x47\x64\xbd\x5e\ 1075 | \xbf\x1c\x11\x3f\x0a\x00\xc7\x35\x6b\x3c\x85\x88\x0f\x37\x1a\x8d\ 1076 | \x2b\x76\xed\xda\xb5\xb7\xc0\xba\x6b\x39\xb6\x02\xc0\x66\xdb\x3e\ 1077 | \x5d\xfc\x44\xc7\x76\xcc\x79\xe2\xbb\x5e\x90\x0e\x48\x72\x9f\x10\ 1078 | \xe2\x7d\x45\x7e\x1e\xc8\x53\xb8\x1c\x31\x90\x24\x89\x7e\xec\xdb\ 1079 | \x7b\x73\xc4\xfe\x4a\x48\x55\xe4\xe8\xfa\x53\xac\xd6\xaa\x16\x7c\ 1080 | \x24\xf9\x9c\x10\xc2\xf4\x6b\x5a\xdb\x75\x69\x15\x9f\x24\xc9\x75\ 1081 | \x8c\xb1\x6b\xad\x3a\x39\x74\x14\x75\x7a\x2f\x8d\xed\xf8\x4d\xe3\ 1082 | \x2b\x71\x04\x99\x87\x52\xa0\x24\xd3\xb3\xb3\xb3\x6f\x1a\x1b\x1b\ 1083 | \xfb\x6f\x53\xe0\x2e\xda\x0f\x0d\x0d\xf5\xf7\xf4\xf4\xe8\x53\xb5\ 1084 | \x1e\x9b\xfc\x55\x93\xa3\x52\x47\x90\xc3\x24\xc9\x73\xeb\xe8\xe1\ 1085 | \x6b\xeb\xca\x34\x4d\xbf\x6a\xb3\xe0\xca\x8a\xe5\x9c\x5f\x0c\x00\ 1086 | \x5f\xb7\xc9\xe7\xc3\xad\xca\x36\xe3\xcf\x1b\x5b\xa9\x23\xc8\x3c\ 1087 | \xa4\x3c\x9b\x0f\x1c\x0e\x18\x11\xef\x12\x42\x5c\x92\x17\x7c\x99\ 1088 | \x71\x49\x92\xdc\xc0\x18\xbb\x3a\x6f\x4e\x5f\x36\xbb\xc8\x3b\x7e\ 1089 | \x9b\xb8\x4a\x0a\xa2\x81\xd9\x4a\xa2\x94\xba\x5b\x4a\xf9\x11\x1b\ 1090 | \xf8\x65\xc5\x72\xce\x6f\x02\x80\x2b\xf3\xe4\xab\xb2\x1c\x95\x3c\ 1091 | \xc5\x6a\x5d\x24\x96\x92\x7c\x22\x4d\xd3\x2f\xe5\x59\x74\x65\xc7\ 1092 | \x24\x49\x72\x0d\x63\xcc\x78\xac\x55\x97\xa3\xf2\x82\xb4\x1c\x49\ 1093 | \x1e\x05\x80\xb7\x98\x2c\xdc\x46\xa3\xb1\x76\x64\x64\xe4\x17\x26\ 1094 | \x31\xae\xda\x72\xce\xdf\x0c\x00\x3f\x37\xc9\x8f\x88\xcf\x20\xe2\ 1095 | \x46\x1f\x36\xda\x33\x19\x77\xd1\x6d\x2b\x7b\x8a\xd5\x0a\x72\xcd\ 1096 | \x9a\x35\xab\x7a\x7b\x7b\x1f\x36\x90\xe4\x1f\xd2\x34\x3d\xb7\xe8\ 1097 | \x62\x74\xb2\xbf\x24\x49\xee\xcb\x7a\x0d\x44\xcb\x31\x3d\x3d\x7d\ 1098 | \xfa\x9e\x3d\x7b\xf6\x77\x72\x4c\x21\xf4\x4d\x82\x34\xab\xd4\x94\ 1099 | \xe4\x47\x00\x70\xea\x62\x85\x43\xc4\x5f\x44\x51\x74\xda\xce\x9d\ 1100 | \x3b\x27\x43\x28\xf0\xfc\x18\x07\x07\x07\x8f\xae\xd7\xeb\x8f\x33\ 1101 | \xc6\xd6\xb5\x99\xdf\x93\xd3\xd3\xd3\x67\x91\x1c\x87\x28\x91\x20\ 1102 | \x2d\xab\xe5\xe4\x93\x4f\xee\x99\x9e\x9e\xbe\x16\x00\x3e\x06\x00\ 1103 | \x47\x1d\xbe\x90\x10\xf1\x9b\x88\xb8\x25\xd4\xd3\x0e\xbd\xe9\x74\ 1104 | \xad\x56\xfb\x22\x00\x7c\x18\x00\x96\xb5\xce\x0f\x0f\xbd\x6e\xee\ 1105 | \xed\xed\xfd\xf8\xd3\x4f\x3f\x3d\x17\x92\xfc\x9d\x1c\x2b\x09\xb2\ 1106 | \x00\x5d\x7d\x41\x71\xf5\xea\xd5\x1f\x8c\xa2\xe8\x78\xfd\x6f\x44\ 1107 | \xd4\x3b\x38\xfe\x38\x4d\xd3\x9f\x76\xb2\x18\x65\xf5\x3d\x30\x30\ 1108 | \xb0\x7a\xf9\xf2\xe5\x7a\x7e\xc7\x34\x73\xbe\xd2\x68\x34\x76\x8c\ 1109 | \x8c\x8c\xfc\x4b\x59\x63\x08\x25\x0f\x09\x12\x4a\xa5\x68\x9c\x4e\ 1110 | \x08\x90\x20\x4e\xb0\x53\xd2\x50\x08\x90\x20\xa1\x54\x8a\xc6\xe9\ 1111 | \x84\x00\x09\xe2\x04\x3b\x25\x0d\x85\x00\x09\x12\x4a\xa5\x68\x9c\ 1112 | \x4e\x08\x90\x20\x4e\xb0\x53\xd2\x50\x08\x90\x20\xa1\x54\x8a\xc6\ 1113 | \xe9\x84\x00\x09\xe2\x04\x3b\x25\x0d\x85\x00\x09\x12\x4a\xa5\x68\ 1114 | \x9c\x4e\x08\x90\x20\x4e\xb0\x53\xd2\x50\x08\x90\x20\xa1\x54\x8a\ 1115 | \xc6\xe9\x84\x00\x09\xe2\x04\x3b\x25\x0d\x85\x00\x09\x12\x4a\xa5\ 1116 | \x68\x9c\x4e\x08\x90\x20\x4e\xb0\x53\xd2\x50\x08\x38\x15\x64\x78\ 1117 | \x78\xf8\xa4\x5a\xad\x76\x36\x63\xec\x0d\x65\x02\xd3\xbb\x41\x33\ 1118 | \xc6\x1e\x90\x52\x3e\x51\x66\xde\x10\x73\x35\xef\x21\xd9\x1c\x45\ 1119 | \xd1\x60\xd9\xf7\x0f\x29\xa5\xc6\x18\x63\xdf\xeb\xd4\x83\x8c\xb2\ 1120 | \xd4\xc3\x95\x20\x7a\x1b\xcc\x4f\x36\x77\xfa\xb3\xda\xcc\x2c\xcb\ 1121 | \x24\x17\x69\xf3\x54\xa3\xd1\xb8\x7a\x64\x64\xe4\x51\xcb\x7e\xba\ 1122 | \x32\x7c\x78\x78\x78\x63\xad\x56\xd3\x4f\x11\x7e\xa3\xc3\x09\xfe\ 1123 | \x52\x29\xf5\x05\x29\xe5\x4d\xfa\xd6\x9c\xb2\xc7\xe1\x42\x90\xc2\ 1124 | \xf6\x88\x2d\x02\x96\x7e\xbc\x00\x22\x5e\x28\xa5\xbc\xb7\x88\xfe\ 1125 | \xba\xa5\x8f\x38\x8e\x2f\x00\x80\x6f\xb6\x7b\x3c\x43\x89\xf3\xd5\ 1126 | \xfb\x00\xe8\xdd\xf5\x4b\x95\xa4\x74\x41\x38\xe7\x57\x02\x80\x7e\ 1127 | \x37\xf0\xe6\x85\x88\xaf\x36\x1a\x8d\x75\x05\xef\xa4\xee\xcd\xfc\ 1128 | \x4c\x07\x32\x34\x34\xf4\x1b\x4b\x96\x2c\x19\x39\xfc\xb6\x5c\xd3\ 1129 | \x7e\x8a\x6e\x8f\x88\x7f\x26\x84\xf8\x4a\xd1\xfd\x2e\xd6\x5f\xd9\ 1130 | \x82\x00\xe7\x7c\x5f\xcb\x36\xff\x65\xce\x75\xd1\x5c\x88\x78\xbb\ 1131 | \x10\xc2\xf4\xc1\x9a\xde\x8c\xbf\xc8\x81\x70\xce\x6f\x01\x80\x2d\ 1132 | \x45\xf6\x59\x44\x5f\x88\xf8\x82\x10\x42\x9f\xee\x35\x8a\xe8\x2f\ 1133 | \x4b\x1f\xa5\x0a\x32\x3c\x3c\xfc\xb6\x5a\xad\xf6\xcf\x59\x06\x56\ 1134 | \x76\x1b\x44\x9c\x10\x42\xcc\xdf\xa3\x5d\x76\x7a\xaf\xf2\x25\x49\ 1135 | \xf2\x1f\x8e\x3f\x77\x1c\x91\x87\x52\xea\x9d\x52\xca\x7f\x2a\x0b\ 1136 | \x58\xa9\x82\x70\xce\x2f\xd4\xe7\xb5\x65\x4d\xce\x34\xcf\x4b\x2f\ 1137 | \xbd\xb4\x7c\x7c\x7c\x7c\xda\x34\xae\x9b\xda\xeb\x9d\x5d\x5e\x7d\ 1138 | \xf5\xd5\x59\x5f\xe7\x84\x88\x17\x09\x21\xee\x29\x6b\x7c\xa5\x0a\ 1139 | \x12\xc7\xf1\x87\xa2\x28\xfa\xfb\xb2\x26\x67\x9a\x27\x4d\x53\xfd\ 1140 | \x8d\x5a\x61\xcf\x21\x34\xcd\xef\x43\x7b\xbd\x1d\x6b\x14\x45\x2f\ 1141 | \xfb\x30\x96\x85\xc6\xd0\xed\x82\x9c\x19\x45\x51\x61\x0f\xa3\x2c\ 1142 | \xb8\x88\xcf\xa5\x69\xfa\xa6\x82\xfb\x0c\xb2\x3b\xce\xf9\xff\x00\ 1143 | \x40\xa9\xd7\xa6\xb2\x82\x52\x4a\xbd\x4d\x4a\xa9\x37\xc0\x2b\xe5\ 1144 | \x55\xea\x11\x84\x31\xa6\x1f\x7f\xfc\xbc\xa7\x1f\xd2\x6f\x15\x42\ 1145 | \x5c\x51\x0a\x75\xcf\x93\x70\xce\x6f\x03\x80\xcb\x7c\x1b\x66\xf3\ 1146 | \x43\xfa\x09\x65\x7e\xd5\x5b\xb6\x20\xcc\xd3\xaf\x79\x67\x11\xf1\ 1147 | \x24\x29\xa5\xfe\x70\x5a\xf9\xd7\xf0\xf0\xf0\xaf\xd7\x6a\x35\xbd\ 1148 | \x31\xb7\xcb\x8b\xb8\xaf\xab\x43\x15\xbe\xe6\xd5\x93\xd6\x17\x0a\ 1149 | \xf5\x46\xca\xe7\x78\xb2\x12\x1b\x4a\xa9\x3f\x96\x52\xea\x2b\xc6\ 1150 | \xf4\x6a\x12\xf0\xf0\x42\xe1\xf7\x9b\x1b\x86\x77\xf7\x85\xc2\x26\ 1151 | \x7f\x2d\x89\x7e\x66\xc5\xc7\x19\x63\xc7\x3a\x5c\x95\xcf\x29\xa5\ 1152 | \x3e\x20\xa5\xfc\xb1\xc3\x31\x78\x9b\x3a\x8e\xe3\x77\x44\x51\xf4\ 1153 | \x65\xc6\xd8\x29\x0e\x07\x39\xa7\x94\xfa\xb4\x94\xf2\x8b\x65\x9e\ 1154 | \x5a\xcd\xcf\xb7\xf4\x53\xac\x56\xd0\x71\x1c\x2f\x65\x8c\x9d\x17\ 1155 | \x45\xd1\xda\x92\x0b\x80\x4a\xa9\xdd\x8d\x46\x63\xdb\xe8\xe8\xa8\ 1156 | \xb7\xdf\xd8\x94\xcc\xe4\x88\xe9\xe2\x38\x3e\x8d\x31\xb6\x29\x8a\ 1157 | \xa2\xa8\xe4\x31\x4d\x34\x1a\x8d\xfb\x5d\x3e\x87\xc5\xa9\x20\x25\ 1158 | \xc3\xa6\x74\x44\xc0\x98\x00\x09\x62\x8c\x8c\x02\xaa\x44\x80\x04\ 1159 | \xa9\x52\xb5\x69\xae\xc6\x04\x48\x10\x63\x64\x14\x50\x25\x02\x24\ 1160 | \x48\x95\xaa\x4d\x73\x35\x26\x40\x82\x18\x23\xa3\x80\x2a\x11\x20\ 1161 | \x41\xaa\x54\x6d\x9a\xab\x31\x01\x12\xc4\x18\x19\x05\x54\x89\x00\ 1162 | \x09\x52\xa5\x6a\xd3\x5c\x8d\x09\x90\x20\xc6\xc8\x28\xa0\x4a\x04\ 1163 | \x48\x90\x2a\x55\x9b\xe6\x6a\x4c\x80\x04\x31\x46\x46\x01\x55\x22\ 1164 | \x40\x82\x54\xa9\xda\x34\x57\x63\x02\x24\x88\x31\x32\x0a\xa8\x12\ 1165 | \x01\x12\x64\x81\x6a\x27\x49\xb2\x41\xff\xbc\x9b\x31\xf6\x66\xc6\ 1166 | \xd8\x09\x7a\x4b\x20\x44\xbc\x4b\x4a\xf9\x40\x37\x2c\x0e\xce\xf9\ 1167 | \x5b\x11\x51\xef\x0f\xf0\x16\xc6\xd8\xaf\x21\xe2\xf3\x88\xf8\x35\ 1168 | \xba\x2f\xe6\xf5\xd5\x25\x41\x5a\x98\x34\xb7\xbc\xb9\x1e\x11\xaf\ 1169 | \x3a\xc2\x96\x9b\xcf\xce\xce\xce\xfe\xfe\xd8\xd8\xd8\xf3\x21\x8a\ 1170 | \x32\x30\x30\x50\x5f\xb1\x62\xc5\x8d\x8b\xdc\x6f\xfe\xc8\xcc\xcc\ 1171 | \xcc\x1f\xec\xde\xbd\xfb\x7f\x43\x9c\x5f\x27\xc6\x4c\x82\x34\xa9\ 1172 | \xae\x59\xb3\x66\x55\x6f\x6f\xef\x8f\x00\xe0\xd4\x36\xa0\xf7\x00\ 1173 | \xc0\x29\x3b\x77\xee\x9c\xec\x44\x41\x3a\xd5\x67\x73\x3b\x9f\x9f\ 1174 | \x30\xc6\xf4\xd1\x71\xb1\xd7\xd3\x07\x0e\x1c\x38\x73\xcf\x9e\x3d\ 1175 | \xfb\x3b\x35\x96\x90\xfa\x25\x41\x18\x63\x4d\x39\x1e\x06\x00\x7d\ 1176 | \xca\x91\xe5\xa5\x37\x52\x3e\x37\x4b\x43\x5f\xda\x24\x49\xa2\xf7\ 1177 | \x23\xfb\x50\x96\xf1\x20\xe2\x33\xd3\xd3\xd3\xa7\x93\x24\x8c\x55\ 1178 | \x5e\x90\x1c\x72\x30\x44\x44\x00\xe0\x69\x9a\x8e\x64\x59\x70\xae\ 1179 | \xdb\x0c\x0d\x0d\xf5\xf7\xf4\xf4\xfc\x3b\x63\x6c\x49\xd6\xb1\x90\ 1180 | \x24\x87\x48\x55\x5a\x10\x7d\xda\x01\x00\x8f\x1a\x1c\x39\xfe\x7f\ 1181 | \x7d\x21\xe2\x67\x85\x10\xd7\x66\x5d\x70\x2e\xdb\x71\xce\x2f\x06\ 1182 | \x80\xaf\x9b\x8e\x41\x4b\x82\x88\x1b\xa5\x94\xaf\x98\xc6\x76\x4b\ 1183 | \xfb\xca\x0a\xd2\x94\xe3\x21\x00\xd0\x1b\x12\x18\xbf\x94\x52\x77\ 1184 | \x4b\x29\x3f\x62\x1c\xe8\x20\x20\x49\x92\x2f\x31\xc6\xf4\x2e\x32\ 1185 | \xc6\x2f\x44\x7c\x1c\x11\xf5\x86\xd1\x95\x94\xa4\x92\x82\xd8\xca\ 1186 | \xa1\x57\x59\x48\x82\x70\xce\xf5\x37\x57\x57\x19\xdb\xd1\x0c\xa8\ 1187 | \xb2\x24\x95\x13\xa4\x08\x39\x9a\xeb\xe6\x13\x69\x9a\xea\x77\x66\ 1188 | \xef\x5f\x71\x1c\x5f\x12\x45\xd1\x9d\x36\x03\xad\xaa\x24\x95\x12\ 1189 | \xa4\xbf\xbf\x7f\x79\x5f\x5f\xdf\x8e\xbc\xa7\x55\xad\x0b\x4c\x29\ 1190 | \xa5\xb7\x2a\xdd\x6d\xb3\xe8\xca\x8a\x5d\xbb\x76\xed\x09\x4b\x97\ 1191 | \x2e\xfd\x37\xdb\xad\x44\xb5\x24\x93\x93\x93\x67\xec\xdb\xb7\xef\ 1192 | \x40\x59\x63\x77\x9d\xa7\x32\x82\x34\xe5\xd8\x0e\x00\x6f\xb7\x85\ 1193 | \x8e\x88\xdf\x15\x42\xfc\x91\x6d\x3f\x65\xc6\x27\x49\x72\x5d\xf3\ 1194 | \xa1\xa9\x56\x69\x11\xf1\xb1\xc9\xc9\xc9\x4d\x55\x91\xa4\x12\x82\ 1195 | \x14\x2c\xc7\x36\x44\x7c\x9f\xcb\x47\x13\xe7\x5c\xe1\x85\x3d\x3c\ 1196 | \xb5\x4a\x92\x74\xbd\x20\x45\xcb\x21\x84\xd0\x4f\x5a\x2d\xec\x21\ 1197 | \x3b\xeb\xd6\xad\x1b\xa8\xd5\x6a\xfa\x99\x80\x67\x30\xc6\x96\xeb\ 1198 | \xc5\x8f\x88\x2f\x02\xc0\x9d\x33\x33\x33\xb7\xed\xde\xbd\xfb\x97\ 1199 | \x39\x85\x58\x28\x6c\x09\xe7\x7c\x2b\x00\x6c\xb6\xed\xb3\x2a\x92\ 1200 | \x74\xb5\x20\x05\xcb\xb1\x5d\x08\xf1\x9e\x22\xe5\xe0\x9c\xbf\x1f\ 1201 | \x00\xee\x9e\x17\x63\x81\x45\x7b\x40\x29\x75\x91\x94\xf2\x7b\xb6\ 1202 | \x0b\xba\x25\x5e\x4b\xf2\x03\x00\xd0\x3f\xc6\xb4\x7a\x69\x49\xa6\ 1203 | \xa6\xa6\xce\xda\xbb\x77\xef\x8c\x55\x47\x1e\x07\x77\xad\x20\xcd\ 1204 | \x1f\xe6\x3d\x58\xd0\x67\x8e\xed\x88\xb8\xb9\xc8\xd3\xaa\x24\x49\ 1205 | \xce\x42\xc4\x07\xda\x3d\x87\x5c\x3f\xc7\x1d\x00\xde\x95\xa6\xe9\ 1206 | \x83\x45\xad\x23\xbd\x69\x38\x00\x6c\x2b\x48\x92\x1d\x53\x53\x53\ 1207 | \xef\xee\x56\x49\xba\x52\x90\xa6\x1c\x3f\x6c\x9e\xb6\x58\xad\x2b\ 1208 | \x44\x2c\x5c\x8e\xe6\x93\xb6\x76\x01\xc0\x49\x59\x06\x87\x88\x63\ 1209 | \x42\x88\x75\x45\x6e\xff\x4f\x92\x64\x21\xdf\x85\x3f\x35\x09\x40\ 1210 | \x0e\xb6\x7e\xfd\xfa\xdf\x45\xc4\x47\xb2\x95\xe8\x50\x2b\xa5\xd4\ 1211 | \xd9\x45\xdf\x8f\x42\x92\xb4\xaf\x40\x57\x1d\x41\x42\x90\x43\x97\ 1212 | \x24\x49\x92\x4f\x31\xc6\xfe\xa6\x7d\x79\x7e\xa5\xc5\x75\x69\x9a\ 1213 | \x7e\xc6\x30\xa6\x6d\xf3\xa6\x24\xf7\x17\x74\xb4\xdd\x81\x88\x5a\ 1214 | \x64\x6f\x1f\x23\xdd\x16\xc8\x61\x0d\xba\x46\x90\x82\xe5\xe8\x68\ 1215 | \xa1\x93\x24\xb9\x99\x31\x66\xfa\xc0\xd0\x9b\xd3\x34\xfd\x53\xd3\ 1216 | \x02\x67\x69\x5f\x30\xbb\x4e\x9c\x92\x66\x99\x46\x47\xda\x74\x85\ 1217 | \x20\x45\xbf\x0b\x76\xfa\x43\x67\x92\x24\x77\x30\xc6\x2e\x35\xa9\ 1218 | \x28\x22\xde\x2e\x84\xb8\xdc\x24\xc6\xa4\x2d\x49\xb2\x30\xad\xe0\ 1219 | \x05\x09\xf1\x3c\xda\x47\x41\xf4\xf2\x20\x49\x5e\x2f\x49\xd0\x82\ 1220 | \xe8\x82\xae\x5c\xb9\x72\x3b\x63\x6c\xa3\xc9\xbb\xe5\x42\x6d\x11\ 1221 | \xb1\xb4\xaf\x2b\x7d\x15\xa4\x45\x92\xa2\xbe\x1e\xdf\x2a\x84\x38\ 1222 | \xcf\xb6\x36\x2e\xe3\x83\x16\x24\x8e\xe3\x2d\x51\x14\xdd\x62\x0b\ 1223 | \xb0\x4c\x39\x9a\x1f\xd2\xbd\x3b\xc5\x6a\x65\x58\xf0\x05\xd6\xf3\ 1224 | \x84\x10\x5b\x6d\x6b\xe4\x2a\x3e\x68\x41\x92\x24\x79\x8a\x31\x76\ 1225 | \xb2\x0d\x3c\x17\x57\x83\x7d\x3e\x82\xcc\xb3\x2c\x50\x92\x9f\xa5\ 1226 | \x69\xfa\xdb\x36\x35\x72\x19\x1b\xac\x20\x27\x9e\x78\x62\xef\xaa\ 1227 | \x55\xab\xa6\x00\x20\xf7\x1c\x5c\xfd\x9e\x28\x04\x41\xf4\xa2\x2c\ 1228 | \x4a\x12\xa5\xd4\x31\x52\xca\x09\x97\x0b\x3d\x6f\xee\xdc\x8b\x2b\ 1229 | \x6f\xc2\xa2\xe2\x06\x07\x07\x4f\xac\xd7\xeb\xcf\xe5\xed\xcf\x95\ 1230 | \x1c\x21\x9c\x62\x15\x7d\xba\x35\x37\x37\xb7\x6e\x74\x74\x74\x34\ 1231 | \x6f\xad\x5c\xc6\x05\x2b\xc8\xd0\xd0\xd0\x51\x3d\x3d\x3d\xb9\x36\ 1232 | \x38\x73\x29\x47\x68\x82\xb4\x1c\x49\x72\xdf\x68\x46\x47\x10\x47\ 1233 | \x8a\x27\x49\xa2\xb7\xdd\xd1\xbf\x51\xca\xfc\xf2\xe1\xae\xb8\x50\ 1234 | \x4e\xb1\x5a\xa1\xe6\xbd\x55\x19\x11\xa5\x10\x82\x67\x2e\x90\x67\ 1235 | \x0d\x83\x3d\x82\x34\xdf\x89\xf5\xc5\x36\xfd\x8d\x50\xa6\x97\x2f\ 1236 | \xf7\x55\x87\x28\x88\x06\x9c\x47\x12\x44\xbc\x44\x08\x71\x57\xa6\ 1237 | \x02\x79\xd8\x28\x68\x41\xf4\x45\xc2\x28\x8a\x9e\xcc\xb0\x9d\xa6\ 1238 | \xbe\x09\xc9\x9b\xed\x6b\x42\x15\x24\x87\x24\x8f\xa4\x69\x7a\xba\ 1239 | \x87\xeb\x3e\xf3\x90\x82\x16\xa4\x59\xb0\xe3\xa2\x28\xd2\xbf\x8c\ 1240 | \x1d\x5a\x64\xd6\xdf\x9f\x9b\x9b\xbb\x70\x74\x74\xf4\xe5\xcc\x64\ 1241 | \x3a\xd8\x30\x64\x41\x34\x96\xc1\xc1\xc1\xa3\xeb\xf5\xfa\xfd\x8c\ 1242 | \xb1\xdf\x59\x04\xd3\xcf\x94\x52\xef\x95\x52\xbe\xd8\x41\x94\x1d\ 1243 | \xef\x3a\x78\x41\x9a\x05\x3b\xb6\x5e\xaf\xff\x35\x22\x5e\x04\x00\ 1244 | \x47\xeb\xbf\xe9\xed\x41\x19\x63\x12\x11\x6f\x90\x52\x7e\xa3\xe3\ 1245 | \x24\x0d\x12\x84\x2e\x88\x9e\xea\x86\x0d\x1b\x56\x28\xa5\xae\x41\ 1246 | \xc4\x4b\x01\xe0\xb8\xf9\xe9\x23\xe2\x5e\x00\xf8\xbb\x34\x4d\x3f\ 1247 | \xaf\x7f\xa5\x6f\x80\xc5\xcb\xa6\x5d\x21\xc8\x3c\x59\x7d\x6d\xa4\ 1248 | \xaf\xaf\xef\xd4\xb9\xb9\xb9\xd9\x28\x8a\x76\xfa\xba\x1b\x60\x37\ 1249 | \x08\x32\xcf\x5c\x3f\x32\x62\x66\x66\xe6\x54\xbd\x5d\xb1\x7e\x43\ 1250 | \x0a\xf5\x7a\xc7\x91\xec\xec\x2a\x41\xbc\x7c\x0b\x5a\x60\x50\xdd\ 1251 | \x24\x48\x28\xcc\xf3\x8e\x93\x04\xc9\x4b\xce\x22\x8e\x04\xb1\x80\ 1252 | \x57\x72\x28\x09\x52\x32\x70\x9d\x8e\x04\x71\x00\x3d\x67\x4a\x12\ 1253 | \x24\x27\x38\x9b\x30\x12\xc4\x86\x5e\xb9\xb1\x24\x48\xb9\xbc\x5f\ 1254 | \xcb\x46\x82\x38\x80\x9e\x33\x25\x09\x92\x13\x9c\x4d\x18\x09\x62\ 1255 | \x43\xaf\xdc\x58\x12\xa4\x5c\xde\x74\x04\x71\xc0\xdb\x26\x25\x09\ 1256 | \x62\x43\x2f\x67\x2c\x1d\x41\x72\x82\x73\x10\x46\x82\x38\x80\x4e\ 1257 | \x82\x38\x80\x9e\x33\x25\x09\x92\x13\x9c\x4d\x18\x09\x62\x43\xaf\ 1258 | \xdc\x58\x12\xa4\x5c\xde\xf4\x19\xc4\x01\x6f\x9b\x94\x24\x88\x0d\ 1259 | \xbd\x9c\xb1\x71\x1c\xdf\x1e\x45\xd1\x9f\x98\x84\x23\xe2\x6d\x42\ 1260 | \x88\x2d\x26\x31\xd4\xd6\x9e\x00\x09\x62\xcf\xd0\xb8\x07\xce\xf9\ 1261 | \xe7\x01\xe0\x2f\x4c\x02\x43\x7a\x2e\xbb\xc9\xbc\x7c\x6f\x4b\x82\ 1262 | \x38\xa8\x50\x1c\xc7\x17\x44\x51\xf4\x2d\x93\xd4\x4a\xa9\x73\xa4\ 1263 | \x94\xff\x68\x12\x43\x6d\xed\x09\x90\x20\xf6\x0c\x8d\x7b\x68\xde\ 1264 | \x4b\x31\xce\x18\x5b\x9d\x31\x78\xff\xc4\xc4\x44\x7f\x55\x1e\x9c\ 1265 | \x99\x91\x49\x29\xcd\x48\x90\x52\x30\xbf\x3e\x49\x92\x24\xd7\x30\ 1266 | \xc6\x32\x3d\x67\x5d\xdf\x98\x24\xa5\xbc\xd1\xd1\x50\x2b\x9d\x96\ 1267 | \x04\x71\x58\x7e\xce\xf9\xbd\x00\x70\xfe\x62\x43\x50\x4a\xdd\x21\ 1268 | \xa5\xbc\xcc\xe1\x30\x2b\x9d\x9a\x04\x71\x5b\x7e\xe0\x9c\x5f\xcf\ 1269 | \x18\xdb\x02\x00\x2b\x5b\x87\x82\x88\x7a\x27\x42\xbd\x23\x48\xb0\ 1270 | \xfb\xda\xba\x45\x5b\x4c\x76\x12\xa4\x18\x8e\x56\xbd\xe8\x4d\xf0\ 1271 | \x6a\xb5\xda\xf9\x51\x14\x1d\xaf\x94\x7a\x81\x31\xf6\x0c\x63\xec\ 1272 | \xe7\xdd\xf4\xa4\x26\x2b\x40\x0e\x83\x49\x10\x87\xf0\x29\xb5\xff\ 1273 | \x04\x48\x10\xff\x6b\x44\x23\x74\x48\x80\x04\x71\x08\x9f\x52\xfb\ 1274 | \x4f\x80\x04\xf1\xbf\x46\x34\x42\x87\x04\x48\x10\x87\xf0\x29\xb5\ 1275 | \xff\x04\x48\x10\xff\x6b\x44\x23\x74\x48\x80\x04\x71\x08\x9f\x52\ 1276 | \xfb\x4f\x80\x04\xf1\xbf\x46\x34\x42\x87\x04\x48\x10\x87\xf0\x29\ 1277 | \xb5\xff\x04\x48\x10\xff\x6b\x44\x23\x74\x48\x80\x04\x71\x08\x9f\ 1278 | \x52\xfb\x4f\x80\x04\xf1\xbf\x46\x34\x42\x87\x04\x48\x10\x87\xf0\ 1279 | \x29\xb5\xff\x04\x48\x10\xff\x6b\x44\x23\x74\x48\x80\x04\x71\x08\ 1280 | \x9f\x52\xfb\x4f\x80\x04\xf1\xbf\x46\x34\x42\x87\x04\x48\x10\x87\ 1281 | \xf0\x29\xb5\xff\x04\x48\x10\xff\x6b\x44\x23\x74\x48\x80\x04\x71\ 1282 | \x08\x9f\x52\xfb\x4f\x80\x04\xf1\xbf\x46\x34\x42\x87\x04\x48\x10\ 1283 | \x87\xf0\x29\xb5\xff\x04\x48\x10\xff\x6b\x44\x23\x74\x48\x80\x04\ 1284 | \x71\x08\x9f\x52\xfb\x4f\x80\x04\xf1\xbf\x46\x34\x42\x87\x04\x48\ 1285 | \x10\x87\xf0\x29\xb5\xff\x04\x48\x10\xff\x6b\x44\x23\x74\x48\x80\ 1286 | \x04\x71\x08\x9f\x52\xfb\x4f\xe0\xff\x00\x30\x8a\x0d\x50\x4f\x8c\ 1287 | \x4b\x65\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ 1288 | " 1289 | 1290 | qt_resource_name = b"\ 1291 | \x00\x05\ 1292 | \x00\x6f\xa6\x53\ 1293 | \x00\x69\ 1294 | \x00\x63\x00\x6f\x00\x6e\x00\x73\ 1295 | \x00\x0a\ 1296 | \x0c\xad\x0f\x07\ 1297 | \x00\x64\ 1298 | \x00\x65\x00\x6c\x00\x65\x00\x74\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\ 1299 | \x00\x08\ 1300 | \x06\x48\x5a\x27\ 1301 | \x00\x64\ 1302 | \x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\ 1303 | \x00\x0a\ 1304 | \x02\xba\xc7\x47\ 1305 | \x00\x66\ 1306 | \x00\x61\x00\x69\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\ 1307 | \x00\x08\ 1308 | \x08\x07\x58\xe7\ 1309 | \x00\x77\ 1310 | \x00\x61\x00\x69\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\ 1311 | " 1312 | 1313 | qt_resource_struct_v1 = b"\ 1314 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ 1315 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x02\ 1316 | \x00\x00\x00\x40\x00\x00\x00\x00\x00\x01\x00\x00\x2c\x6c\ 1317 | \x00\x00\x00\x2a\x00\x00\x00\x00\x00\x01\x00\x00\x22\x2e\ 1318 | \x00\x00\x00\x5a\x00\x00\x00\x00\x00\x01\x00\x00\x3b\x81\ 1319 | \x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ 1320 | " 1321 | 1322 | qt_resource_struct_v2 = b"\ 1323 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ 1324 | \x00\x00\x00\x00\x00\x00\x00\x00\ 1325 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x02\ 1326 | \x00\x00\x00\x00\x00\x00\x00\x00\ 1327 | \x00\x00\x00\x40\x00\x00\x00\x00\x00\x01\x00\x00\x2c\x6c\ 1328 | \x00\x00\x01\x69\x6c\x05\x9c\xc8\ 1329 | \x00\x00\x00\x2a\x00\x00\x00\x00\x00\x01\x00\x00\x22\x2e\ 1330 | \x00\x00\x01\x69\x6c\x05\xdf\x30\ 1331 | \x00\x00\x00\x5a\x00\x00\x00\x00\x00\x01\x00\x00\x3b\x81\ 1332 | \x00\x00\x01\x69\x6b\xfc\xd6\xb0\ 1333 | \x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ 1334 | \x00\x00\x01\x69\x7a\xde\x2e\x18\ 1335 | " 1336 | 1337 | qt_version = QtCore.qVersion().split('.') 1338 | if qt_version < ['5', '8', '0']: 1339 | rcc_version = 1 1340 | qt_resource_struct = qt_resource_struct_v1 1341 | else: 1342 | rcc_version = 2 1343 | qt_resource_struct = qt_resource_struct_v2 1344 | 1345 | def qInitResources(): 1346 | QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) 1347 | 1348 | def qCleanupResources(): 1349 | QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) 1350 | 1351 | qInitResources() 1352 | -------------------------------------------------------------------------------- /addon/UIForm/icons_rc.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | delete.png 4 | done.png 5 | failed.png 6 | wait.png 7 | 8 | 9 | -------------------------------------------------------------------------------- /addon/UIForm/loginDialog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'designer/loginDialog.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.12.1 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | 12 | class Ui_LoginDialog(object): 13 | def setupUi(self, LoginDialog): 14 | LoginDialog.setObjectName("LoginDialog") 15 | LoginDialog.resize(505, 480) 16 | self.gridLayout = QtWidgets.QGridLayout(LoginDialog) 17 | self.gridLayout.setObjectName("gridLayout") 18 | self.reloadBtn = QtWidgets.QPushButton(LoginDialog) 19 | self.reloadBtn.setObjectName("reloadBtn") 20 | self.gridLayout.addWidget(self.reloadBtn, 0, 1, 1, 1) 21 | self.pageContainer = QtWidgets.QVBoxLayout() 22 | self.pageContainer.setObjectName("pageContainer") 23 | self.gridLayout.addLayout(self.pageContainer, 1, 0, 1, 2) 24 | self.address = QtWidgets.QLineEdit(LoginDialog) 25 | self.address.setClearButtonEnabled(True) 26 | self.address.setObjectName("address") 27 | self.gridLayout.addWidget(self.address, 0, 0, 1, 1) 28 | 29 | self.retranslateUi(LoginDialog) 30 | QtCore.QMetaObject.connectSlotsByName(LoginDialog) 31 | 32 | def retranslateUi(self, LoginDialog): 33 | _translate = QtCore.QCoreApplication.translate 34 | LoginDialog.setWindowTitle(_translate("LoginDialog", "Login")) 35 | self.reloadBtn.setText(_translate("LoginDialog", "reload")) 36 | 37 | 38 | -------------------------------------------------------------------------------- /addon/UIForm/loginDialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | LoginDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 505 10 | 480 11 | 12 | 13 | 14 | Login 15 | 16 | 17 | 18 | 19 | 20 | reload 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | true 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /addon/UIForm/mainUI.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'main_ui.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.9.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_Dialog(object): 12 | def setupUi(self, Dialog): 13 | Dialog.setObjectName("Dialog") 14 | Dialog.resize(595, 533) 15 | self.main_layout = QtWidgets.QVBoxLayout(Dialog) 16 | self.main_layout.setObjectName("main_layout") 17 | self.tabWidget = QtWidgets.QTabWidget(Dialog) 18 | self.tabWidget.setAutoFillBackground(False) 19 | self.tabWidget.setObjectName("tabWidget") 20 | self.mainTab = QtWidgets.QWidget() 21 | self.mainTab.setObjectName("mainTab") 22 | self.gridLayout_4 = QtWidgets.QGridLayout(self.mainTab) 23 | self.gridLayout_4.setObjectName("gridLayout_4") 24 | self.syncBtn = QtWidgets.QPushButton(self.mainTab) 25 | self.syncBtn.setEnabled(False) 26 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) 27 | sizePolicy.setHorizontalStretch(0) 28 | sizePolicy.setVerticalStretch(0) 29 | sizePolicy.setHeightForWidth(self.syncBtn.sizePolicy().hasHeightForWidth()) 30 | self.syncBtn.setSizePolicy(sizePolicy) 31 | self.syncBtn.setMinimumSize(QtCore.QSize(100, 0)) 32 | self.syncBtn.setObjectName("syncBtn") 33 | self.gridLayout_4.addWidget(self.syncBtn, 4, 4, 1, 1) 34 | self.deckLayout = QtWidgets.QHBoxLayout() 35 | self.deckLayout.setObjectName("deckLayout") 36 | self.deckLabel = QtWidgets.QLabel(self.mainTab) 37 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 38 | sizePolicy.setHorizontalStretch(0) 39 | sizePolicy.setVerticalStretch(0) 40 | sizePolicy.setHeightForWidth(self.deckLabel.sizePolicy().hasHeightForWidth()) 41 | self.deckLabel.setSizePolicy(sizePolicy) 42 | self.deckLabel.setObjectName("deckLabel") 43 | self.deckLayout.addWidget(self.deckLabel) 44 | self.deckComboBox = QtWidgets.QComboBox(self.mainTab) 45 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 46 | sizePolicy.setHorizontalStretch(0) 47 | sizePolicy.setVerticalStretch(0) 48 | sizePolicy.setHeightForWidth(self.deckComboBox.sizePolicy().hasHeightForWidth()) 49 | self.deckComboBox.setSizePolicy(sizePolicy) 50 | self.deckComboBox.setEditable(True) 51 | self.deckComboBox.setObjectName("deckComboBox") 52 | self.deckLayout.addWidget(self.deckComboBox) 53 | self.gridLayout_4.addLayout(self.deckLayout, 0, 0, 1, 5) 54 | self.horizontalLayout = QtWidgets.QHBoxLayout() 55 | self.horizontalLayout.setObjectName("horizontalLayout") 56 | self.verticalLayout = QtWidgets.QVBoxLayout() 57 | self.verticalLayout.setSpacing(2) 58 | self.verticalLayout.setObjectName("verticalLayout") 59 | self.label = QtWidgets.QLabel(self.mainTab) 60 | self.label.setObjectName("label") 61 | self.verticalLayout.addWidget(self.label) 62 | self.newWordListWidget = QtWidgets.QListWidget(self.mainTab) 63 | self.newWordListWidget.setAlternatingRowColors(True) 64 | self.newWordListWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) 65 | self.newWordListWidget.setObjectName("newWordListWidget") 66 | self.verticalLayout.addWidget(self.newWordListWidget) 67 | self.horizontalLayout.addLayout(self.verticalLayout) 68 | self.verticalLayout_2 = QtWidgets.QVBoxLayout() 69 | self.verticalLayout_2.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) 70 | self.verticalLayout_2.setSpacing(2) 71 | self.verticalLayout_2.setObjectName("verticalLayout_2") 72 | self.label_2 = QtWidgets.QLabel(self.mainTab) 73 | self.label_2.setObjectName("label_2") 74 | self.verticalLayout_2.addWidget(self.label_2) 75 | self.needDeleteWordListWidget = QtWidgets.QListWidget(self.mainTab) 76 | self.needDeleteWordListWidget.setAlternatingRowColors(True) 77 | self.needDeleteWordListWidget.setObjectName("needDeleteWordListWidget") 78 | self.verticalLayout_2.addWidget(self.needDeleteWordListWidget) 79 | self.horizontalLayout.addLayout(self.verticalLayout_2) 80 | self.gridLayout_4.addLayout(self.horizontalLayout, 3, 0, 1, 5) 81 | self.apiLayout = QtWidgets.QHBoxLayout() 82 | self.apiLayout.setObjectName("apiLayout") 83 | self.apiLabel = QtWidgets.QLabel(self.mainTab) 84 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 85 | sizePolicy.setHorizontalStretch(0) 86 | sizePolicy.setVerticalStretch(0) 87 | sizePolicy.setHeightForWidth(self.apiLabel.sizePolicy().hasHeightForWidth()) 88 | self.apiLabel.setSizePolicy(sizePolicy) 89 | self.apiLabel.setObjectName("apiLabel") 90 | self.apiLayout.addWidget(self.apiLabel) 91 | self.apiComboBox = QtWidgets.QComboBox(self.mainTab) 92 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 93 | sizePolicy.setHorizontalStretch(0) 94 | sizePolicy.setVerticalStretch(0) 95 | sizePolicy.setHeightForWidth(self.apiComboBox.sizePolicy().hasHeightForWidth()) 96 | self.apiComboBox.setSizePolicy(sizePolicy) 97 | self.apiComboBox.setObjectName("apiComboBox") 98 | self.apiLayout.addWidget(self.apiComboBox) 99 | self.gridLayout_4.addLayout(self.apiLayout, 2, 0, 1, 5) 100 | self.dictionaryLayout = QtWidgets.QHBoxLayout() 101 | self.dictionaryLayout.setObjectName("dictionaryLayout") 102 | self.dictionaryLabel = QtWidgets.QLabel(self.mainTab) 103 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 104 | sizePolicy.setHorizontalStretch(0) 105 | sizePolicy.setVerticalStretch(0) 106 | sizePolicy.setHeightForWidth(self.dictionaryLabel.sizePolicy().hasHeightForWidth()) 107 | self.dictionaryLabel.setSizePolicy(sizePolicy) 108 | self.dictionaryLabel.setObjectName("dictionaryLabel") 109 | self.dictionaryLayout.addWidget(self.dictionaryLabel) 110 | self.dictionaryComboBox = QtWidgets.QComboBox(self.mainTab) 111 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 112 | sizePolicy.setHorizontalStretch(0) 113 | sizePolicy.setVerticalStretch(0) 114 | sizePolicy.setHeightForWidth(self.dictionaryComboBox.sizePolicy().hasHeightForWidth()) 115 | self.dictionaryComboBox.setSizePolicy(sizePolicy) 116 | self.dictionaryComboBox.setObjectName("dictionaryComboBox") 117 | self.dictionaryLayout.addWidget(self.dictionaryComboBox) 118 | self.gridLayout_4.addLayout(self.dictionaryLayout, 1, 0, 1, 5) 119 | self.pullRemoteWordsBtn = QtWidgets.QPushButton(self.mainTab) 120 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) 121 | sizePolicy.setHorizontalStretch(0) 122 | sizePolicy.setVerticalStretch(0) 123 | sizePolicy.setHeightForWidth(self.pullRemoteWordsBtn.sizePolicy().hasHeightForWidth()) 124 | self.pullRemoteWordsBtn.setSizePolicy(sizePolicy) 125 | self.pullRemoteWordsBtn.setMinimumSize(QtCore.QSize(100, 0)) 126 | self.pullRemoteWordsBtn.setObjectName("pullRemoteWordsBtn") 127 | self.gridLayout_4.addWidget(self.pullRemoteWordsBtn, 4, 0, 1, 1) 128 | self.queryBtn = QtWidgets.QPushButton(self.mainTab) 129 | self.queryBtn.setEnabled(False) 130 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) 131 | sizePolicy.setHorizontalStretch(0) 132 | sizePolicy.setVerticalStretch(0) 133 | sizePolicy.setHeightForWidth(self.queryBtn.sizePolicy().hasHeightForWidth()) 134 | self.queryBtn.setSizePolicy(sizePolicy) 135 | self.queryBtn.setMinimumSize(QtCore.QSize(100, 0)) 136 | self.queryBtn.setObjectName("queryBtn") 137 | self.gridLayout_4.addWidget(self.queryBtn, 4, 1, 1, 1) 138 | self.tabWidget.addTab(self.mainTab, "") 139 | self.settingTab = QtWidgets.QWidget() 140 | self.settingTab.setObjectName("settingTab") 141 | self.gridLayout_2 = QtWidgets.QGridLayout(self.settingTab) 142 | self.gridLayout_2.setObjectName("gridLayout_2") 143 | self.defaultConfigGroupBox = QtWidgets.QGroupBox(self.settingTab) 144 | self.defaultConfigGroupBox.setObjectName("defaultConfigGroupBox") 145 | self.gridLayout = QtWidgets.QGridLayout(self.defaultConfigGroupBox) 146 | self.gridLayout.setObjectName("gridLayout") 147 | self.sentenceCheckBox = QtWidgets.QCheckBox(self.defaultConfigGroupBox) 148 | self.sentenceCheckBox.setChecked(True) 149 | self.sentenceCheckBox.setObjectName("sentenceCheckBox") 150 | self.gridLayout.addWidget(self.sentenceCheckBox, 0, 1, 1, 1) 151 | self.definitionCheckBox = QtWidgets.QCheckBox(self.defaultConfigGroupBox) 152 | self.definitionCheckBox.setChecked(True) 153 | self.definitionCheckBox.setObjectName("definitionCheckBox") 154 | self.gridLayout.addWidget(self.definitionCheckBox, 0, 0, 1, 1) 155 | self.noPronRadioButton = QtWidgets.QRadioButton(self.defaultConfigGroupBox) 156 | self.noPronRadioButton.setChecked(True) 157 | self.noPronRadioButton.setObjectName("noPronRadioButton") 158 | self.gridLayout.addWidget(self.noPronRadioButton, 5, 2, 1, 1) 159 | self.phraseCheckBox = QtWidgets.QCheckBox(self.defaultConfigGroupBox) 160 | self.phraseCheckBox.setChecked(True) 161 | self.phraseCheckBox.setObjectName("phraseCheckBox") 162 | self.gridLayout.addWidget(self.phraseCheckBox, 0, 2, 1, 1) 163 | self.BrEPronRadioButton = QtWidgets.QRadioButton(self.defaultConfigGroupBox) 164 | self.BrEPronRadioButton.setChecked(False) 165 | self.BrEPronRadioButton.setObjectName("BrEPronRadioButton") 166 | self.gridLayout.addWidget(self.BrEPronRadioButton, 5, 0, 1, 1) 167 | self.AmEPronRadioButton = QtWidgets.QRadioButton(self.defaultConfigGroupBox) 168 | self.AmEPronRadioButton.setObjectName("AmEPronRadioButton") 169 | self.gridLayout.addWidget(self.AmEPronRadioButton, 5, 1, 1, 1) 170 | self.BrEPhoneticCheckBox = QtWidgets.QCheckBox(self.defaultConfigGroupBox) 171 | self.BrEPhoneticCheckBox.setChecked(True) 172 | self.BrEPhoneticCheckBox.setObjectName("BrEPhoneticCheckBox") 173 | self.gridLayout.addWidget(self.BrEPhoneticCheckBox, 1, 1, 1, 1) 174 | self.AmEPhoneticCheckBox = QtWidgets.QCheckBox(self.defaultConfigGroupBox) 175 | self.AmEPhoneticCheckBox.setChecked(True) 176 | self.AmEPhoneticCheckBox.setObjectName("AmEPhoneticCheckBox") 177 | self.gridLayout.addWidget(self.AmEPhoneticCheckBox, 1, 2, 1, 1) 178 | self.imageCheckBox = QtWidgets.QCheckBox(self.defaultConfigGroupBox) 179 | self.imageCheckBox.setChecked(True) 180 | self.imageCheckBox.setObjectName("imageCheckBox") 181 | self.gridLayout.addWidget(self.imageCheckBox, 1, 0, 1, 1) 182 | self.gridLayout_2.addWidget(self.defaultConfigGroupBox, 1, 0, 1, 2) 183 | self.credentialGroupBox = QtWidgets.QGroupBox(self.settingTab) 184 | self.credentialGroupBox.setObjectName("credentialGroupBox") 185 | self.gridLayout_3 = QtWidgets.QGridLayout(self.credentialGroupBox) 186 | self.gridLayout_3.setObjectName("gridLayout_3") 187 | self.currentDictionaryLabel = QtWidgets.QLabel(self.credentialGroupBox) 188 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 189 | sizePolicy.setHorizontalStretch(0) 190 | sizePolicy.setVerticalStretch(0) 191 | sizePolicy.setHeightForWidth(self.currentDictionaryLabel.sizePolicy().hasHeightForWidth()) 192 | self.currentDictionaryLabel.setSizePolicy(sizePolicy) 193 | self.currentDictionaryLabel.setObjectName("currentDictionaryLabel") 194 | self.gridLayout_3.addWidget(self.currentDictionaryLabel, 0, 0, 1, 2) 195 | self.usernameLabel = QtWidgets.QLabel(self.credentialGroupBox) 196 | self.usernameLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) 197 | self.usernameLabel.setObjectName("usernameLabel") 198 | self.gridLayout_3.addWidget(self.usernameLabel, 1, 0, 1, 1) 199 | self.usernameLineEdit = QtWidgets.QLineEdit(self.credentialGroupBox) 200 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) 201 | sizePolicy.setHorizontalStretch(0) 202 | sizePolicy.setVerticalStretch(0) 203 | sizePolicy.setHeightForWidth(self.usernameLineEdit.sizePolicy().hasHeightForWidth()) 204 | self.usernameLineEdit.setSizePolicy(sizePolicy) 205 | self.usernameLineEdit.setObjectName("usernameLineEdit") 206 | self.gridLayout_3.addWidget(self.usernameLineEdit, 1, 1, 1, 1) 207 | self.passwordLabel = QtWidgets.QLabel(self.credentialGroupBox) 208 | self.passwordLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) 209 | self.passwordLabel.setObjectName("passwordLabel") 210 | self.gridLayout_3.addWidget(self.passwordLabel, 2, 0, 1, 1) 211 | self.passwordLineEdit = QtWidgets.QLineEdit(self.credentialGroupBox) 212 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) 213 | sizePolicy.setHorizontalStretch(0) 214 | sizePolicy.setVerticalStretch(0) 215 | sizePolicy.setHeightForWidth(self.passwordLineEdit.sizePolicy().hasHeightForWidth()) 216 | self.passwordLineEdit.setSizePolicy(sizePolicy) 217 | self.passwordLineEdit.setEchoMode(QtWidgets.QLineEdit.PasswordEchoOnEdit) 218 | self.passwordLineEdit.setObjectName("passwordLineEdit") 219 | self.gridLayout_3.addWidget(self.passwordLineEdit, 2, 1, 1, 1) 220 | self.cookieLabel = QtWidgets.QLabel(self.credentialGroupBox) 221 | self.cookieLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) 222 | self.cookieLabel.setObjectName("cookieLabel") 223 | self.gridLayout_3.addWidget(self.cookieLabel, 3, 0, 1, 1) 224 | self.cookieLineEdit = QtWidgets.QLineEdit(self.credentialGroupBox) 225 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) 226 | sizePolicy.setHorizontalStretch(0) 227 | sizePolicy.setVerticalStretch(0) 228 | sizePolicy.setHeightForWidth(self.cookieLineEdit.sizePolicy().hasHeightForWidth()) 229 | self.cookieLineEdit.setSizePolicy(sizePolicy) 230 | self.cookieLineEdit.setClearButtonEnabled(True) 231 | self.cookieLineEdit.setObjectName("cookieLineEdit") 232 | self.gridLayout_3.addWidget(self.cookieLineEdit, 3, 1, 1, 1) 233 | self.gridLayout_2.addWidget(self.credentialGroupBox, 0, 0, 1, 2) 234 | self.tabWidget.addTab(self.settingTab, "") 235 | self.logTab = QtWidgets.QWidget() 236 | self.logTab.setObjectName("logTab") 237 | self.tabWidget.addTab(self.logTab, "") 238 | self.main_layout.addWidget(self.tabWidget) 239 | self.progressBar = QtWidgets.QProgressBar(Dialog) 240 | self.progressBar.setProperty("value", 0) 241 | self.progressBar.setTextVisible(False) 242 | self.progressBar.setObjectName("progressBar") 243 | self.main_layout.addWidget(self.progressBar) 244 | 245 | self.retranslateUi(Dialog) 246 | self.tabWidget.setCurrentIndex(0) 247 | QtCore.QMetaObject.connectSlotsByName(Dialog) 248 | 249 | def retranslateUi(self, Dialog): 250 | _translate = QtCore.QCoreApplication.translate 251 | Dialog.setWindowTitle(_translate("Dialog", "Dialog")) 252 | self.syncBtn.setText(_translate("Dialog", "开始同步")) 253 | self.deckLabel.setText(_translate("Dialog", "牌组")) 254 | self.label.setText(_translate("Dialog", "新单词")) 255 | self.label_2.setText(_translate("Dialog", "待删除")) 256 | self.apiLabel.setText(_translate("Dialog", "查询")) 257 | self.dictionaryLabel.setText(_translate("Dialog", "词典")) 258 | self.pullRemoteWordsBtn.setText(_translate("Dialog", "获取单词")) 259 | self.queryBtn.setText(_translate("Dialog", "查询")) 260 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.mainTab), _translate("Dialog", "同步")) 261 | self.defaultConfigGroupBox.setTitle(_translate("Dialog", "默认设置")) 262 | self.sentenceCheckBox.setText(_translate("Dialog", "例句")) 263 | self.definitionCheckBox.setText(_translate("Dialog", "释义")) 264 | self.noPronRadioButton.setText(_translate("Dialog", "无发音")) 265 | self.phraseCheckBox.setText(_translate("Dialog", "短语")) 266 | self.BrEPronRadioButton.setText(_translate("Dialog", "英式发音")) 267 | self.AmEPronRadioButton.setText(_translate("Dialog", "美式发音")) 268 | self.BrEPhoneticCheckBox.setText(_translate("Dialog", "英式英标")) 269 | self.AmEPhoneticCheckBox.setText(_translate("Dialog", "美式英标")) 270 | self.imageCheckBox.setText(_translate("Dialog", "图片")) 271 | self.credentialGroupBox.setTitle(_translate("Dialog", "账号设置")) 272 | self.currentDictionaryLabel.setText(_translate("Dialog", "当前选择词典: ")) 273 | self.usernameLabel.setText(_translate("Dialog", "账号")) 274 | self.passwordLabel.setText(_translate("Dialog", "密码")) 275 | self.cookieLabel.setText(_translate("Dialog", "Cookie")) 276 | self.cookieLineEdit.setPlaceholderText(_translate("Dialog", "选填")) 277 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.settingTab), _translate("Dialog", "设置")) 278 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.logTab), _translate("Dialog", "日志")) 279 | 280 | -------------------------------------------------------------------------------- /addon/UIForm/main_ui.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 595 10 | 533 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | false 21 | 22 | 23 | 0 24 | 25 | 26 | 27 | 同步 28 | 29 | 30 | 31 | 32 | 33 | false 34 | 35 | 36 | 37 | 0 38 | 0 39 | 40 | 41 | 42 | 43 | 100 44 | 0 45 | 46 | 47 | 48 | 开始同步 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 0 59 | 0 60 | 61 | 62 | 63 | 牌组 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 0 72 | 0 73 | 74 | 75 | 76 | true 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 2 88 | 89 | 90 | 91 | 92 | 新单词 93 | 94 | 95 | 96 | 97 | 98 | 99 | true 100 | 101 | 102 | QAbstractItemView::MultiSelection 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 2 112 | 113 | 114 | QLayout::SetDefaultConstraint 115 | 116 | 117 | 118 | 119 | 待删除 120 | 121 | 122 | 123 | 124 | 125 | 126 | true 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 0 141 | 0 142 | 143 | 144 | 145 | 查询 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 0 154 | 0 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 0 168 | 0 169 | 170 | 171 | 172 | 词典 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 0 181 | 0 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 0 193 | 0 194 | 195 | 196 | 197 | 198 | 100 199 | 0 200 | 201 | 202 | 203 | 获取单词 204 | 205 | 206 | 207 | 208 | 209 | 210 | false 211 | 212 | 213 | 214 | 0 215 | 0 216 | 217 | 218 | 219 | 220 | 100 221 | 0 222 | 223 | 224 | 225 | 查询 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 设置 234 | 235 | 236 | 237 | 238 | 239 | 默认设置 240 | 241 | 242 | 243 | 244 | 245 | 例句 246 | 247 | 248 | true 249 | 250 | 251 | 252 | 253 | 254 | 255 | 释义 256 | 257 | 258 | true 259 | 260 | 261 | 262 | 263 | 264 | 265 | 无发音 266 | 267 | 268 | true 269 | 270 | 271 | 272 | 273 | 274 | 275 | 短语 276 | 277 | 278 | true 279 | 280 | 281 | 282 | 283 | 284 | 285 | 英式发音 286 | 287 | 288 | false 289 | 290 | 291 | 292 | 293 | 294 | 295 | 美式发音 296 | 297 | 298 | 299 | 300 | 301 | 302 | 英式英标 303 | 304 | 305 | true 306 | 307 | 308 | 309 | 310 | 311 | 312 | 美式英标 313 | 314 | 315 | true 316 | 317 | 318 | 319 | 320 | 321 | 322 | 图片 323 | 324 | 325 | true 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 账号设置 336 | 337 | 338 | 339 | 340 | 341 | 342 | 0 343 | 0 344 | 345 | 346 | 347 | 当前选择词典: 348 | 349 | 350 | 351 | 352 | 353 | 354 | 账号 355 | 356 | 357 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 0 366 | 0 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 密码 375 | 376 | 377 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 0 386 | 0 387 | 388 | 389 | 390 | QLineEdit::PasswordEchoOnEdit 391 | 392 | 393 | 394 | 395 | 396 | 397 | Cookie 398 | 399 | 400 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 0 409 | 0 410 | 411 | 412 | 413 | 选填 414 | 415 | 416 | true 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 日志 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 0 436 | 437 | 438 | false 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | -------------------------------------------------------------------------------- /addon/UIForm/wait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megachweng/Dict2Anki/4fe993d83d73e0a4ed3090330241d0a9de22b009/addon/UIForm/wait.png -------------------------------------------------------------------------------- /addon/UIForm/wordGroup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'word_group.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.9.2 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_Dialog(object): 12 | def setupUi(self, Dialog): 13 | Dialog.setObjectName("Dialog") 14 | Dialog.resize(395, 261) 15 | self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) 16 | self.verticalLayout.setObjectName("verticalLayout") 17 | self.wordGroupListWidget = QtWidgets.QListWidget(Dialog) 18 | self.wordGroupListWidget.setAlternatingRowColors(True) 19 | self.wordGroupListWidget.setObjectName("wordGroupListWidget") 20 | self.verticalLayout.addWidget(self.wordGroupListWidget) 21 | self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) 22 | self.buttonBox.setOrientation(QtCore.Qt.Horizontal) 23 | self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) 24 | self.buttonBox.setObjectName("buttonBox") 25 | self.verticalLayout.addWidget(self.buttonBox) 26 | 27 | self.retranslateUi(Dialog) 28 | self.buttonBox.accepted.connect(Dialog.accept) 29 | self.buttonBox.rejected.connect(Dialog.reject) 30 | QtCore.QMetaObject.connectSlotsByName(Dialog) 31 | 32 | def retranslateUi(self, Dialog): 33 | _translate = QtCore.QCoreApplication.translate 34 | Dialog.setWindowTitle(_translate("Dialog", "单词本分组")) 35 | 36 | -------------------------------------------------------------------------------- /addon/UIForm/word_group.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 395 10 | 261 11 | 12 | 13 | 14 | 单词本分组 15 | 16 | 17 | 18 | 19 | 20 | true 21 | 22 | 23 | 24 | 25 | 26 | 27 | Qt::Horizontal 28 | 29 | 30 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | buttonBox 40 | accepted() 41 | Dialog 42 | accept() 43 | 44 | 45 | 248 46 | 254 47 | 48 | 49 | 157 50 | 274 51 | 52 | 53 | 54 | 55 | buttonBox 56 | rejected() 57 | Dialog 58 | reject() 59 | 60 | 61 | 316 62 | 260 63 | 64 | 65 | 286 66 | 274 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /addon/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megachweng/Dict2Anki/4fe993d83d73e0a4ed3090330241d0a9de22b009/addon/__init__.py -------------------------------------------------------------------------------- /addon/addonWindow.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import logging 4 | import json 5 | from copy import deepcopy 6 | from tempfile import gettempdir 7 | 8 | from PyQt5.QtGui import QIcon 9 | from PyQt5.QtWidgets import QPlainTextEdit, QDialog, QListWidgetItem, QVBoxLayout, QPushButton 10 | from PyQt5.QtCore import pyqtSlot, QThread, Qt 11 | 12 | from .queryApi import apis 13 | from .UIForm import wordGroup, mainUI, icons_rc 14 | from .workers import LoginStateCheckWorker, VersionCheckWorker, RemoteWordFetchingWorker, QueryWorker, AudioDownloadWorker 15 | from .dictionary import dictionaries 16 | from .logger import Handler 17 | from .loginDialog import LoginDialog 18 | from .misc import Mask 19 | from .constants import BASIC_OPTION, EXTRA_OPTION, MODEL_NAME, RELEASE_URL 20 | 21 | try: 22 | from aqt import mw 23 | from aqt.utils import askUser, showCritical, showInfo, tooltip, openLink 24 | from .noteManager import getOrCreateDeck, getDeckList, getOrCreateModel, getOrCreateModelCardTemplate, addNoteToDeck, getWordsByDeck, getNotes 25 | except ImportError: 26 | from test.dummy_aqt import mw, askUser, showCritical, showInfo, tooltip, openLink 27 | from test.dummy_noteManager import getOrCreateDeck, getDeckList, getOrCreateModel, getOrCreateModelCardTemplate, addNoteToDeck, getWordsByDeck, getNotes 28 | 29 | logger = logging.getLogger('dict2Anki') 30 | 31 | 32 | def fatal_error(exc_type, exc_value, exc_traceback): 33 | logger.exception(exc_value, exc_info=(exc_type, exc_value, exc_traceback)) 34 | 35 | 36 | # 未知异常日志 37 | sys.excepthook = fatal_error 38 | 39 | 40 | class Windows(QDialog, mainUI.Ui_Dialog): 41 | isRunning = False 42 | 43 | def __init__(self, parent=None): 44 | super(Windows, self).__init__(parent) 45 | self.selectedDict = None 46 | self.currentConfig = dict() 47 | self.localWords = [] 48 | self.selectedGroups = [] 49 | 50 | self.workerThread = QThread(self) 51 | self.workerThread.start() 52 | self.updateCheckThead = QThread(self) 53 | self.updateCheckThead.start() 54 | self.audioDownloadThread = QThread(self) 55 | 56 | self.updateCheckWork = None 57 | self.loginWorker = None 58 | self.queryWorker = None 59 | self.pullWorker = None 60 | self.audioDownloadWorker = None 61 | 62 | self.setupUi(self) 63 | self.setWindowTitle(MODEL_NAME) 64 | self.setupLogger() 65 | self.initCore() 66 | self.checkUpdate() 67 | # self.__dev() # 以备调试时使用 68 | 69 | def __dev(self): 70 | def on_dev(): 71 | logger.debug('whatever') 72 | 73 | self.devBtn = QPushButton('Magic Button', self.mainTab) 74 | self.devBtn.clicked.connect(on_dev) 75 | self.gridLayout_4.addWidget(self.devBtn, 4, 3, 1, 1) 76 | 77 | def closeEvent(self, event): 78 | # 插件关闭时退出所有线程 79 | if self.workerThread.isRunning(): 80 | self.workerThread.requestInterruption() 81 | self.workerThread.quit() 82 | self.workerThread.wait() 83 | 84 | if self.updateCheckThead.isRunning(): 85 | self.updateCheckThead.quit() 86 | self.updateCheckThead.wait() 87 | 88 | if self.audioDownloadThread.isRunning(): 89 | self.audioDownloadThread.requestInterruption() 90 | self.workerThread.quit() 91 | self.workerThread.wait() 92 | 93 | event.accept() 94 | 95 | def setupLogger(self): 96 | """初始化 Logger """ 97 | 98 | def onDestroyed(): 99 | logger.removeHandler(QtHandler) 100 | 101 | # 防止 debug 信息写入stdout/stderr 导致 Anki 崩溃 102 | logFile = os.path.join(gettempdir(), 'dict2anki.log') 103 | logging.basicConfig(handlers=[logging.FileHandler(logFile, 'w', 'utf-8')], level=logging.DEBUG, format='[%(asctime)s][%(levelname)8s] -- %(message)s - (%(name)s)') 104 | 105 | logTextBox = QPlainTextEdit(self) 106 | logTextBox.setLineWrapMode(QPlainTextEdit.NoWrap) 107 | layout = QVBoxLayout() 108 | layout.addWidget(logTextBox) 109 | self.logTab.setLayout(layout) 110 | QtHandler = Handler(self) 111 | logger.addHandler(QtHandler) 112 | QtHandler.newRecord.connect(logTextBox.appendPlainText) 113 | 114 | # 日志Widget销毁时移除 Handlers 115 | logTextBox.destroyed.connect(onDestroyed) 116 | 117 | def setupGUIByConfig(self): 118 | config = mw.addonManager.getConfig(__name__) 119 | self.deckComboBox.setCurrentText(config['deck']) 120 | self.dictionaryComboBox.setCurrentIndex(config['selectedDict']) 121 | self.apiComboBox.setCurrentIndex(config['selectedApi']) 122 | self.usernameLineEdit.setText(config['credential'][config['selectedDict']]['username']) 123 | self.passwordLineEdit.setText(config['credential'][config['selectedDict']]['password']) 124 | self.cookieLineEdit.setText(config['credential'][config['selectedDict']]['cookie']) 125 | self.definitionCheckBox.setChecked(config['definition']) 126 | self.imageCheckBox.setChecked(config['image']) 127 | self.sentenceCheckBox.setChecked(config['sentence']) 128 | self.phraseCheckBox.setChecked(config['phrase']) 129 | self.AmEPhoneticCheckBox.setChecked(config['AmEPhonetic']) 130 | self.BrEPhoneticCheckBox.setChecked(config['BrEPhonetic']) 131 | self.BrEPronRadioButton.setChecked(config['BrEPron']) 132 | self.AmEPronRadioButton.setChecked(config['AmEPron']) 133 | self.noPronRadioButton.setChecked(config['noPron']) 134 | self.selectedGroups = config['selectedGroup'] 135 | 136 | def initCore(self): 137 | self.usernameLineEdit.hide() 138 | self.usernameLabel.hide() 139 | self.passwordLabel.hide() 140 | self.passwordLineEdit.hide() 141 | self.dictionaryComboBox.addItems([d.name for d in dictionaries]) 142 | self.apiComboBox.addItems([d.name for d in apis]) 143 | self.deckComboBox.addItems(getDeckList()) 144 | self.setupGUIByConfig() 145 | 146 | def getAndSaveCurrentConfig(self) -> dict: 147 | """获取当前设置""" 148 | currentConfig = dict( 149 | selectedDict=self.dictionaryComboBox.currentIndex(), 150 | selectedApi=self.apiComboBox.currentIndex(), 151 | selectedGroup=self.selectedGroups, 152 | deck=self.deckComboBox.currentText(), 153 | username=self.usernameLineEdit.text(), 154 | password=Mask(self.passwordLineEdit.text()), 155 | cookie=Mask(self.cookieLineEdit.text()), 156 | definition=self.definitionCheckBox.isChecked(), 157 | sentence=self.sentenceCheckBox.isChecked(), 158 | image=self.imageCheckBox.isChecked(), 159 | phrase=self.phraseCheckBox.isChecked(), 160 | AmEPhonetic=self.AmEPhoneticCheckBox.isChecked(), 161 | BrEPhonetic=self.BrEPhoneticCheckBox.isChecked(), 162 | BrEPron=self.BrEPronRadioButton.isChecked(), 163 | AmEPron=self.AmEPronRadioButton.isChecked(), 164 | noPron=self.noPronRadioButton.isChecked(), 165 | ) 166 | logger.info(f'当前设置:{currentConfig}') 167 | self._saveConfig(currentConfig) 168 | self.currentConfig = currentConfig 169 | return currentConfig 170 | 171 | @staticmethod 172 | def _saveConfig(config): 173 | _config = deepcopy(config) 174 | _config['credential'] = [dict(username='', password='', cookie='')] * len(dictionaries) 175 | _config['credential'][_config['selectedDict']] = dict( 176 | username=_config.pop('username'), 177 | password=str(_config.pop('password')), 178 | cookie=str(_config.pop('cookie')) 179 | ) 180 | maskedConfig = deepcopy(_config) 181 | maskedCredential = [ 182 | dict( 183 | username=c['username'], 184 | password=Mask(c['password']), 185 | cookie=Mask(c['cookie'])) for c in maskedConfig['credential'] 186 | ] 187 | maskedConfig['credential'] = maskedCredential 188 | logger.info(f'保存配置项:{maskedConfig}') 189 | mw.addonManager.writeConfig(__name__, _config) 190 | 191 | def checkUpdate(self): 192 | @pyqtSlot(str, str) 193 | def on_haveNewVersion(version, changeLog): 194 | if askUser(f'有新版本:{version}是否更新?\n\n{changeLog.strip()}'): 195 | openLink(RELEASE_URL) 196 | 197 | self.updateCheckWork = VersionCheckWorker() 198 | self.updateCheckWork.moveToThread(self.updateCheckThead) 199 | self.updateCheckWork.haveNewVersion.connect(on_haveNewVersion) 200 | self.updateCheckWork.finished.connect(self.updateCheckThead.quit) 201 | self.updateCheckWork.start.connect(self.updateCheckWork.run) 202 | self.updateCheckWork.start.emit() 203 | 204 | @pyqtSlot(int) 205 | def on_dictionaryComboBox_currentIndexChanged(self, index): 206 | """词典候选框改变事件""" 207 | self.currentDictionaryLabel.setText(f'当前选择词典: {self.dictionaryComboBox.currentText()}') 208 | config = mw.addonManager.getConfig(__name__) 209 | self.cookieLineEdit.setText(config['credential'][index]['cookie']) 210 | 211 | @pyqtSlot() 212 | def on_pullRemoteWordsBtn_clicked(self): 213 | """获取单词按钮点击事件""" 214 | if not self.deckComboBox.currentText(): 215 | showInfo('\n请选择或输入要同步的牌组') 216 | return 217 | 218 | self.mainTab.setEnabled(False) 219 | self.progressBar.setValue(0) 220 | self.progressBar.setMaximum(0) 221 | 222 | currentConfig = self.getAndSaveCurrentConfig() 223 | self.selectedDict = dictionaries[currentConfig['selectedDict']]() 224 | 225 | # 登陆线程 226 | self.loginWorker = LoginStateCheckWorker(self.selectedDict.checkCookie, json.loads(self.cookieLineEdit.text() or '{}')) 227 | self.loginWorker.moveToThread(self.workerThread) 228 | self.loginWorker.start.connect(self.loginWorker.run) 229 | self.loginWorker.logSuccess.connect(self.onLogSuccess) 230 | self.loginWorker.logFailed.connect(self.onLoginFailed) 231 | self.loginWorker.start.emit() 232 | 233 | @pyqtSlot() 234 | def onLoginFailed(self): 235 | showCritical('第一次登录或cookie失效!请重新登录') 236 | self.progressBar.setValue(0) 237 | self.progressBar.setMaximum(1) 238 | self.mainTab.setEnabled(True) 239 | self.cookieLineEdit.clear() 240 | self.loginDialog = LoginDialog( 241 | loginUrl=self.selectedDict.loginUrl, 242 | loginCheckCallbackFn=self.selectedDict.loginCheckCallbackFn, 243 | parent=self 244 | ) 245 | self.loginDialog.loginSucceed.connect(self.onLogSuccess) 246 | self.loginDialog.show() 247 | 248 | @pyqtSlot(str) 249 | def onLogSuccess(self, cookie): 250 | self.cookieLineEdit.setText(cookie) 251 | self.getAndSaveCurrentConfig() 252 | self.selectedDict.checkCookie(json.loads(cookie)) 253 | self.selectedDict.getGroups() 254 | 255 | container = QDialog(self) 256 | group = wordGroup.Ui_Dialog() 257 | group.setupUi(container) 258 | 259 | for groupName in [str(group_name) for group_name, _ in self.selectedDict.groups]: 260 | item = QListWidgetItem() 261 | item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) 262 | item.setText(groupName) 263 | item.setCheckState(Qt.Unchecked) 264 | group.wordGroupListWidget.addItem(item) 265 | 266 | # 恢复上次选择的单词本分组 267 | if self.selectedGroups: 268 | for groupName in self.selectedGroups[self.currentConfig['selectedDict']]: 269 | items = group.wordGroupListWidget.findItems(groupName, Qt.MatchExactly) 270 | for item in items: 271 | item.setCheckState(Qt.Checked) 272 | else: 273 | self.selectedGroups = [list()] * len(dictionaries) 274 | 275 | def onAccepted(): 276 | """选择单词本弹窗确定事件""" 277 | # 清空 listWidget 278 | self.newWordListWidget.clear() 279 | self.needDeleteWordListWidget.clear() 280 | self.mainTab.setEnabled(False) 281 | 282 | selectedGroups = [group.wordGroupListWidget.item(index).text() for index in range(group.wordGroupListWidget.count()) if 283 | group.wordGroupListWidget.item(index).checkState() == Qt.Checked] 284 | # 保存分组记录 285 | self.selectedGroups[self.currentConfig['selectedDict']] = selectedGroups 286 | self.progressBar.setValue(0) 287 | self.progressBar.setMaximum(1) 288 | logger.info(f'选中单词本{selectedGroups}') 289 | self.getRemoteWordList(selectedGroups) 290 | 291 | def onRejected(): 292 | """选择单词本弹窗取消事件""" 293 | self.progressBar.setValue(0) 294 | self.progressBar.setMaximum(1) 295 | self.mainTab.setEnabled(True) 296 | 297 | group.buttonBox.accepted.connect(onAccepted) 298 | group.buttonBox.rejected.connect(onRejected) 299 | container.exec() 300 | 301 | def getRemoteWordList(self, selected_groups: [str]): 302 | """根据选中到分组获取分组下到全部单词,并添加到 newWordListWidget""" 303 | group_map = dict(self.selectedDict.groups) 304 | self.localWords = getWordsByDeck(self.deckComboBox.currentText()) 305 | 306 | # 启动单词获取线程 307 | self.pullWorker = RemoteWordFetchingWorker(self.selectedDict, [(group_name, group_map[group_name],) for group_name in selected_groups]) 308 | self.pullWorker.moveToThread(self.workerThread) 309 | self.pullWorker.start.connect(self.pullWorker.run) 310 | self.pullWorker.tick.connect(lambda: self.progressBar.setValue(self.progressBar.value() + 1)) 311 | self.pullWorker.setProgress.connect(self.progressBar.setMaximum) 312 | self.pullWorker.doneThisGroup.connect(self.insertWordToListWidget) 313 | self.pullWorker.done.connect(self.on_allPullWork_done) 314 | self.pullWorker.start.emit() 315 | 316 | @pyqtSlot(list) 317 | def insertWordToListWidget(self, words: list): 318 | """一个分组获取完毕事件""" 319 | for word in words: 320 | wordItem = QListWidgetItem(word, self.newWordListWidget) 321 | wordItem.setData(Qt.UserRole, None) 322 | self.newWordListWidget.clearSelection() 323 | 324 | @pyqtSlot() 325 | def on_allPullWork_done(self): 326 | """全部分组获取完毕事件""" 327 | localWordList = set(getWordsByDeck(self.deckComboBox.currentText())) 328 | remoteWordList = set([self.newWordListWidget.item(row).text() for row in range(self.newWordListWidget.count())]) 329 | 330 | newWords = remoteWordList - localWordList # 新单词 331 | needToDeleteWords = localWordList - remoteWordList # 需要删除的单词 332 | logger.info(f'本地: {localWordList}') 333 | logger.info(f'远程: {remoteWordList}') 334 | logger.info(f'待查: {newWords}') 335 | logger.info(f'待删: {needToDeleteWords}') 336 | waitIcon = QIcon(':/icons/wait.png') 337 | delIcon = QIcon(':/icons/delete.png') 338 | self.newWordListWidget.clear() 339 | self.needDeleteWordListWidget.clear() 340 | 341 | for word in needToDeleteWords: 342 | item = QListWidgetItem(word) 343 | item.setCheckState(Qt.Checked) 344 | item.setIcon(delIcon) 345 | self.needDeleteWordListWidget.addItem(item) 346 | 347 | for word in newWords: 348 | item = QListWidgetItem(word) 349 | item.setIcon(waitIcon) 350 | self.newWordListWidget.addItem(item) 351 | self.newWordListWidget.clearSelection() 352 | 353 | self.dictionaryComboBox.setEnabled(True) 354 | self.apiComboBox.setEnabled(True) 355 | self.deckComboBox.setEnabled(True) 356 | self.pullRemoteWordsBtn.setEnabled(True) 357 | self.queryBtn.setEnabled(self.newWordListWidget.count() > 0) 358 | self.syncBtn.setEnabled(self.newWordListWidget.count() == 0 and self.needDeleteWordListWidget.count() > 0) 359 | if self.needDeleteWordListWidget.count() == self.newWordListWidget.count() == 0: 360 | logger.info('无需同步') 361 | tooltip('无需同步') 362 | self.mainTab.setEnabled(True) 363 | 364 | @pyqtSlot() 365 | def on_queryBtn_clicked(self): 366 | logger.info('点击查询按钮') 367 | currentConfig = self.getAndSaveCurrentConfig() 368 | self.queryBtn.setEnabled(False) 369 | self.pullRemoteWordsBtn.setEnabled(False) 370 | self.syncBtn.setEnabled(False) 371 | 372 | wordList = [] 373 | selectedWords = self.newWordListWidget.selectedItems() 374 | if selectedWords: 375 | # 如果选中单词则只查询选中的单词 376 | for wordItem in selectedWords: 377 | wordBundle = dict() 378 | row = self.newWordListWidget.row(wordItem) 379 | wordBundle['term'] = wordItem.text() 380 | for configName in BASIC_OPTION + EXTRA_OPTION: 381 | wordBundle[configName] = currentConfig[configName] 382 | wordBundle['row'] = row 383 | wordList.append(wordBundle) 384 | else: # 没有选择则查询全部 385 | for row in range(self.newWordListWidget.count()): 386 | wordBundle = dict() 387 | wordItem = self.newWordListWidget.item(row) 388 | wordBundle['term'] = wordItem.text() 389 | for configName in BASIC_OPTION + EXTRA_OPTION: 390 | wordBundle[configName] = currentConfig[configName] 391 | wordBundle['row'] = row 392 | wordList.append(wordBundle) 393 | 394 | logger.info(f'待查询单词{wordList}') 395 | # 查询线程 396 | self.progressBar.setMaximum(len(wordList)) 397 | self.queryWorker = QueryWorker(wordList, apis[currentConfig['selectedApi']]) 398 | self.queryWorker.moveToThread(self.workerThread) 399 | self.queryWorker.thisRowDone.connect(self.on_thisRowDone) 400 | self.queryWorker.thisRowFailed.connect(self.on_thisRowFailed) 401 | self.queryWorker.tick.connect(lambda: self.progressBar.setValue(self.progressBar.value() + 1)) 402 | self.queryWorker.allQueryDone.connect(self.on_allQueryDone) 403 | self.queryWorker.start.connect(self.queryWorker.run) 404 | self.queryWorker.start.emit() 405 | 406 | @pyqtSlot(int, dict) 407 | def on_thisRowDone(self, row, result): 408 | """该行单词查询完毕""" 409 | doneIcon = QIcon(':/icons/done.png') 410 | wordItem = self.newWordListWidget.item(row) 411 | wordItem.setIcon(doneIcon) 412 | wordItem.setData(Qt.UserRole, result) 413 | 414 | @pyqtSlot(int) 415 | def on_thisRowFailed(self, row): 416 | failedIcon = QIcon(':/icons/failed.png') 417 | failedWordItem = self.newWordListWidget.item(row) 418 | failedWordItem.setIcon(failedIcon) 419 | 420 | @pyqtSlot() 421 | def on_allQueryDone(self): 422 | failed = [] 423 | 424 | for i in range(self.newWordListWidget.count()): 425 | wordItem = self.newWordListWidget.item(i) 426 | if not wordItem.data(Qt.UserRole): 427 | failed.append(wordItem.text()) 428 | 429 | if failed: 430 | logger.warning(f'查询失败或未查询:{failed}') 431 | 432 | self.pullRemoteWordsBtn.setEnabled(True) 433 | self.queryBtn.setEnabled(True) 434 | self.syncBtn.setEnabled(True) 435 | 436 | @pyqtSlot() 437 | def on_syncBtn_clicked(self): 438 | 439 | failedGenerator = (self.newWordListWidget.item(row).data(Qt.UserRole) is None for row in range(self.newWordListWidget.count())) 440 | if any(failedGenerator): 441 | if not askUser('存在未查询或失败的单词,确定要加入单词本吗?\n 你可以选择失败的单词点击 "查询按钮" 来重试。'): 442 | return 443 | 444 | currentConfig = self.getAndSaveCurrentConfig() 445 | model = getOrCreateModel(MODEL_NAME) 446 | getOrCreateModelCardTemplate(model, 'default') 447 | deck = getOrCreateDeck(self.deckComboBox.currentText(), model=model) 448 | 449 | logger.info('同步点击') 450 | audiosDownloadTasks = [] 451 | newWordCount = self.newWordListWidget.count() 452 | 453 | # 判断是否需要下载发音 454 | if currentConfig['noPron']: 455 | logger.info('不下载发音') 456 | whichPron = None 457 | else: 458 | whichPron = 'AmEPron' if self.AmEPronRadioButton.isChecked() else 'BrEPron' 459 | logger.info(f'下载发音{whichPron}') 460 | 461 | added = 0 462 | for row in range(newWordCount): 463 | wordItem = self.newWordListWidget.item(row) 464 | wordItemData = wordItem.data(Qt.UserRole) 465 | if wordItemData: 466 | addNoteToDeck(deck, model, currentConfig, wordItemData) 467 | added += 1 468 | # 添加发音任务 469 | if whichPron and wordItemData.get(whichPron): 470 | audiosDownloadTasks.append((f"{whichPron}_{wordItemData['term']}.mp3", wordItemData[whichPron],)) 471 | mw.reset() 472 | 473 | logger.info(f'发音下载任务:{audiosDownloadTasks}') 474 | 475 | if audiosDownloadTasks: 476 | self.syncBtn.setEnabled(False) 477 | self.progressBar.setValue(0) 478 | self.progressBar.setMaximum(len(audiosDownloadTasks)) 479 | if self.audioDownloadThread is not None: 480 | self.audioDownloadThread.requestInterruption() 481 | self.audioDownloadThread.quit() 482 | self.audioDownloadThread.wait() 483 | 484 | self.audioDownloadThread = QThread(self) 485 | self.audioDownloadThread.start() 486 | self.audioDownloadWorker = AudioDownloadWorker(audiosDownloadTasks) 487 | self.audioDownloadWorker.moveToThread(self.audioDownloadThread) 488 | self.audioDownloadWorker.tick.connect(lambda: self.progressBar.setValue(self.progressBar.value() + 1)) 489 | self.audioDownloadWorker.start.connect(self.audioDownloadWorker.run) 490 | self.audioDownloadWorker.done.connect(lambda: tooltip(f'发音下载完成')) 491 | self.audioDownloadWorker.done.connect(self.audioDownloadThread.quit) 492 | self.audioDownloadWorker.start.emit() 493 | 494 | self.newWordListWidget.clear() 495 | 496 | needToDeleteWordItems = [ 497 | self.needDeleteWordListWidget.item(row) 498 | for row in range(self.needDeleteWordListWidget.count()) 499 | if self.needDeleteWordListWidget.item(row).checkState() == Qt.Checked 500 | ] 501 | needToDeleteWords = [i.text() for i in needToDeleteWordItems] 502 | 503 | deleted = 0 504 | 505 | if needToDeleteWords and askUser(f'确定要删除这些单词吗:{needToDeleteWords[:3]}...({len(needToDeleteWords)}个)', title='Dict2Anki', parent=self): 506 | needToDeleteWordNoteIds = getNotes(needToDeleteWords, currentConfig['deck']) 507 | mw.col.remNotes(needToDeleteWordNoteIds) 508 | deleted += 1 509 | mw.col.reset() 510 | mw.reset() 511 | for item in needToDeleteWordItems: 512 | self.needDeleteWordListWidget.takeItem(self.needDeleteWordListWidget.row(item)) 513 | logger.info('删除完成') 514 | logger.info('完成') 515 | 516 | if not audiosDownloadTasks: 517 | tooltip(f'添加{added}个笔记\n删除{deleted}个笔记') 518 | -------------------------------------------------------------------------------- /addon/constants.py: -------------------------------------------------------------------------------- 1 | VERSION = 'v6.1.6' 2 | RELEASE_URL = 'https://github.com/megachweng/Dict2Anki' 3 | VERSION_CHECK_API = 'https://api.github.com/repos/megachweng/Dict2Anki/releases/latest' 4 | MODEL_NAME = f'Dict2Anki-{VERSION}' 5 | 6 | BASIC_OPTION = ['definition', 'sentence', 'phrase', 'image', 'BrEPhonetic', 'AmEPhonetic'] # 顺序和名称不可修改 7 | EXTRA_OPTION = ['BrEPron', 'AmEPron', 'noPron'] # 顺序和名称不可修改 8 | 9 | MODEL_FIELDS = ['term', 'definition', 'sentenceFront', 'sentenceBack', 'phraseFront', 'phraseBack', 'image', 'BrEPhonetic', 'AmEPhonetic', 'BrEPron', 'AmEPron'] # 名称不可修改 -------------------------------------------------------------------------------- /addon/dictionary/README.md: -------------------------------------------------------------------------------- 1 | ## 词典模块 2 | 3 | ## Development Guide 4 | 继承 `misc.AbstractDictionary` 确保你的词典模块能和插件兼容 5 | 并将你的模块添加到 `dictionary.__init__`中的 `dictionaries`列表中以便插件读取 -------------------------------------------------------------------------------- /addon/dictionary/__init__.py: -------------------------------------------------------------------------------- 1 | from . import eudict, youdao 2 | 3 | dictionaries = (eudict.Eudict, youdao.Youdao,) 4 | -------------------------------------------------------------------------------- /addon/dictionary/eudict.py: -------------------------------------------------------------------------------- 1 | import time 2 | import logging 3 | import requests 4 | from math import ceil 5 | from bs4 import BeautifulSoup 6 | from urllib3.util.retry import Retry 7 | from requests.adapters import HTTPAdapter 8 | from ..misc import AbstractDictionary 9 | 10 | logger = logging.getLogger('dict2Anki.dictionary.eudict') 11 | 12 | 13 | class Eudict(AbstractDictionary): 14 | name = '欧陆词典' 15 | loginUrl = 'https://dict.eudic.net/account/login' 16 | timeout = 10 17 | headers = { 18 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', 19 | } 20 | retries = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504]) 21 | session = requests.Session() 22 | session.mount('http://', HTTPAdapter(max_retries=retries)) 23 | session.mount('https://', HTTPAdapter(max_retries=retries)) 24 | 25 | def __init__(self): 26 | self.groups = [] 27 | self.indexSoup = None 28 | 29 | def checkCookie(self, cookie: dict) -> bool: 30 | """ 31 | cookie有效性检验 32 | :param cookie: 33 | :return: Boolean cookie是否有效 34 | """ 35 | rsp = requests.get('https://my.eudic.net/studylist', cookies=cookie, headers=self.headers) 36 | if 'dict.eudic.net/account/login' not in rsp.url: 37 | self.indexSoup = BeautifulSoup(rsp.text, features="html.parser") 38 | logger.info('Cookie有效') 39 | cookiesJar = requests.utils.cookiejar_from_dict(cookie, cookiejar=None, overwrite=True) 40 | self.session.cookies = cookiesJar 41 | return True 42 | logger.info('Cookie失效') 43 | return False 44 | 45 | @staticmethod 46 | def loginCheckCallbackFn(cookie, content): 47 | if 'EudicWebSession' in cookie: 48 | return True 49 | return False 50 | 51 | def getGroups(self) -> [(str, int)]: 52 | """ 53 | 获取单词本分组 54 | :return: [(group_name,group_id)] 55 | """ 56 | elements = self.indexSoup.find_all('a', class_='media_heading_a new_cateitem_click') 57 | groups = [] 58 | if elements: 59 | groups = [(el.string, el['data-id']) for el in elements] 60 | 61 | logger.info(f'单词本分组:{groups}') 62 | self.groups = groups 63 | 64 | def getTotalPage(self, groupName: str, groupId: int) -> int: 65 | """ 66 | 获取分组下总页数 67 | :param groupName: 分组名称 68 | :param groupId:分组id 69 | :return: 70 | """ 71 | try: 72 | r = self.session.post( 73 | url='https://my.eudic.net/StudyList/WordsDataSource', 74 | timeout=self.timeout, 75 | data={'categoryid': groupId} 76 | ) 77 | records = r.json()['recordsTotal'] 78 | totalPages = ceil(records / 100) 79 | logger.info(f'该分组({groupName}-{groupId})下共有{totalPages}页') 80 | return totalPages 81 | except Exception as error: 82 | logger.exception(f'网络异常{error}') 83 | return 0 84 | 85 | def getWordsByPage(self, pageNo: int, groupName: str, groupId: int) -> [str]: 86 | wordList = [] 87 | data = { 88 | 'columns[2][data]': 'word', 89 | 'start': pageNo * 100, 90 | 'length': 100, 91 | 'categoryid': groupId, 92 | '_': int(time.time()) * 1000, 93 | } 94 | try: 95 | logger.info(f'获取单词本(f{groupName}-{groupId})第:{pageNo + 1}页') 96 | r = self.session.post( 97 | url='https://my.eudic.net/StudyList/WordsDataSource', 98 | timeout=self.timeout, 99 | data=data 100 | ) 101 | wl = r.json() 102 | wordList = list(set(word['uuid'] for word in wl['data'])) 103 | except Exception as error: 104 | logger.exception(f'网络异常{error}') 105 | finally: 106 | logger.info(wordList) 107 | return wordList 108 | -------------------------------------------------------------------------------- /addon/dictionary/youdao.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from math import ceil 3 | import requests 4 | from bs4 import BeautifulSoup 5 | from urllib3.util.retry import Retry 6 | from requests.adapters import HTTPAdapter 7 | from ..misc import AbstractDictionary 8 | 9 | logger = logging.getLogger('dict2Anki.dictionary.youdao') 10 | 11 | 12 | class Youdao(AbstractDictionary): 13 | name = '有道词典' 14 | loginUrl = 'http://account.youdao.com/login?service=dict&back_url=http://dict.youdao.com/wordbook/wordlist%3Fkeyfrom%3Dnull' 15 | timeout = 10 16 | headers = { 17 | 'Host': 'dict.youdao.com', 18 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', 19 | } 20 | retries = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504]) 21 | session = requests.Session() 22 | session.mount('http://', HTTPAdapter(max_retries=retries)) 23 | session.mount('https://', HTTPAdapter(max_retries=retries)) 24 | 25 | def __init__(self): 26 | self.indexSoup = None 27 | self.groups = [] 28 | 29 | def checkCookie(self, cookie: dict) -> bool: 30 | """ 31 | cookie有效性检验 32 | :param cookie: 33 | :return: bool 34 | """ 35 | rsp = requests.get('http://dict.youdao.com/login/acc/query/accountinfo', cookies=cookie, headers=self.headers) 36 | if rsp.json().get('code', None) == 0: 37 | self.indexSoup = BeautifulSoup(rsp.text, features="html.parser") 38 | logger.info('Cookie有效') 39 | cookiesJar = requests.utils.cookiejar_from_dict(cookie, cookiejar=None, overwrite=True) 40 | self.session.cookies = cookiesJar 41 | return True 42 | logger.info('Cookie失效') 43 | return False 44 | 45 | @staticmethod 46 | def loginCheckCallbackFn(cookie, content): 47 | if 'DICT_SESS' in cookie: 48 | return True 49 | return False 50 | 51 | def getGroups(self) -> [(str, int)]: 52 | """ 53 | 获取单词本分组 54 | :return: [(group_name,group_id)] 55 | """ 56 | r = self.session.get( 57 | url='http://dict.youdao.com/wordbook/webapi/books', 58 | timeout=self.timeout, 59 | ) 60 | groups = [(g['bookName'], g['bookId']) for g in r.json()['data']] 61 | logger.info(f'单词本分组:{groups}') 62 | self.groups = groups 63 | 64 | return groups 65 | 66 | def getTotalPage(self, groupName: str, groupId: int) -> int: 67 | """ 68 | 获取分组下总页数 69 | :param groupName: 分组名称 70 | :param groupId:分组id 71 | :return: 72 | """ 73 | try: 74 | r = self.session.get( 75 | url='http://dict.youdao.com/wordbook/webapi/words', 76 | timeout=self.timeout, 77 | params={'bookId': groupId, 'limit': 1, 'offset': 0} 78 | ) 79 | totalWords = r.json()['data']['total'] 80 | totalPages = ceil(totalWords / 15) # 这里按网页默认每页取15个 81 | 82 | except Exception as error: 83 | logger.exception(f'网络异常{error}') 84 | 85 | else: 86 | logger.info(f'该分组({groupName}-{groupId})下共有{totalPages}页') 87 | return totalPages 88 | 89 | def getWordsByPage(self, pageNo: int, groupName: str, groupId: str) -> [str]: 90 | """ 91 | 获取分组下每一页的单词 92 | :param pageNo: 页数 93 | :param groupName: 分组名 94 | :param groupId: 分组id 95 | :return: 96 | """ 97 | wordList = [] 98 | try: 99 | logger.info(f'获取单词本(f{groupName}-{groupId})第:{pageNo}页') 100 | r = self.session.get( 101 | 'http://dict.youdao.com/wordbook/webapi/words', 102 | timeout=self.timeout, 103 | params={'bookId': groupId, 'limit': 15, 'offset': pageNo * 15} 104 | ) 105 | wordList = [item['word'] for item in r.json()['data']['itemList']] 106 | except Exception as e: 107 | logger.exception(f'网络异常{e}') 108 | finally: 109 | logger.info(wordList) 110 | return wordList 111 | -------------------------------------------------------------------------------- /addon/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from PyQt5.QtCore import pyqtSignal, QObject 3 | 4 | 5 | class Handler(QObject, logging.Handler): 6 | newRecord = pyqtSignal(object) 7 | 8 | def __init__(self, parent): 9 | super().__init__(parent) 10 | super(logging.Handler).__init__() 11 | 12 | formatter = Formatter('[%(asctime)s][%(levelname)8s] -- %(message)s - (%(name)s)', '%d/%m/%Y %H:%M:%S') 13 | self.setFormatter(formatter) 14 | self.setLevel(logging.DEBUG) 15 | 16 | def emit(self, record): 17 | msg = self.format(record) 18 | self.newRecord.emit(msg) 19 | 20 | 21 | class Formatter(logging.Formatter): 22 | def formatException(self, ei): 23 | result = super(Formatter, self).formatException(ei) 24 | return result 25 | 26 | def format(self, record): 27 | s = super(Formatter, self).format(record) 28 | if record.exc_text: 29 | s = s.replace('\n', '') 30 | return s 31 | -------------------------------------------------------------------------------- /addon/loginDialog.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | import logging 4 | from PyQt5.QtCore import QUrl, pyqtSignal 5 | from .UIForm import loginDialog 6 | from PyQt5.QtWidgets import QDialog 7 | from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile 8 | 9 | logger = logging.getLogger('dict2Anki') 10 | 11 | 12 | class LoginDialog(QDialog, loginDialog.Ui_LoginDialog): 13 | loginSucceed = pyqtSignal(str) 14 | 15 | def __init__(self, loginUrl, loginCheckCallbackFn, parent=None): 16 | super().__init__(parent) 17 | self.url = QUrl(loginUrl) 18 | self.loginCheckCallbackFn = loginCheckCallbackFn 19 | self.setupUi(self) 20 | self.page = LoginWebEngineView(self) 21 | self.pageContainer.addWidget(self.page) 22 | self.page.load(self.url) 23 | self.makeConnection() 24 | 25 | def makeConnection(self): 26 | self.reloadBtn.clicked.connect(self._reload) 27 | self.page.loadFinished.connect(self.checkLoginState) 28 | 29 | def _reload(self): 30 | logger.debug('Reload page') 31 | self.page.cookieStore.deleteAllCookies() 32 | self.page.load(QUrl(self.address.text())) 33 | 34 | def checkLoginState(self): 35 | def contentLoaded(content): 36 | logger.debug(f'Cookie:{self.page.cookie}') 37 | logger.debug(f'Content{content}') 38 | if self.loginCheckCallbackFn(cookie=self.page.cookie, content=content): 39 | logger.info(f'Login Success!') 40 | self.onLoginSucceed() 41 | logger.info(f'Login Fail!') 42 | 43 | self.page.page().toHtml(contentLoaded) 44 | 45 | def onLoginSucceed(self): 46 | logger.info('Destruct login dialog') 47 | self.close() 48 | logger.debug('emit cookie') 49 | self.loginSucceed.emit(json.dumps(self.page.cookie)) 50 | 51 | 52 | class LoginWebEngineView(QWebEngineView): 53 | def __init__(self, *args, **kwargs): 54 | super().__init__(*args, **kwargs) 55 | # 绑定cookie被添加的信号槽 56 | self.profile = QWebEngineProfile.defaultProfile() 57 | self.profile.setHttpUserAgent( 58 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko)' 59 | ' Chrome/69.0.3497.100 Safari/537.36' 60 | ) 61 | self.cookieStore = self.profile.cookieStore() 62 | self.cookieStore.cookieAdded.connect(self.onCookieAdd) 63 | self._cookies = {} 64 | self.show() 65 | 66 | def onCookieAdd(self, cookie): 67 | name = cookie.name().data().decode('utf-8') 68 | value = cookie.value().data().decode('utf-8') 69 | self._cookies[name] = value 70 | 71 | @property 72 | def cookie(self) -> dict: 73 | return self._cookies 74 | -------------------------------------------------------------------------------- /addon/misc.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from queue import Queue 3 | from threading import Thread 4 | from abc import ABC, abstractmethod 5 | 6 | logger = logging.getLogger('dict2Anki.misc') 7 | 8 | 9 | class AbstractDictionary(ABC): 10 | 11 | @staticmethod 12 | @abstractmethod 13 | def loginCheckCallbackFn(cookie: dict, content: str): 14 | pass 15 | 16 | @abstractmethod 17 | def checkCookie(self, cookie: dict): 18 | pass 19 | 20 | @abstractmethod 21 | def getGroups(self) -> [(str, int)]: 22 | pass 23 | 24 | @abstractmethod 25 | def getTotalPage(self, groupName: str, groupId: int) -> int: 26 | pass 27 | 28 | @abstractmethod 29 | def getWordsByPage(self, pageNo: int, groupName: str, groupId: str) -> [str]: 30 | pass 31 | 32 | 33 | class AbstractQueryAPI(ABC): 34 | @classmethod 35 | @abstractmethod 36 | def query(cls, word) -> dict: 37 | """ 38 | 查询 39 | :param word: 单词 40 | :return: 查询结果 dict(term, definition, phrase, image, sentence, BrEPhonetic, AmEPhonetic, BrEPron, AmEPron) 41 | """ 42 | pass 43 | 44 | 45 | class Mask: 46 | def __init__(self, info): 47 | self.info = info 48 | 49 | def __repr__(self): 50 | return '*******' 51 | 52 | def __str__(self): 53 | return self.info 54 | 55 | 56 | class Worker(Thread): 57 | def __init__(self, queue, result_queue): 58 | super(Worker, self).__init__() 59 | self._q = queue 60 | self.result_queue = result_queue 61 | self.daemon = True 62 | self.start() 63 | 64 | def run(self): 65 | while True: 66 | try: 67 | f, args, kwargs = self._q.get() 68 | result = f(*args, **kwargs) 69 | if result: 70 | self.result_queue.put(result) 71 | except Exception as e: 72 | logger.exception(e) 73 | finally: 74 | self._q.task_done() 75 | 76 | 77 | class ThreadPool: 78 | def __init__(self, max_workers): 79 | self._q = Queue(max_workers) 80 | self.results_q = Queue() 81 | self.result = [] 82 | # Create Worker Thread 83 | for _ in range(max_workers): 84 | Worker(self._q, self.results_q) 85 | 86 | def submit(self, f, *args, **kwargs): 87 | self._q.put((f, args, kwargs)) 88 | 89 | def wait_complete(self): 90 | self._q.join() 91 | while not self.results_q.empty(): 92 | self.result.append(self.results_q.get()) 93 | return self.result 94 | 95 | def __enter__(self): 96 | return self 97 | 98 | def __exit__(self, exc_type, exc_val, exc_tb): 99 | self.wait_complete() -------------------------------------------------------------------------------- /addon/noteManager.py: -------------------------------------------------------------------------------- 1 | from .constants import MODEL_FIELDS, BASIC_OPTION, EXTRA_OPTION 2 | import logging 3 | 4 | logger = logging.getLogger('dict2Anki.noteManager') 5 | try: 6 | from aqt import mw 7 | import anki 8 | except ImportError: 9 | from test.dummy_aqt import mw 10 | from test import dummy_anki as anki 11 | 12 | 13 | def getDeckList(): 14 | return [deck['name'] for deck in mw.col.decks.all()] 15 | 16 | 17 | def getWordsByDeck(deckName) -> [str]: 18 | notes = mw.col.findNotes(f'deck:"{deckName}"') 19 | words = [] 20 | for nid in notes: 21 | note = mw.col.getNote(nid) 22 | if note.model().get('name', '').lower().startswith('dict2anki') and note['term']: 23 | words.append(note['term']) 24 | return words 25 | 26 | 27 | def getNotes(wordList, deckName) -> list: 28 | notes = [] 29 | for word in wordList: 30 | note = mw.col.findNotes(f'deck:"{deckName}" term:"{word}"') 31 | if note: 32 | notes.append(note[0]) 33 | return notes 34 | 35 | 36 | def getOrCreateDeck(deckName, model): 37 | deck_id = mw.col.decks.id(deckName) 38 | deck = mw.col.decks.get(deck_id) 39 | mw.col.decks.select(deck['id']) 40 | mw.col.decks.save(deck) 41 | mw.col.models.setCurrent(model) 42 | model['did'] = deck['id'] 43 | mw.col.models.save(model) 44 | mw.col.reset() 45 | mw.reset() 46 | return deck 47 | 48 | 49 | def getOrCreateModel(modelName): 50 | model = mw.col.models.byName(modelName) 51 | if model: 52 | if set([f['name'] for f in model['flds']]) == set(MODEL_FIELDS): 53 | return model 54 | else: 55 | logger.warning('模版字段异常,自动删除重建') 56 | mw.col.models.rem(model) 57 | 58 | logger.info(f'创建新模版:{modelName}') 59 | newModel = mw.col.models.new(modelName) 60 | for field in MODEL_FIELDS: 61 | mw.col.models.addField(newModel, mw.col.models.newField(field)) 62 | return newModel 63 | 64 | 65 | def getOrCreateModelCardTemplate(modelObject, cardTemplateName): 66 | logger.info(f'添加卡片类型:{cardTemplateName}') 67 | existingCardTemplate = modelObject['tmpls'] 68 | if cardTemplateName in [t.get('name') for t in existingCardTemplate]: 69 | return 70 | cardTemplate = mw.col.models.newTemplate(cardTemplateName) 71 | cardTemplate['qfmt'] = ''' 72 | 73 | 74 | 75 | 76 | 77 |

{{term}}


英 [{{BrEPhonetic}}] 美 [{{AmEPhonetic}}]
78 |
79 | 释义: 80 |
Tap to View
81 |
82 | 短语: 83 | {{phraseFront}}
84 |
85 | 例句: 86 | {{sentenceFront}}
87 | {{BrEPron}} 88 | {{AmEPron}} 89 | ''' 90 | cardTemplate['afmt'] = ''' 91 | 92 | 93 | 94 | 95 | 96 |

{{term}}


英 [{{BrEPhonetic}}] 美 [{{AmEPhonetic}}]
97 |
98 | 释义: 99 |
{{definition}}
100 |
101 | 短语: 102 | {{phraseBack}}
103 |
104 | 例句: 105 | {{sentenceBack}}
106 | ''' 107 | modelObject['css'] = ''' 108 | .card { 109 | font-family: arial; 110 | font-size: 20px; 111 | text-align: left; 112 | color: black; 113 | background-color: white; 114 | } 115 | .term { 116 | font-size : 35px; 117 | } 118 | ''' 119 | mw.col.models.addTemplate(modelObject, cardTemplate) 120 | mw.col.models.add(modelObject) 121 | 122 | 123 | def addNoteToDeck(deckObject, modelObject, currentConfig: dict, oneQueryResult: dict): 124 | if not oneQueryResult: 125 | logger.warning(f'查询结果{oneQueryResult} 异常,忽略') 126 | return 127 | modelObject['did'] = deckObject['id'] 128 | 129 | newNote = anki.notes.Note(mw.col, modelObject) 130 | newNote['term'] = oneQueryResult['term'] 131 | for configName in BASIC_OPTION + EXTRA_OPTION: 132 | logger.debug(f'字段:{configName}--结果:{oneQueryResult.get(configName)}') 133 | if oneQueryResult.get(configName): 134 | # 短语例句 135 | if configName in ['sentence', 'phrase'] and currentConfig[configName]: 136 | newNote[f'{configName}Front'] = '\n'.join( 137 | [f'{e.strip()}' for e, _ in oneQueryResult[configName]]) 138 | newNote[f'{configName}Back'] = '\n'.join( 139 | [f'{e.strip()}
{c.strip()}' for e, c in oneQueryResult[configName]]) 140 | # 图片 141 | elif configName == 'image': 142 | newNote[configName] = f'src="{oneQueryResult[configName]}"' 143 | # 释义 144 | elif configName == 'definition' and currentConfig[configName]: 145 | newNote[configName] = ' '.join(oneQueryResult[configName]) 146 | # 发音 147 | elif configName in EXTRA_OPTION[:2]: 148 | newNote[configName] = f"[sound:{configName}_{oneQueryResult['term']}.mp3]" 149 | # 其他 150 | elif currentConfig[configName]: 151 | newNote[configName] = oneQueryResult[configName] 152 | 153 | mw.col.addNote(newNote) 154 | mw.col.reset() 155 | logger.info(f"添加笔记{newNote['term']}") 156 | -------------------------------------------------------------------------------- /addon/queryApi/README.md: -------------------------------------------------------------------------------- 1 | ## 单词查询 API 模块 2 | 3 | ## Development Guide 4 | 可在该模块下添加自定义查询API,继承 `misc.AbstractQueryAPI`确保API能和插件兼容 5 | 之后将你的API 添加到当前目录`__init.py` 中的 `apis` 列表中以便插件读取,并且查询返回结果满足 6 | ```python 7 | { 8 | 'term': str, 9 | 'definition': [str], 10 | 'phrase': [(str,str)], 11 | 'image': str, 12 | 'sentence': [(str,str)], 13 | 'BrEPhonetic': str, 14 | 'AmEPhonetic': str, 15 | 'BrEPron': str, 16 | 'AmEPron': str 17 | } 18 | 19 | ``` 20 | -------------------------------------------------------------------------------- /addon/queryApi/__init__.py: -------------------------------------------------------------------------------- 1 | from . import youdao, bing, eudict 2 | 3 | apis = [youdao.API, eudict.API] 4 | -------------------------------------------------------------------------------- /addon/queryApi/bing.py: -------------------------------------------------------------------------------- 1 | import string 2 | import logging 3 | import requests 4 | from urllib3 import Retry 5 | from urllib.parse import urlencode 6 | from requests.adapters import HTTPAdapter 7 | from ..misc import AbstractQueryAPI 8 | logger = logging.getLogger('dict2Anki.queryApi.bing') 9 | __all__ = ['API'] 10 | 11 | 12 | class Parser: 13 | def __init__(self, json_obj, term): 14 | self._result = json_obj 15 | self.term = term 16 | 17 | @property 18 | def definition(self) -> list: 19 | return [''.join([d.get('pos', ''), d.get('def', '')]) for d in self._result.get('defs') or []] 20 | 21 | @property 22 | def pronunciations(self) -> dict: 23 | return self._result.get('pronunciation') or dict() 24 | 25 | @property 26 | def BrEPhonetic(self) -> str: 27 | """英式音标""" 28 | return self.pronunciations.get('BrE') 29 | 30 | @property 31 | def AmEPhonetic(self) -> str: 32 | """美式音标""" 33 | return self.pronunciations.get('AmE') 34 | 35 | @property 36 | def BrEPron(self) -> str: 37 | """英式发音url""" 38 | return self.pronunciations.get('BrEmp3') 39 | 40 | @property 41 | def AmEPron(self) -> str: 42 | """美式发音url""" 43 | return self.pronunciations.get('AmEmp3') 44 | 45 | @property 46 | def sentence(self) -> list: 47 | return [(s.get('eng'), s.get('chn'),) for s in self._result.get('sams') or []] 48 | 49 | @property 50 | def image(self) -> None: 51 | return None 52 | 53 | @property 54 | def result(self) -> dict: 55 | return { 56 | 'term': self.term, 57 | 'definition': self.definition, 58 | 'phrase': None, 59 | 'image': self.image, 60 | 'sentence': self.sentence, 61 | 'BrEPhonetic': self.BrEPhonetic, 62 | 'AmEPhonetic': self.AmEPhonetic, 63 | 'BrEPron': self.BrEPron, 64 | 'AmEPron': self.AmEPron 65 | } 66 | 67 | 68 | class API(AbstractQueryAPI): 69 | name = '必应 API' 70 | timeout = 10 71 | headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'} 72 | retries = Retry(total=5, backoff_factor=3, status_forcelist=[500, 502, 503, 504]) 73 | session = requests.Session() 74 | session.mount('http://', HTTPAdapter(max_retries=retries)) 75 | session.mount('https://', HTTPAdapter(max_retries=retries)) 76 | url = 'http://xtk.azurewebsites.net/BingDictService.aspx' 77 | parser = Parser 78 | 79 | @classmethod 80 | def query(cls, word) -> dict: 81 | validator = str.maketrans(string.punctuation, ' ' * len(string.punctuation)) # 第三方Bing API查询包含标点的单词时有可能会报错,所以用空格替换所有标点 82 | query_result = None 83 | try: 84 | rsp = cls.session.get(cls.url, params=urlencode({'Word': word.translate(validator)}), timeout=cls.timeout) 85 | logger.debug(f'code:{rsp.status_code}- word:{word} text:{rsp.text}') 86 | query_result = cls.parser(rsp.json(), word).result 87 | except Exception as e: 88 | logger.exception(e) 89 | finally: 90 | logger.debug(query_result) 91 | return query_result 92 | -------------------------------------------------------------------------------- /addon/queryApi/eudict.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import requests 3 | from urllib3 import Retry 4 | from requests.adapters import HTTPAdapter 5 | from ..misc import AbstractQueryAPI 6 | from bs4 import BeautifulSoup 7 | logger = logging.getLogger('dict2Anki.queryApi.eudict') 8 | __all__ = ['API'] 9 | 10 | 11 | class Parser: 12 | def __init__(self, html, term): 13 | self._soap = BeautifulSoup(html, 'html.parser') 14 | self.term = term 15 | 16 | @staticmethod 17 | def __fix_url_without_http(url): 18 | if url[0:2] == '//': 19 | return 'https:' + url 20 | else: 21 | return url 22 | 23 | @property 24 | def definition(self) -> list: 25 | ret = [] 26 | div = self._soap.select('div #ExpFCChild') 27 | if not div: 28 | return ret 29 | 30 | div = div[0] 31 | els = div.select('li') # 多词性 32 | if not els: # 单一词性 33 | els = div.select('.exp') 34 | if not els: # 还有一奇怪的情况,不在任何的标签里面 35 | trans = div.find(id='trans') 36 | trans.replace_with('') if trans else '' 37 | 38 | script = div.find('script') 39 | script.replace_with('') if script else '' 40 | 41 | for atag in div.find_all('a'): # 赞踩这些字样 42 | atag.replace_with('') 43 | els = [div] 44 | 45 | for el in els: 46 | ret.append(el.get_text(strip=True)) 47 | 48 | return ret 49 | 50 | @property 51 | def pronunciations(self) -> dict: 52 | url = 'https://api.frdic.com/api/v2/speech/speakweb?' 53 | pron = { 54 | 'AmEPhonetic': None, 55 | 'AmEUrl': None, 56 | 'BrEPhonetic': None, 57 | 'BrEUrl': None 58 | } 59 | 60 | els = self._soap.select('.phonitic-line') 61 | if not els: 62 | return pron 63 | 64 | el = els[0] 65 | links = el.select('a') 66 | phons = el.select('.Phonitic') 67 | 68 | if not links: 69 | # 可能是只有一个发音的情况 70 | links = self._soap.select('div .gv_details .voice-button') 71 | # 返回两个相同的。下载只会按照用户选择下载一个,这样至少可以保证总是有发音 72 | links = [links[0], links[0]] if links else '' 73 | 74 | try: 75 | pron['BrEPhonetic'] = phons[0].get_text(strip=True) 76 | except (KeyError, IndexError): 77 | pass 78 | 79 | try: 80 | pron['BrEUrl'] = "{}{}".format('' if 'http' in links[0]['data-rel'] else url, links[0]['data-rel']) 81 | except (TypeError, KeyError, IndexError): 82 | pass 83 | 84 | try: 85 | pron['AmEPhonetic'] = phons[1].get_text(strip=True) 86 | except (KeyError, IndexError): 87 | pass 88 | 89 | try: 90 | pron['AmEUrl'] = "{}{}".format('' if 'http' in links[1]['data-rel'] else url, links[1]['data-rel']) 91 | except (TypeError, KeyError, IndexError): 92 | pass 93 | 94 | return pron 95 | 96 | @property 97 | def BrEPhonetic(self) -> str: 98 | """英式音标""" 99 | return self.pronunciations['BrEPhonetic'] 100 | 101 | @property 102 | def AmEPhonetic(self) -> str: 103 | """美式音标""" 104 | return self.pronunciations['AmEPhonetic'] 105 | 106 | @property 107 | def BrEPron(self) -> str: 108 | """英式发音url""" 109 | return self.pronunciations['BrEUrl'] 110 | 111 | @property 112 | def AmEPron(self) -> str: 113 | """美式发音url""" 114 | return self.pronunciations['AmEUrl'] 115 | 116 | @property 117 | def sentence(self) -> list: 118 | els = self._soap.select('div #ExpLJChild .lj_item') 119 | ret = [] 120 | for el in els: 121 | try: 122 | line = el.select('p') 123 | sentence = "".join([ str(c) for c in line[0].contents]) 124 | sentence_translation = line[1].get_text(strip=True) 125 | ret.append((sentence, sentence_translation)) 126 | except KeyError as e: 127 | pass 128 | return ret 129 | 130 | @property 131 | def image(self) -> str: 132 | els = self._soap.select('div .word-thumbnail-container img') 133 | ret = None 134 | if els: 135 | try: 136 | img = els[0] 137 | if 'title' not in img.attrs: 138 | ret = self.__fix_url_without_http(img['src']) 139 | except KeyError: 140 | pass 141 | return ret 142 | 143 | @property 144 | def phrase(self) -> list: 145 | els = self._soap.select('div #ExpSPECChild #phrase') 146 | ret = [] 147 | for el in els: 148 | try: 149 | phrase = el.find('i').get_text(strip=True) 150 | exp = el.find(class_='exp').get_text(strip=True) 151 | ret.append((phrase, exp)) 152 | except AttributeError: 153 | pass 154 | return ret 155 | 156 | @property 157 | def result(self): 158 | return { 159 | 'term': self.term, 160 | 'definition': self.definition, 161 | 'phrase': self.phrase, 162 | 'image': self.image, 163 | 'sentence': self.sentence, 164 | 'BrEPhonetic': self.BrEPhonetic, 165 | 'AmEPhonetic': self.AmEPhonetic, 166 | 'BrEPron': self.BrEPron, 167 | 'AmEPron': self.AmEPron 168 | } 169 | 170 | 171 | class API(AbstractQueryAPI): 172 | name = '欧陆词典 API' 173 | timeout = 10 174 | headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'} 175 | retries = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504]) 176 | session = requests.Session() 177 | session.mount('http://', HTTPAdapter(max_retries=retries)) 178 | session.mount('https://', HTTPAdapter(max_retries=retries)) 179 | url = 'https://dict.eudic.net/dicts/en/{}' 180 | parser = Parser 181 | 182 | @classmethod 183 | def query(cls, word) -> dict: 184 | queryResult = None 185 | try: 186 | rsp = cls.session.get(cls.url.format(word), timeout=cls.timeout) 187 | logger.debug(f'code:{rsp.status_code}- word:{word} text:{rsp.text[:100]}') 188 | queryResult = cls.parser(rsp.text, word).result 189 | except Exception as e: 190 | logger.exception(e) 191 | finally: 192 | logger.debug(queryResult) 193 | return queryResult 194 | -------------------------------------------------------------------------------- /addon/queryApi/youdao.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import requests 3 | from urllib3 import Retry 4 | from urllib.parse import urlencode 5 | from requests.adapters import HTTPAdapter 6 | from ..misc import AbstractQueryAPI 7 | logger = logging.getLogger('dict2Anki.queryApi.youdao') 8 | __all__ = ['API'] 9 | 10 | 11 | class Parser: 12 | def __init__(self, json_obj, term): 13 | self._result = json_obj 14 | self.term = term 15 | 16 | @property 17 | def definition(self) -> list: 18 | try: 19 | ec = [d['tr'][0]['l']['i'][0] for d in self._result['ec']['word'][0]['trs']][:3] 20 | except KeyError: 21 | ec = [] 22 | 23 | try: 24 | ee = [ d['pos'] + d['tr'][0]['l']['i'] for d in self._result['ee']['word']['trs']] 25 | except KeyError: 26 | ee = [] 27 | 28 | ec += ee 29 | 30 | try: 31 | web_trans = [w['value'] for w in self._result['web_trans']['web-translation'][0]['trans']][:3] 32 | except KeyError: 33 | web_trans = [] 34 | return ec if ec else web_trans 35 | 36 | @property 37 | def pronunciations(self) -> dict: 38 | url = 'http://dict.youdao.com/dictvoice?audio=' 39 | pron = { 40 | 'AmEPhonetic': None, 41 | 'AmEUrl': None, 42 | 'BrEPhonetic': None, 43 | 'BrEUrl': None 44 | } 45 | try: 46 | pron['AmEPhonetic'] = self._result['simple']['word'][0]['usphone'] 47 | except KeyError: 48 | pass 49 | 50 | try: 51 | pron['BrEPhonetic'] = self._result['simple']['word'][0]['ukphone'] 52 | except KeyError: 53 | pass 54 | 55 | try: 56 | pron['AmEUrl'] = url + self._result['simple']['word'][0]['usspeech'] 57 | except (TypeError, KeyError): 58 | pass 59 | 60 | try: 61 | pron['BrEUrl'] = url + self._result['simple']['word'][0]['ukspeech'] 62 | except (TypeError, KeyError): 63 | pass 64 | 65 | return pron 66 | 67 | @property 68 | def BrEPhonetic(self)->str: 69 | """英式音标""" 70 | return self.pronunciations['BrEPhonetic'] 71 | 72 | @property 73 | def AmEPhonetic(self)->str: 74 | """美式音标""" 75 | return self.pronunciations['AmEPhonetic'] 76 | 77 | @property 78 | def BrEPron(self)->str: 79 | """英式发音url""" 80 | return self.pronunciations['BrEUrl'] 81 | 82 | @property 83 | def AmEPron(self)->str: 84 | """美式发音url""" 85 | return self.pronunciations['AmEUrl'] 86 | 87 | @property 88 | def sentence(self) -> list: 89 | try: 90 | return [(s['sentence'], s['sentence-translation'],) for s in self._result['blng_sents_part']['sentence-pair']] 91 | except KeyError: 92 | return [] 93 | 94 | @property 95 | def image(self)->str: 96 | try: 97 | return [i['image'] for i in self._result['pic_dict']['pic']][0] 98 | except (KeyError, IndexError): 99 | return None 100 | 101 | @property 102 | def phrase(self) -> list: 103 | phrase = self._result.get('phrs', dict()).get('phrs', []) 104 | return [ 105 | ( 106 | p.get('phr', dict()).get('headword', dict()).get('l', dict()).get('i', None), 107 | p.get('phr', dict()).get('trs', [dict()])[0].get('tr', dict()).get('l', dict()).get('i', None) 108 | ) 109 | for p in phrase if phrase 110 | ] 111 | 112 | @property 113 | def result(self): 114 | return { 115 | 'term': self.term, 116 | 'definition': self.definition, 117 | 'phrase': self.phrase, 118 | 'image': self.image, 119 | 'sentence': self.sentence, 120 | 'BrEPhonetic': self.BrEPhonetic, 121 | 'AmEPhonetic': self.AmEPhonetic, 122 | 'BrEPron': self.BrEPron, 123 | 'AmEPron': self.AmEPron 124 | } 125 | 126 | 127 | class API(AbstractQueryAPI): 128 | name = '有道 API' 129 | timeout = 10 130 | headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'} 131 | retries = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504]) 132 | session = requests.Session() 133 | session.mount('http://', HTTPAdapter(max_retries=retries)) 134 | session.mount('https://', HTTPAdapter(max_retries=retries)) 135 | url = 'https://dict.youdao.com/jsonapi' 136 | params = {"dicts": {"count": 99, "dicts": [["ec", "ee", "phrs", "pic_dict"], ["web_trans"], ["fanyi"], ["blng_sents_part"]]}} 137 | parser = Parser 138 | 139 | @classmethod 140 | def query(cls, word) -> dict: 141 | queryResult = None 142 | try: 143 | rsp = cls.session.get(cls.url, params=urlencode(dict(cls.params, **{'q': word})), timeout=cls.timeout) 144 | logger.debug(f'code:{rsp.status_code}- word:{word} text:{rsp.text}') 145 | queryResult = cls.parser(rsp.json(), word).result 146 | except Exception as e: 147 | logger.exception(e) 148 | finally: 149 | logger.debug(queryResult) 150 | return queryResult 151 | -------------------------------------------------------------------------------- /addon/workers.py: -------------------------------------------------------------------------------- 1 | import json 2 | import logging 3 | import requests 4 | from urllib3 import Retry 5 | from itertools import chain 6 | from .misc import ThreadPool 7 | from requests.adapters import HTTPAdapter 8 | from .constants import VERSION, VERSION_CHECK_API 9 | from PyQt5.QtCore import QObject, pyqtSignal, QThread 10 | import aqt 11 | import os 12 | 13 | class VersionCheckWorker(QObject): 14 | haveNewVersion = pyqtSignal(str, str) 15 | finished = pyqtSignal() 16 | start = pyqtSignal() 17 | logger = logging.getLogger('dict2Anki.workers.UpdateCheckWorker') 18 | 19 | def run(self): 20 | try: 21 | self.logger.info('检查新版本') 22 | rsp = requests.get(VERSION_CHECK_API, timeout=20).json() 23 | version = rsp['tag_name'] 24 | changeLog = rsp['body'] 25 | if version != VERSION: 26 | self.logger.info(f'检查到新版本:{version}--{changeLog.strip()}') 27 | self.haveNewVersion.emit(version.strip(), changeLog.strip()) 28 | else: 29 | self.logger.info(f'当前为最新版本:{VERSION}') 30 | except Exception as e: 31 | self.logger.error(f'版本检查失败{e}') 32 | 33 | finally: 34 | self.finished.emit() 35 | 36 | 37 | class LoginStateCheckWorker(QObject): 38 | start = pyqtSignal() 39 | logSuccess = pyqtSignal(str) 40 | logFailed = pyqtSignal() 41 | 42 | def __init__(self, checkFn, cookie): 43 | super().__init__() 44 | self.checkFn = checkFn 45 | self.cookie = cookie 46 | 47 | def run(self): 48 | loginState = self.checkFn(self.cookie) 49 | if loginState: 50 | self.logSuccess.emit(json.dumps(self.cookie)) 51 | else: 52 | self.logFailed.emit() 53 | 54 | 55 | class RemoteWordFetchingWorker(QObject): 56 | start = pyqtSignal() 57 | tick = pyqtSignal() 58 | setProgress = pyqtSignal(int) 59 | done = pyqtSignal() 60 | doneThisGroup = pyqtSignal(list) 61 | logger = logging.getLogger('dict2Anki.workers.RemoteWordFetchingWorker') 62 | 63 | def __init__(self, selectedDict, selectedGroups: [tuple]): 64 | super().__init__() 65 | self.selectedDict = selectedDict 66 | self.selectedGroups = selectedGroups 67 | 68 | def run(self): 69 | currentThread = QThread.currentThread() 70 | 71 | def _pull(*args): 72 | if currentThread.isInterruptionRequested(): 73 | return 74 | wordPerPage = self.selectedDict.getWordsByPage(*args) 75 | self.tick.emit() 76 | return wordPerPage 77 | 78 | for groupName, groupId in self.selectedGroups: 79 | totalPage = self.selectedDict.getTotalPage(groupName, groupId) 80 | self.setProgress.emit(totalPage) 81 | with ThreadPool(max_workers=3) as executor: 82 | for i in range(totalPage): 83 | executor.submit(_pull, i, groupName, groupId) 84 | remoteWordList = list(chain(*[ft for ft in executor.result])) 85 | self.doneThisGroup.emit(remoteWordList) 86 | 87 | self.done.emit() 88 | 89 | 90 | class QueryWorker(QObject): 91 | start = pyqtSignal() 92 | tick = pyqtSignal() 93 | thisRowDone = pyqtSignal(int, dict) 94 | thisRowFailed = pyqtSignal(int) 95 | allQueryDone = pyqtSignal() 96 | logger = logging.getLogger('dict2Anki.workers.QueryWorker') 97 | 98 | def __init__(self, wordList: [dict], api): 99 | super().__init__() 100 | self.wordList = wordList 101 | self.api = api 102 | 103 | def run(self): 104 | currentThread = QThread.currentThread() 105 | 106 | def _query(word, row): 107 | if currentThread.isInterruptionRequested(): 108 | return 109 | queryResult = self.api.query(word) 110 | if queryResult: 111 | self.logger.info(f'查询成功: {word} -- {queryResult}') 112 | self.thisRowDone.emit(row, queryResult) 113 | else: 114 | self.logger.warning(f'查询失败: {word}') 115 | self.thisRowFailed.emit(row) 116 | 117 | self.tick.emit() 118 | return queryResult 119 | 120 | with ThreadPool(max_workers=3) as executor: 121 | for word in self.wordList: 122 | executor.submit(_query, word['term'], word['row']) 123 | 124 | self.allQueryDone.emit() 125 | 126 | 127 | class AudioDownloadWorker(QObject): 128 | start = pyqtSignal() 129 | tick = pyqtSignal() 130 | done = pyqtSignal() 131 | logger = logging.getLogger('dict2Anki.workers.AudioDownloadWorker') 132 | retries = Retry(total=5, backoff_factor=3, status_forcelist=[500, 502, 503, 504]) 133 | session = requests.Session() 134 | session.mount('http://', HTTPAdapter(max_retries=retries)) 135 | session.mount('https://', HTTPAdapter(max_retries=retries)) 136 | 137 | def __init__(self, audios: [tuple]): 138 | super().__init__() 139 | self.audios = audios 140 | 141 | def run(self): 142 | currentThread = QThread.currentThread() 143 | 144 | def __download(fileName, url): 145 | try: 146 | if currentThread.isInterruptionRequested(): 147 | return 148 | r = self.session.get(url, stream=True) 149 | with open(fileName, 'wb') as f: 150 | for chunk in r.iter_content(chunk_size=1024): 151 | if chunk: 152 | f.write(chunk) 153 | self.logger.info(f'{fileName} 下载完成') 154 | aqt.mw.col.media.add_file(fileName) 155 | os.remove(fileName) 156 | self.logger.info(f"{fileName} 添加到媒体库,临时文件已删除") 157 | except Exception as e: 158 | self.logger.warning(f'下载{fileName}:{url}异常: {e}') 159 | finally: 160 | self.tick.emit() 161 | 162 | with ThreadPool(max_workers=3) as executor: 163 | for fileName, url in self.audios: 164 | executor.submit(__download, fileName, url) 165 | self.done.emit() 166 | -------------------------------------------------------------------------------- /anki_addon_page.tpl: -------------------------------------------------------------------------------- 1 | 2 | Dict2Anki 是一款方便有道词典欧陆词典用户同步生成单词本卡片至Anki的插件 3 | 4 | Change Logs: 5 | v6.1.5: 6 | 更新有道词典API,解决首次登录无法唤出登陆页的问题 7 | v6.1.4: 8 | 修复Anki 2.1.4版本同步失败的问题 THX to @YLongo 9 | 修复Anki 2.1.4版本首次同步默认到Default Deck的问题 10 | v6.1.3: 11 | 修复欧陆字典无法登录的问题 THX to @cythb 12 | v6.1.2 13 | 修复有道单词本分组获取失败的问题 14 | v6.1.1: 15 | 添加欧陆词典查询API THX to wd 16 | v6.1.0: 17 | 支持第三方登陆 18 | 加入模版字段检查 19 | v6.0.2: 20 | 添加英英注释 THX to deluser8 21 | v6.0.1: 22 | 修复菜单栏不雅词汇 23 | v6.0.0: 24 | 导入指定单词分组 25 | 添加必应(bing)词典查询API 26 | 添加待删除单词列表,可选择需要删除的 Anki 卡片 27 | 恢复卡片 短语字段 28 | 一些UI优化 29 | 重构代码,解决上版本奔溃问题 30 | 添加单元测试 31 | v5.0.2: 添加单词发音下载功能 32 | v5.0.1 解决欧陆词典单词数过大时产生的异常 33 | 34 | Features: 35 | 导入有道词典、欧陆词典生词本 36 | 检测词典软件的生词变化,并在Anki中相应的添加或删除删除卡片 37 | 获取图片、发音、注解、音标、短语、例句 38 | 39 | How to use: 40 | 同步 41 | 42 | 43 | 同步删除 44 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "deck": "", 3 | "selectedDict": 0, 4 | "selectedGroup": null, 5 | "selectedApi": 0, 6 | "credential": [ 7 | { 8 | "username": "", 9 | "password": "", 10 | "cookie": "" 11 | }, 12 | { 13 | "username": "", 14 | "password": "", 15 | "cookie": "" 16 | } 17 | ], 18 | "definition": true, 19 | "sentence": true, 20 | "image": true, 21 | "phrase": true, 22 | "AmEPhonetic": true, 23 | "BrEPhonetic": true, 24 | "BrEPron": false, 25 | "AmEPron": false, 26 | "noPron": true 27 | } 28 | -------------------------------------------------------------------------------- /deploy.py: -------------------------------------------------------------------------------- 1 | import os 2 | from zipfile import ZipFile 3 | 4 | from bs4 import BeautifulSoup 5 | from requests.sessions import Session 6 | 7 | from addon.constants import MODEL_NAME 8 | 9 | username = os.environ.get('ANKI_USERNAME') 10 | password = os.environ.get('ANKI_PASSWORD') 11 | addon_id = os.environ.get('ANKI_ADDON_ID') 12 | 13 | print(username) 14 | print(password) 15 | print(addon_id) 16 | 17 | 18 | def create_zip(): 19 | file_paths = [] 20 | exclude_dirs = ['test', '__pycache__', '.git', '.idea', '.pytest_cache', 'screenshots', 'venv'] 21 | exclude_files = ['README.md', '.gitignore', '.travis.yml', 'deploy.py', 'requirements.txt', '.DS_Store', 22 | 'meta.json'] 23 | exclude_ext = ['.png', '.ui', '.qrc', '.log', '.zip', '.tpl'] 24 | for dirname, sub_dirs, files in os.walk("."): 25 | for d in exclude_dirs: 26 | if d in sub_dirs: 27 | sub_dirs.remove(d) 28 | for f in exclude_files: 29 | if f in files: 30 | files.remove(f) 31 | for ext in exclude_ext: 32 | for f in files[:]: 33 | if f.endswith(ext): 34 | files.remove(f) 35 | for filename in files: 36 | file_paths.append(os.path.join(dirname, filename)) 37 | 38 | with ZipFile(f'{MODEL_NAME}.zip', 'w') as zf: 39 | for file in file_paths: 40 | zf.write(file) 41 | 42 | 43 | def update(title, tags, desc): 44 | s = Session() 45 | URL = 'https://ankiweb.net/account/login' 46 | rsp = s.get(URL) 47 | soup = BeautifulSoup(rsp.text, features="html.parser") 48 | csrf_token = soup.find('input', {'name': 'csrf_token'}).get('value') 49 | s.post(URL, data={'submit': 1, 'csrf_token': csrf_token, 'username': username, 'password': password}) 50 | 51 | URL = 'https://ankiweb.net/shared/upload' 52 | file = {'v21file': open(f'{MODEL_NAME}.zip', 'rb')} 53 | rsp = s.post(URL, files=file, data={ 54 | 'title': title, 55 | 'tags': tags, 56 | 'desc': desc, 57 | 'id': addon_id, 58 | 'submit': 'Update', 59 | 'v21file': file, 60 | 'v20file': '', 61 | }) 62 | if rsp.url == f'https://ankiweb.net/shared/info/{addon_id}': 63 | return True 64 | else: 65 | return False 66 | 67 | 68 | def main(): 69 | create_zip() 70 | # with open('anki_addon_page.tpl', encoding='utf-8') as tpl: 71 | # return update('Dict2Anki(有道,欧陆词典单词本同步工具)', '有道 欧陆 导入 同步', tpl.read()) 72 | 73 | 74 | if __name__ == '__main__': 75 | main() 76 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4==4.7.1 2 | PyQt5==5.9.2 3 | pytest==4.3.1 4 | pytest-mock==1.10.1 5 | pytest-qt==3.2.2 6 | requests==2.21.0 -------------------------------------------------------------------------------- /screenshots/del.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megachweng/Dict2Anki/4fe993d83d73e0a4ed3090330241d0a9de22b009/screenshots/del.gif -------------------------------------------------------------------------------- /screenshots/sync.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megachweng/Dict2Anki/4fe993d83d73e0a4ed3090330241d0a9de22b009/screenshots/sync.gif -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/megachweng/Dict2Anki/4fe993d83d73e0a4ed3090330241d0a9de22b009/test/__init__.py -------------------------------------------------------------------------------- /test/dummy_anki/__init__.py: -------------------------------------------------------------------------------- 1 | from . import dummy_notes 2 | 3 | notes = dummy_notes 4 | -------------------------------------------------------------------------------- /test/dummy_anki/dummy_collection.py: -------------------------------------------------------------------------------- 1 | from test.dummy_anki.dummy_deck import Deck 2 | from test.dummy_anki.dummy_notes import Note 3 | from test.dummy_anki.dummy_models import Model 4 | 5 | 6 | class Collection: 7 | decks = Deck 8 | models = Model 9 | 10 | @staticmethod 11 | def reset(): 12 | pass 13 | 14 | @staticmethod 15 | def remNotes(*args, **kwargs): 16 | pass 17 | 18 | @staticmethod 19 | def getNote(nid): 20 | return Note(nid) 21 | 22 | @staticmethod 23 | def findNotes(): 24 | return [] 25 | -------------------------------------------------------------------------------- /test/dummy_anki/dummy_deck.py: -------------------------------------------------------------------------------- 1 | class Deck: 2 | @staticmethod 3 | def id(*args, **kwargs): 4 | pass 5 | 6 | @staticmethod 7 | def get(*args, **kwargs): 8 | pass 9 | 10 | @staticmethod 11 | def reset(*args, **kwargs): 12 | pass 13 | 14 | @staticmethod 15 | def save(*args, **kwargs): 16 | pass 17 | -------------------------------------------------------------------------------- /test/dummy_anki/dummy_models.py: -------------------------------------------------------------------------------- 1 | class Model: 2 | @staticmethod 3 | def byName(*args, **kwargs): 4 | pass 5 | 6 | @staticmethod 7 | def new(*args, **kwargs): 8 | pass 9 | 10 | @staticmethod 11 | def addField(*args, **kwargs): 12 | pass 13 | 14 | @staticmethod 15 | def newField(*args, **kwargs): 16 | pass 17 | 18 | @staticmethod 19 | def update(*args, **kwargs): 20 | pass 21 | 22 | @staticmethod 23 | def newTemplate(*args, **kwargs): 24 | pass 25 | 26 | @staticmethod 27 | def addTemplate(*args, **kwargs): 28 | pass 29 | -------------------------------------------------------------------------------- /test/dummy_anki/dummy_notes.py: -------------------------------------------------------------------------------- 1 | class Note: 2 | 3 | def __init__(self, nid): 4 | self.nid = nid 5 | 6 | @staticmethod 7 | def model(): 8 | return dict() 9 | 10 | def __getitem__(self, item): 11 | pass 12 | 13 | def __setitem__(self, key, value): 14 | pass 15 | -------------------------------------------------------------------------------- /test/dummy_aqt/__init__.py: -------------------------------------------------------------------------------- 1 | from test.dummy_aqt.dummy_addon import AddonManager 2 | from test.dummy_anki.dummy_collection import Collection 3 | 4 | 5 | class mw: 6 | addonManager = AddonManager 7 | col = Collection 8 | 9 | @staticmethod 10 | def reset(): 11 | pass 12 | 13 | 14 | def askUser(*args, **kwargs): 15 | return True 16 | 17 | 18 | def showCritical(*args, **kwargs): 19 | pass 20 | 21 | 22 | def showInfo(*args, **kwargs): 23 | pass 24 | 25 | 26 | def tooltip(*args, **kwargs): 27 | pass 28 | 29 | 30 | def openLink(*args, **kwargs): 31 | pass 32 | -------------------------------------------------------------------------------- /test/dummy_aqt/dummyConfig.json: -------------------------------------------------------------------------------- 1 | {"selectedDict": 0, "selectedApi": 1, "selectedGroup": [["Anki Group"], []], "deck": "dummy", "definition": true, "sentence": false, "image": true, "phrase": false, "AmEPhonetic": true, "BrEPhonetic": false, "BrEPron": false, "AmEPron": false, "noPron": true, "credential": [{"username": "", "password": "", "cookie": "{\"EudicWeb\": \"724BC7A269EC57B1ADE1C3712E6F3AD93BDF1C2A2F0062583FC0B0277F9284EBEE40C7D08F5E81077F95D0068C9A622BD8B70238E4DC5A2FC89DD90CECDB135642ADA629DFD89AF6F63BAB18049CEE9B05D0104958331166CC2B7F65FD9C6742BD7C95DA2221D13DC0F7D653612867253C5FE7702539B51BD4D31C02A06E1BE09AEC2B38\", \"__cfduid\": \"d5c8c2830d8104d4026d3b49137f6b6991552664695\", \"ASP.NET_SessionId\": \"1md3x05xf0gap02lu5gq5ap1\", \"EudicWebSession\": \"QYNeyJ0b2tlbiI6InpKeVpOdldpYjdHYzdRdndYanAvd0dQWmVDMD0iLCJleHBpcmVpbiI6MTMxNDAwMCwidXNlcmlkIjoiYTMxOWU5OGQtYTBkZS0xMWU3LWFjODMtMDAwYzI5ZmZlZjliIiwidXNlcm5hbWUiOiJtZWdhY2h3ZW5nQDE2My5jb20iLCJjcmVhdGlvbl9kYXRlIjoiMjAxNy0wOS0yNFQwNDoxMjo1NFoiLCJyb2xlcyI6bnVsbCwib3BlbmlkX3R5cGUiOm51bGwsIm9wZW5pZF9kZXNjIjpudWxsLCJwcm9maWxlIjp7Im5pY2tuYW1lIjoiTUdDIiwiZW1haWwiOiJtZWdhY2h3ZW5nQDE2My5jb20iLCJnZW5kZXIiOiIiLCJwYXNzd29yZCI6bnVsbCwidm9jYWJ1bGFyaWVzIjp7fX19\"}"}, {"username": "", "password": "", "cookie": ""}]} -------------------------------------------------------------------------------- /test/dummy_aqt/dummy_addon.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | base = os.path.abspath(os.path.dirname(__file__)) 5 | configPath = os.path.join(base, 'dummyConfig.json') 6 | 7 | 8 | class AddonManager: 9 | @staticmethod 10 | def writeConfig(*args, **kwargs): 11 | with open(configPath, 'w') as fp: 12 | json.dump(args[1], fp) 13 | 14 | @staticmethod 15 | def getConfig(*args, **kwargs): 16 | with open(configPath) as fp: 17 | return json.load(fp) 18 | -------------------------------------------------------------------------------- /test/dummy_noteManager.py: -------------------------------------------------------------------------------- 1 | def getDeckList(): 2 | return ['deck1', 'deck2'] 3 | 4 | 5 | def getOrCreateDeck(deck_name): 6 | return deck_name 7 | 8 | 9 | def getOrCreateModel(modelName): 10 | return modelName 11 | 12 | 13 | def getOrCreateModelCardTemplate(modelObject, cardTemplateName): 14 | pass 15 | 16 | 17 | def addNoteToDeck(deckObject, modelObject, currentConfig: dict, oneQueryResult: dict): 18 | pass 19 | 20 | 21 | def getWordsByDeck(*args, **kwargs): 22 | return [] 23 | 24 | 25 | def getNotes(*args, **kwargs): 26 | return [] 27 | -------------------------------------------------------------------------------- /test/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts : --continue-on-collection-errors 3 | log_format = [%(levelname)s] %(message)s 4 | log_cli=true 5 | log_level=INFO -------------------------------------------------------------------------------- /test/test_main.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from PyQt5.QtCore import Qt 3 | 4 | from addon.addonWindow import Windows 5 | from addon.constants import VERSION 6 | import json 7 | from PyQt5.QtWidgets import QApplication 8 | import sys 9 | 10 | 11 | @pytest.fixture 12 | def fresh_config(): 13 | return json.loads('''{ 14 | "deck": "", 15 | "selectedDict": 0, 16 | "selectedGroup": null, 17 | "selectedApi": 0, 18 | "credential": [ 19 | { 20 | "username": "", 21 | "password": "", 22 | "cookie": "" 23 | }, 24 | { 25 | "username": "", 26 | "password": "", 27 | "cookie": "" 28 | } 29 | ], 30 | "definition": true, 31 | "sentence": true, 32 | "image": true, 33 | "phrase": true, 34 | "AmEPhonetic": true, 35 | "BrEPhonetic": true, 36 | "BrEPron": false, 37 | "AmEPron": true, 38 | "noPron": false 39 | }''') 40 | 41 | 42 | @pytest.fixture(autouse=True) 43 | def no_requests(monkeypatch): 44 | # monkeypatch.delattr("requests.sessions.Session.request") 45 | pass 46 | 47 | 48 | @pytest.fixture(scope='function') 49 | def window(qtbot): 50 | event_loop = QApplication(sys.argv) 51 | w = Windows() 52 | qtbot.addWidget(w) 53 | qtbot.wait(500) 54 | yield w 55 | 56 | 57 | @pytest.mark.skip 58 | def test_start_up_with_fresh_config(qtbot, mocker, fresh_config): 59 | app = QApplication(sys.argv) 60 | mocked_getConfig = mocker.patch('addon.addonWindow.mw.addonManager.getConfig', return_value=fresh_config) 61 | w = Windows() 62 | qtbot.addWidget(w) 63 | qtbot.wait(200) 64 | assert VERSION in w.windowTitle() 65 | assert w.workerThread.isRunning() 66 | mocked_getConfig.assert_called() 67 | assert w.usernameLineEdit.text() == w.passwordLineEdit.text() == w.cookieLineEdit.text() == '' 68 | 69 | 70 | @pytest.mark.skip 71 | def test_version_check(qtbot, mocker, monkeypatch): 72 | mocked_VersionCheckWorker_run = mocker.patch('addon.addonWindow.VersionCheckWorker.run') 73 | mocked_askUser = mocker.patch('addon.addonWindow.askUser') 74 | app = QApplication(sys.argv) 75 | w = Windows() 76 | qtbot.addWidget(w) 77 | qtbot.waitUntil(w.updateCheckThead.isRunning) 78 | mocked_VersionCheckWorker_run.assert_called() 79 | w.updateCheckWork.haveNewVersion.emit('xxx', 'yyy') 80 | qtbot.wait(100) 81 | mocked_askUser.assert_called_with(f'有新版本:xxx是否更新?\n\nyyy') 82 | 83 | 84 | @pytest.mark.skip 85 | @pytest.mark.parametrize('index', [0, 1]) 86 | def test_dictionary_combobox_change(qtbot, index, mocker, fresh_config): 87 | fresh_config['credential'] = [{'username': '0', 'password': '0', 'cookie': '0'}, 88 | {'username': '1', 'password': '1', 'cookie': '1'}] 89 | mocker.patch('addon.addonWindow.mw.addonManager.getConfig', return_value=fresh_config) 90 | app = QApplication(sys.argv) 91 | w = Windows() 92 | qtbot.addWidget(w) 93 | qtbot.wait(500) 94 | w.dictionaryComboBox.setCurrentIndex(index) 95 | assert w.dictionaryComboBox.currentText() in w.currentDictionaryLabel.text() 96 | # assert w.usernameLineEdit.text() == fresh_config['credential'][index]['username'] 97 | # assert w.passwordLineEdit.text() == fresh_config['credential'][index]['password'] 98 | assert w.cookieLineEdit.text() == fresh_config['credential'][index]['cookie'] 99 | 100 | 101 | @pytest.mark.skip 102 | def test_get_deck_list(qtbot, fresh_config, mocker): 103 | fresh_config['deck'] = 'b' 104 | mocker.patch('addon.addonWindow.mw.addonManager.getConfig', return_value=fresh_config) 105 | mocker.patch('addon.addonWindow.getDeckList', return_value=['a', 'b', 'c']) 106 | app = QApplication(sys.argv) 107 | w = Windows() 108 | qtbot.addWidget(w) 109 | qtbot.wait(200) 110 | assert [w.deckComboBox.itemText(row) for row in range(w.deckComboBox.count())] == ['a', 'b', 'c'] 111 | assert w.deckComboBox.currentText() == 'b' 112 | 113 | 114 | @pytest.mark.skip 115 | @pytest.mark.parametrize('words', [ 116 | ['a', 'b', 'c', 'd'], 117 | [] 118 | ]) 119 | def test_newWordWidget(window, words): 120 | window.insertWordToListWidget(words) 121 | assert [window.newWordListWidget.item(row).text() for row in range(window.newWordListWidget.count())] == words 122 | assert all( 123 | window.newWordListWidget.item(row).data(Qt.UserRole) is None for row in range(window.newWordListWidget.count())) 124 | 125 | 126 | @pytest.mark.skip 127 | @pytest.mark.parametrize('local_words,remote_words,test_index', [ 128 | ([], [], 0), 129 | ([], ['a', 'b'], 1), 130 | (['a'], ['a'], 2), 131 | (['a'], ['a', 'b'], 3), 132 | (['a', 'b'], ['c', 'd'], 4), 133 | (['a', 'b'], ['c', 'b'], 5), 134 | ]) 135 | def test_fetch_word_and_compare(monkeypatch, mocker, window, qtbot, local_words, remote_words, test_index): 136 | mocker.patch('addon.dictionary.eudict.Eudict.getWordsByPage', return_value=remote_words) 137 | mocker.patch('addon.dictionary.eudict.Eudict.getTotalPage', return_value=1) 138 | mocker.patch('addon.addonWindow.getWordsByDeck', return_value=local_words) 139 | mocked_tooltip = mocker.patch('addon.addonWindow.tooltip') 140 | from addon.dictionary.eudict import Eudict 141 | window.selectedDict = Eudict 142 | window.selectedDict.groups = [('group_1', 'group_1_id')] 143 | qtbot.waitUntil(window.workerThread.isRunning, timeout=5000) 144 | window.getRemoteWordList(['group_1']) 145 | qtbot.wait(1000) 146 | item_in_list_widget = [window.newWordListWidget.item(row) for row in range(window.newWordListWidget.count())] 147 | item_in_del_widget = [window.needDeleteWordListWidget.item(row) for row in 148 | range(window.needDeleteWordListWidget.count())] 149 | words_in_list_widget = [i.text() for i in item_in_list_widget] 150 | words_in_del_widget = [i.text() for i in item_in_del_widget] 151 | 152 | assert all([item.data(Qt.UserRole) is None for item in item_in_list_widget]) 153 | if test_index == 0: 154 | assert item_in_list_widget == [] 155 | assert item_in_del_widget == [] 156 | assert mocked_tooltip.called_with('无需同步') 157 | elif test_index == 1: 158 | assert sorted(words_in_list_widget) == sorted(remote_words) 159 | assert item_in_del_widget == [] 160 | elif test_index == 2: 161 | assert item_in_list_widget == [] 162 | assert item_in_del_widget == [] 163 | assert mocked_tooltip.called_with('无需同步') 164 | elif test_index == 3: 165 | assert words_in_list_widget == ['b'] 166 | assert item_in_del_widget == [] 167 | elif test_index == 4: 168 | assert sorted(words_in_list_widget) == sorted(remote_words) 169 | assert sorted(words_in_del_widget) == sorted(local_words) 170 | elif test_index == 5: 171 | assert words_in_list_widget == ['c'] 172 | assert words_in_del_widget == ['a'] 173 | -------------------------------------------------------------------------------- /test/test_queryapi.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | from addon.queryApi.eudict import API 4 | import pytest 5 | logger = logging.getLogger(__name__) 6 | api = API() 7 | 8 | keys = ('term', 'definition', 'phrase', 'image', 'sentence', 'BrEPhonetic', 'AmEPhonetic', 'BrEPron', 'AmEPron') 9 | 10 | 11 | def get_missing_fileds_set(res): 12 | ret = [] 13 | for key in keys: 14 | if not res.get(key): 15 | ret.append(key) 16 | return set(ret) 17 | 18 | 19 | def test_eudict_no_phrase_and_image(): 20 | res = api.query('stint') 21 | ret = get_missing_fileds_set(res) 22 | expect = {'image', 'phrase'} 23 | assert ret == expect 24 | 25 | 26 | def test_eudict_with_all(): 27 | res = api.query('flower') 28 | ret = get_missing_fileds_set(res) 29 | assert ret == set() 30 | 31 | 32 | def test_eudict_with_none(): 33 | res = api.query('asafesdf') 34 | ret = get_missing_fileds_set(res) 35 | assert ret == set(keys) - {'term'} 36 | 37 | 38 | def test_eudict_implication(): 39 | # 不包含图片,定义不在正常规则内,包含 trans 40 | res = api.query('implication') 41 | ret = get_missing_fileds_set(res) 42 | expect = {'image'} 43 | assert ret == expect 44 | 45 | 46 | def test_eudict_epitomize(): 47 | # 不包含图片,定义不在正常规则内 48 | res = api.query('epitomize') 49 | ret = get_missing_fileds_set(res) 50 | expect = {'image', 'phrase'} 51 | assert ret == expect 52 | 53 | 54 | def test_eudict_periodical(): 55 | # 包含图片,定义不在正常规则内 56 | res = api.query('periodical') 57 | ret = get_missing_fileds_set(res) 58 | assert ret == set() 59 | 60 | 61 | def test_eudict_divisional(): 62 | # 又一种特殊情况,只有一个音标 63 | res = api.query('divisional') 64 | ret = get_missing_fileds_set(res) 65 | expect = {'image', 'AmEPhonetic'} 66 | assert expect == ret 67 | 68 | 69 | @pytest.mark.skipif("TRAVIS" in os.environ and os.environ["TRAVIS"] == "true", reason="Travis中查询结果没有image字段") 70 | def test_eudict_image_url_without_https(): 71 | res = api.query('gelatin') 72 | assert res['image'].startswith('https://') 73 | --------------------------------------------------------------------------------