Repository: GoAdminGroup/go-admin Branch: main Commit: c47763c7bb63 Files: 368 Total size: 2.9 MB Directory structure: gitextract_hu_9kfne/ ├── .deepsource.toml ├── .drone.yml ├── .github/ │ ├── FUNDING.yml │ └── ISSUE_TEMPLATE/ │ ├── bug_report.md │ ├── bug_report_zh.md │ ├── proposal.md │ ├── proposal_zh.md │ ├── questions.md │ └── questions_zh.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CONTRIBUTING_CN.md ├── DONATION.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── README_CN.md ├── SECURITY.md ├── adapter/ │ ├── adapter.go │ ├── beego/ │ │ └── beego.go │ ├── beego2/ │ │ └── beego2.go │ ├── buffalo/ │ │ └── buffalo.go │ ├── chi/ │ │ └── chi.go │ ├── echo/ │ │ └── echo.go │ ├── fasthttp/ │ │ └── fasthttp.go │ ├── gear/ │ │ └── gear.go │ ├── gf/ │ │ └── gf.go │ ├── gf2/ │ │ └── gf2.go │ ├── gin/ │ │ └── gin.go │ ├── gofiber/ │ │ └── gofiber.go │ ├── gorilla/ │ │ └── gorilla.go │ ├── iris/ │ │ └── iris.go │ └── nethttp/ │ └── nethttp.go ├── context/ │ ├── context.go │ ├── context_test.go │ └── trie.go ├── data/ │ ├── admin.mssql │ ├── admin.pgsql │ ├── admin.sql │ └── migrations/ │ ├── admin_2020_04_14_100427_ms.sql │ ├── admin_2020_04_14_100427_mysql.sql │ ├── admin_2020_04_14_100427_postgres.sql │ ├── admin_2020_04_14_100427_sqlite.sql │ ├── admin_2020_08_04_092427_ms.sql │ ├── admin_2020_08_04_092427_mysql.sql │ ├── admin_2020_08_04_092427_postgres.sql │ └── admin_2020_08_04_092427_sqlite.sql ├── docker-compose.yml ├── engine/ │ └── engine.go ├── examples/ │ ├── beego/ │ │ └── main.go │ ├── beego2/ │ │ └── main.go │ ├── buffalo/ │ │ └── main.go │ ├── chi/ │ │ └── main.go │ ├── datamodel/ │ │ ├── authors.go │ │ ├── bootstrap.go │ │ ├── config.json │ │ ├── content.go │ │ ├── goadmin_super_users.go │ │ ├── mysql_types.go │ │ ├── posts.go │ │ ├── tables.go │ │ └── user.go │ ├── echo/ │ │ └── main.go │ ├── fasthttp/ │ │ └── main.go │ ├── gear/ │ │ └── main.go │ ├── gf/ │ │ └── main.go │ ├── gf2/ │ │ └── main.go │ ├── gin/ │ │ └── main.go │ ├── gofiber/ │ │ └── main.go │ ├── gorilla/ │ │ └── main.go │ ├── iris/ │ │ └── main.go │ └── nethttp/ │ └── main.go ├── go.mod ├── go.sum ├── modules/ │ ├── auth/ │ │ ├── auth.go │ │ ├── auth_test.go │ │ ├── middleware.go │ │ ├── middleware_test.go │ │ └── session.go │ ├── collection/ │ │ ├── collection.go │ │ └── collection_test.go │ ├── config/ │ │ ├── config.go │ │ ├── config.ini │ │ ├── config.yaml │ │ └── config_test.go │ ├── constant/ │ │ └── constant.go │ ├── db/ │ │ ├── base.go │ │ ├── connection.go │ │ ├── converter.go │ │ ├── dialect/ │ │ │ ├── common.go │ │ │ ├── dialect.go │ │ │ ├── mssql.go │ │ │ ├── mysql.go │ │ │ ├── oceanbase.go │ │ │ ├── postgresql.go │ │ │ └── sqlite.go │ │ ├── drivers/ │ │ │ ├── mssql/ │ │ │ │ └── mssql.go │ │ │ ├── mysql/ │ │ │ │ └── mysql.go │ │ │ ├── oceanbase/ │ │ │ │ └── oceanbase.go │ │ │ ├── postgres/ │ │ │ │ └── postgres.go │ │ │ └── sqlite/ │ │ │ └── sqlite.go │ │ ├── mssql.go │ │ ├── mysql.go │ │ ├── oceanbase.go │ │ ├── performer.go │ │ ├── postgresql.go │ │ ├── sqlite.go │ │ ├── statement.go │ │ ├── statement_mssql_test.go │ │ ├── statement_mysql_test.go │ │ ├── statement_postgresql_test.go │ │ ├── statement_sqlite_test.go │ │ ├── statement_test.go │ │ ├── types.go │ │ └── types_test.go │ ├── errors/ │ │ └── error.go │ ├── file/ │ │ ├── file.go │ │ └── local.go │ ├── language/ │ │ ├── cn.go │ │ ├── en.go │ │ ├── jp.go │ │ ├── language.go │ │ ├── language_test.go │ │ ├── pt-BR.go │ │ ├── ru.go │ │ └── tc.go │ ├── logger/ │ │ ├── logger.go │ │ └── logger_test.go │ ├── menu/ │ │ ├── menu.go │ │ └── menu_test.go │ ├── page/ │ │ └── page.go │ ├── remote_server/ │ │ └── remote_server.go │ ├── service/ │ │ └── service.go │ ├── system/ │ │ ├── application.go │ │ └── version.go │ ├── trace/ │ │ └── trace.go │ ├── ui/ │ │ └── ui.go │ └── utils/ │ ├── utils.go │ └── utils_test.go ├── plugins/ │ ├── admin/ │ │ ├── admin.go │ │ ├── controller/ │ │ │ ├── Update.go │ │ │ ├── api_create.go │ │ │ ├── api_detail.go │ │ │ ├── api_list.go │ │ │ ├── api_update.go │ │ │ ├── auth.go │ │ │ ├── common.go │ │ │ ├── common_test.go │ │ │ ├── delete.go │ │ │ ├── detail.go │ │ │ ├── edit.go │ │ │ ├── handler.go │ │ │ ├── install.go │ │ │ ├── menu.go │ │ │ ├── new.go │ │ │ ├── operation.go │ │ │ ├── plugins.go │ │ │ ├── plugins_tmpl.go │ │ │ ├── show.go │ │ │ └── system.go │ │ ├── data/ │ │ │ └── mysql/ │ │ │ └── admin.sql │ │ ├── models/ │ │ │ ├── base.go │ │ │ ├── menu.go │ │ │ ├── operation_log.go │ │ │ ├── permission.go │ │ │ ├── role.go │ │ │ ├── site.go │ │ │ └── user.go │ │ ├── modules/ │ │ │ ├── captcha/ │ │ │ │ └── captcha.go │ │ │ ├── constant/ │ │ │ │ └── constant.go │ │ │ ├── form/ │ │ │ │ └── form.go │ │ │ ├── guard/ │ │ │ │ ├── delete.go │ │ │ │ ├── edit.go │ │ │ │ ├── export.go │ │ │ │ ├── guard.go │ │ │ │ ├── menu_delete.go │ │ │ │ ├── menu_edit.go │ │ │ │ ├── menu_new.go │ │ │ │ ├── new.go │ │ │ │ ├── server_login.go │ │ │ │ └── update.go │ │ │ ├── helper.go │ │ │ ├── helper_test.go │ │ │ ├── paginator/ │ │ │ │ ├── paginator.go │ │ │ │ └── paginator_test.go │ │ │ ├── parameter/ │ │ │ │ ├── parameter.go │ │ │ │ └── parameter_test.go │ │ │ ├── response/ │ │ │ │ └── response.go │ │ │ ├── table/ │ │ │ │ ├── config.go │ │ │ │ ├── default.go │ │ │ │ ├── default_test.go │ │ │ │ ├── generators.go │ │ │ │ ├── table.go │ │ │ │ ├── tmpl/ │ │ │ │ │ ├── choose_table_ajax.tmpl │ │ │ │ │ └── generator.tmpl │ │ │ │ └── tmpl.go │ │ │ └── tools/ │ │ │ ├── generator.go │ │ │ └── template.go │ │ └── router.go │ ├── example/ │ │ ├── controller.go │ │ ├── example.go │ │ ├── go_plugin/ │ │ │ ├── Makefile │ │ │ └── main.go │ │ └── router.go │ ├── plugins.go │ └── plugins_test.go ├── template/ │ ├── chartjs/ │ │ ├── assets.go │ │ ├── assets_list.go │ │ ├── bar.go │ │ ├── chart.go │ │ ├── chartjs.tmpl │ │ ├── line.go │ │ ├── pie.go │ │ ├── radar.go │ │ └── template.go │ ├── color/ │ │ └── color.go │ ├── components/ │ │ ├── alert.go │ │ ├── base.go │ │ ├── box.go │ │ ├── button.go │ │ ├── col.go │ │ ├── composer.go │ │ ├── form.go │ │ ├── image.go │ │ ├── label.go │ │ ├── link.go │ │ ├── paninator.go │ │ ├── popup.go │ │ ├── product.go │ │ ├── row.go │ │ ├── table.go │ │ ├── tabs.go │ │ ├── tree.go │ │ └── treeview.go │ ├── icon/ │ │ └── icon.go │ ├── installation/ │ │ ├── Makefile │ │ ├── assets/ │ │ │ └── src/ │ │ │ ├── css/ │ │ │ │ ├── main.css │ │ │ │ └── noscript.css │ │ │ ├── fonts/ │ │ │ │ └── FontAwesome.otf │ │ │ └── js/ │ │ │ └── main.js │ │ ├── assets.go │ │ ├── assets_list.go │ │ ├── installation.go │ │ ├── installation.tmpl │ │ └── template.go │ ├── login/ │ │ ├── Makefile │ │ ├── assets/ │ │ │ └── src/ │ │ │ ├── css/ │ │ │ │ ├── 0_font.css │ │ │ │ ├── 2_animate.css │ │ │ │ └── 3_style.css │ │ │ └── js/ │ │ │ └── combine/ │ │ │ ├── 3_particles.js │ │ │ └── 4_main.js │ │ ├── assets.go │ │ ├── assets_list.go │ │ ├── login.go │ │ ├── login.tmpl │ │ └── template.go │ ├── template.go │ ├── template_test.go │ └── types/ │ ├── action/ │ │ ├── ajax.go │ │ ├── base.go │ │ ├── event.go │ │ ├── fieldfilter.go │ │ ├── file_upload.go │ │ ├── jump.go │ │ ├── jump_selectbox.go │ │ └── popup.go │ ├── button.go │ ├── components.go │ ├── display/ │ │ ├── base.go │ │ ├── bool.go │ │ ├── carousel.go │ │ ├── copy.go │ │ ├── date.go │ │ ├── dot.go │ │ ├── downloadable.go │ │ ├── filesize.go │ │ ├── icon.go │ │ ├── image.go │ │ ├── label.go │ │ ├── link.go │ │ ├── loading.go │ │ ├── progressbar.go │ │ └── qrcode.go │ ├── display.go │ ├── display_test.go │ ├── form/ │ │ ├── form.go │ │ ├── form_test.go │ │ └── select/ │ │ └── select.go │ ├── form.go │ ├── form_test.go │ ├── info.go │ ├── info_test.go │ ├── operators.go │ ├── operators_test.go │ ├── page.go │ ├── select.go │ ├── size.go │ ├── table/ │ │ └── table.go │ ├── tmpl.go │ └── tmpls/ │ ├── choose.tmpl │ ├── choose_ajax.tmpl │ ├── choose_custom.tmpl │ ├── choose_disable.tmpl │ ├── choose_hide.tmpl │ ├── choose_map.tmpl │ └── choose_show.tmpl └── tests/ ├── common/ │ ├── api.go │ ├── auth.go │ ├── checklist.md │ ├── common.go │ ├── config.json │ ├── config_ms.json │ ├── config_pg.json │ ├── config_sqlite.json │ ├── external.go │ ├── manager.go │ ├── menu.go │ ├── normal.go │ ├── operation_log.go │ ├── permission.go │ └── role.go ├── data/ │ ├── admin.sql │ ├── admin_ms.bak │ ├── admin_ms.sql │ └── admin_pg.sql ├── frameworks/ │ ├── beego/ │ │ ├── beego.go │ │ └── beego_test.go │ ├── beego2/ │ │ ├── beego.go │ │ └── beego_test.go │ ├── buffalo/ │ │ ├── buffalo.go │ │ └── buffalo_test.go │ ├── chi/ │ │ ├── chi.go │ │ └── chi_test.go │ ├── echo/ │ │ ├── echo.go │ │ └── echo_test.go │ ├── fasthttp/ │ │ ├── fasthttp.go │ │ └── fasthttp_test.go │ ├── gear/ │ │ ├── gear.go │ │ └── gear_test.go │ ├── gf/ │ │ ├── gf.go │ │ └── gf_test.go │ ├── gf2/ │ │ ├── gf.go │ │ └── gf_test.go │ ├── gin/ │ │ ├── gin.go │ │ └── gin_test.go │ ├── gofiber/ │ │ ├── gofiber.go │ │ └── gofiber_test.go │ ├── gorilla/ │ │ ├── gorilla.go │ │ └── gorilla_test.go │ ├── iris/ │ │ ├── iris.go │ │ └── iris_test.go │ └── nethttp/ │ ├── nethttp.go │ └── nethttp_test.go ├── tables/ │ ├── authors.go │ ├── content.go │ ├── external.go │ ├── posts.go │ ├── tables.go │ └── user.go ├── test.go ├── test_test.go └── web/ ├── README_CN.md ├── config.json ├── page.go ├── test.go └── web_test.go ================================================ FILE CONTENTS ================================================ ================================================ FILE: .deepsource.toml ================================================ version = 1 [[analyzers]] name = "go" enabled = true [analyzers.meta] import_paths = ["github.com/GoAdminGroup/go-admin"] ================================================ FILE: .drone.yml ================================================ --- kind: pipeline type: docker name: api_mysql trigger: event: - pull_request clone: disable: true services: - name: db_mysql image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: go-admin-test steps: - name: api image: chg80333/goadmin-test:v9 environment: GO111MODULE: on GOPROXY: https://goproxy.cn commands: - cd /go/src/github.com/GoAdminGroup/go-admin - git pull - git fetch origin pull/$DRONE_PULL_REQUEST/head:pr$DRONE_PULL_REQUEST - git checkout pr$DRONE_PULL_REQUEST - go version - sleep 80 - GOPROXY=https://goproxy.cn make mysql-test # --- # kind: pipeline # type: docker # name: api_mssql # trigger: # event: # - pull_request # clone: # disable: true # volumes: # - name: data # temp: {} # services: # - name: db_mssql # image: mcr.microsoft.com/mssql/server:2017-latest # volumes: # - name: data # path: /home/data # environment: # ACCEPT_EULA: Y # SA_PASSWORD: Aa123456 # steps: # - name: api # image: chg80333/goadmin-test:v9 # volumes: # - name: data # path: /go/src/github.com/GoAdminGroup/go-admin/tests/data # environment: # GO111MODULE: on # GOPROXY: https://goproxy.cn # commands: # - cd /go/src/github.com/GoAdminGroup/go-admin # - git pull # - git fetch origin pull/$DRONE_PULL_REQUEST/head:pr$DRONE_PULL_REQUEST # - git checkout pr$DRONE_PULL_REQUEST # - go version # - sleep 80 # - GOPROXY=https://goproxy.cn make ms-test --- kind: pipeline type: docker name: api_postgres trigger: event: - pull_request clone: disable: true services: - name: db_pgsql image: postgres:10 environment: POSTGRES_USER: postgres POSTGRES_DB: go-admin-test POSTGRES_PASSWORD: root steps: - name: api image: chg80333/goadmin-test:v9 environment: GO111MODULE: on GOPROXY: https://goproxy.cn commands: - cd /go/src/github.com/GoAdminGroup/go-admin - git pull - git fetch origin pull/$DRONE_PULL_REQUEST/head:pr$DRONE_PULL_REQUEST - git checkout pr$DRONE_PULL_REQUEST - go version - sleep 80 - GOPROXY=https://goproxy.cn make pg-test --- kind: pipeline type: docker name: api_sqlite trigger: event: - pull_request clone: disable: true steps: - name: api image: chg80333/goadmin-test:v9 environment: GO111MODULE: on GOPROXY: https://goproxy.cn commands: - cd /go/src/github.com/GoAdminGroup/go-admin - git pull - git fetch origin pull/$DRONE_PULL_REQUEST/head:pr$DRONE_PULL_REQUEST - git checkout pr$DRONE_PULL_REQUEST - go version - sleep 80 - GOPROXY=https://goproxy.cn make sqlite-test --- kind: pipeline type: docker name: frontend trigger: event: - pull_request clone: disable: true services: - name: db_mysql image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: go-admin-test steps: - name: chrome image: chg80333/goadmin-test:v9 environment: GO111MODULE: on GOPROXY: https://goproxy.cn commands: - cd /go/src/github.com/GoAdminGroup/go-admin - git pull - git fetch origin pull/$DRONE_PULL_REQUEST/head:pr$DRONE_PULL_REQUEST - git checkout pr$DRONE_PULL_REQUEST - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & - sleep 8 - GOPROXY=https://goproxy.cn make web-test ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: patreon: open_collective: go-admin ko_fi: tidelift: community_bridge: liberapay: issuehunt: otechie: custom: ['https://www.paypal.me/cg80333'] ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: "[BUG]" labels: "\U0001F41Bbug" assignees: '' --- ### Bug Description [describe the bug in detail] ### How to reproduce [describe the steps how to reproduce the bug] ### Expect [describe your expect result] ### Reproduction code [here to show your codes or examples] ### Versions - GoAdmin version: [e.g. 1.0.0] - golang version - Browser - OS [e.g. mac OS] ### Others [screenshots or others info here] ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report_zh.md ================================================ --- name: Bug 报告 about: 提交bug帮助我们修复 title: "[BUG]" labels: "\U0001F41Bbug" assignees: '' --- ### bug 描述 [详细地描述 bug,让大家都能理解] ### 复现步骤 [清晰描述复现步骤,让别人也能看到问题] ### 期望结果 [描述你原本期望看到的结果] ### 复现代码 [提供可复现的代码,仓库,或线上示例] ### 版本信息: - GoAdmin 版本: - golang 版本: - 浏览器环境: - 开发环境: ### 其他信息 [如截图等其他信息可以贴在这里] ================================================ FILE: .github/ISSUE_TEMPLATE/proposal.md ================================================ --- name: Proposal about: Any advice for GoAdmin title: "[Proposal]" labels: '' assignees: '' --- ### Description [describe your advice] ### Solution [if any solutions, describe here] ### Others [screenshots and other info] ================================================ FILE: .github/ISSUE_TEMPLATE/proposal_zh.md ================================================ --- name: 功能需求 about: 对 GoAdmin 的需求或建议 title: "[Proposal]" labels: '' assignees: '' --- ### 需求描述 [详细地描述需求,让大家都能理解] ### 解决方案 [如果你有解决方案,在这里清晰地阐述] ### 其他信息 [如截图等其他信息可以贴在这里] ================================================ FILE: .github/ISSUE_TEMPLATE/questions.md ================================================ --- name: Questions about: Any questions when using GoAdmin title: "[Question]" labels: '' assignees: '' --- ### Description [describe your questions] ### Example code [If you have any code info] ### Others [screenshots or other info] ================================================ FILE: .github/ISSUE_TEMPLATE/questions_zh.md ================================================ --- name: 疑问或需要帮助 ❓ about: 关于 GoAdmin 的问题 title: "[Question]" labels: '' assignees: '' --- ### 问题描述 [详细地描述问题,让大家都能理解] ### 示例代码 [如果有必要,展示代码,线上示例,或仓库] ### 其他信息 [如截图等其他信息可以贴在这里] ================================================ FILE: .gitignore ================================================ .idea .vscode .DS_Store demo/config.json demo/config demo/deploy.yml demo/hosts demo/go-admin demo/Makefile demo/deploy.retry vendor/** !vendor/vendor.json logs adm/build template/login/assets/login uploads ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: - Using welcoming and inclusive language - Being respectful of differing viewpoints and experiences - Gracefully accepting constructive criticism - Focusing on what is best for the community - Showing empathy towards other community members Examples of unacceptable behavior by participants include: - The use of sexualized language or imagery and unwelcome sexual attention or advances - Trolling, insulting/derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or electronic address, without explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at chg80333@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing If you want to contribute, but not sure what to do, here's a list of things that I always need help with: * Translations * README.md * [docs](https://github.com/GoAdminGroup/docs/issues/1) * Bug-hunting * Finding security problems * Themes and Plugins See [manual](https://github.com/GoAdminGroup/go-admin/projects/3) for more information. You can view all open issues on github, which is usually a good starting point if you want to start contributing: https://github.com/search?q=org%3AGoAdminGroup+is%3Aopen+is%3Aissue+archived%3Afalse&type=Issues ## how to GoAdmin uses GitHub to manage reviews of pull requests: - If you have a trivial fix or improvement, go ahead and create a pull request. - If you plan to do something more involved, discuss your ideas on the relevant GitHub issue. For now, you need to add your fork as a remote on the original **\$GOPATH**/src/github.com/GoAdminGroup/go-admin clone, so: ```bash $ go get github.com/GoAdminGroup/go-admin $ cd $GOPATH/src/github.com/GoAdminGroup/go-admin # GOPATH is $HOME/go by default. $ git remote add ``` And before you commit, remember to execute the command: ``` make test ``` See the Makefile for more details. Notice: `go get` return `package github.com/GoAdminGroup/go-admin: no Go files in /go/src/github.com/GoAdminGroup/go-admin` is normal. ### Dependency management We uses [Go modules](https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more) to manage dependencies on external packages. This requires a working Go environment with version 1.13 or greater and git installed. To add or update a new dependency, use the `go get` command: ```bash # Pick the latest tagged release. go get example.com/some/module/pkg # Pick a specific version. go get example.com/some/module/pkg@vX.Y.Z ``` Tidy up the `go.mod` and `go.sum` files: ```bash go mod tidy go mod vendor git add go.mod go.sum vendor git commit ``` You have to commit the changes to `go.mod` and `go.sum` before submitting the pull request. # Support You can also donate or become a patreon, which helps out covering server costs and potentially make it possible to put out bounties: * **Support on [Open Collective](https://opencollective.com/go-admin)** * Donate via [PayPal](https://paypal.me/cg80333) # Members If you are a member of the official GoAdmin developer Team: * [Discussions](http://forum.go-admin.cn) * [Tasks](https://github.com/GoAdminGroup/go-admin/projects) * [Chat](https://t.me/joinchat/NlyH6Bch2QARZkArithKvg) ================================================ FILE: CONTRIBUTING_CN.md ================================================ # 贡献 如果你想要对项目作出贡献,却不知道怎么做,下面有一些帮助: * 翻译 * README.md * [docs](https://github.com/GoAdminGroup/docs/issues/1) * 寻找BUG * 寻找安全问题 * 主题和插件 在这里:[功能规划](https://github.com/GoAdminGroup/go-admin/projects/3) 可以获得更多信息。 你也可以看一下所有开放的issues,从这里去入手: https://github.com/search?q=org%3AGoAdminGroup+is%3Aopen+is%3Aissue+archived%3Afalse&type=Issues ## 如何做贡献 GoAdmin 使用 GitHub 来管理项目代码: - 如果你发现一些微不足道的fix或者功能增加,直接提pr即可; - 如果你有一些提议,那么你可以先开一个issue进行讨论; 然后,你需要fork远程的master分支到你本地 **\$GOPATH**/src/github.com/GoAdminGroup/go-admin : ```bash $ go get github.com/GoAdminGroup/go-admin $ cd $GOPATH/src/github.com/GoAdminGroup/go-admin # GOPATH is $HOME/go by default. $ git remote add ``` 在你提交代码之前,记得执行下面这个命令: ``` make test ``` 看根目录下的```Makefile```获得更多信息。 注意了: `go get` 返回 `package github.com/GoAdminGroup/go-admin: no Go files in /go/src/github.com/GoAdminGroup/go-admin` 是正常的。 ### 依赖管理 我们使用 [Go modules](https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more) 来管理依赖。 这需要 golang 版本大于1.11,以及安装了 git 要增加或更新依赖,就使用 `go get` 命令: ```bash # Pick the latest tagged release. go get example.com/some/module/pkg # Pick a specific version. go get example.com/some/module/pkg@vX.Y.Z ``` 整理好 `go.mod` 和 `go.sum`: ```bash go mod tidy go mod vendor git add go.mod go.sum vendor git commit ``` 直接提交 `go.mod` and `go.sum` 的修改。 # 赞助 你可以捐助或参与众筹来帮助我们维护服务器费用,以及提供一些奖金资助项目发展。 * **Support on [Open Collective](https://opencollective.com/go-admin)** * Donate via [PayPal](https://paypal.me/cg80333) # 成员 如果你已经是GoAdmin的官方开发组成员: * [Discussions](http://forum.go-admin.cn) * [Tasks](https://github.com/GoAdminGroup/go-admin/projects) * [Chat](https://t.me/joinchat/NlyH6Bch2QARZkArithKvg) ================================================ FILE: DONATION.md ================================================ # Donation List 捐赠名单(排名不分先后) ================================================ FILE: Dockerfile ================================================ # This file describes the standard way to build GoAdmin develop env image, and using container # # Usage: # # # Assemble the code dev environment, get related database tools in docker-compose.yml, It is slow the first time. # docker build -t goadmin:1.0 . # # # Mount your source code to container for quick developing: # docker run -v `pwd`:/home/goadmin --name -d goadmin:1.0 # docker exec -it goadmin /bin/bash # # if your local code has been changed ,you can restart the container to take effect # docker restart goadmin # FROM golang:latest MAINTAINER josingcjx COPY . /home/goadmin ENV GOPATH=$GOPATH:/home/goadmin/ GOPROXY=https://mirrors.aliyun.com/goproxy,https://goproxy.cn,direct RUN apt-get update --fix-missing && \ apt-get install -y zip vim postgresql mysql-common default-mysql-server && \ tar -C / -xvf /home/goadmin/tools/godependacy.tgz #if install dependacy tools failed, you can copy local's to remote #mkdir -p /go/bin && \ #mv /home/goadmin/tools/{gotest,goimports,golint,golangci-lint,adm} /go/bin #go get golang.org/x/tools/cmd/goimports && \ #go get github.com/rakyll/gotest && \ #go get -u golang.org/x/lint/golint && \ #go install github.com/GoAdminGroup/adm@latest && \ #go get -u github.com/golangci/golangci-lint/cmd/golangci-lint WORKDIR /home/goadmin ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: Makefile ================================================ GOCMD = go GOBUILD = $(GOCMD) build TEST_CONFIG_PATH=./../../common/config.json TEST_CONFIG_PQ_PATH=./../../common/config_pg.json TEST_CONFIG_SQLITE_PATH=./../../common/config_sqlite.json TEST_CONFIG_MS_PATH=./../../common/config_ms.json TEST_FRAMEWORK_DIR=./tests/frameworks ## database configs MYSQL_HOST = db_mysql MYSQL_PORT = 3306 MYSQL_USER = root MYSQL_PWD = root POSTGRESSQL_HOST = db_pgsql POSTGRESSQL_PORT = 5432 POSTGRESSQL_USER = postgres POSTGRESSQL_PWD = root TEST_DB = go-admin-test all: test ## tests test: cp-mod black-box-test web-test restore-mod ## tests: black box tests black-box-test: mysql-test pg-test sqlite-test ms-test mysql-test: $(TEST_FRAMEWORK_DIR)/* go get github.com/ugorji/go/codec@none for file in $^ ; do \ make import-mysql ; \ go test -mod=mod -gcflags=all=-l -v ./$${file}/... -args $(TEST_CONFIG_PATH) ; \ done sqlite-test: $(TEST_FRAMEWORK_DIR)/* for file in $^ ; do \ make import-sqlite ; \ go test -mod=mod -gcflags=all=-l ./$${file}/... -args $(TEST_CONFIG_SQLITE_PATH) ; \ done pg-test: $(TEST_FRAMEWORK_DIR)/* for file in $^ ; do \ make import-postgresql ; \ go test -mod=mod -gcflags=all=-l ./$${file}/... -args $(TEST_CONFIG_PQ_PATH) ; \ done ms-test: $(TEST_FRAMEWORK_DIR)/* for file in $^ ; do \ make import-mssql ; \ go test -mod=mod -gcflags=all=-l ./$${file}/... -args $(TEST_CONFIG_MS_PATH) ; \ done ## tests: user acceptance tests web-test: import-mysql go test -mod=mod ./tests/web/... rm -rf ./tests/web/User* web-test-debug: import-mysql go test -mod=mod ./tests/web/... -args true ## tests: unit tests unit-test: go test -mod=mod ./adm/... go test -mod=mod ./context/... go test -mod=mod ./modules/... go test -mod=mod ./plugins/admin/controller/... go test -mod=mod ./plugins/admin/modules/parameter/... go test -mod=mod ./plugins/admin/modules/table/... go test -mod=mod ./plugins/admin/modules/... ## tests: helpers import-sqlite: rm -rf ./tests/common/admin.db cp ./tests/data/admin.db ./tests/common/admin.db import-mysql: mysql -h$(MYSQL_HOST) -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PWD} -e "create database if not exists \`${TEST_DB}\`" mysql -h$(MYSQL_HOST) -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PWD} ${TEST_DB} < ./tests/data/admin.sql import-postgresql: PGPASSWORD=${POSTGRESSQL_PWD} dropdb -h ${POSTGRESSQL_HOST} -p ${POSTGRESSQL_PORT} -U ${POSTGRESSQL_USER} ${TEST_DB} PGPASSWORD=${POSTGRESSQL_PWD} createdb -h ${POSTGRESSQL_HOST} -p ${POSTGRESSQL_PORT} -U ${POSTGRESSQL_USER} ${TEST_DB} PGPASSWORD=${POSTGRESSQL_PWD} psql -h ${POSTGRESSQL_HOST} -p ${POSTGRESSQL_PORT} -d ${TEST_DB} -U ${POSTGRESSQL_USER} -f ./tests/data/admin_pg.sql import-mssql: /opt/mssql-tools/bin/sqlcmd -S db_mssql -U SA -P Aa123456 -Q "RESTORE DATABASE [goadmin] FROM DISK = N'/home/data/admin_ms.bak' WITH FILE = 1, NOUNLOAD, REPLACE, RECOVERY, STATS = 5" backup-mssql: docker exec mssql /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P Aa123456 -Q "BACKUP DATABASE [goadmin] TO DISK = N'/home/data/admin_ms.bak' WITH NOFORMAT, NOINIT, NAME = 'goadmin-full', SKIP, NOREWIND, NOUNLOAD, STATS = 10" cp-mod: cp go.mod go.mod.old cp go.sum go.sum.old restore-mod: mv go.mod.old go.mod mv go.sum.old go.sum ## code style check lint: fmt golint govet cilint fmt: GO111MODULE=off go fmt ./... GO111MODULE=off goimports -l -w . govet: GO111MODULE=off go vet ./... cilint: GO111MODULE=off golangci-lint run golint: GO111MODULE=off golint ./... build-tmpl: ## form tmpl build adm compile tpl --src ./template/types/tmpls/ --dist ./template/types/tmpl.go --package types --var tmpls ## generator tmpl build adm compile tpl --src ./plugins/admin/modules/table/tmpl --dist ./plugins/admin/modules/table/tmpl.go --package table --var tmpls .PHONY: all fmt golint govet cp-mod restore-mod test black-box-test mysql-test sqlite-test import-sqlite import-mysql import-postgresql pg-test lint cilint cli ================================================ FILE: README.md ================================================

go-admin

the missing golang data admin panel builder tool.

Documentation | 中文文档 | 中文介绍 | DEMO | 中文DEMO | Twitter | Forum

Build Status Go Report Card golang discord telegram license

Inspired by laravel-admin

## Preface GoAdmin is a toolkit to help you build a data visualization admin panel for your golang app. Online demo: [https://demo.go-admin.com](https://demo.go-admin.com) ![interface](http://file.go-admin.cn/introduction/interface_en_3.png) ## Features - 🚀 **Fast**: build a production admin panel app in **ten** minutes. - 🎨 **Theming**: beautiful ui themes supported(default adminlte, more themes are coming.) - 🔢 **Plugins**: many plugins to use(more useful and powerful plugins are coming.) - ✅ **Rbac**: out of box rbac auth system. - ⚙️ **Frameworks**: support most of the go web frameworks. ## Translation We need your help: [https://github.com/GoAdminGroup/docs/issues/1](https://github.com/GoAdminGroup/docs/issues/1) ## Who is using [Comment the issue to tell us](https://github.com/GoAdminGroup/go-admin/issues/71). ## How to Following three steps to run it. ```shell $ mkdir new_project && cd new_project $ go install github.com/GoAdminGroup/adm@latest $ adm init web ``` ## Example Quick follow up example: - [pure golang](https://github.com/GoAdminGroup/example), simple and less dependency - [golang with frontend template](https://github.com/GoAdminGroup/example_with_frontend), change template by yourself - [golang with vue](https://github.com/GoAdminGroup/example_with_vue), if you have vue experience See the [docs](https://book.go-admin.cn) for more details. ## Backers Your support will help me do better! [[Become a backer](https://opencollective.com/go-admin#backer)] ## Contribution [here for contribution guide](CONTRIBUTING.md) here to join into the develop team [join telegram](https://t.me/joinchat/NlyH6Bch2QARZkArithKvg) ================================================ FILE: README_CN.md ================================================

go-admin

遗失的Golang编写的数据可视化与管理平台构建框架

Build Status Go Report Card golang discord telegram license

laravel-admin启发

## 前言 GoAdmin 可以帮助你的golang应用快速实现数据可视化,搭建一个数据管理平台。 [文档](http://doc.go-admin.cn/zh) | [论坛](http://discuss.go-admin.com) | [Demo](https://demo.go-admin.cn) | [上手例子](https://github.com/GoAdminGroup/example/blob/master/README_CN.md) | [GoAdmin+vue 例子](https://github.com/GoAdminGroup/goadmin-vue-example) ![](http://file.go-admin.cn/introduction/interface_3.png) ## 特征 - 🚀 **高生产效率**: 10分钟内做一个好看的管理后台 - 🎨 **主题**: 默认为adminlte,更多好看的主题正在制作中,欢迎给我们留言 - 🔢 **插件化**: 提供插件使用,真正实现一个插件解决不了问题,那就两个 - ✅ **认证**: 开箱即用的rbac认证系统 - ⚙️ **框架支持**: 支持大部分框架接入,让你更容易去上手和扩展 ## 例子 - [纯golang](https://github.com/GoAdminGroup/example), 简单很少依赖 - [golang + 前端模版](https://github.com/GoAdminGroup/example_with_frontend), 你可以自己修改模版 - [golang + vue](https://github.com/GoAdminGroup/example_with_vue), 如果你会vue的话,不妨试试 ## 翻译 我们需要您的帮忙: [https://github.com/GoAdminGroup/docs/issues/1](https://github.com/GoAdminGroup/docs/issues/1) ## 谁在使用GoAdmin [评论这个issue告诉我们](https://github.com/GoAdminGroup/go-admin/issues/71). ## 使用 ```shell $ go install github.com/GoAdminGroup/adm@latest $ mkdir new_project && cd new_project $ adm init web -l cn ``` 运行后将会启动一个网页安装程序,根据程序内容填写安装运行即可。 ## 贡献 [这里有一份贡献指南](CONTRIBUTING_CN.md) 非常欢迎提pr,这里可以加入开发小组 QQ群:[694446792](https://qm.qq.com/q/bp3hsYyUzS),记得备注加群来意 这里是[开发计划](https://github.com/GoAdminGroup/go-admin/projects) [点击这里申请加微信群(记得备注加群)](http://quick.go-admin.cn/resource/wechat_qrcode_02.jpg) 注:在社区中如有问题提问,请务必清晰描述,包括但不限于问题详叙/问题代码/复现方法/已经尝试过的方法。 ## 十分感谢 inspired by [laravel-admin](https://github.com/z-song/laravel-admin) ## 打赏 留下您的github/gitee用户名,我们将会展示在[捐赠名单](DONATION.md)中。 ================================================ FILE: SECURITY.md ================================================ # Security Policy ## Reporting a Vulnerability Please report security issues to `chg80333@gmail.com` ================================================ FILE: adapter/adapter.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package adapter import ( "bytes" "fmt" "net/http" "net/url" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/constant" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/menu" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" ) // WebFrameWork is an interface which is used as an adapter of // framework and goAdmin. It must implement two methods. Use registers // the routes and the corresponding handlers. Content writes the // response to the corresponding context of framework. type WebFrameWork interface { // Name return the web framework name. Name() string // Use method inject the plugins to the web framework engine which is the // first parameter. Use(app interface{}, plugins []plugins.Plugin) error // Content add the panel html response of the given callback function to // the web framework context which is the first parameter. Content(ctx interface{}, fn types.GetPanelFn, fn2 context.NodeProcessor, navButtons ...types.Button) // User get the auth user model from the given web framework context. User(ctx interface{}) (models.UserModel, bool) // AddHandler inject the route and handlers of GoAdmin to the web framework. AddHandler(method, path string, handlers context.Handlers) DisableLog() Static(prefix, path string) Run() error // Helper functions // ================================ SetApp(app interface{}) error SetConnection(db.Connection) GetConnection() db.Connection SetContext(ctx interface{}) WebFrameWork GetCookie() (string, error) Lang() string Path() string Method() string Request() *http.Request FormParam() url.Values Query() url.Values IsPjax() bool Redirect() SetContentType() Write(body []byte) CookieKey() string HTMLContentType() string } // BaseAdapter is a base adapter contains some helper functions. type BaseAdapter struct { db db.Connection } // SetConnection set the db connection. func (base *BaseAdapter) SetConnection(conn db.Connection) { base.db = conn } // GetConnection get the db connection. func (base *BaseAdapter) GetConnection() db.Connection { return base.db } // HTMLContentType return the default content type header. func (*BaseAdapter) HTMLContentType() string { return "text/html; charset=utf-8" } // CookieKey return the cookie key. func (*BaseAdapter) CookieKey() string { return auth.DefaultCookieKey } // GetUser is a helper function get the auth user model from the context. func (*BaseAdapter) GetUser(ctx interface{}, wf WebFrameWork) (models.UserModel, bool) { cookie, err := wf.SetContext(ctx).GetCookie() if err != nil { return models.UserModel{}, false } user, exist := auth.GetCurUser(cookie, wf.GetConnection()) return user.ReleaseConn(), exist } // GetUse is a helper function adds the plugins to the framework. func (*BaseAdapter) GetUse(app interface{}, plugin []plugins.Plugin, wf WebFrameWork) error { if err := wf.SetApp(app); err != nil { return err } for _, plug := range plugin { for path, handlers := range plug.GetHandler() { if plug.Prefix() == "" { wf.AddHandler(path.Method, path.URL, handlers) } else { wf.AddHandler(path.Method, config.Url("/"+plug.Prefix()+path.URL), handlers) } } } return nil } func (*BaseAdapter) Run() error { panic("not implement") } func (*BaseAdapter) DisableLog() { panic("not implement") } func (*BaseAdapter) Static(_, _ string) { panic("not implement") } // GetContent is a helper function of adapter.Content func (base *BaseAdapter) GetContent(ctx interface{}, getPanelFn types.GetPanelFn, wf WebFrameWork, navButtons types.Buttons, fn context.NodeProcessor) { var ( newBase = wf.SetContext(ctx) cookie, hasError = newBase.GetCookie() ) if hasError != nil || cookie == "" { newBase.Redirect() return } user, authSuccess := auth.GetCurUser(cookie, wf.GetConnection()) if !authSuccess { newBase.Redirect() return } var ( panel types.Panel err error ) gctx := context.NewContext(newBase.Request()) if !auth.CheckPermissions(user, newBase.Path(), newBase.Method(), newBase.FormParam()) { panel = template.WarningPanel(gctx, errors.NoPermission, template.NoPermission403Page) } else { panel, err = getPanelFn(ctx) if err != nil { panel = template.WarningPanel(gctx, err.Error()) } } fn(panel.Callbacks...) tmpl, tmplName := template.Default(gctx).GetTemplate(newBase.IsPjax()) buf := new(bytes.Buffer) hasError = tmpl.ExecuteTemplate(buf, tmplName, types.NewPage(gctx, &types.NewPageParam{ User: user, Menu: menu.GetGlobalMenu(user, wf.GetConnection(), newBase.Lang()).SetActiveClass(config.URLRemovePrefix(newBase.Path())), Panel: panel.GetContent(config.IsProductionEnvironment()), Assets: template.GetComponentAssetImportHTML(gctx), Buttons: navButtons.CheckPermission(user), TmplHeadHTML: template.Default(gctx).GetHeadHTML(), TmplFootJS: template.Default(gctx).GetFootJS(), Iframe: newBase.Query().Get(constant.IframeKey) == "true", })) if hasError != nil { logger.Error(fmt.Sprintf("error: %s adapter content, ", newBase.Name()), hasError) } newBase.SetContentType() newBase.Write(buf.Bytes()) } ================================================ FILE: adapter/beego/beego.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package beego import ( "bytes" "errors" "net/http" "net/url" "strings" "github.com/GoAdminGroup/go-admin/adapter" gctx "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" "github.com/astaxie/beego" "github.com/astaxie/beego/context" ) // Beego structure value is a Beego GoAdmin adapter. type Beego struct { adapter.BaseAdapter ctx *context.Context app *beego.App } func init() { engine.Register(new(Beego)) } // User implements the method Adapter.User. func (bee *Beego) User(ctx interface{}) (models.UserModel, bool) { return bee.GetUser(ctx, bee) } // Use implements the method Adapter.Use. func (bee *Beego) Use(app interface{}, plugs []plugins.Plugin) error { return bee.GetUse(app, plugs, bee) } // Content implements the method Adapter.Content. func (bee *Beego) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn gctx.NodeProcessor, navButtons ...types.Button) { bee.GetContent(ctx, getPanelFn, bee, navButtons, fn) } type HandlerFunc func(ctx *context.Context) (types.Panel, error) func Content(handler HandlerFunc) beego.FilterFunc { return func(ctx *context.Context) { engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(*context.Context)) }) } } // SetApp implements the method Adapter.SetApp. func (bee *Beego) SetApp(app interface{}) error { var ( eng *beego.App ok bool ) if eng, ok = app.(*beego.App); !ok { return errors.New("beego adapter SetApp: wrong parameter") } bee.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (bee *Beego) AddHandler(method, path string, handlers gctx.Handlers) { bee.app.Handlers.AddMethod(method, path, func(c *context.Context) { for key, value := range c.Input.Params() { if c.Request.URL.RawQuery == "" { c.Request.URL.RawQuery += strings.ReplaceAll(key, ":", "") + "=" + value } else { c.Request.URL.RawQuery += "&" + strings.ReplaceAll(key, ":", "") + "=" + value } } ctx := gctx.NewContext(c.Request) ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.ResponseWriter.Header().Add(key, head[0]) } c.ResponseWriter.WriteHeader(ctx.Response.StatusCode) if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) c.WriteString(buf.String()) } }) } // Name implements the method Adapter.Name. func (*Beego) Name() string { return "beego" } // SetContext implements the method Adapter.SetContext. func (*Beego) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx *context.Context ok bool ) if ctx, ok = contextInterface.(*context.Context); !ok { panic("beego adapter SetContext: wrong parameter") } return &Beego{ctx: ctx} } // Redirect implements the method Adapter.Redirect. func (bee *Beego) Redirect() { bee.ctx.Redirect(http.StatusFound, config.Url(config.GetLoginUrl())) } // SetContentType implements the method Adapter.SetContentType. func (bee *Beego) SetContentType() { bee.ctx.ResponseWriter.Header().Set("Content-Type", bee.HTMLContentType()) } // Write implements the method Adapter.Write. func (bee *Beego) Write(body []byte) { _, _ = bee.ctx.ResponseWriter.Write(body) } // GetCookie implements the method Adapter.GetCookie. func (bee *Beego) GetCookie() (string, error) { return bee.ctx.GetCookie(bee.CookieKey()), nil } // Lang implements the method Adapter.Lang. func (bee *Beego) Lang() string { return bee.ctx.Request.URL.Query().Get("__ga_lang") } // Path implements the method Adapter.Path. func (bee *Beego) Path() string { return bee.ctx.Request.URL.Path } // Method implements the method Adapter.Method. func (bee *Beego) Method() string { return bee.ctx.Request.Method } // FormParam implements the method Adapter.FormParam. func (bee *Beego) FormParam() url.Values { _ = bee.ctx.Request.ParseMultipartForm(32 << 20) return bee.ctx.Request.PostForm } // IsPjax implements the method Adapter.IsPjax. func (bee *Beego) IsPjax() bool { return bee.ctx.Request.Header.Get(constant.PjaxHeader) == "true" } // Query implements the method Adapter.Query. func (bee *Beego) Query() url.Values { return bee.ctx.Request.URL.Query() } // Request implements the method Adapter.Request. func (bee *Beego) Request() *http.Request { return bee.ctx.Request } ================================================ FILE: adapter/beego2/beego2.go ================================================ package beego2 import ( "bytes" "errors" "net/http" "net/url" "strings" "github.com/GoAdminGroup/go-admin/adapter" gctx "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/template/types" "github.com/beego/beego/v2/server/web" "github.com/beego/beego/v2/server/web/context" ) type Beego2 struct { adapter.BaseAdapter ctx *context.Context app *web.HttpServer } func init() { engine.Register(new(Beego2)) } func (*Beego2) Name() string { return "beego2" } func (bee2 *Beego2) Use(app interface{}, plugins []plugins.Plugin) error { return bee2.GetUse(app, plugins, bee2) } func (bee2 *Beego2) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn gctx.NodeProcessor, navButtons ...types.Button) { bee2.GetContent(ctx, getPanelFn, bee2, navButtons, fn) } func (bee2 *Beego2) User(ctx interface{}) (models.UserModel, bool) { return bee2.GetUser(ctx, bee2) } func (bee2 *Beego2) AddHandler(method, path string, handlers gctx.Handlers) { bee2.app.Handlers.AddMethod(method, path, func(c *context.Context) { for key, value := range c.Input.Params() { if c.Request.URL.RawQuery == "" { c.Request.URL.RawQuery += strings.ReplaceAll(key, ":", "") + "=" + value } else { c.Request.URL.RawQuery += "&" + strings.ReplaceAll(key, ":", "") + "=" + value } } ctx := gctx.NewContext(c.Request) ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.ResponseWriter.Header().Add(key, head[0]) } c.ResponseWriter.WriteHeader(ctx.Response.StatusCode) if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) c.WriteString(buf.String()) } }) } func (bee2 *Beego2) SetApp(app interface{}) error { var ( eng *web.HttpServer ok bool ) if eng, ok = app.(*web.HttpServer); !ok { return errors.New("beego2 adapter SetApp: wrong parameter") } bee2.app = eng return nil } func (*Beego2) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx *context.Context ok bool ) if ctx, ok = contextInterface.(*context.Context); !ok { panic("beego2 adapter SetContext: wrong parameter") } return &Beego2{ctx: ctx} } func (bee2 *Beego2) GetCookie() (string, error) { return bee2.ctx.GetCookie(bee2.CookieKey()), nil } func (bee2 *Beego2) Lang() string { return bee2.ctx.Request.URL.Query().Get("__ga_lang") } func (bee2 *Beego2) Path() string { return bee2.ctx.Request.URL.Path } func (bee2 *Beego2) Method() string { return bee2.ctx.Request.Method } func (bee2 *Beego2) FormParam() url.Values { _ = bee2.ctx.Request.ParseMultipartForm(32 << 20) return bee2.ctx.Request.PostForm } func (bee2 *Beego2) Query() url.Values { return bee2.ctx.Request.URL.Query() } func (bee2 *Beego2) IsPjax() bool { return bee2.ctx.Request.Header.Get(constant.PjaxHeader) == "true" } func (bee2 *Beego2) Redirect() { bee2.ctx.Redirect(http.StatusFound, config.Url(config.GetLoginUrl())) } func (bee2 *Beego2) SetContentType() { bee2.ctx.ResponseWriter.Header().Set("Content-Type", bee2.HTMLContentType()) } func (bee2 *Beego2) Write(body []byte) { _, _ = bee2.ctx.ResponseWriter.Write(body) } // Request implements the method Adapter.Request. func (bee2 *Beego2) Request() *http.Request { return bee2.ctx.Request } ================================================ FILE: adapter/buffalo/buffalo.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package buffalo import ( "bytes" "errors" "net/http" neturl "net/url" "regexp" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" "github.com/gobuffalo/buffalo" ) // Buffalo structure value is a Buffalo GoAdmin adapter. type Buffalo struct { adapter.BaseAdapter ctx buffalo.Context app *buffalo.App } func init() { engine.Register(new(Buffalo)) } // User implements the method Adapter.User. func (bu *Buffalo) User(ctx interface{}) (models.UserModel, bool) { return bu.GetUser(ctx, bu) } // Use implements the method Adapter.Use. func (bu *Buffalo) Use(app interface{}, plugs []plugins.Plugin) error { return bu.GetUse(app, plugs, bu) } // Content implements the method Adapter.Content. func (bu *Buffalo) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { bu.GetContent(ctx, getPanelFn, bu, btns, fn) } type HandlerFunc func(ctx buffalo.Context) (types.Panel, error) func Content(handler HandlerFunc) buffalo.Handler { return func(ctx buffalo.Context) error { engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(buffalo.Context)) }) return nil } } // SetApp implements the method Adapter.SetApp. func (bu *Buffalo) SetApp(app interface{}) error { var ( eng *buffalo.App ok bool ) if eng, ok = app.(*buffalo.App); !ok { return errors.New("buffalo adapter SetApp: wrong parameter") } bu.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (bu *Buffalo) AddHandler(method, path string, handlers context.Handlers) { url := path reg1 := regexp.MustCompile(":(.*?)/") reg2 := regexp.MustCompile(":(.*?)$") url = reg1.ReplaceAllString(url, "{$1}/") url = reg2.ReplaceAllString(url, "{$1}") getHandleFunc(bu.app, strings.ToUpper(method))(url, func(c buffalo.Context) error { if c.Request().URL.Path[len(c.Request().URL.Path)-1] == '/' { c.Request().URL.Path = c.Request().URL.Path[:len(c.Request().URL.Path)-1] } ctx := context.NewContext(c.Request()) params := c.Params().(neturl.Values) for key, param := range params { if c.Request().URL.RawQuery == "" { c.Request().URL.RawQuery += strings.ReplaceAll(key, ":", "") + "=" + param[0] } else { c.Request().URL.RawQuery += "&" + strings.ReplaceAll(key, ":", "") + "=" + param[0] } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.Response().Header().Set(key, head[0]) } if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) c.Response().WriteHeader(ctx.Response.StatusCode) _, _ = c.Response().Write(buf.Bytes()) } else { c.Response().WriteHeader(ctx.Response.StatusCode) } return nil }) } // HandleFun is type of route methods of buffalo. type HandleFun func(p string, h buffalo.Handler) *buffalo.RouteInfo func getHandleFunc(eng *buffalo.App, method string) HandleFun { switch method { case "GET": return eng.GET case "POST": return eng.POST case "PUT": return eng.PUT case "DELETE": return eng.DELETE case "HEAD": return eng.HEAD case "OPTIONS": return eng.OPTIONS case "PATCH": return eng.PATCH default: panic("wrong method") } } // Name implements the method Adapter.Name. func (*Buffalo) Name() string { return "buffalo" } // SetContext implements the method Adapter.SetContext. func (*Buffalo) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx buffalo.Context ok bool ) if ctx, ok = contextInterface.(buffalo.Context); !ok { panic("buffalo adapter SetContext: wrong parameter") } return &Buffalo{ctx: ctx} } // Redirect implements the method Adapter.Redirect. func (bu *Buffalo) Redirect() { _ = bu.ctx.Redirect(http.StatusFound, config.Url(config.GetLoginUrl())) } // SetContentType implements the method Adapter.SetContentType. func (bu *Buffalo) SetContentType() { bu.ctx.Response().Header().Set("Content-Type", bu.HTMLContentType()) } // Write implements the method Adapter.Write. func (bu *Buffalo) Write(body []byte) { bu.ctx.Response().WriteHeader(http.StatusOK) _, _ = bu.ctx.Response().Write(body) } // GetCookie implements the method Adapter.GetCookie. func (bu *Buffalo) GetCookie() (string, error) { return bu.ctx.Cookies().Get(bu.CookieKey()) } // Lang implements the method Adapter.Lang. func (bu *Buffalo) Lang() string { return bu.ctx.Request().URL.Query().Get("__ga_lang") } // Path implements the method Adapter.Path. func (bu *Buffalo) Path() string { return bu.ctx.Request().URL.Path } // Method implements the method Adapter.Method. func (bu *Buffalo) Method() string { return bu.ctx.Request().Method } // FormParam implements the method Adapter.FormParam. func (bu *Buffalo) FormParam() neturl.Values { _ = bu.ctx.Request().ParseMultipartForm(32 << 20) return bu.ctx.Request().PostForm } // IsPjax implements the method Adapter.IsPjax. func (bu *Buffalo) IsPjax() bool { return bu.ctx.Request().Header.Get(constant.PjaxHeader) == "true" } // Query implements the method Adapter.Query. func (bu *Buffalo) Query() neturl.Values { return bu.ctx.Request().URL.Query() } // Request implements the method Adapter.Request. func (bu *Buffalo) Request() *http.Request { return bu.ctx.Request() } ================================================ FILE: adapter/chi/chi.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package chi import ( "bytes" "errors" "net/http" "net/url" "regexp" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" cfg "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" "github.com/go-chi/chi" ) // Chi structure value is a Chi GoAdmin adapter. type Chi struct { adapter.BaseAdapter ctx Context app *chi.Mux } func init() { engine.Register(new(Chi)) } // User implements the method Adapter.User. func (ch *Chi) User(ctx interface{}) (models.UserModel, bool) { return ch.GetUser(ctx, ch) } // Use implements the method Adapter.Use. func (ch *Chi) Use(app interface{}, plugs []plugins.Plugin) error { return ch.GetUse(app, plugs, ch) } // Content implements the method Adapter.Content. func (ch *Chi) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { ch.GetContent(ctx, getPanelFn, ch, btns, fn) } type HandlerFunc func(ctx Context) (types.Panel, error) func Content(handler HandlerFunc) http.HandlerFunc { return func(writer http.ResponseWriter, request *http.Request) { ctx := Context{ Request: request, Response: writer, } engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(Context)) }) } } // SetApp implements the method Adapter.SetApp. func (ch *Chi) SetApp(app interface{}) error { var ( eng *chi.Mux ok bool ) if eng, ok = app.(*chi.Mux); !ok { return errors.New("chi adapter SetApp: wrong parameter") } ch.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (ch *Chi) AddHandler(method, path string, handlers context.Handlers) { url := path reg1 := regexp.MustCompile(":(.*?)/") reg2 := regexp.MustCompile(":(.*?)$") url = reg1.ReplaceAllString(url, "{$1}/") url = reg2.ReplaceAllString(url, "{$1}") if len(url) > 1 && url[0] == '/' && url[1] == '/' { url = url[1:] } getHandleFunc(ch.app, strings.ToUpper(method))(url, func(w http.ResponseWriter, r *http.Request) { if r.URL.Path[len(r.URL.Path)-1] == '/' { r.URL.Path = r.URL.Path[:len(r.URL.Path)-1] } ctx := context.NewContext(r) params := chi.RouteContext(r.Context()).URLParams for i := 0; i < len(params.Values); i++ { if r.URL.RawQuery == "" { r.URL.RawQuery += strings.ReplaceAll(params.Keys[i], ":", "") + "=" + params.Values[i] } else { r.URL.RawQuery += "&" + strings.ReplaceAll(params.Keys[i], ":", "") + "=" + params.Values[i] } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { w.Header().Set(key, head[0]) } if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) w.WriteHeader(ctx.Response.StatusCode) _, _ = w.Write(buf.Bytes()) } else { w.WriteHeader(ctx.Response.StatusCode) } }) } // HandleFun is type of route methods of chi. type HandleFun func(pattern string, handlerFn http.HandlerFunc) func getHandleFunc(eng *chi.Mux, method string) HandleFun { switch method { case "GET": return eng.Get case "POST": return eng.Post case "PUT": return eng.Put case "DELETE": return eng.Delete case "HEAD": return eng.Head case "OPTIONS": return eng.Options case "PATCH": return eng.Patch default: panic("wrong method") } } // Context wraps the Request and Response object of Chi. type Context struct { Request *http.Request Response http.ResponseWriter } // SetContext implements the method Adapter.SetContext. func (*Chi) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx Context ok bool ) if ctx, ok = contextInterface.(Context); !ok { panic("chi adapter SetContext: wrong parameter") } return &Chi{ctx: ctx} } // Name implements the method Adapter.Name. func (*Chi) Name() string { return "chi" } // Redirect implements the method Adapter.Redirect. func (ch *Chi) Redirect() { http.Redirect(ch.ctx.Response, ch.ctx.Request, cfg.Url(cfg.GetLoginUrl()), http.StatusFound) } // SetContentType implements the method Adapter.SetContentType. func (ch *Chi) SetContentType() { ch.ctx.Response.Header().Set("Content-Type", ch.HTMLContentType()) } // Write implements the method Adapter.Write. func (ch *Chi) Write(body []byte) { ch.ctx.Response.WriteHeader(http.StatusOK) _, _ = ch.ctx.Response.Write(body) } // GetCookie implements the method Adapter.GetCookie. func (ch *Chi) GetCookie() (string, error) { cookie, err := ch.ctx.Request.Cookie(ch.CookieKey()) if err != nil { return "", err } return cookie.Value, err } // Lang implements the method Adapter.Lang. func (ch *Chi) Lang() string { return ch.ctx.Request.URL.Query().Get("__ga_lang") } // Path implements the method Adapter.Path. func (ch *Chi) Path() string { return ch.ctx.Request.URL.Path } // Method implements the method Adapter.Method. func (ch *Chi) Method() string { return ch.ctx.Request.Method } // FormParam implements the method Adapter.FormParam. func (ch *Chi) FormParam() url.Values { _ = ch.ctx.Request.ParseMultipartForm(32 << 20) return ch.ctx.Request.PostForm } // IsPjax implements the method Adapter.IsPjax. func (ch *Chi) IsPjax() bool { return ch.ctx.Request.Header.Get(constant.PjaxHeader) == "true" } // Query implements the method Adapter.Query. func (ch *Chi) Query() url.Values { return ch.ctx.Request.URL.Query() } // Request implements the method Adapter.Request. func (ch *Chi) Request() *http.Request { return ch.ctx.Request } ================================================ FILE: adapter/echo/echo.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package echo import ( "bytes" "errors" "net/http" "net/url" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" "github.com/labstack/echo/v4" ) // Echo structure value is an Echo GoAdmin adapter. type Echo struct { adapter.BaseAdapter ctx echo.Context app *echo.Echo } func init() { engine.Register(new(Echo)) } // User implements the method Adapter.User. func (e *Echo) User(ctx interface{}) (models.UserModel, bool) { return e.GetUser(ctx, e) } // Use implements the method Adapter.Use. func (e *Echo) Use(app interface{}, plugs []plugins.Plugin) error { return e.GetUse(app, plugs, e) } // Content implements the method Adapter.Content. func (e *Echo) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { e.GetContent(ctx, getPanelFn, e, btns, fn) } type HandlerFunc func(ctx echo.Context) (types.Panel, error) func Content(handler HandlerFunc) echo.HandlerFunc { return func(ctx echo.Context) error { engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(echo.Context)) }) return nil } } // SetApp implements the method Adapter.SetApp. func (e *Echo) SetApp(app interface{}) error { var ( eng *echo.Echo ok bool ) if eng, ok = app.(*echo.Echo); !ok { return errors.New("echo adapter SetApp: wrong parameter") } e.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (e *Echo) AddHandler(method, path string, handlers context.Handlers) { e.app.Add(strings.ToUpper(method), path, func(c echo.Context) error { ctx := context.NewContext(c.Request()) for _, key := range c.ParamNames() { if c.Request().URL.RawQuery == "" { c.Request().URL.RawQuery += strings.ReplaceAll(key, ":", "") + "=" + c.Param(key) } else { c.Request().URL.RawQuery += "&" + strings.ReplaceAll(key, ":", "") + "=" + c.Param(key) } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.Response().Header().Set(key, head[0]) } if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) _ = c.String(ctx.Response.StatusCode, buf.String()) } else { c.Response().WriteHeader(ctx.Response.StatusCode) } return nil }) } // Name implements the method Adapter.Name. func (*Echo) Name() string { return "echo" } // SetContext implements the method Adapter.SetContext. func (*Echo) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx echo.Context ok bool ) if ctx, ok = contextInterface.(echo.Context); !ok { panic("echo adapter SetContext: wrong parameter") } return &Echo{ctx: ctx} } // Redirect implements the method Adapter.Redirect. func (e *Echo) Redirect() { _ = e.ctx.Redirect(http.StatusFound, config.Url(config.GetLoginUrl())) } // SetContentType implements the method Adapter.SetContentType. func (e *Echo) SetContentType() { e.ctx.Response().Header().Set("Content-Type", e.HTMLContentType()) } // Write implements the method Adapter.Write. func (e *Echo) Write(body []byte) { e.ctx.Response().WriteHeader(http.StatusOK) _, _ = e.ctx.Response().Write(body) } // GetCookie implements the method Adapter.GetCookie. func (e *Echo) GetCookie() (string, error) { cookie, err := e.ctx.Cookie(e.CookieKey()) if err != nil { return "", err } return cookie.Value, err } // Lang implements the method Adapter.Lang. func (e *Echo) Lang() string { return e.ctx.Request().URL.Query().Get("__ga_lang") } // Path implements the method Adapter.Path. func (e *Echo) Path() string { return e.ctx.Request().URL.Path } // Method implements the method Adapter.Method. func (e *Echo) Method() string { return e.ctx.Request().Method } // FormParam implements the method Adapter.FormParam. func (e *Echo) FormParam() url.Values { _ = e.ctx.Request().ParseMultipartForm(32 << 20) return e.ctx.Request().PostForm } // IsPjax implements the method Adapter.IsPjax. func (e *Echo) IsPjax() bool { return e.ctx.Request().Header.Get(constant.PjaxHeader) == "true" } // Query implements the method Adapter.Query. func (e *Echo) Query() url.Values { return e.ctx.Request().URL.Query() } // Request implements the method Adapter.Request. func (e *Echo) Request() *http.Request { return e.ctx.Request() } ================================================ FILE: adapter/fasthttp/fasthttp.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package fasthttp import ( "bytes" "errors" "io" "net/http" "net/url" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" "github.com/buaazp/fasthttprouter" "github.com/valyala/fasthttp" ) // Fasthttp structure value is a Fasthttp GoAdmin adapter. type Fasthttp struct { adapter.BaseAdapter ctx *fasthttp.RequestCtx app *fasthttprouter.Router } func init() { engine.Register(new(Fasthttp)) } // User implements the method Adapter.User. func (fast *Fasthttp) User(ctx interface{}) (models.UserModel, bool) { return fast.GetUser(ctx, fast) } // Use implements the method Adapter.Use. func (fast *Fasthttp) Use(app interface{}, plugs []plugins.Plugin) error { return fast.GetUse(app, plugs, fast) } // Content implements the method Adapter.Content. func (fast *Fasthttp) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { fast.GetContent(ctx, getPanelFn, fast, btns, fn) } type HandlerFunc func(ctx *fasthttp.RequestCtx) (types.Panel, error) func Content(handler HandlerFunc) fasthttp.RequestHandler { return func(ctx *fasthttp.RequestCtx) { engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(*fasthttp.RequestCtx)) }) } } // SetApp implements the method Adapter.SetApp. func (fast *Fasthttp) SetApp(app interface{}) error { var ( eng *fasthttprouter.Router ok bool ) if eng, ok = app.(*fasthttprouter.Router); !ok { return errors.New("fasthttp adapter SetApp: wrong parameter") } fast.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (fast *Fasthttp) AddHandler(method, path string, handlers context.Handlers) { fast.app.Handle(strings.ToUpper(method), path, func(c *fasthttp.RequestCtx) { httpreq := convertCtx(c) ctx := context.NewContext(httpreq) var params = make(map[string]string) c.VisitUserValues(func(i []byte, i2 interface{}) { if value, ok := i2.(string); ok { params[string(i)] = value } }) for key, value := range params { if httpreq.URL.RawQuery == "" { httpreq.URL.RawQuery += strings.ReplaceAll(key, ":", "") + "=" + value } else { httpreq.URL.RawQuery += "&" + strings.ReplaceAll(key, ":", "") + "=" + value } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.Response.Header.Set(key, head[0]) } if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) _, _ = c.WriteString(buf.String()) } c.Response.SetStatusCode(ctx.Response.StatusCode) }) } func convertCtx(ctx *fasthttp.RequestCtx) *http.Request { var r http.Request body := ctx.PostBody() r.Method = string(ctx.Method()) r.Proto = "HTTP/1.1" r.ProtoMajor = 1 r.ProtoMinor = 1 r.RequestURI = string(ctx.RequestURI()) r.ContentLength = int64(len(body)) r.Host = string(ctx.Host()) r.RemoteAddr = ctx.RemoteAddr().String() hdr := make(http.Header) ctx.Request.Header.VisitAll(func(k, v []byte) { sk := string(k) sv := string(v) switch sk { case "Transfer-Encoding": r.TransferEncoding = append(r.TransferEncoding, sv) default: hdr.Set(sk, sv) } }) r.Header = hdr r.Body = &netHTTPBody{body} rURL, err := url.ParseRequestURI(r.RequestURI) if err != nil { ctx.Logger().Printf("cannot parse requestURI %q: %s", r.RequestURI, err) ctx.Error("Internal Server Error", fasthttp.StatusInternalServerError) return &r } r.URL = rURL return &r } type netHTTPBody struct { b []byte } func (r *netHTTPBody) Read(p []byte) (int, error) { if len(r.b) == 0 { return 0, io.EOF } n := copy(p, r.b) r.b = r.b[n:] return n, nil } func (r *netHTTPBody) Close() error { r.b = r.b[:0] return nil } // Name implements the method Adapter.Name. func (*Fasthttp) Name() string { return "fasthttp" } // SetContext implements the method Adapter.SetContext. func (*Fasthttp) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx *fasthttp.RequestCtx ok bool ) if ctx, ok = contextInterface.(*fasthttp.RequestCtx); !ok { panic("fasthttp adapter SetContext: wrong parameter") } return &Fasthttp{ctx: ctx} } // Redirect implements the method Adapter.Redirect. func (fast *Fasthttp) Redirect() { fast.ctx.Redirect(config.Url(config.GetLoginUrl()), http.StatusFound) } // SetContentType implements the method Adapter.SetContentType. func (fast *Fasthttp) SetContentType() { fast.ctx.Response.Header.Set("Content-Type", fast.HTMLContentType()) } // Write implements the method Adapter.Write. func (fast *Fasthttp) Write(body []byte) { _, _ = fast.ctx.Write(body) } // GetCookie implements the method Adapter.GetCookie. func (fast *Fasthttp) GetCookie() (string, error) { return string(fast.ctx.Request.Header.Cookie(fast.CookieKey())), nil } // Lang implements the method Adapter.Lang. func (fast *Fasthttp) Lang() string { return string(fast.ctx.Request.URI().QueryArgs().Peek("__ga_lang")) } // Path implements the method Adapter.Path. func (fast *Fasthttp) Path() string { return string(fast.ctx.Path()) } // Method implements the method Adapter.Method. func (fast *Fasthttp) Method() string { return string(fast.ctx.Method()) } // FormParam implements the method Adapter.FormParam. func (fast *Fasthttp) FormParam() url.Values { f, _ := fast.ctx.MultipartForm() if f != nil { return f.Value } return url.Values{} } // IsPjax implements the method Adapter.IsPjax. func (fast *Fasthttp) IsPjax() bool { return string(fast.ctx.Request.Header.Peek(constant.PjaxHeader)) == "true" } // Query implements the method Adapter.Query. func (fast *Fasthttp) Query() url.Values { queryStr := fast.ctx.URI().QueryString() queryObj, err := url.Parse(string(queryStr)) if err != nil { return url.Values{} } return queryObj.Query() } // Request implements the method Adapter.Request. func (fast *Fasthttp) Request() *http.Request { return convertCtx(fast.ctx) } ================================================ FILE: adapter/gear/gear.go ================================================ /*** # File Name: ../../adapter/gear/gear.go # Author: eavesmy # Email: eavesmy@gmail.com # Created Time: 2021年06月03日 星期四 19时05分06秒 ***/ package gear import ( "bytes" "errors" "net/http" "net/url" "regexp" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" "github.com/teambition/gear" ) // Gear structure value is a Gin GoAdmin adapter. type Gear struct { adapter.BaseAdapter ctx *gear.Context app *gear.App router *gear.Router } func init() { engine.Register(new(Gear)) } // User implements the method Adapter.User. func (gears *Gear) User(ctx interface{}) (models.UserModel, bool) { return gears.GetUser(ctx, gears) } // Use implements the method Adapter.Use. func (gears *Gear) Use(app interface{}, plugs []plugins.Plugin) error { return gears.GetUse(app, plugs, gears) } // Content implements the method Adapter.Content. func (gears *Gear) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { gears.GetContent(ctx, getPanelFn, gears, btns, fn) } type HandlerFunc func(ctx *gear.Context) (types.Panel, error) func Content(handler HandlerFunc) gear.Middleware { return func(ctx *gear.Context) error { engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(*gear.Context)) }) return nil } } // SetApp implements the method Adapter.SetApp. func (gears *Gear) SetApp(app interface{}) error { gears.app = app.(*gear.App) gears.router = gear.NewRouter() var ( eng *gear.App ok bool ) if eng, ok = app.(*gear.App); !ok { return errors.New("beego adapter SetApp: wrong parameter") } gears.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (gears *Gear) AddHandler(method, path string, handlers context.Handlers) { if gears.router == nil { gears.router = gear.NewRouter() } gears.router.Handle(strings.ToUpper(method), path, func(c *gear.Context) error { ctx := context.NewContext(c.Req) newPath := path reg1 := regexp.MustCompile(":(.*?)/") reg2 := regexp.MustCompile(":(.*?)$") params := reg1.FindAllString(newPath, -1) newPath = reg1.ReplaceAllString(newPath, "") params = append(params, reg2.FindAllString(newPath, -1)...) for _, param := range params { p := utils.ReplaceAll(param, ":", "", "/", "") if c.Req.URL.RawQuery == "" { c.Req.URL.RawQuery += p + "=" + c.Param(p) } else { c.Req.URL.RawQuery += "&" + p + "=" + c.Param(p) } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.Res.Header().Add(key, head[0]) } if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) return c.End(ctx.Response.StatusCode, buf.Bytes()) } c.Status(ctx.Response.StatusCode) return nil }) gears.app.UseHandler(gears.router) } // Name implements the method Adapter.Name. func (*Gear) Name() string { return "gear" } // SetContext implements the method Adapter.SetContext. func (*Gear) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx *gear.Context ok bool ) if ctx, ok = contextInterface.(*gear.Context); !ok { panic("gear adapter SetContext: wrong parameter") } return &Gear{ctx: ctx} } // Redirect implements the method Adapter.Redirect. func (gears *Gear) Redirect() { gears.ctx.Redirect(config.Url(config.GetLoginUrl())) } // SetContentType implements the method Adapter.SetContentType. func (gears *Gear) SetContentType() { gears.ctx.Res.Header().Set("Content-Type", gears.HTMLContentType()) } // Write implements the method Adapter.Write. func (gears *Gear) Write(body []byte) { gears.ctx.End(http.StatusOK, body) } // GetCookie implements the method Adapter.GetCookie. func (gears *Gear) GetCookie() (string, error) { return gears.ctx.Cookies.Get(gears.CookieKey()) } // Lang implements the method Adapter.Lang. func (gears *Gear) Lang() string { return gears.ctx.Req.URL.Query().Get("__ga_lang") } // Path implements the method Adapter.Path. func (gears *Gear) Path() string { return gears.ctx.Req.URL.Path } // Method implements the method Adapter.Method. func (gears *Gear) Method() string { return gears.ctx.Req.Method } // FormParam implements the method Adapter.FormParam. func (gears *Gear) FormParam() url.Values { _ = gears.ctx.Req.ParseMultipartForm(32 << 20) return gears.ctx.Req.PostForm } // IsPjax implements the method Adapter.IsPjax. func (gears *Gear) IsPjax() bool { return gears.ctx.Req.Header.Get(constant.PjaxHeader) == "true" } // Query implements the method Adapter.Query. func (gears *Gear) Query() url.Values { return gears.ctx.Req.URL.Query() } // Request implements the method Adapter.Request. func (gears *Gear) Request() *http.Request { return gears.ctx.Req } ================================================ FILE: adapter/gf/gf.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package gf import ( "bytes" "errors" "net/http" "net/url" "regexp" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" "github.com/gogf/gf/net/ghttp" ) // Gf structure value is a Gf GoAdmin adapter. type Gf struct { adapter.BaseAdapter ctx *ghttp.Request app *ghttp.Server } func init() { engine.Register(new(Gf)) } // User implements the method Adapter.User. func (gf *Gf) User(ctx interface{}) (models.UserModel, bool) { return gf.GetUser(ctx, gf) } // Use implements the method Adapter.Use. func (gf *Gf) Use(app interface{}, plugs []plugins.Plugin) error { return gf.GetUse(app, plugs, gf) } // Content implements the method Adapter.Content. func (gf *Gf) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { gf.GetContent(ctx, getPanelFn, gf, btns, fn) } type HandlerFunc func(ctx *ghttp.Request) (types.Panel, error) func Content(handler HandlerFunc) ghttp.HandlerFunc { return func(ctx *ghttp.Request) { engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(*ghttp.Request)) }) } } // SetApp implements the method Adapter.SetApp. func (gf *Gf) SetApp(app interface{}) error { var ( eng *ghttp.Server ok bool ) if eng, ok = app.(*ghttp.Server); !ok { return errors.New("gf adapter SetApp: wrong parameter") } gf.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (gf *Gf) AddHandler(method, path string, handlers context.Handlers) { gf.app.BindHandler(strings.ToUpper(method)+":"+path, func(c *ghttp.Request) { ctx := context.NewContext(c.Request) newPath := path reg1 := regexp.MustCompile(":(.*?)/") reg2 := regexp.MustCompile(":(.*?)$") params := reg1.FindAllString(newPath, -1) newPath = reg1.ReplaceAllString(newPath, "") params = append(params, reg2.FindAllString(newPath, -1)...) for _, param := range params { p := utils.ReplaceAll(param, ":", "", "/", "") if c.Request.URL.RawQuery == "" { c.Request.URL.RawQuery += p + "=" + c.GetRequestString(p) } else { c.Request.URL.RawQuery += "&" + p + "=" + c.GetRequestString(p) } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.Response.Header().Add(key, head[0]) } if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) c.Response.WriteStatus(ctx.Response.StatusCode, buf.Bytes()) } else { c.Response.WriteStatus(ctx.Response.StatusCode) } }) } // Name implements the method Adapter.Name. func (*Gf) Name() string { return "gf" } // SetContext implements the method Adapter.SetContext. func (*Gf) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx *ghttp.Request ok bool ) if ctx, ok = contextInterface.(*ghttp.Request); !ok { panic("gf adapter SetContext: wrong parameter") } return &Gf{ctx: ctx} } // Redirect implements the method Adapter.Redirect. func (gf *Gf) Redirect() { gf.ctx.Response.RedirectTo(config.Url(config.GetLoginUrl())) } // SetContentType implements the method Adapter.SetContentType. func (gf *Gf) SetContentType() { gf.ctx.Response.Header().Add("Content-Type", gf.HTMLContentType()) } // Write implements the method Adapter.Write. func (gf *Gf) Write(body []byte) { gf.ctx.Response.WriteStatus(http.StatusOK, body) } // GetCookie implements the method Adapter.GetCookie. func (gf *Gf) GetCookie() (string, error) { return gf.ctx.Cookie.Get(gf.CookieKey()), nil } // Lang implements the method Adapter.Lang. func (gf *Gf) Lang() string { return gf.ctx.Request.URL.Query().Get("__ga_lang") } // Path implements the method Adapter.Path. func (gf *Gf) Path() string { return gf.ctx.URL.Path } // Method implements the method Adapter.Method. func (gf *Gf) Method() string { return gf.ctx.Method } // FormParam implements the method Adapter.FormParam. func (gf *Gf) FormParam() url.Values { return gf.ctx.Form } // IsPjax implements the method Adapter.IsPjax. func (gf *Gf) IsPjax() bool { return gf.ctx.Header.Get(constant.PjaxHeader) == "true" } // Query implements the method Adapter.Query. func (gf *Gf) Query() url.Values { return gf.ctx.Request.URL.Query() } // Request implements the method Adapter.Request. func (gf *Gf) Request() *http.Request { return gf.ctx.Request } ================================================ FILE: adapter/gf2/gf2.go ================================================ package gf2 import ( "bytes" "errors" "net/http" "net/url" "regexp" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/constant" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/template/types" "github.com/gogf/gf/v2/net/ghttp" ) type GF2 struct { adapter.BaseAdapter ctx *ghttp.Request app *ghttp.Server } func init() { engine.Register(new(GF2)) } func (*GF2) Name() string { return "gf2" } func (gf2 *GF2) Use(app interface{}, plugins []plugins.Plugin) error { return gf2.GetUse(app, plugins, gf2) } func (gf2 *GF2) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { gf2.GetContent(ctx, getPanelFn, gf2, btns, fn) } func (gf2 *GF2) User(ctx interface{}) (models.UserModel, bool) { return gf2.GetUser(ctx, gf2) } func (gf2 *GF2) AddHandler(method, path string, handlers context.Handlers) { gf2.app.BindHandler(strings.ToUpper(method)+":"+path, func(c *ghttp.Request) { ctx := context.NewContext(c.Request) newPath := path reg1 := regexp.MustCompile(":(.*?)/") reg2 := regexp.MustCompile(":(.*?)$") params := reg1.FindAllString(newPath, -1) newPath = reg1.ReplaceAllString(newPath, "") params = append(params, reg2.FindAllString(newPath, -1)...) for _, param := range params { p := utils.ReplaceAll(param, ":", "", "/", "") if c.Request.URL.RawQuery == "" { c.Request.URL.RawQuery += p + "=" + c.GetRequest(p).String() } else { c.Request.URL.RawQuery += "&" + p + "=" + c.GetRequest(p).String() } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.Response.Header().Add(key, head[0]) } if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) c.Response.WriteStatus(ctx.Response.StatusCode, buf.Bytes()) } else { c.Response.WriteStatus(ctx.Response.StatusCode) } }) } func (gf2 *GF2) SetApp(app interface{}) error { var ( eng *ghttp.Server ok bool ) if eng, ok = app.(*ghttp.Server); !ok { return errors.New("gf2 adapter SetApp: wrong parameter") } gf2.app = eng return nil } func (*GF2) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx *ghttp.Request ok bool ) if ctx, ok = contextInterface.(*ghttp.Request); !ok { panic("gf2 adapter SetContext: wrong parameter") } return &GF2{ctx: ctx} } func (gf2 *GF2) GetCookie() (string, error) { return gf2.ctx.Cookie.Get(gf2.CookieKey()).String(), nil } func (gf2 *GF2) Lang() string { return gf2.ctx.Request.URL.Query().Get("__ga_lang") } func (gf2 *GF2) Path() string { return gf2.ctx.URL.Path } func (gf2 *GF2) Method() string { return gf2.ctx.Method } func (gf2 *GF2) FormParam() url.Values { return gf2.ctx.Form } func (gf2 *GF2) Query() url.Values { return gf2.ctx.Request.URL.Query() } func (gf2 *GF2) IsPjax() bool { return gf2.ctx.Header.Get(constant.PjaxHeader) == "true" } func (gf2 *GF2) Redirect() { gf2.ctx.Response.RedirectTo(config.Url(config.GetLoginUrl())) } func (gf2 *GF2) SetContentType() { gf2.ctx.Response.Header().Add("Content-Type", gf2.HTMLContentType()) } func (gf2 *GF2) Write(body []byte) { gf2.ctx.Response.WriteStatus(http.StatusOK, body) } // Request implements the method Adapter.Request. func (gf2 *GF2) Request() *http.Request { return gf2.ctx.Request } ================================================ FILE: adapter/gin/gin.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package gin import ( "bytes" "errors" "net/http" "net/url" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" "github.com/gin-gonic/gin" ) // Gin structure value is a Gin GoAdmin adapter. type Gin struct { adapter.BaseAdapter ctx *gin.Context app *gin.Engine } func init() { engine.Register(new(Gin)) } // User implements the method Adapter.User. func (gins *Gin) User(ctx interface{}) (models.UserModel, bool) { return gins.GetUser(ctx, gins) } // Use implements the method Adapter.Use. func (gins *Gin) Use(app interface{}, plugs []plugins.Plugin) error { return gins.GetUse(app, plugs, gins) } // Content implements the method Adapter.Content. func (gins *Gin) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { gins.GetContent(ctx, getPanelFn, gins, btns, fn) } type HandlerFunc func(ctx *gin.Context) (types.Panel, error) func Content(handler HandlerFunc) gin.HandlerFunc { return func(ctx *gin.Context) { engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(*gin.Context)) }) } } // SetApp implements the method Adapter.SetApp. func (gins *Gin) SetApp(app interface{}) error { var ( eng *gin.Engine ok bool ) if eng, ok = app.(*gin.Engine); !ok { return errors.New("gin adapter SetApp: wrong parameter") } gins.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (gins *Gin) AddHandler(method, path string, handlers context.Handlers) { gins.app.Handle(strings.ToUpper(method), path, func(c *gin.Context) { ctx := context.NewContext(c.Request) for _, param := range c.Params { if c.Request.URL.RawQuery == "" { c.Request.URL.RawQuery += strings.ReplaceAll(param.Key, ":", "") + "=" + param.Value } else { c.Request.URL.RawQuery += "&" + strings.ReplaceAll(param.Key, ":", "") + "=" + param.Value } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.Header(key, head[0]) } if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) c.String(ctx.Response.StatusCode, buf.String()) } else { c.Status(ctx.Response.StatusCode) } }) } // Name implements the method Adapter.Name. func (*Gin) Name() string { return "gin" } // SetContext implements the method Adapter.SetContext. func (*Gin) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx *gin.Context ok bool ) if ctx, ok = contextInterface.(*gin.Context); !ok { panic("gin adapter SetContext: wrong parameter") } return &Gin{ctx: ctx} } // Redirect implements the method Adapter.Redirect. func (gins *Gin) Redirect() { gins.ctx.Redirect(http.StatusFound, config.Url(config.GetLoginUrl())) gins.ctx.Abort() } // SetContentType implements the method Adapter.SetContentType. func (*Gin) SetContentType() {} // Write implements the method Adapter.Write. func (gins *Gin) Write(body []byte) { gins.ctx.Data(http.StatusOK, gins.HTMLContentType(), body) } // GetCookie implements the method Adapter.GetCookie. func (gins *Gin) GetCookie() (string, error) { return gins.ctx.Cookie(gins.CookieKey()) } // Lang implements the method Adapter.Lang. func (gins *Gin) Lang() string { return gins.ctx.Request.URL.Query().Get("__ga_lang") } // Path implements the method Adapter.Path. func (gins *Gin) Path() string { return gins.ctx.Request.URL.Path } // Method implements the method Adapter.Method. func (gins *Gin) Method() string { return gins.ctx.Request.Method } // FormParam implements the method Adapter.FormParam. func (gins *Gin) FormParam() url.Values { _ = gins.ctx.Request.ParseMultipartForm(32 << 20) return gins.ctx.Request.PostForm } // IsPjax implements the method Adapter.IsPjax. func (gins *Gin) IsPjax() bool { return gins.ctx.Request.Header.Get(constant.PjaxHeader) == "true" } // Query implements the method Adapter.Query. func (gins *Gin) Query() url.Values { return gins.ctx.Request.URL.Query() } // Request implements the method Adapter.Request. func (gins *Gin) Request() *http.Request { return gins.ctx.Request } ================================================ FILE: adapter/gofiber/gofiber.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package gofiber import ( "errors" "io" "net/http" "net/url" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" "github.com/gofiber/fiber/v2" "github.com/valyala/fasthttp" ) // Fasthttp structure value is a Fasthttp GoAdmin adapter. type Gofiber struct { adapter.BaseAdapter ctx *fiber.Ctx app *fiber.App } func init() { engine.Register(new(Gofiber)) } // User implements the method Adapter.User. func (gof *Gofiber) User(ctx interface{}) (models.UserModel, bool) { return gof.GetUser(ctx, gof) } // Use implements the method Adapter.Use. func (gof *Gofiber) Use(app interface{}, plugs []plugins.Plugin) error { return gof.GetUse(app, plugs, gof) } // Content implements the method Adapter.Content. func (gof *Gofiber) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { gof.GetContent(ctx, getPanelFn, gof, btns, fn) } // SetApp implements the method Adapter.SetApp. func (gof *Gofiber) SetApp(app interface{}) error { var ( eng *fiber.App ok bool ) if eng, ok = app.(*fiber.App); !ok { return errors.New("fiber.App adapter SetApp: wrong parameter") } gof.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (gof *Gofiber) AddHandler(method, path string, handlers context.Handlers) { gof.app.Add(strings.ToUpper(method), path, func(c *fiber.Ctx) error { httpreq := convertCtx(c.Context()) ctx := context.NewContext(httpreq) for _, key := range c.Route().Params { if httpreq.URL.RawQuery == "" { httpreq.URL.RawQuery += strings.ReplaceAll(key, ":", "") + "=" + c.Params(key) } else { httpreq.URL.RawQuery += "&" + strings.ReplaceAll(key, ":", "") + "=" + c.Params(key) } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.Set(key, head[0]) } return c.Status(ctx.Response.StatusCode).SendStream(ctx.Response.Body) }) } func convertCtx(ctx *fasthttp.RequestCtx) *http.Request { var r http.Request body := ctx.PostBody() r.Method = string(ctx.Method()) r.Proto = "HTTP/1.1" r.ProtoMajor = 1 r.ProtoMinor = 1 r.RequestURI = string(ctx.RequestURI()) r.ContentLength = int64(len(body)) r.Host = string(ctx.Host()) r.RemoteAddr = ctx.RemoteAddr().String() hdr := make(http.Header) ctx.Request.Header.VisitAll(func(k, v []byte) { sk := string(k) sv := string(v) switch sk { case "Transfer-Encoding": r.TransferEncoding = append(r.TransferEncoding, sv) default: hdr.Set(sk, sv) } }) r.Header = hdr r.Body = &netHTTPBody{body} rURL, err := url.ParseRequestURI(r.RequestURI) if err != nil { ctx.Logger().Printf("cannot parse requestURI %q: %s", r.RequestURI, err) ctx.Error("Internal Server Error", fasthttp.StatusInternalServerError) return &r } r.URL = rURL return &r } type netHTTPBody struct { b []byte } func (r *netHTTPBody) Read(p []byte) (int, error) { if len(r.b) == 0 { return 0, io.EOF } n := copy(p, r.b) r.b = r.b[n:] return n, nil } func (r *netHTTPBody) Close() error { r.b = r.b[:0] return nil } // Name implements the method Adapter.Name. func (*Gofiber) Name() string { return "gofiber" } // SetContext implements the method Adapter.SetContext. func (*Gofiber) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx *fiber.Ctx ok bool ) if ctx, ok = contextInterface.(*fiber.Ctx); !ok { panic("gofiber adapter SetContext: wrong parameter") } return &Gofiber{ctx: ctx} } // Redirect implements the method Adapter.Redirect. func (gof *Gofiber) Redirect() { _ = gof.ctx.Redirect(config.Url(config.GetLoginUrl()), http.StatusFound) } // SetContentType implements the method Adapter.SetContentType. func (gof *Gofiber) SetContentType() { gof.ctx.Response().Header.Set("Content-Type", gof.HTMLContentType()) } // Write implements the method Adapter.Write. func (gof *Gofiber) Write(body []byte) { _, _ = gof.ctx.Write(body) } // GetCookie implements the method Adapter.GetCookie. func (gof *Gofiber) GetCookie() (string, error) { return string(gof.ctx.Cookies(gof.CookieKey())), nil } // Lang implements the method Adapter.Lang. func (gof *Gofiber) Lang() string { return string(gof.ctx.Request().URI().QueryArgs().Peek("__ga_lang")) } // Path implements the method Adapter.Path. func (gof *Gofiber) Path() string { return string(gof.ctx.Path()) } // Method implements the method Adapter.Method. func (gof *Gofiber) Method() string { return string(gof.ctx.Method()) } // FormParam implements the method Adapter.FormParam. func (gof *Gofiber) FormParam() url.Values { f, _ := gof.ctx.MultipartForm() if f != nil { return f.Value } return url.Values{} } // IsPjax implements the method Adapter.IsPjax. func (gof *Gofiber) IsPjax() bool { return string(gof.ctx.Request().Header.Peek(constant.PjaxHeader)) == "true" } // Query implements the method Adapter.Query. func (gof *Gofiber) Query() url.Values { queryStr := gof.ctx.Context().QueryArgs().QueryString() queryObj, err := url.Parse(string(queryStr)) if err != nil { return url.Values{} } return queryObj.Query() } // Request implements the method Adapter.Request. func (gof *Gofiber) Request() *http.Request { return convertCtx(gof.ctx.Context()) } ================================================ FILE: adapter/gorilla/gorilla.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package gorilla import ( "bytes" "errors" "net/http" "net/url" "regexp" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" "github.com/gorilla/mux" ) // Gorilla structure value is a Gorilla GoAdmin adapter. type Gorilla struct { adapter.BaseAdapter ctx Context app *mux.Router } func init() { engine.Register(new(Gorilla)) } // User implements the method Adapter.User. func (g *Gorilla) User(ctx interface{}) (models.UserModel, bool) { return g.GetUser(ctx, g) } // Use implements the method Adapter.Use. func (g *Gorilla) Use(app interface{}, plugs []plugins.Plugin) error { return g.GetUse(app, plugs, g) } // Content implements the method Adapter.Content. func (g *Gorilla) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { g.GetContent(ctx, getPanelFn, g, btns, fn) } type HandlerFunc func(ctx Context) (types.Panel, error) func Content(handler HandlerFunc) http.HandlerFunc { return func(writer http.ResponseWriter, request *http.Request) { ctx := Context{ Request: request, Response: writer, } engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(Context)) }) } } // SetApp implements the method Adapter.SetApp. func (g *Gorilla) SetApp(app interface{}) error { var ( eng *mux.Router ok bool ) if eng, ok = app.(*mux.Router); !ok { return errors.New("gorilla adapter SetApp: wrong parameter") } g.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (g *Gorilla) AddHandler(method, path string, handlers context.Handlers) { reg1 := regexp.MustCompile(":(.*?)/") reg2 := regexp.MustCompile(":(.*?)$") u := path u = reg1.ReplaceAllString(u, "{$1}/") u = reg2.ReplaceAllString(u, "{$1}") g.app.HandleFunc(u, func(w http.ResponseWriter, r *http.Request) { ctx := context.NewContext(r) params := mux.Vars(r) for key, param := range params { if r.URL.RawQuery == "" { r.URL.RawQuery += strings.ReplaceAll(key, ":", "") + "=" + param } else { r.URL.RawQuery += "&" + strings.ReplaceAll(key, ":", "") + "=" + param } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { w.Header().Add(key, head[0]) } if ctx.Response.Body == nil { w.WriteHeader(ctx.Response.StatusCode) return } w.WriteHeader(ctx.Response.StatusCode) buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) _, err := w.Write(buf.Bytes()) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } }).Methods(strings.ToUpper(method)) } // Context wraps the Request and Response object of Gorilla. type Context struct { Request *http.Request Response http.ResponseWriter } // Name implements the method Adapter.Name. func (*Gorilla) Name() string { return "gorilla" } // SetContext implements the method Adapter.SetContext. func (*Gorilla) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx Context ok bool ) if ctx, ok = contextInterface.(Context); !ok { panic("gorilla adapter SetContext: wrong parameter") } return &Gorilla{ctx: ctx} } // Redirect implements the method Adapter.Redirect. func (g *Gorilla) Redirect() { http.Redirect(g.ctx.Response, g.ctx.Request, config.Url(config.GetLoginUrl()), http.StatusFound) } // SetContentType implements the method Adapter.SetContentType. func (g *Gorilla) SetContentType() { g.ctx.Response.Header().Set("Content-Type", g.HTMLContentType()) } // Write implements the method Adapter.Write. func (g *Gorilla) Write(body []byte) { _, _ = g.ctx.Response.Write(body) } // GetCookie implements the method Adapter.GetCookie. func (g *Gorilla) GetCookie() (string, error) { cookie, err := g.ctx.Request.Cookie(g.CookieKey()) if err != nil { return "", err } return cookie.Value, err } // Lang implements the method Adapter.Lang. func (g *Gorilla) Lang() string { return g.ctx.Request.URL.Query().Get("__ga_lang") } // Path implements the method Adapter.Path. func (g *Gorilla) Path() string { return g.ctx.Request.RequestURI } // Method implements the method Adapter.Method. func (g *Gorilla) Method() string { return g.ctx.Request.Method } // FormParam implements the method Adapter.FormParam. func (g *Gorilla) FormParam() url.Values { _ = g.ctx.Request.ParseMultipartForm(32 << 20) return g.ctx.Request.PostForm } // IsPjax implements the method Adapter.IsPjax. func (g *Gorilla) IsPjax() bool { return g.ctx.Request.Header.Get(constant.PjaxHeader) == "true" } // Query implements the method Adapter.Query. func (g *Gorilla) Query() url.Values { return g.ctx.Request.URL.Query() } // Request implements the method Adapter.Request. func (g *Gorilla) Request() *http.Request { return g.ctx.Request } ================================================ FILE: adapter/iris/iris.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package iris import ( "bytes" "errors" "net/http" "net/url" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/template/types" "github.com/kataras/iris/v12" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" ) // Iris structure value is an Iris GoAdmin adapter. type Iris struct { adapter.BaseAdapter ctx iris.Context app *iris.Application } func init() { engine.Register(new(Iris)) } // User implements the method Adapter.User. func (is *Iris) User(ctx interface{}) (models.UserModel, bool) { return is.GetUser(ctx, is) } // Use implements the method Adapter.Use. func (is *Iris) Use(app interface{}, plugs []plugins.Plugin) error { return is.GetUse(app, plugs, is) } // Content implements the method Adapter.Content. func (is *Iris) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { is.GetContent(ctx, getPanelFn, is, btns, fn) } type HandlerFunc func(ctx iris.Context) (types.Panel, error) func Content(handler HandlerFunc) iris.Handler { return func(ctx iris.Context) { engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(iris.Context)) }) } } // SetApp implements the method Adapter.SetApp. func (is *Iris) SetApp(app interface{}) error { var ( eng *iris.Application ok bool ) if eng, ok = app.(*iris.Application); !ok { return errors.New("iris adapter SetApp: wrong parameter") } is.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (is *Iris) AddHandler(method, path string, handlers context.Handlers) { is.app.Handle(strings.ToUpper(method), path, func(c iris.Context) { ctx := context.NewContext(c.Request()) var params = map[string]string{} c.Params().Visit(func(key string, value string) { params[key] = value }) for key, value := range params { if c.Request().URL.RawQuery == "" { c.Request().URL.RawQuery += strings.ReplaceAll(key, ":", "") + "=" + value } else { c.Request().URL.RawQuery += "&" + strings.ReplaceAll(key, ":", "") + "=" + value } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { c.Header(key, head[0]) } c.StatusCode(ctx.Response.StatusCode) if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) _, _ = c.WriteString(buf.String()) } }) } // Name implements the method Adapter.Name. func (*Iris) Name() string { return "iris" } // SetContext implements the method Adapter.SetContext. func (*Iris) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx iris.Context ok bool ) if ctx, ok = contextInterface.(iris.Context); !ok { panic("iris adapter SetContext: wrong parameter") } return &Iris{ctx: ctx} } // Redirect implements the method Adapter.Redirect. func (is *Iris) Redirect() { is.ctx.Redirect(config.Url(config.GetLoginUrl()), http.StatusFound) } // SetContentType implements the method Adapter.SetContentType. func (is *Iris) SetContentType() { is.ctx.Header("Content-Type", is.HTMLContentType()) } // Write implements the method Adapter.Write. func (is *Iris) Write(body []byte) { _, _ = is.ctx.Write(body) } // GetCookie implements the method Adapter.GetCookie. func (is *Iris) GetCookie() (string, error) { return is.ctx.GetCookie(is.CookieKey()), nil } // Lang implements the method Adapter.Lang. func (is *Iris) Lang() string { return is.ctx.Request().URL.Query().Get("__ga_lang") } // Path implements the method Adapter.Path. func (is *Iris) Path() string { return is.ctx.Path() } // Method implements the method Adapter.Method. func (is *Iris) Method() string { return is.ctx.Method() } // FormParam implements the method Adapter.FormParam. func (is *Iris) FormParam() url.Values { return is.ctx.FormValues() } // IsPjax implements the method Adapter.IsPjax. func (is *Iris) IsPjax() bool { return is.ctx.GetHeader(constant.PjaxHeader) == "true" } // Query implements the method Adapter.Query. func (is *Iris) Query() url.Values { return is.ctx.Request().URL.Query() } // Request implements the method Adapter.Request. func (is *Iris) Request() *http.Request { return is.ctx.Request() } ================================================ FILE: adapter/nethttp/nethttp.go ================================================ package nethttp import ( "bytes" "errors" "fmt" "net/http" "net/url" "regexp" "strings" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/engine" cfg "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/template/types" ) type NetHTTP struct { adapter.BaseAdapter ctx Context app *http.ServeMux } func init() { engine.Register(new(NetHTTP)) } // User implements the method Adapter.User. func (nh *NetHTTP) User(ctx interface{}) (models.UserModel, bool) { return nh.GetUser(ctx, nh) } // Use implements the method Adapter.Use. func (nh *NetHTTP) Use(app interface{}, plugs []plugins.Plugin) error { return nh.GetUse(app, plugs, nh) } // Content implements the method Adapter.Content. func (nh *NetHTTP) Content(ctx interface{}, getPanelFn types.GetPanelFn, fn context.NodeProcessor, btns ...types.Button) { nh.GetContent(ctx, getPanelFn, nh, btns, fn) } type HandlerFunc func(ctx Context) (types.Panel, error) func Content(handler HandlerFunc) http.HandlerFunc { return func(writer http.ResponseWriter, request *http.Request) { ctx := Context{ Request: request, Response: writer, } engine.Content(ctx, func(ctx interface{}) (types.Panel, error) { return handler(ctx.(Context)) }) } } // SetApp implements the method Adapter.SetApp. func (nh *NetHTTP) SetApp(app interface{}) error { var ( eng *http.ServeMux ok bool ) if eng, ok = app.(*http.ServeMux); !ok { return errors.New("net/http adapter SetApp: wrong parameter") } nh.app = eng return nil } // AddHandler implements the method Adapter.AddHandler. func (nh *NetHTTP) AddHandler(method, path string, handlers context.Handlers) { url := path reg1 := regexp.MustCompile(":(.*?)/") reg2 := regexp.MustCompile(":(.*?)$") url = reg1.ReplaceAllString(url, "{$1}/") url = reg2.ReplaceAllString(url, "{$1}") if len(url) > 1 && url[0] == '/' && url[1] == '/' { url = url[1:] } pattern := fmt.Sprintf("%s %s", strings.ToUpper(method), url) nh.app.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) { if r.URL.Path[len(r.URL.Path)-1] == '/' { r.URL.Path = r.URL.Path[:len(r.URL.Path)-1] } ctx := context.NewContext(r) params := getPathParams(url, r.URL.Path) for key, value := range params { if r.URL.RawQuery == "" { r.URL.RawQuery += strings.ReplaceAll(key, ":", "") + "=" + value } else { r.URL.RawQuery += "&" + strings.ReplaceAll(key, ":", "") + "=" + value } } ctx.SetHandlers(handlers).Next() for key, head := range ctx.Response.Header { w.Header().Set(key, head[0]) } if ctx.Response.Body != nil { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(ctx.Response.Body) w.WriteHeader(ctx.Response.StatusCode) _, _ = w.Write(buf.Bytes()) } else { w.WriteHeader(ctx.Response.StatusCode) } }) } // HandleFun is type of route methods of chi. type HandleFun func(pattern string, handlerFn http.HandlerFunc) // Context wraps the Request and Response object of Chi. type Context struct { Request *http.Request Response http.ResponseWriter } // SetContext implements the method Adapter.SetContext. func (*NetHTTP) SetContext(contextInterface interface{}) adapter.WebFrameWork { var ( ctx Context ok bool ) if ctx, ok = contextInterface.(Context); !ok { panic("net/http adapter SetContext: wrong parameter") } return &NetHTTP{ctx: ctx} } // Name implements the method Adapter.Name. func (*NetHTTP) Name() string { return "net/http" } // Redirect implements the method Adapter.Redirect. func (nh *NetHTTP) Redirect() { http.Redirect(nh.ctx.Response, nh.ctx.Request, cfg.Url(cfg.GetLoginUrl()), http.StatusFound) } // SetContentType implements the method Adapter.SetContentType. func (nh *NetHTTP) SetContentType() { nh.ctx.Response.Header().Set("Content-Type", nh.HTMLContentType()) } // Write implements the method Adapter.Write. func (nh *NetHTTP) Write(body []byte) { nh.ctx.Response.WriteHeader(http.StatusOK) _, _ = nh.ctx.Response.Write(body) } // GetCookie implements the method Adapter.GetCookie. func (nh *NetHTTP) GetCookie() (string, error) { cookie, err := nh.ctx.Request.Cookie(nh.CookieKey()) if err != nil { return "", err } return cookie.Value, err } // Lang implements the method Adapter.Lang. func (nh *NetHTTP) Lang() string { return nh.ctx.Request.URL.Query().Get("__ga_lang") } // Path implements the method Adapter.Path. func (nh *NetHTTP) Path() string { return nh.ctx.Request.URL.Path } // Method implements the method Adapter.Method. func (nh *NetHTTP) Method() string { return nh.ctx.Request.Method } // FormParam implements the method Adapter.FormParam. func (nh *NetHTTP) FormParam() url.Values { _ = nh.ctx.Request.ParseMultipartForm(32 << 20) return nh.ctx.Request.PostForm } // IsPjax implements the method Adapter.IsPjax. func (nh *NetHTTP) IsPjax() bool { return nh.ctx.Request.Header.Get(constant.PjaxHeader) == "true" } // Query implements the method Adapter.Query. func (nh *NetHTTP) Query() url.Values { return nh.ctx.Request.URL.Query() } // Request implements the method Adapter.Request. func (nh *NetHTTP) Request() *http.Request { return nh.ctx.Request } // getPathParams extracts path parameters from a URL based on a given pattern. func getPathParams(pattern, url string) map[string]string { params := make(map[string]string) // Convert pattern to regex placeholderRegex := regexp.MustCompile(`\{(\w+)\}`) regexPattern := "^" + placeholderRegex.ReplaceAllStringFunc(pattern, func(s string) string { return `(?P<` + s[1:len(s)-1] + `>\w+)` }) + `$` // Compile regex regex := regexp.MustCompile(regexPattern) // Match the URL against the regex match := regex.FindStringSubmatch(url) if match == nil { return nil } // Extract named groups for i, name := range regex.SubexpNames() { if i != 0 && name != "" { // Ignore the whole match at index 0 params[name] = match[i] } } return params } ================================================ FILE: context/context.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package context import ( "bytes" "encoding/json" "errors" "fmt" "io" "math" "net" "net/http" "net/url" "os" "path" "strings" "time" "github.com/GoAdminGroup/go-admin/modules/constant" ) const abortIndex int8 = math.MaxInt8 / 2 // Context is the simplify version of web framework context. // But it is important which will be used in plugins to custom // the request and response. And adapter will help to transform // the Context to the web framework`s context. It has three attributes. // Request and response are belongs to net/http package. UserValue // is the custom key-value store of context. type Context struct { Request *http.Request Response *http.Response UserValue map[string]interface{} index int8 handlers Handlers } // Path is used in the matching of request and response. Url stores the // raw register url. RegUrl contains the wildcard which on behalf of // the route params. type Path struct { URL string Method string } type RouterMap map[string]Router func (r RouterMap) Get(name string) Router { return r[name] } type Router struct { Methods []string Patten string } func (r Router) Method() string { return r.Methods[0] } func (r Router) GetURL(value ...string) string { u := r.Patten for i := 0; i < len(value); i += 2 { u = strings.ReplaceAll(u, ":__"+value[i], value[i+1]) } return u } type NodeProcessor func(...Node) type Node struct { Path string Method string Handlers []Handler Value map[string]interface{} } // SetUserValue set the value of user context. func (ctx *Context) SetUserValue(key string, value interface{}) { ctx.UserValue[key] = value } // GetUserValue get the value of key. func (ctx *Context) GetUserValue(key string) interface{} { return ctx.UserValue[key] } // Path return the url path. func (ctx *Context) Path() string { return ctx.Request.URL.Path } // Abort abort the context. func (ctx *Context) Abort() { ctx.index = abortIndex } // Next should be used only inside middleware. func (ctx *Context) Next() { ctx.index++ for s := int8(len(ctx.handlers)); ctx.index < s; ctx.index++ { ctx.handlers[ctx.index](ctx) } } // SetHandlers set the handlers of Context. func (ctx *Context) SetHandlers(handlers Handlers) *Context { ctx.handlers = handlers return ctx } // Method return the request method. func (ctx *Context) Method() string { return ctx.Request.Method } // NewContext used in adapter which return a Context with request // and slice of UserValue and a default Response. func NewContext(req *http.Request) *Context { return &Context{ Request: req, UserValue: make(map[string]interface{}), Response: &http.Response{ StatusCode: http.StatusOK, Header: make(http.Header), }, index: -1, } } const ( HeaderContentType = "Content-Type" HeaderLastModified = "Last-Modified" HeaderIfModifiedSince = "If-Modified-Since" HeaderCacheControl = "Cache-Control" HeaderETag = "ETag" HeaderContentDisposition = "Content-Disposition" HeaderContentLength = "Content-Length" HeaderContentEncoding = "Content-Encoding" GzipHeaderValue = "gzip" HeaderAcceptEncoding = "Accept-Encoding" HeaderVary = "Vary" ThemeKey = "__ga_theme" ) func (ctx *Context) BindJSON(data interface{}) error { if ctx.Request.Body != nil { b, err := io.ReadAll(ctx.Request.Body) if err == nil { return json.Unmarshal(b, data) } return err } return errors.New("empty request body") } func (ctx *Context) MustBindJSON(data interface{}) { if ctx.Request.Body != nil { b, err := io.ReadAll(ctx.Request.Body) if err != nil { panic(err) } err = json.Unmarshal(b, data) if err != nil { panic(err) } } panic("empty request body") } // Write save the given status code, headers and body string into the response. func (ctx *Context) Write(code int, header map[string]string, Body string) { ctx.Response.StatusCode = code for key, head := range header { ctx.AddHeader(key, head) } ctx.Response.Body = io.NopCloser(strings.NewReader(Body)) } // JSON serializes the given struct as JSON into the response body. // It also sets the Content-Type as "application/json". func (ctx *Context) JSON(code int, Body map[string]interface{}) { ctx.Response.StatusCode = code ctx.SetContentType("application/json") BodyStr, err := json.Marshal(Body) if err != nil { panic(err) } ctx.Response.Body = io.NopCloser(bytes.NewReader(BodyStr)) } // DataWithHeaders save the given status code, headers and body data into the response. func (ctx *Context) DataWithHeaders(code int, header map[string]string, data []byte) { ctx.Response.StatusCode = code for key, head := range header { ctx.AddHeader(key, head) } ctx.Response.Body = io.NopCloser(bytes.NewBuffer(data)) } // Data writes some data into the body stream and updates the HTTP code. func (ctx *Context) Data(code int, contentType string, data []byte) { ctx.Response.StatusCode = code ctx.SetContentType(contentType) ctx.Response.Body = io.NopCloser(bytes.NewBuffer(data)) } // Redirect add redirect url to header. func (ctx *Context) Redirect(path string) { ctx.Response.StatusCode = http.StatusFound ctx.SetContentType("text/html; charset=utf-8") ctx.AddHeader("Location", path) } // HTML output html response. func (ctx *Context) HTML(code int, body string) { ctx.SetContentType("text/html; charset=utf-8") ctx.SetStatusCode(code) ctx.WriteString(body) } // HTMLByte output html response. func (ctx *Context) HTMLByte(code int, body []byte) { ctx.SetContentType("text/html; charset=utf-8") ctx.SetStatusCode(code) ctx.Response.Body = io.NopCloser(bytes.NewBuffer(body)) } // WriteString save the given body string into the response. func (ctx *Context) WriteString(body string) { ctx.Response.Body = io.NopCloser(strings.NewReader(body)) } // SetStatusCode save the given status code into the response. func (ctx *Context) SetStatusCode(code int) { ctx.Response.StatusCode = code } // SetContentType save the given content type header into the response header. func (ctx *Context) SetContentType(contentType string) { ctx.AddHeader(HeaderContentType, contentType) } func (ctx *Context) SetLastModified(modtime time.Time) { if !IsZeroTime(modtime) { ctx.AddHeader(HeaderLastModified, modtime.UTC().Format(http.TimeFormat)) // or modtime.UTC()? } } var unixEpochTime = time.Unix(0, 0) // IsZeroTime reports whether t is obviously unspecified (either zero or Unix()=0). func IsZeroTime(t time.Time) bool { return t.IsZero() || t.Equal(unixEpochTime) } // ParseTime parses a time header (such as the Date: header), // trying each forth formats // that are allowed by HTTP/1.1: // time.RFC850, and time.ANSIC. var ParseTime = func(text string) (t time.Time, err error) { t, err = time.Parse(http.TimeFormat, text) if err != nil { return http.ParseTime(text) } return } func (ctx *Context) WriteNotModified() { // RFC 7232 section 4.1: // a sender SHOULD NOT generate representation metadata other than the // above listed fields unless said metadata exists for the purpose of // guiding cache updates (e.g.," Last-Modified" might be useful if the // response does not have an ETag field). delete(ctx.Response.Header, HeaderContentType) delete(ctx.Response.Header, HeaderContentLength) if ctx.Headers(HeaderETag) != "" { delete(ctx.Response.Header, HeaderLastModified) } ctx.SetStatusCode(http.StatusNotModified) } func (ctx *Context) CheckIfModifiedSince(modtime time.Time) (bool, error) { if method := ctx.Method(); method != http.MethodGet && method != http.MethodHead { return false, errors.New("skip: method") } ims := ctx.Headers(HeaderIfModifiedSince) if ims == "" || IsZeroTime(modtime) { return false, errors.New("skip: zero time") } t, err := ParseTime(ims) if err != nil { return false, errors.New("skip: " + err.Error()) } // sub-second precision, so // use mtime < t+1s instead of mtime <= t to check for unmodified. if modtime.UTC().Before(t.Add(1 * time.Second)) { return false, nil } return true, nil } // LocalIP return the request client ip. func (ctx *Context) LocalIP() string { xForwardedFor := ctx.Request.Header.Get("X-Forwarded-For") ip := strings.TrimSpace(strings.Split(xForwardedFor, ",")[0]) if ip != "" { return ip } ip = strings.TrimSpace(ctx.Request.Header.Get("X-Real-Ip")) if ip != "" { return ip } if ip, _, err := net.SplitHostPort(strings.TrimSpace(ctx.Request.RemoteAddr)); err == nil { return ip } return "127.0.0.1" } // SetCookie save the given cookie obj into the response Set-Cookie header. func (ctx *Context) SetCookie(cookie *http.Cookie) { if v := cookie.String(); v != "" { ctx.AddHeader("Set-Cookie", v) } } // Query get the query parameter of url. func (ctx *Context) Query(key string) string { return ctx.Request.URL.Query().Get(key) } // QueryAll get the query parameters of url. func (ctx *Context) QueryAll(key string) []string { return ctx.Request.URL.Query()[key] } // QueryDefault get the query parameter of url. If it is empty, return the default. func (ctx *Context) QueryDefault(key, def string) string { value := ctx.Query(key) if value == "" { return def } return value } // Lang get the query parameter of url with given key __ga_lang. func (ctx *Context) Lang() string { return ctx.Query("__ga_lang") } // Theme get the request theme with given key __ga_theme. func (ctx *Context) Theme() string { queryTheme := ctx.Query(ThemeKey) if queryTheme != "" { return queryTheme } cookieTheme := ctx.Cookie(ThemeKey) if cookieTheme != "" { return cookieTheme } return ctx.RefererQuery(ThemeKey) } // Headers get the value of request headers key. func (ctx *Context) Headers(key string) string { return ctx.Request.Header.Get(key) } // Referer get the url string of request header Referer. func (ctx *Context) Referer() string { return ctx.Headers("Referer") } // RefererURL get the url.URL object of request header Referer. func (ctx *Context) RefererURL() *url.URL { ref := ctx.Headers("Referer") if ref == "" { return nil } u, err := url.Parse(ref) if err != nil { return nil } return u } // RefererQuery retrieve the value of given key from url.URL object of request header Referer. func (ctx *Context) RefererQuery(key string) string { if u := ctx.RefererURL(); u != nil { return u.Query().Get(key) } return "" } // FormValue get the value of request form key. func (ctx *Context) FormValue(key string) string { return ctx.Request.FormValue(key) } // PostForm get the values of request form. func (ctx *Context) PostForm() url.Values { _ = ctx.Request.ParseMultipartForm(32 << 20) return ctx.Request.PostForm } func (ctx *Context) WantHTML() bool { return ctx.Method() == "GET" && strings.Contains(ctx.Headers("Accept"), "html") } func (ctx *Context) WantJSON() bool { return strings.Contains(ctx.Headers("Accept"), "json") } // AddHeader adds the key, value pair to the header. func (ctx *Context) AddHeader(key, value string) { ctx.Response.Header.Add(key, value) } // PjaxUrl add pjax url header. func (ctx *Context) PjaxUrl(url string) { ctx.Response.Header.Add(constant.PjaxUrlHeader, url) } // IsPjax check request is pjax or not. func (ctx *Context) IsPjax() bool { return ctx.Headers(constant.PjaxHeader) == "true" } // IsIframe check request is iframe or not. func (ctx *Context) IsIframe() bool { return ctx.Query(constant.IframeKey) == "true" || ctx.Headers(constant.IframeKey) == "true" } // SetHeader set the key, value pair to the header. func (ctx *Context) SetHeader(key, value string) { ctx.Response.Header.Set(key, value) } func (ctx *Context) GetContentType() string { return ctx.Request.Header.Get("Content-Type") } func (ctx *Context) Cookie(name string) string { for _, ck := range ctx.Request.Cookies() { if ck.Name == name { return ck.Value } } return "" } // User return the current login user. func (ctx *Context) User() interface{} { return ctx.UserValue["user"] } // ServeContent serves content, headers are autoset // receives three parameters, it's low-level function, instead you can use .ServeFile(string,bool)/SendFile(string,string) // // You can define your own "Content-Type" header also, after this function call // Doesn't implements resuming (by range), use ctx.SendFile instead func (ctx *Context) ServeContent(content io.ReadSeeker, filename string, modtime time.Time, gzipCompression bool) error { if modified, err := ctx.CheckIfModifiedSince(modtime); !modified && err == nil { ctx.WriteNotModified() return nil } if ctx.GetContentType() == "" { ctx.SetContentType(filename) } buf, _ := io.ReadAll(content) ctx.Response.Body = io.NopCloser(bytes.NewBuffer(buf)) return nil } // ServeFile serves a view file, to send a file ( zip for example) to the client you should use the SendFile(serverfilename,clientfilename) func (ctx *Context) ServeFile(filename string, gzipCompression bool) error { f, err := os.Open(filename) if err != nil { return fmt.Errorf("%d", http.StatusNotFound) } defer func() { _ = f.Close() }() fi, _ := f.Stat() if fi.IsDir() { return ctx.ServeFile(path.Join(filename, "index.html"), gzipCompression) } return ctx.ServeContent(f, fi.Name(), fi.ModTime(), gzipCompression) } type HandlerMap map[Path]Handlers // App is the key struct of the package. App as a member of plugin // entity contains the request and the corresponding handler. Prefix // is the url prefix and MiddlewareList is for control flow. type App struct { Requests []Path Handlers HandlerMap Middlewares Handlers Prefix string Routers RouterMap routeIndex int routeANY bool } // NewApp return an empty app. func NewApp() *App { return &App{ Requests: make([]Path, 0), Handlers: make(HandlerMap), Prefix: "/", Middlewares: make([]Handler, 0), routeIndex: -1, Routers: make(RouterMap), } } // Handler defines the handler used by the middleware as return value. type Handler func(ctx *Context) // Handlers is the array of Handler type Handlers []Handler // AppendReqAndResp stores the request info and handle into app. // support the route parameter. The route parameter will be recognized as // wildcard store into the RegUrl of Path struct. For example: // // /user/:id => /user/(.*) // /user/:id/info => /user/(.*?)/info // // The RegUrl will be used to recognize the incoming path and find // the handler. func (app *App) AppendReqAndResp(url, method string, handler []Handler) { app.Requests = append(app.Requests, Path{ URL: join(app.Prefix, url), Method: method, }) app.routeIndex++ app.Handlers[Path{ URL: join(app.Prefix, url), Method: method, }] = append(app.Middlewares, handler...) } // Find is public helper method for findPath of tree. func (app *App) Find(url, method string) []Handler { app.routeANY = false return app.Handlers[Path{URL: url, Method: method}] } // POST is a shortcut for app.AppendReqAndResp(url, "post", handler). func (app *App) POST(url string, handler ...Handler) *App { app.routeANY = false app.AppendReqAndResp(url, "post", handler) return app } // GET is a shortcut for app.AppendReqAndResp(url, "get", handler). func (app *App) GET(url string, handler ...Handler) *App { app.routeANY = false app.AppendReqAndResp(url, "get", handler) return app } // DELETE is a shortcut for app.AppendReqAndResp(url, "delete", handler). func (app *App) DELETE(url string, handler ...Handler) *App { app.routeANY = false app.AppendReqAndResp(url, "delete", handler) return app } // PUT is a shortcut for app.AppendReqAndResp(url, "put", handler). func (app *App) PUT(url string, handler ...Handler) *App { app.routeANY = false app.AppendReqAndResp(url, "put", handler) return app } // OPTIONS is a shortcut for app.AppendReqAndResp(url, "options", handler). func (app *App) OPTIONS(url string, handler ...Handler) *App { app.routeANY = false app.AppendReqAndResp(url, "options", handler) return app } // HEAD is a shortcut for app.AppendReqAndResp(url, "head", handler). func (app *App) HEAD(url string, handler ...Handler) *App { app.routeANY = false app.AppendReqAndResp(url, "head", handler) return app } // ANY registers a route that matches all the HTTP methods. // GET, POST, PUT, HEAD, OPTIONS, DELETE. func (app *App) ANY(url string, handler ...Handler) *App { app.routeANY = true app.AppendReqAndResp(url, "post", handler) app.AppendReqAndResp(url, "get", handler) app.AppendReqAndResp(url, "delete", handler) app.AppendReqAndResp(url, "put", handler) app.AppendReqAndResp(url, "options", handler) app.AppendReqAndResp(url, "head", handler) return app } func (app *App) Name(name string) { if app.routeANY { app.Routers[name] = Router{ Methods: []string{"POST", "GET", "DELETE", "PUT", "OPTIONS", "HEAD"}, Patten: app.Requests[app.routeIndex].URL, } } else { app.Routers[name] = Router{ Methods: []string{app.Requests[app.routeIndex].Method}, Patten: app.Requests[app.routeIndex].URL, } } } // Group add middlewares and prefix for App. func (app *App) Group(prefix string, middleware ...Handler) *RouterGroup { return &RouterGroup{ app: app, Middlewares: append(app.Middlewares, middleware...), Prefix: slash(prefix), } } // RouterGroup is a group of routes. type RouterGroup struct { app *App Middlewares Handlers Prefix string } // AppendReqAndResp stores the request info and handle into app. // support the route parameter. The route parameter will be recognized as // wildcard store into the RegUrl of Path struct. For example: // // /user/:id => /user/(.*) // /user/:id/info => /user/(.*?)/info // // The RegUrl will be used to recognize the incoming path and find // the handler. func (g *RouterGroup) AppendReqAndResp(url, method string, handler []Handler) { g.app.Requests = append(g.app.Requests, Path{ URL: join(g.Prefix, url), Method: method, }) g.app.routeIndex++ var h = make([]Handler, len(g.Middlewares)) copy(h, g.Middlewares) g.app.Handlers[Path{ URL: join(g.Prefix, url), Method: method, }] = append(h, handler...) } // POST is a shortcut for app.AppendReqAndResp(url, "post", handler). func (g *RouterGroup) POST(url string, handler ...Handler) *RouterGroup { g.app.routeANY = false g.AppendReqAndResp(url, "post", handler) return g } // GET is a shortcut for app.AppendReqAndResp(url, "get", handler). func (g *RouterGroup) GET(url string, handler ...Handler) *RouterGroup { g.app.routeANY = false g.AppendReqAndResp(url, "get", handler) return g } // DELETE is a shortcut for app.AppendReqAndResp(url, "delete", handler). func (g *RouterGroup) DELETE(url string, handler ...Handler) *RouterGroup { g.app.routeANY = false g.AppendReqAndResp(url, "delete", handler) return g } // PUT is a shortcut for app.AppendReqAndResp(url, "put", handler). func (g *RouterGroup) PUT(url string, handler ...Handler) *RouterGroup { g.app.routeANY = false g.AppendReqAndResp(url, "put", handler) return g } // OPTIONS is a shortcut for app.AppendReqAndResp(url, "options", handler). func (g *RouterGroup) OPTIONS(url string, handler ...Handler) *RouterGroup { g.app.routeANY = false g.AppendReqAndResp(url, "options", handler) return g } // HEAD is a shortcut for app.AppendReqAndResp(url, "head", handler). func (g *RouterGroup) HEAD(url string, handler ...Handler) *RouterGroup { g.app.routeANY = false g.AppendReqAndResp(url, "head", handler) return g } // ANY registers a route that matches all the HTTP methods. // GET, POST, PUT, HEAD, OPTIONS, DELETE. func (g *RouterGroup) ANY(url string, handler ...Handler) *RouterGroup { g.app.routeANY = true g.AppendReqAndResp(url, "post", handler) g.AppendReqAndResp(url, "get", handler) g.AppendReqAndResp(url, "delete", handler) g.AppendReqAndResp(url, "put", handler) g.AppendReqAndResp(url, "options", handler) g.AppendReqAndResp(url, "head", handler) return g } func (g *RouterGroup) Name(name string) { g.app.Name(name) } // Group add middlewares and prefix for RouterGroup. func (g *RouterGroup) Group(prefix string, middleware ...Handler) *RouterGroup { return &RouterGroup{ app: g.app, Middlewares: append(g.Middlewares, middleware...), Prefix: join(slash(g.Prefix), slash(prefix)), } } // slash fix the path which has wrong format problem. // // "" => "/" // "abc/" => "/abc" // "/abc/" => "/abc" // "/abc" => "/abc" // "/" => "/" func slash(prefix string) string { prefix = strings.TrimSpace(prefix) if prefix == "" || prefix == "/" { return "/" } if prefix[0] != '/' { if prefix[len(prefix)-1] == '/' { return "/" + prefix[:len(prefix)-1] } return "/" + prefix } if prefix[len(prefix)-1] == '/' { return prefix[:len(prefix)-1] } return prefix } // join join the path. func join(prefix, suffix string) string { if prefix == "/" { return suffix } if suffix == "/" { return prefix } return prefix + suffix } ================================================ FILE: context/context_test.go ================================================ package context import ( "fmt" "testing" "github.com/magiconair/properties/assert" ) func TestSlash(t *testing.T) { assert.Equal(t, "/abc", slash("/abc")) assert.Equal(t, "/", slash("")) assert.Equal(t, "/abc", slash("abc/")) assert.Equal(t, "/", slash("/")) assert.Equal(t, "/abc", slash("/abc/")) assert.Equal(t, "/", slash("//")) } func TestJoin(t *testing.T) { assert.Equal(t, "/abc/abc", join(slash("/abc"), slash("/abc"))) assert.Equal(t, "/", join(slash("/"), slash("/"))) assert.Equal(t, "/abc", join(slash("/"), slash("/abc"))) assert.Equal(t, "/abc", join(slash("abc/"), slash("/"))) assert.Equal(t, "/abc", join(slash("/abc/"), slash("/"))) } func TestTree(t *testing.T) { tree := tree() tree.addPath(stringToArr("/adm"), "GET", []Handler{func(ctx *Context) { fmt.Println(1) }}) tree.addPath(stringToArr("/admi"), "GET", []Handler{func(ctx *Context) { fmt.Println(1) }}) tree.addPath(stringToArr("/admin"), "GET", []Handler{func(ctx *Context) { fmt.Println(1) }}) tree.addPath(stringToArr("/admin/menu/new"), "POST", []Handler{func(ctx *Context) { fmt.Println(1) }}) tree.addPath(stringToArr("/admin/menu/new"), "GET", []Handler{func(ctx *Context) { fmt.Println(1) }}) tree.addPath(stringToArr("/admin/info/:__prefix"), "GET", []Handler{ func(ctx *Context) { fmt.Println("auth") }, func(ctx *Context) { fmt.Println("init") }, func(ctx *Context) { fmt.Println("info") }, }) tree.addPath(stringToArr("/admin/info/:__prefix/detail"), "GET", []Handler{ func(ctx *Context) { fmt.Println("auth") }, func(ctx *Context) { fmt.Println("detail") }, }) fmt.Println("/admin/menu/new", "GET") h := tree.findPath(stringToArr("/admin/menu/new"), "GET") assert.Equal(t, h != nil, true) printHandler(h) fmt.Println("/admin/menu/new", "POST") h = tree.findPath(stringToArr("/admin/menu/new"), "POST") assert.Equal(t, h != nil, true) printHandler(h) fmt.Println("/admin/me/new", "POST") h = tree.findPath(stringToArr("/admin/me/new"), "POST") assert.Equal(t, h == nil, true) printHandler(h) fmt.Println("/admin/info/user", "GET") h = tree.findPath(stringToArr("/admin/info/user"), "GET") assert.Equal(t, h != nil, true) printHandler(h) fmt.Println("/admin/info/user/detail", "GET") h = tree.findPath(stringToArr("/admin/info/user/detail"), "GET") assert.Equal(t, h != nil, true) printHandler(h) fmt.Println("=========== printChildren ===========") tree.printChildren() } func printHandler(h []Handler) { for _, value := range h { value(&Context{}) } } ================================================ FILE: context/trie.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package context import "fmt" type node struct { children []*node value string method []string handle [][]Handler } func tree() *node { return &node{ children: make([]*node, 0), value: "/", handle: nil, } } func (n *node) hasMethod(method string) int { for k, m := range n.method { if m == method { return k } } return -1 } func (n *node) addMethodAndHandler(method string, handler []Handler) { n.method = append(n.method, method) n.handle = append(n.handle, handler) } func (n *node) addChild(child *node) { n.children = append(n.children, child) } func (n *node) addContent(value string) *node { var child = n.search(value) if child == nil { child = &node{ children: make([]*node, 0), value: value, } n.addChild(child) } return child } func (n *node) search(value string) *node { for _, child := range n.children { if child.value == value || child.value == "*" { return child } } return nil } func (n *node) addPath(paths []string, method string, handler []Handler) { child := n for i := 0; i < len(paths); i++ { child = child.addContent(paths[i]) } child.addMethodAndHandler(method, handler) } func (n *node) findPath(paths []string, method string) []Handler { child := n for i := 0; i < len(paths); i++ { child = child.search(paths[i]) if child == nil { return nil } } methodIndex := child.hasMethod(method) if methodIndex == -1 { return nil } return child.handle[methodIndex] } func (n *node) print() { fmt.Println(n) } func (n *node) printChildren() { n.print() for _, child := range n.children { child.printChildren() } } func stringToArr(path string) []string { var ( paths = make([]string, 0) start = 0 end int isWildcard = false ) for i := 0; i < len(path); i++ { if i == 0 && path[0] == '/' { start = 1 continue } if path[i] == ':' { isWildcard = true } if i == len(path)-1 { end = i + 1 if isWildcard { paths = append(paths, "*") } else { paths = append(paths, path[start:end]) } } if path[i] == '/' { end = i if isWildcard { paths = append(paths, "*") } else { paths = append(paths, path[start:end]) } start = i + 1 isWildcard = false } } return paths } ================================================ FILE: data/admin.mssql ================================================ CREATE TABLE [goadmin_menu] ( [id] int identity(1,1) , [parent_id] int NOT NULL DEFAULT 0, [type] tinyint NOT NULL DEFAULT 0, [order] int NOT NULL DEFAULT '0', [title] varchar(50) NOT NULL, [icon] varchar(50) NOT NULL, [uri] varchar(3000) NOT NULL DEFAULT '', [header] varchar(150) DEFAULT NULL, [uuid] varchar(150) DEFAULT NULL, [plugin_name] varchar(150) NOT NULL DEFAULT '', [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([id]), ) set IDENTITY_INSERT [goadmin_menu] ON INSERT INTO[goadmin_menu] ([id],[parent_id],[type],[order],[title],[icon],[uri],[header],[created_at],[updated_at]) VALUES (1,0,1,2,'Admin','fa-tasks','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,1,1,2,'Users','fa-users','/info/manager',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (3,1,1,3,'Roles','fa-user','/info/roles',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (4,1,1,4,'Permission','fa-ban','/info/permission',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (5,1,1,5,'Menu','fa-bars','/menu',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (6,1,1,6,'Operation log','fa-history','/info/op',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (7,0,1,1,'Dashboard','fa-bar-chart','/',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'); set IDENTITY_INSERT [goadmin_menu] OFF CREATE TABLE[goadmin_operation_log] ( [id] int identity(1,1) , [user_id] int NOT NULL, [path] varchar(255) NOT NULL, [method] varchar(10) NOT NULL, [ip] varchar(15) NOT NULL, [input] text NOT NULL, [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([id]), ) CREATE TABLE[goadmin_site] ( [id] int identity(1,1) , [key] varchar(100) NOT NULL, [value] text NOT NULL, [state] tinyint NOT NULL DEFAULT 0, [description] varchar(3000) DEFAULT NULL, [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([id]), ) CREATE TABLE[goadmin_permissions] ( [id] int identity(1,1) , [name] varchar(50) NOT NULL, [slug] varchar(50) NOT NULL, [http_method] varchar(255) DEFAULT NULL, [http_path] text NOT NULL, [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([id]), ) set IDENTITY_INSERT [goadmin_permissions] ON INSERT INTO[goadmin_permissions] ([id],[name],[slug],[http_method],[http_path],[created_at],[updated_at]) VALUES (1,'All permission','*','','*','2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,'Dashboard','dashboard','GET,PUT,POST,DELETE','/','2019-09-10 00:00:00','2019-09-10 00:00:00'); set IDENTITY_INSERT [goadmin_permissions] OFF CREATE TABLE[goadmin_role_menu] ( [role_id] int NOT NULL, [menu_id] int NOT NULL, [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY([role_id],[menu_id]) ) INSERT INTO[goadmin_role_menu] ([role_id],[menu_id],[created_at],[updated_at]) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (1,7,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,7,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (1,8,'2019-09-11 10:20:55','2019-09-11 10:20:55'), (2,8,'2019-09-11 10:20:55','2019-09-11 10:20:55'); CREATE TABLE[goadmin_role_permissions] ( [role_id] int NOT NULL, [permission_id] int NOT NULL, [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([role_id],[permission_id]) ) INSERT INTO[goadmin_role_permissions] ([role_id],[permission_id],[created_at],[updated_at]) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (1,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'); CREATE TABLE[goadmin_role_users] ( [role_id] int NOT NULL, [user_id] int NOT NULL, [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([role_id],[user_id]) ) INSERT INTO[goadmin_role_users] ([role_id],[user_id],[created_at],[updated_at]) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'); CREATE TABLE[goadmin_roles] ( [id] int identity(1,1) , [name] varchar(50) NOT NULL UNIQUE, [slug] varchar(50) NOT NULL, [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([id]), ) set IDENTITY_INSERT [goadmin_roles] ON INSERT INTO[goadmin_roles] ([id],[name],[slug],[created_at],[updated_at]) VALUES (1,'Administrator','administrator','2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,'Operator','operator','2019-09-10 00:00:00','2019-09-10 00:00:00'); set IDENTITY_INSERT [goadmin_roles] OFF CREATE TABLE[goadmin_session] ( [id] int identity(1,1) , [sid] varchar(50) DEFAULT '', [values] varchar(3000) DEFAULT '', [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([id]) ) CREATE TABLE[goadmin_user_permissions] ( [user_id] int NOT NULL, [permission_id] int NOT NULL, [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([user_id],[permission_id]) ) INSERT INTO[goadmin_user_permissions] ([user_id],[permission_id],[created_at],[updated_at]) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'); CREATE TABLE[goadmin_users] ( [id] int identity(1,1) , [username] varchar(100) NOT NULL UNIQUE, [password] varchar(100) NOT NULL DEFAULT '', [name] varchar(100) NOT NULL, [avatar] varchar(255) DEFAULT NULL, [remember_token] varchar(100) DEFAULT NULL, [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([id]), ) set IDENTITY_INSERT [goadmin_users] ON INSERT INTO[goadmin_users] ([id],[username],[password],[name],[avatar],[remember_token],[created_at],[updated_at]) VALUES (1,'admin','$2a$10$U3F/NSaf2kaVbyXTBp7ppOn0jZFyRqXRnYXB.AMioCjXl3Ciaj4oy','admin','','tlNcBVK9AvfYH7WEnwB1RKvocJu8FfRy4um3DJtwdHuJy0dwFsLOgAc0xUfh','2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,'operator','$2a$10$rVqkOzHjN2MdlEprRflb1eGP0oZXuSrbJLOmJagFsCd81YZm0bsh.','Operator','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'); set IDENTITY_INSERT [goadmin_users] OFF ================================================ FILE: data/admin.pgsql ================================================ -- -- PostgreSQL database dump -- -- Dumped from database version 9.5.14 -- Dumped by pg_dump version 10.5 SET statement_timeout = 0; SET lock_timeout = 0; SET idle_in_transaction_session_timeout = 0; SET client_encoding = 'UTF8'; SET standard_conforming_strings = on; SELECT pg_catalog.set_config('search_path', '', false); SET check_function_bodies = false; SET client_min_messages = warning; SET row_security = off; -- -- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -- CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; -- -- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -- COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; -- -- Name: goadmin_menu_myid_seq; Type: SEQUENCE; Schema: public; Owner: postgres -- CREATE SEQUENCE public.goadmin_menu_myid_seq START WITH 1 INCREMENT BY 1 NO MINVALUE MAXVALUE 99999999 CACHE 1; ALTER TABLE public.goadmin_menu_myid_seq OWNER TO postgres; SET default_tablespace = ''; SET default_with_oids = false; -- -- Name: goadmin_menu; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_menu ( id integer DEFAULT nextval('public.goadmin_menu_myid_seq'::regclass) NOT NULL, parent_id integer DEFAULT 0 NOT NULL, type integer DEFAULT 0, "order" integer DEFAULT 0 NOT NULL, title character varying(50) NOT NULL, header character varying(100), plugin_name character varying(100) NOT NULL, icon character varying(50) NOT NULL, uri character varying(3000) NOT NULL, uuid character varying(100), created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_menu OWNER TO postgres; -- -- Name: goadmin_operation_log_myid_seq; Type: SEQUENCE; Schema: public; Owner: postgres -- CREATE SEQUENCE public.goadmin_operation_log_myid_seq START WITH 1 INCREMENT BY 1 NO MINVALUE MAXVALUE 99999999 CACHE 1; ALTER TABLE public.goadmin_operation_log_myid_seq OWNER TO postgres; -- -- Name: goadmin_operation_log; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_operation_log ( id integer DEFAULT nextval('public.goadmin_operation_log_myid_seq'::regclass) NOT NULL, user_id integer NOT NULL, path character varying(255) NOT NULL, method character varying(10) NOT NULL, ip character varying(15) NOT NULL, input text NOT NULL, created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_operation_log OWNER TO postgres; -- -- Name: goadmin_site_myid_seq; Type: SEQUENCE; Schema: public; Owner: postgres -- CREATE SEQUENCE public.goadmin_site_myid_seq START WITH 1 INCREMENT BY 1 NO MINVALUE MAXVALUE 99999999 CACHE 1; ALTER TABLE public.goadmin_site_myid_seq OWNER TO postgres; -- -- Name: goadmin_site; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_site ( id integer DEFAULT nextval('public.goadmin_site_myid_seq'::regclass) NOT NULL, key character varying(100) NOT NULL, value text NOT NULL, type integer DEFAULT 0, description character varying(3000), state integer DEFAULT 0, created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_site OWNER TO postgres; -- -- Name: goadmin_permissions_myid_seq; Type: SEQUENCE; Schema: public; Owner: postgres -- CREATE SEQUENCE public.goadmin_permissions_myid_seq START WITH 1 INCREMENT BY 1 NO MINVALUE MAXVALUE 99999999 CACHE 1; ALTER TABLE public.goadmin_permissions_myid_seq OWNER TO postgres; -- -- Name: goadmin_permissions; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_permissions ( id integer DEFAULT nextval('public.goadmin_permissions_myid_seq'::regclass) NOT NULL, name character varying(50) NOT NULL, slug character varying(50) NOT NULL, http_method character varying(255), http_path text NOT NULL, created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_permissions OWNER TO postgres; -- -- Name: goadmin_role_menu; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_role_menu ( role_id integer NOT NULL, menu_id integer NOT NULL, created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_role_menu OWNER TO postgres; -- -- Name: goadmin_role_permissions; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_role_permissions ( role_id integer NOT NULL, permission_id integer NOT NULL, created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_role_permissions OWNER TO postgres; -- -- Name: goadmin_role_users; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_role_users ( role_id integer NOT NULL, user_id integer NOT NULL, created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_role_users OWNER TO postgres; -- -- Name: goadmin_roles_myid_seq; Type: SEQUENCE; Schema: public; Owner: postgres -- CREATE SEQUENCE public.goadmin_roles_myid_seq START WITH 1 INCREMENT BY 1 NO MINVALUE MAXVALUE 99999999 CACHE 1; ALTER TABLE public.goadmin_roles_myid_seq OWNER TO postgres; -- -- Name: goadmin_roles; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_roles ( id integer DEFAULT nextval('public.goadmin_roles_myid_seq'::regclass) NOT NULL, name character varying NOT NULL, slug character varying NOT NULL, created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_roles OWNER TO postgres; -- -- Name: goadmin_session_myid_seq; Type: SEQUENCE; Schema: public; Owner: postgres -- CREATE SEQUENCE public.goadmin_session_myid_seq START WITH 1 INCREMENT BY 1 NO MINVALUE MAXVALUE 99999999 CACHE 1; ALTER TABLE public.goadmin_session_myid_seq OWNER TO postgres; -- -- Name: goadmin_session; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_session ( id integer DEFAULT nextval('public.goadmin_session_myid_seq'::regclass) NOT NULL, sid character varying(50) NOT NULL, "values" character varying(3000) NOT NULL, created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_session OWNER TO postgres; -- -- Name: goadmin_user_permissions; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_user_permissions ( user_id integer NOT NULL, permission_id integer NOT NULL, created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_user_permissions OWNER TO postgres; -- -- Name: goadmin_users_myid_seq; Type: SEQUENCE; Schema: public; Owner: postgres -- CREATE SEQUENCE public.goadmin_users_myid_seq START WITH 1 INCREMENT BY 1 NO MINVALUE MAXVALUE 99999999 CACHE 1; ALTER TABLE public.goadmin_users_myid_seq OWNER TO postgres; -- -- Name: goadmin_users; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_users ( id integer DEFAULT nextval('public.goadmin_users_myid_seq'::regclass) NOT NULL, username character varying(100) NOT NULL, password character varying(100) NOT NULL, name character varying(100) NOT NULL, avatar character varying(255), remember_token character varying(100), created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_users OWNER TO postgres; -- -- Data for Name: goadmin_menu; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_menu (id, parent_id, type, "order", title, plugin_name, header, icon, uri, created_at, updated_at) FROM stdin; 1 0 1 2 Admin \N fa-tasks 2019-09-10 00:00:00 2019-09-10 00:00:00 2 1 1 2 Users \N fa-users /info/manager 2019-09-10 00:00:00 2019-09-10 00:00:00 3 1 1 3 Roles \N fa-user /info/roles 2019-09-10 00:00:00 2019-09-10 00:00:00 4 1 1 4 Permission \N fa-ban /info/permission 2019-09-10 00:00:00 2019-09-10 00:00:00 5 1 1 5 Menu \N fa-bars /menu 2019-09-10 00:00:00 2019-09-10 00:00:00 6 1 1 6 Operation log \N fa-history /info/op 2019-09-10 00:00:00 2019-09-10 00:00:00 7 0 1 1 Dashboard \N fa-bar-chart / 2019-09-10 00:00:00 2019-09-10 00:00:00 \. -- -- Data for Name: goadmin_operation_log; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_operation_log (id, user_id, path, method, ip, input, created_at, updated_at) FROM stdin; \. -- -- Data for Name: goadmin_site; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_site (id, key, value, description, state, created_at, updated_at) FROM stdin; \. -- -- Data for Name: goadmin_permissions; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_permissions (id, name, slug, http_method, http_path, created_at, updated_at) FROM stdin; 1 All permission * * 2019-09-10 00:00:00 2019-09-10 00:00:00 2 Dashboard dashboard GET,PUT,POST,DELETE / 2019-09-10 00:00:00 2019-09-10 00:00:00 \. -- -- Data for Name: goadmin_role_menu; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_role_menu (role_id, menu_id, created_at, updated_at) FROM stdin; 1 1 2019-09-10 00:00:00 2019-09-10 00:00:00 1 7 2019-09-10 00:00:00 2019-09-10 00:00:00 2 7 2019-09-10 00:00:00 2019-09-10 00:00:00 \. -- -- Data for Name: goadmin_role_permissions; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_role_permissions (role_id, permission_id, created_at, updated_at) FROM stdin; 1 1 2019-09-10 00:00:00 2019-09-10 00:00:00 1 2 2019-09-10 00:00:00 2019-09-10 00:00:00 2 2 2019-09-10 00:00:00 2019-09-10 00:00:00 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N 0 3 \N \N \. -- -- Data for Name: goadmin_role_users; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_role_users (role_id, user_id, created_at, updated_at) FROM stdin; 1 1 2019-09-10 00:00:00 2019-09-10 00:00:00 2 2 2019-09-10 00:00:00 2019-09-10 00:00:00 \. -- -- Data for Name: goadmin_roles; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_roles (id, name, slug, created_at, updated_at) FROM stdin; 1 Administrator administrator 2019-09-10 00:00:00 2019-09-10 00:00:00 2 Operator operator 2019-09-10 00:00:00 2019-09-10 00:00:00 \. -- -- Data for Name: goadmin_session; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_session (id, sid, "values", created_at, updated_at) FROM stdin; \. -- -- Data for Name: goadmin_user_permissions; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_user_permissions (user_id, permission_id, created_at, updated_at) FROM stdin; 1 1 2019-09-10 00:00:00 2019-09-10 00:00:00 2 2 2019-09-10 00:00:00 2019-09-10 00:00:00 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N 0 1 \N \N \. -- -- Data for Name: goadmin_users; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_users (id, username, password, name, avatar, remember_token, created_at, updated_at) FROM stdin; 1 admin $2a$10$OxWYJJGTP2gi00l2x06QuOWqw5VR47MQCJ0vNKnbMYfrutij10Hwe admin tlNcBVK9AvfYH7WEnwB1RKvocJu8FfRy4um3DJtwdHuJy0dwFsLOgAc0xUfh 2019-09-10 00:00:00 2019-09-10 00:00:00 2 operator $2a$10$rVqkOzHjN2MdlEprRflb1eGP0oZXuSrbJLOmJagFsCd81YZm0bsh. Operator \N 2019-09-10 00:00:00 2019-09-10 00:00:00 \. -- -- Name: goadmin_menu_myid_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres -- SELECT pg_catalog.setval('public.goadmin_menu_myid_seq', 7, true); -- -- Name: goadmin_operation_log_myid_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres -- SELECT pg_catalog.setval('public.goadmin_operation_log_myid_seq', 1, true); -- -- Name: goadmin_permissions_myid_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres -- SELECT pg_catalog.setval('public.goadmin_permissions_myid_seq', 2, true); -- -- Name: goadmin_roles_myid_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres -- SELECT pg_catalog.setval('public.goadmin_roles_myid_seq', 2, true); -- -- Name: goadmin_site_myid_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres -- SELECT pg_catalog.setval('public.goadmin_site_myid_seq', 1, true); -- -- Name: goadmin_session_myid_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres -- SELECT pg_catalog.setval('public.goadmin_session_myid_seq', 1, true); -- -- Name: goadmin_users_myid_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres -- SELECT pg_catalog.setval('public.goadmin_users_myid_seq', 2, true); -- -- Name: goadmin_menu goadmin_menu_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres -- ALTER TABLE ONLY public.goadmin_menu ADD CONSTRAINT goadmin_menu_pkey PRIMARY KEY (id); -- -- Name: goadmin_operation_log goadmin_operation_log_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres -- ALTER TABLE ONLY public.goadmin_operation_log ADD CONSTRAINT goadmin_operation_log_pkey PRIMARY KEY (id); -- -- Name: goadmin_permissions goadmin_permissions_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres -- ALTER TABLE ONLY public.goadmin_permissions ADD CONSTRAINT goadmin_permissions_pkey PRIMARY KEY (id); -- -- Name: goadmin_roles goadmin_roles_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres -- ALTER TABLE ONLY public.goadmin_roles ADD CONSTRAINT goadmin_roles_pkey PRIMARY KEY (id); -- -- Name: goadmin_site goadmin_site_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres -- ALTER TABLE ONLY public.goadmin_site ADD CONSTRAINT goadmin_site_pkey PRIMARY KEY (id); -- -- Name: goadmin_session goadmin_session_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres -- ALTER TABLE ONLY public.goadmin_session ADD CONSTRAINT goadmin_session_pkey PRIMARY KEY (id); -- -- Name: goadmin_users goadmin_users_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres -- ALTER TABLE ONLY public.goadmin_users ADD CONSTRAINT goadmin_users_pkey PRIMARY KEY (id); -- -- Name: SCHEMA public; Type: ACL; Schema: -; Owner: postgres -- REVOKE ALL ON SCHEMA public FROM PUBLIC; REVOKE ALL ON SCHEMA public FROM postgres; GRANT ALL ON SCHEMA public TO postgres; GRANT ALL ON SCHEMA public TO PUBLIC; -- -- PostgreSQL database dump complete -- ================================================ FILE: data/admin.sql ================================================ # ************************************************************ # Sequel Pro SQL dump # Version 4468 # # http://www.sequelpro.com/ # https://github.com/sequelpro/sequelpro # # Host: 127.0.0.1 (MySQL 5.7.19) # Database: godmin # Generation Time: 2019-09-12 04:16:47 +0000 # ************************************************************ /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; # Dump of table goadmin_menu # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_menu`; CREATE TABLE `goadmin_menu` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `parent_id` int(11) unsigned NOT NULL DEFAULT '0', `type` tinyint(4) unsigned NOT NULL DEFAULT '0', `order` int(11) unsigned NOT NULL DEFAULT '0', `title` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `icon` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `uri` varchar(3000) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `header` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `plugin_name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `uuid` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_menu` WRITE; /*!40000 ALTER TABLE `goadmin_menu` DISABLE KEYS */; INSERT INTO `goadmin_menu` (`id`, `parent_id`, `type`, `order`, `title`, `icon`, `uri`, `plugin_name`, `header`, `created_at`, `updated_at`) VALUES (1,0,1,2,'Admin','fa-tasks','','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,1,1,2,'Users','fa-users','/info/manager','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (3,1,1,3,'Roles','fa-user','/info/roles','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (4,1,1,4,'Permission','fa-ban','/info/permission','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (5,1,1,5,'Menu','fa-bars','/menu','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (6,1,1,6,'Operation log','fa-history','/info/op','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (7,0,1,1,'Dashboard','fa-bar-chart','/','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_menu` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_operation_log # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_operation_log`; CREATE TABLE `goadmin_operation_log` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(11) unsigned NOT NULL, `path` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `method` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL, `ip` varchar(15) COLLATE utf8mb4_unicode_ci NOT NULL, `input` text COLLATE utf8mb4_unicode_ci NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `admin_operation_log_user_id_index` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; # Dump of table goadmin_site # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_site`; CREATE TABLE `goadmin_site` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `key` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `value` longtext COLLATE utf8mb4_unicode_ci, `description` varchar(3000) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `state` tinyint(3) unsigned NOT NULL DEFAULT '0', `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; # Dump of table goadmin_permissions # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_permissions`; CREATE TABLE `goadmin_permissions` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `slug` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `http_method` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `http_path` text COLLATE utf8mb4_unicode_ci NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `admin_permissions_name_unique` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_permissions` WRITE; /*!40000 ALTER TABLE `goadmin_permissions` DISABLE KEYS */; INSERT INTO `goadmin_permissions` (`id`, `name`, `slug`, `http_method`, `http_path`, `created_at`, `updated_at`) VALUES (1,'All permission','*','','*','2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,'Dashboard','dashboard','GET,PUT,POST,DELETE','/','2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_permissions` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_role_menu # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_role_menu`; CREATE TABLE `goadmin_role_menu` ( `role_id` int(11) unsigned NOT NULL, `menu_id` int(11) unsigned NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, KEY `admin_role_menu_role_id_menu_id_index` (`role_id`,`menu_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_role_menu` WRITE; /*!40000 ALTER TABLE `goadmin_role_menu` DISABLE KEYS */; INSERT INTO `goadmin_role_menu` (`role_id`, `menu_id`, `created_at`, `updated_at`) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (1,7,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,7,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (1,8,'2019-09-11 10:20:55','2019-09-11 10:20:55'), (2,8,'2019-09-11 10:20:55','2019-09-11 10:20:55'); /*!40000 ALTER TABLE `goadmin_role_menu` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_role_permissions # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_role_permissions`; CREATE TABLE `goadmin_role_permissions` ( `role_id` int(11) unsigned NOT NULL, `permission_id` int(11) unsigned NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `admin_role_permissions` (`role_id`,`permission_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_role_permissions` WRITE; /*!40000 ALTER TABLE `goadmin_role_permissions` DISABLE KEYS */; INSERT INTO `goadmin_role_permissions` (`role_id`, `permission_id`, `created_at`, `updated_at`) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (1,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_role_permissions` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_role_users # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_role_users`; CREATE TABLE `goadmin_role_users` ( `role_id` int(11) unsigned NOT NULL, `user_id` int(11) unsigned NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `admin_user_roles` (`role_id`,`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_role_users` WRITE; /*!40000 ALTER TABLE `goadmin_role_users` DISABLE KEYS */; INSERT INTO `goadmin_role_users` (`role_id`, `user_id`, `created_at`, `updated_at`) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_role_users` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_roles # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_roles`; CREATE TABLE `goadmin_roles` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `slug` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `admin_roles_name_unique` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_roles` WRITE; /*!40000 ALTER TABLE `goadmin_roles` DISABLE KEYS */; INSERT INTO `goadmin_roles` (`id`, `name`, `slug`, `created_at`, `updated_at`) VALUES (1,'Administrator','administrator','2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,'Operator','operator','2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_roles` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_session # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_session`; CREATE TABLE `goadmin_session` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `sid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `values` varchar(3000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # Dump of table goadmin_user_permissions # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_user_permissions`; CREATE TABLE `goadmin_user_permissions` ( `user_id` int(11) unsigned NOT NULL, `permission_id` int(11) unsigned NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `admin_user_permissions` (`user_id`,`permission_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_user_permissions` WRITE; /*!40000 ALTER TABLE `goadmin_user_permissions` DISABLE KEYS */; INSERT INTO `goadmin_user_permissions` (`user_id`, `permission_id`, `created_at`, `updated_at`) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_user_permissions` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_users # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_users`; CREATE TABLE `goadmin_users` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, `password` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, `avatar` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `admin_users_username_unique` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_users` WRITE; /*!40000 ALTER TABLE `goadmin_users` DISABLE KEYS */; INSERT INTO `goadmin_users` (`id`, `username`, `password`, `name`, `avatar`, `remember_token`, `created_at`, `updated_at`) VALUES (1,'admin','$2a$10$U3F/NSaf2kaVbyXTBp7ppOn0jZFyRqXRnYXB.AMioCjXl3Ciaj4oy','admin','','tlNcBVK9AvfYH7WEnwB1RKvocJu8FfRy4um3DJtwdHuJy0dwFsLOgAc0xUfh','2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,'operator','$2a$10$rVqkOzHjN2MdlEprRflb1eGP0oZXuSrbJLOmJagFsCd81YZm0bsh.','Operator','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_users` ENABLE KEYS */; UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; ================================================ FILE: data/migrations/admin_2020_04_14_100427_ms.sql ================================================ CREATE TABLE[goadmin_site] ( [id] int identity(1,1) , [key] varchar(100) NOT NULL, [value] text NOT NULL, [state] tinyint NOT NULL DEFAULT 0, [description] varchar(3000) NOT NULL, [created_at] datetime NULL DEFAULT GETDATE(), [updated_at] datetime NULL DEFAULT GETDATE(), PRIMARY KEY ([id]), ) ================================================ FILE: data/migrations/admin_2020_04_14_100427_mysql.sql ================================================ CREATE TABLE `goadmin_site` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `key` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `value` longtext COLLATE utf8mb4_unicode_ci, `description` varchar(3000) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `state` tinyint(3) unsigned NOT NULL DEFAULT '0', `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ================================================ FILE: data/migrations/admin_2020_04_14_100427_postgres.sql ================================================ -- -- PostgreSQL database dump -- -- Dumped from database version 9.5.14 -- Dumped by pg_dump version 10.5 SET statement_timeout = 0; SET lock_timeout = 0; SET idle_in_transaction_session_timeout = 0; SET client_encoding = 'EUC_CN'; SET standard_conforming_strings = on; SELECT pg_catalog.set_config('search_path', '', false); SET check_function_bodies = false; SET client_min_messages = warning; SET row_security = off; SET default_tablespace = ''; SET default_with_oids = false; -- -- Name: goadmin_site_myid_seq; Type: SEQUENCE; Schema: public; Owner: postgres -- CREATE SEQUENCE public.goadmin_site_myid_seq START WITH 1 INCREMENT BY 1 NO MINVALUE MAXVALUE 99999999 CACHE 1; ALTER TABLE public.goadmin_site_myid_seq OWNER TO postgres; -- -- Name: goadmin_site; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.goadmin_site ( id integer DEFAULT nextval('public.goadmin_site_myid_seq'::regclass) NOT NULL, key character varying(100) NOT NULL, value text NOT NULL, type integer DEFAULT 0, description character varying(3000), state integer DEFAULT 0, created_at timestamp without time zone DEFAULT now(), updated_at timestamp without time zone DEFAULT now() ); ALTER TABLE public.goadmin_site OWNER TO postgres; -- -- Data for Name: goadmin_site; Type: TABLE DATA; Schema: public; Owner: postgres -- COPY public.goadmin_site (id, key, value, type, description, state, created_at, updated_at) FROM stdin; \. -- -- Name: goadmin_site goadmin_site_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres -- ALTER TABLE ONLY public.goadmin_site ADD CONSTRAINT goadmin_site_pkey PRIMARY KEY (id); -- -- PostgreSQL database dump complete -- ================================================ FILE: data/migrations/admin_2020_04_14_100427_sqlite.sql ================================================ CREATE TABLE IF NOT EXISTS "goadmin_site" ( `id` integer PRIMARY KEY autoincrement, `key` CHAR(100) COLLATE NOCASE NOT NULL, `value` text COLLATE NOCASE NOT NULL, `state` INT NOT NULL DEFAULT '0', `description` CHAR(3000) COLLATE NOCASE, `created_at` TIMESTAMP default CURRENT_TIMESTAMP, `updated_at` TIMESTAMP default CURRENT_TIMESTAMP ); ================================================ FILE: data/migrations/admin_2020_08_04_092427_ms.sql ================================================ ALTER TABLE goadmin_menu ADD plugin_name varchar(150) NOT NULL DEFAULT '', ADD uuid varchar(150) NOT NULL DEFAULT ''; ================================================ FILE: data/migrations/admin_2020_08_04_092427_mysql.sql ================================================ ALTER TABLE goadmin_menu ADD COLUMN `uuid` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', ADD COLUMN `plugin_name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; ================================================ FILE: data/migrations/admin_2020_08_04_092427_postgres.sql ================================================ ALTER TABLE goadmin_menu ADD COLUMN plugin_name character varying(150) NOT NULL DEFAULT '', ADD COLUMN uuid character varying(150) NOT NULL DEFAULT ''; ================================================ FILE: data/migrations/admin_2020_08_04_092427_sqlite.sql ================================================ ALTER TABLE goadmin_menu ADD COLUMN `uuid` varchar(150) NOT NULL DEFAULT '', ADD COLUMN `plugin_name` varchar(150) NOT NULL DEFAULT ''; ================================================ FILE: docker-compose.yml ================================================ version: "3.3" services: mysql: image: mysql:5.6 container_name: mysql ports: - "3306:3306" volumes: - mysql:/data networks: - goadmin environment: - MYSQL_ROOT_PASSWORD=goadmin postgres: image: postgres:latest container_name: postgres ports: - "5432:5432" volumes: - postgres:/data networks: - goadmin environment: - POSTGRES_PASSWORD=goadmin goadmin: image: josingcjx/goadmin:1.1 tty: true container_name: goadmin volumes: - .:/home/goadmin networks: - goadmin command: - /bin/bash portainer: image: portainer/portainer:latest container_name: portainer restart: always ports: - "9000:9000" networks: - goadmin volumes: - /var/run/docker.sock:/var/run/docker.sock - portainer:/data networks: goadmin: {} volumes: portainer: {} postgres: {} mysql: {} ================================================ FILE: engine/engine.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package engine import ( "bytes" "encoding/json" errors2 "errors" "fmt" template2 "html/template" "net/http" "runtime/debug" "strings" "sync" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/template/icon" "github.com/GoAdminGroup/go-admin/template/types/action" "github.com/GoAdminGroup/go-admin/adapter" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/menu" "github.com/GoAdminGroup/go-admin/modules/service" "github.com/GoAdminGroup/go-admin/modules/system" "github.com/GoAdminGroup/go-admin/modules/ui" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" ) // Engine is the core component of goAdmin. It has two attributes. // PluginList is an array of plugin. Adapter is the adapter of // web framework context and goAdmin context. The relationship of adapter and // plugin is that the adapter use the plugin which contains routers and // controller methods to inject into the framework entity and make it work. type Engine struct { PluginList plugins.Plugins Adapter adapter.WebFrameWork Services service.List NavButtons *types.Buttons config *config.Config announceLock sync.Once } // Default return the default engine instance. func Default() *Engine { engine = &Engine{ Adapter: defaultAdapter, Services: service.GetServices(), NavButtons: new(types.Buttons), } return engine } // Use enable the adapter. func (eng *Engine) Use(router interface{}) error { if eng.Adapter == nil { emptyAdapterPanic() } eng.Services.Add(auth.InitCSRFTokenSrv(eng.DefaultConnection())) eng.initSiteSetting() eng.initJumpNavButtons() eng.initPlugins() printInitMsg(language.Get("initialize success")) return eng.Adapter.Use(router, eng.PluginList) } // AddPlugins add the plugins func (eng *Engine) AddPlugins(plugs ...plugins.Plugin) *Engine { if len(plugs) == 0 { return eng } for _, plug := range plugs { eng.PluginList = eng.PluginList.Add(plug) } return eng } // AddPluginList add the plugins func (eng *Engine) AddPluginList(plugs plugins.Plugins) *Engine { if len(plugs) == 0 { return eng } for _, plug := range plugs { eng.PluginList = eng.PluginList.Add(plug) } return eng } // FindPluginByName find the register plugin by given name. func (eng *Engine) FindPluginByName(name string) (plugins.Plugin, bool) { for _, plug := range eng.PluginList { if plug.Name() == name { return plug, true } } return nil, false } // AddAuthService customize the auth logic with given callback function. func (eng *Engine) AddAuthService(processor auth.Processor) *Engine { eng.Services.Add("auth", auth.NewService(processor)) return eng } // ============================ // Config APIs // ============================ func (eng *Engine) announce() *Engine { if eng.config.Debug { eng.announceLock.Do(func() { fmt.Printf(language.Get("goadmin is now running. \nrunning in \"debug\" mode. switch to \"release\" mode in production.\n\n")) }) } return eng } // AddConfig set the global config. func (eng *Engine) AddConfig(cfg *config.Config) *Engine { return eng.setConfig(cfg).announce().initDatabase() } // setConfig set the config of engine. func (eng *Engine) setConfig(cfg *config.Config) *Engine { eng.config = config.Initialize(cfg) sysCheck, themeCheck := template.CheckRequirements() if !sysCheck { logger.Panicf(language.Get("wrong goadmin version, theme %s required goadmin version are %s"), eng.config.Theme, strings.Join(template.Default().GetRequirements(), ",")) } if !themeCheck { logger.Panicf(language.Get("wrong theme version, goadmin %s required version of theme %s is %s"), system.Version(), eng.config.Theme, strings.Join(system.RequireThemeVersion()[eng.config.Theme], ",")) } return eng } // AddConfigFromJSON set the global config from json file. func (eng *Engine) AddConfigFromJSON(path string) *Engine { cfg := config.ReadFromJson(path) return eng.setConfig(&cfg).announce().initDatabase() } // AddConfigFromYAML set the global config from yaml file. func (eng *Engine) AddConfigFromYAML(path string) *Engine { cfg := config.ReadFromYaml(path) return eng.setConfig(&cfg).announce().initDatabase() } // AddConfigFromINI set the global config from ini file. func (eng *Engine) AddConfigFromINI(path string) *Engine { cfg := config.ReadFromINI(path) return eng.setConfig(&cfg).announce().initDatabase() } // InitDatabase initialize all database connection. func (eng *Engine) initDatabase() *Engine { printInitMsg(language.Get("initialize database connections")) for driver, databaseCfg := range eng.config.Databases.GroupByDriver() { eng.Services.Add(driver, db.GetConnectionByDriver(driver).InitDB(databaseCfg)) } if defaultAdapter == nil { emptyAdapterPanic() } defaultConnection := db.GetConnection(eng.Services) defaultAdapter.SetConnection(defaultConnection) eng.Adapter.SetConnection(defaultConnection) return eng } // AddAdapter add the adapter of engine. func (eng *Engine) AddAdapter(ada adapter.WebFrameWork) *Engine { eng.Adapter = ada defaultAdapter = ada return eng } // defaultAdapter is the default adapter of engine. var defaultAdapter adapter.WebFrameWork var engine *Engine // navButtons is the default buttons in the navigation bar. var navButtons = new(types.Buttons) func emptyAdapterPanic() { logger.Panic(language.Get("adapter is nil, import the default adapter or use addadapter method add the adapter")) } // Register set default adapter of engine. func Register(ada adapter.WebFrameWork) { if ada == nil { emptyAdapterPanic() } defaultAdapter = ada } // User call the User method of defaultAdapter. func User(ctx interface{}) (models.UserModel, bool) { return defaultAdapter.User(ctx) } // User call the User method of engine adapter. func (eng *Engine) User(ctx interface{}) (models.UserModel, bool) { return eng.Adapter.User(ctx) } // ============================ // DB Connection APIs // ============================ // DB return the db connection of given driver. func (eng *Engine) DB(driver string) db.Connection { return db.GetConnectionFromService(eng.Services.Get(driver)) } // DefaultConnection return the default db connection. func (eng *Engine) DefaultConnection() db.Connection { return eng.DB(eng.config.Databases.GetDefault().Driver) } // MysqlConnection return the mysql db connection of given driver. func (eng *Engine) MysqlConnection() db.Connection { return db.GetConnectionFromService(eng.Services.Get(db.DriverMysql)) } // MssqlConnection return the mssql db connection of given driver. func (eng *Engine) MssqlConnection() db.Connection { return db.GetConnectionFromService(eng.Services.Get(db.DriverMssql)) } // PostgresqlConnection return the postgresql db connection of given driver. func (eng *Engine) PostgresqlConnection() db.Connection { return db.GetConnectionFromService(eng.Services.Get(db.DriverPostgresql)) } // SqliteConnection return the sqlite db connection of given driver. func (eng *Engine) SqliteConnection() db.Connection { return db.GetConnectionFromService(eng.Services.Get(db.DriverSqlite)) } // OceanBaseConnection return the OceanBase db connection of given driver. func (eng *Engine) OceanBaseConnection() db.Connection { return db.GetConnectionFromService(eng.Services.Get(db.DriverOceanBase)) } type ConnectionSetter func(db.Connection) // ResolveConnection resolve the specified driver connection. func (eng *Engine) ResolveConnection(setter ConnectionSetter, driver string) *Engine { setter(eng.DB(driver)) return eng } // ResolveMysqlConnection resolve the mysql connection. func (eng *Engine) ResolveMysqlConnection(setter ConnectionSetter) *Engine { eng.ResolveConnection(setter, db.DriverMysql) return eng } // ResolveMssqlConnection resolve the mssql connection. func (eng *Engine) ResolveMssqlConnection(setter ConnectionSetter) *Engine { eng.ResolveConnection(setter, db.DriverMssql) return eng } // ResolveSqliteConnection resolve the sqlite connection. func (eng *Engine) ResolveSqliteConnection(setter ConnectionSetter) *Engine { eng.ResolveConnection(setter, db.DriverSqlite) return eng } // ResolvePostgresqlConnection resolve the postgres connection. func (eng *Engine) ResolvePostgresqlConnection(setter ConnectionSetter) *Engine { eng.ResolveConnection(setter, db.DriverPostgresql) return eng } type Setter func(*Engine) // Clone copy a new Engine. func (eng *Engine) Clone(e *Engine) *Engine { e = eng return eng } // ClonedBySetter copy a new Engine by a setter callback function. func (eng *Engine) ClonedBySetter(setter Setter) *Engine { setter(eng) return eng } func (eng *Engine) deferHandler(conn db.Connection) context.Handler { return func(ctx *context.Context) { defer func(ctx *context.Context) { if user, ok := ctx.UserValue["user"].(models.UserModel); ok { var input []byte form := ctx.Request.MultipartForm if form != nil { input, _ = json.Marshal((*form).Value) } models.OperationLog().SetConn(conn).New(user.Id, ctx.Path(), ctx.Method(), ctx.LocalIP(), string(input)) } if err := recover(); err != nil { logger.Error(err) logger.Error(string(debug.Stack())) var ( errMsg string ok bool e error ) if errMsg, ok = err.(string); !ok { if e, ok = err.(error); ok { errMsg = e.Error() } } if errMsg == "" { errMsg = "system error" } if ctx.WantJSON() { response.Error(ctx, errMsg) return } eng.errorPanelHTML(ctx, new(bytes.Buffer), errors2.New(errMsg)) } }(ctx) ctx.Next() } } // wrapWithAuthMiddleware wrap a auth middleware to the given handler. func (eng *Engine) wrapWithAuthMiddleware(handler context.Handler) context.Handlers { conn := db.GetConnection(eng.Services) return []context.Handler{eng.deferHandler(conn), response.OffLineHandler, auth.Middleware(conn), handler} } // wrapWithAuthMiddleware wrap a auth middleware to the given handler. func (eng *Engine) wrap(handler context.Handler) context.Handlers { conn := db.GetConnection(eng.Services) return []context.Handler{eng.deferHandler(conn), response.OffLineHandler, handler} } // ============================ // Initialize methods // ============================ // AddNavButtons add the nav buttons. func (eng *Engine) AddNavButtons(title template2.HTML, icon string, action types.Action) *Engine { btn := types.GetNavButton(title, icon, action) *eng.NavButtons = append(*eng.NavButtons, btn) return eng } // AddNavButtonsRaw add the nav buttons. func (eng *Engine) AddNavButtonsRaw(btns ...types.Button) *Engine { *eng.NavButtons = append(*eng.NavButtons, btns...) return eng } type navJumpButtonParam struct { Exist bool Icon string BtnName string URL string Title string TitleScore string } func (eng *Engine) addJumpNavButton(param navJumpButtonParam) *Engine { if param.Exist { *eng.NavButtons = (*eng.NavButtons).AddNavButton(param.Icon, param.BtnName, action.JumpInNewTab(config.Url(param.URL), language.GetWithScope(param.Title, param.TitleScore))) } return eng } func printInitMsg(msg string) { logger.Info(msg) } func (eng *Engine) initJumpNavButtons() { printInitMsg(language.Get("initialize navigation buttons")) for _, param := range eng.initNavJumpButtonParams() { eng.addJumpNavButton(param) } navButtons = eng.NavButtons eng.Services.Add(ui.ServiceKey, ui.NewService(eng.NavButtons)) } func (eng *Engine) initPlugins() { printInitMsg(language.Get("initialize plugins")) eng.AddPlugins(admin.NewAdmin()).AddPluginList(plugins.Get()) var plugGenerators = make(table.GeneratorList) for i := range eng.PluginList { if eng.PluginList[i].Name() != "admin" { printInitMsg("--> " + eng.PluginList[i].Name()) eng.PluginList[i].InitPlugin(eng.Services) if !eng.PluginList[i].GetInfo().SkipInstallation { eng.AddGenerator("plugin_"+eng.PluginList[i].Name(), eng.PluginList[i].GetSettingPage()) } plugGenerators = plugGenerators.Combine(eng.PluginList[i].GetGenerators()) } } adm := eng.AdminPlugin().AddGenerators(plugGenerators) adm.InitPlugin(eng.Services) plugins.Add(adm) } func (eng *Engine) initNavJumpButtonParams() []navJumpButtonParam { return []navJumpButtonParam{ { Exist: !eng.config.HideConfigCenterEntrance, Icon: icon.Gear, BtnName: types.NavBtnSiteName, URL: "/info/site/edit", Title: "site setting", TitleScore: "config", }, { Exist: !eng.config.HideToolEntrance && eng.config.IsNotProductionEnvironment(), Icon: icon.Wrench, BtnName: types.NavBtnToolName, URL: "/info/generate/new", Title: "code generate tool", TitleScore: "tool", }, { Exist: !eng.config.HideAppInfoEntrance, Icon: icon.Info, BtnName: types.NavBtnInfoName, URL: "/application/info", Title: "site info", TitleScore: "system", }, { Exist: !eng.config.HidePluginEntrance, Icon: icon.Th, BtnName: types.NavBtnPlugName, URL: "/plugins", Title: "plugins", TitleScore: "plugin", }, } } func (eng *Engine) initSiteSetting() { printInitMsg(language.Get("initialize configuration")) err := eng.config.Update(models.Site(). SetConn(eng.DefaultConnection()). Init(eng.config.ToMap()). AllToMap()) if err != nil { logger.Panic(err) } eng.Services.Add("config", config.SrvWithConfig(eng.config)) errors.Init() } // ============================ // HTML Content Render APIs // ============================ // Content call the Content method of engine adapter. // If adapter is nil, it will panic. func (eng *Engine) Content(ctx interface{}, panel types.GetPanelFn) { if eng.Adapter == nil { emptyAdapterPanic() } eng.Adapter.Content(ctx, panel, eng.AdminPlugin().GetAddOperationFn(), *eng.NavButtons...) } // Content call the Content method of defaultAdapter. // If defaultAdapter is nil, it will panic. func Content(ctx interface{}, panel types.GetPanelFn) { if defaultAdapter == nil { emptyAdapterPanic() } defaultAdapter.Content(ctx, panel, engine.AdminPlugin().GetAddOperationFn(), *navButtons...) } // Data inject the route and corresponding handler to the web framework. func (eng *Engine) Data(method, url string, handler context.Handler, noAuth ...bool) { if len(noAuth) > 0 && noAuth[0] { eng.Adapter.AddHandler(method, url, eng.wrap(handler)) } else { eng.Adapter.AddHandler(method, url, eng.wrapWithAuthMiddleware(handler)) } } // HTML inject the route and corresponding handler wrapped by the given function to the web framework. func (eng *Engine) HTML(method, url string, fn types.GetPanelInfoFn, noAuth ...bool) { var handler = func(ctx *context.Context) { panel, err := fn(ctx) if err != nil { panel = template.WarningPanel(ctx, err.Error()) } eng.AdminPlugin().GetAddOperationFn()(panel.Callbacks...) var ( tmpl, tmplName = template.Default(ctx).GetTemplate(ctx.IsPjax()) user = auth.Auth(ctx) buf = new(bytes.Buffer) ) hasError := tmpl.ExecuteTemplate(buf, tmplName, types.NewPage(ctx, &types.NewPageParam{ User: user, Menu: menu.GetGlobalMenu(user, eng.Adapter.GetConnection(), ctx.Lang()).SetActiveClass(config.URLRemovePrefix(ctx.Path())), Panel: panel.GetContent(eng.config.IsProductionEnvironment()), Assets: template.GetComponentAssetImportHTML(ctx), Buttons: eng.NavButtons.CheckPermission(user), TmplHeadHTML: template.Default(ctx).GetHeadHTML(), TmplFootJS: template.Default(ctx).GetFootJS(), Iframe: ctx.IsIframe(), })) if hasError != nil { logger.Error(fmt.Sprintf("error: %s adapter content, ", eng.Adapter.Name()), hasError) } ctx.HTMLByte(http.StatusOK, buf.Bytes()) } if len(noAuth) > 0 && noAuth[0] { eng.Adapter.AddHandler(method, url, eng.wrap(handler)) } else { eng.Adapter.AddHandler(method, url, eng.wrapWithAuthMiddleware(handler)) } } // HTMLFile inject the route and corresponding handler which returns the panel content of given html file path // to the web framework. func (eng *Engine) HTMLFile(method, url, path string, data map[string]interface{}, noAuth ...bool) { var handler = func(ctx *context.Context) { cbuf := new(bytes.Buffer) t, err := template2.ParseFiles(path) if err != nil { eng.errorPanelHTML(ctx, cbuf, err) return } else if err := t.Execute(cbuf, data); err != nil { eng.errorPanelHTML(ctx, cbuf, err) return } var ( tmpl, tmplName = template.Default(ctx).GetTemplate(ctx.IsPjax()) user = auth.Auth(ctx) buf = new(bytes.Buffer) ) hasError := tmpl.ExecuteTemplate(buf, tmplName, types.NewPage(ctx, &types.NewPageParam{ User: user, Menu: menu.GetGlobalMenu(user, eng.Adapter.GetConnection(), ctx.Lang()).SetActiveClass(eng.config.URLRemovePrefix(ctx.Path())), Panel: types.Panel{ Content: template.HTML(cbuf.String()), }, Assets: template.GetComponentAssetImportHTML(ctx), Buttons: eng.NavButtons.CheckPermission(user), TmplHeadHTML: template.Default(ctx).GetHeadHTML(), TmplFootJS: template.Default(ctx).GetFootJS(), Iframe: ctx.IsIframe(), })) if hasError != nil { logger.Error(fmt.Sprintf("error: %s adapter content, ", eng.Adapter.Name()), hasError) } ctx.HTMLByte(http.StatusOK, buf.Bytes()) } if len(noAuth) > 0 && noAuth[0] { eng.Adapter.AddHandler(method, url, eng.wrap(handler)) } else { eng.Adapter.AddHandler(method, url, eng.wrapWithAuthMiddleware(handler)) } } // HTMLFiles inject the route and corresponding handler which returns the panel content of given html files path // to the web framework. func (eng *Engine) HTMLFiles(method, url string, data map[string]interface{}, files ...string) { eng.Adapter.AddHandler(method, url, eng.wrapWithAuthMiddleware(eng.htmlFilesHandler(data, files...))) } // HTMLFilesNoAuth inject the route and corresponding handler which returns the panel content of given html files path // to the web framework without auth check. func (eng *Engine) HTMLFilesNoAuth(method, url string, data map[string]interface{}, files ...string) { eng.Adapter.AddHandler(method, url, eng.wrap(eng.htmlFilesHandler(data, files...))) } // HTMLFiles inject the route and corresponding handler which returns the panel content of given html files path // to the web framework. func (eng *Engine) htmlFilesHandler(data map[string]interface{}, files ...string) context.Handler { return func(ctx *context.Context) { cbuf := new(bytes.Buffer) t, err := template2.ParseFiles(files...) if err != nil { eng.errorPanelHTML(ctx, cbuf, err) return } else if err := t.Execute(cbuf, data); err != nil { eng.errorPanelHTML(ctx, cbuf, err) return } var ( tmpl, tmplName = template.Default(ctx).GetTemplate(ctx.IsPjax()) user = auth.Auth(ctx) buf = new(bytes.Buffer) ) hasError := tmpl.ExecuteTemplate(buf, tmplName, types.NewPage(ctx, &types.NewPageParam{ User: user, Menu: menu.GetGlobalMenu(user, eng.Adapter.GetConnection(), ctx.Lang()).SetActiveClass(eng.config.URLRemovePrefix(ctx.Path())), Panel: types.Panel{ Content: template.HTML(cbuf.String()), }, Assets: template.GetComponentAssetImportHTML(ctx), Buttons: eng.NavButtons.CheckPermission(user), TmplHeadHTML: template.Default(ctx).GetHeadHTML(), TmplFootJS: template.Default(ctx).GetFootJS(), Iframe: ctx.IsIframe(), })) if hasError != nil { logger.Error(fmt.Sprintf("error: %s adapter content, ", eng.Adapter.Name()), hasError) } ctx.HTMLByte(http.StatusOK, buf.Bytes()) } } // errorPanelHTML add an error panel html to context response. func (eng *Engine) errorPanelHTML(ctx *context.Context, buf *bytes.Buffer, err error) { user := auth.Auth(ctx) tmpl, tmplName := template.Default(ctx).GetTemplate(ctx.IsPjax()) hasError := tmpl.ExecuteTemplate(buf, tmplName, types.NewPage(ctx, &types.NewPageParam{ User: user, Menu: menu.GetGlobalMenu(user, eng.Adapter.GetConnection(), ctx.Lang()).SetActiveClass(eng.config.URLRemovePrefix(ctx.Path())), Panel: template.WarningPanel(ctx, err.Error()).GetContent(eng.config.IsProductionEnvironment()), Assets: template.GetComponentAssetImportHTML(ctx), Buttons: (*eng.NavButtons).CheckPermission(user), TmplHeadHTML: template.Default(ctx).GetHeadHTML(), TmplFootJS: template.Default(ctx).GetFootJS(), Iframe: ctx.IsIframe(), })) if hasError != nil { logger.Error(fmt.Sprintf("error: %s adapter content, ", eng.Adapter.Name()), hasError) } ctx.HTMLByte(http.StatusOK, buf.Bytes()) } // ============================ // Admin Plugin APIs // ============================ // AddGenerators add the admin generators. func (eng *Engine) AddGenerators(list ...table.GeneratorList) *Engine { plug, exist := eng.FindPluginByName("admin") if exist { plug.(*admin.Admin).AddGenerators(list...) return eng } eng.PluginList = append(eng.PluginList, admin.NewAdmin(list...)) return eng } // AdminPlugin get the admin plugin. if not exist, create one. func (eng *Engine) AdminPlugin() *admin.Admin { plug, exist := eng.FindPluginByName("admin") if exist { return plug.(*admin.Admin) } adm := admin.NewAdmin() eng.PluginList = append(eng.PluginList, adm) return adm } // SetCaptcha set the captcha config. func (eng *Engine) SetCaptcha(captcha map[string]string) *Engine { eng.AdminPlugin().SetCaptcha(captcha) return eng } // SetCaptchaDriver set the captcha config with driver. func (eng *Engine) SetCaptchaDriver(driver string) *Engine { eng.AdminPlugin().SetCaptcha(map[string]string{"driver": driver}) return eng } // AddGenerator add table model generator. func (eng *Engine) AddGenerator(key string, g table.Generator) *Engine { eng.AdminPlugin().AddGenerator(key, g) return eng } // AddGlobalDisplayProcessFn call types.AddGlobalDisplayProcessFn. func (eng *Engine) AddGlobalDisplayProcessFn(f types.FieldFilterFn) *Engine { types.AddGlobalDisplayProcessFn(f) return eng } // AddDisplayFilterLimit call types.AddDisplayFilterLimit. func (eng *Engine) AddDisplayFilterLimit(limit int) *Engine { types.AddLimit(limit) return eng } // AddDisplayFilterTrimSpace call types.AddDisplayFilterTrimSpace. func (eng *Engine) AddDisplayFilterTrimSpace() *Engine { types.AddTrimSpace() return eng } // AddDisplayFilterSubstr call types.AddDisplayFilterSubstr. func (eng *Engine) AddDisplayFilterSubstr(start int, end int) *Engine { types.AddSubstr(start, end) return eng } // AddDisplayFilterToTitle call types.AddDisplayFilterToTitle. func (eng *Engine) AddDisplayFilterToTitle() *Engine { types.AddToTitle() return eng } // AddDisplayFilterToUpper call types.AddDisplayFilterToUpper. func (eng *Engine) AddDisplayFilterToUpper() *Engine { types.AddToUpper() return eng } // AddDisplayFilterToLower call types.AddDisplayFilterToLower. func (eng *Engine) AddDisplayFilterToLower() *Engine { types.AddToUpper() return eng } // AddDisplayFilterXssFilter call types.AddDisplayFilterXssFilter. func (eng *Engine) AddDisplayFilterXssFilter() *Engine { types.AddXssFilter() return eng } // AddDisplayFilterXssJsFilter call types.AddDisplayFilterXssJsFilter. func (eng *Engine) AddDisplayFilterXssJsFilter() *Engine { types.AddXssJsFilter() return eng } ================================================ FILE: examples/beego/main.go ================================================ package main import ( "log" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/beego" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/themes/adminlte" "github.com/astaxie/beego" ) func main() { app := beego.NewApp() eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, }, }, Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, UrlPrefix: "admin", IndexUrl: "/", Debug: true, Language: language.CN, ColorScheme: adminlte.ColorschemeSkinBlack, } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // eng.AddConfigFromJSON("../datamodel/config.json") beego.SetStaticPath("/uploads", "uploads") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(app); err != nil { panic(err) } // you can custom your pages like: eng.HTML("GET", "/admin", datamodel.GetContent) beego.BConfig.Listen.HTTPAddr = "127.0.0.1" beego.BConfig.Listen.HTTPPort = 9087 go app.Run() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } ================================================ FILE: examples/beego2/main.go ================================================ package main import ( "log" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/beego2" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/themes/adminlte" "github.com/beego/beego/v2/server/web" ) func main() { app := web.NewHttpSever() eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "123456", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, }, }, Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, UrlPrefix: "admin", IndexUrl: "/", Debug: true, Language: language.CN, ColorScheme: adminlte.ColorschemeSkinBlack, } template.AddComp(chartjs.NewChart()) examplePlugin := example.NewExample() web.SetStaticPath("/uploads", "uploads") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(app); err != nil { panic(err) } eng.HTML("GET", "/admin", datamodel.GetContent) app.Cfg.Listen.HTTPSAddr = "127.0.0.1" app.Cfg.Listen.HTTPPort = 9087 go app.Run("") quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } ================================================ FILE: examples/buffalo/main.go ================================================ package main import ( "log" "net/http" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/buffalo" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/themes/adminlte" "github.com/gobuffalo/buffalo" ) func main() { bu := buffalo.New(buffalo.Options{ Env: "test", Addr: "127.0.0.1:9033", }) eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, }, }, UrlPrefix: "admin", Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, Language: language.EN, IndexUrl: "/", Debug: true, ColorScheme: adminlte.ColorschemeSkinBlack, } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // eng.AddConfigFromJSON("../datamodel/config.json") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(bu); err != nil { panic(err) } bu.ServeFiles("/uploads", http.Dir("./uploads")) // you can custom your pages like: eng.HTML("GET", "/admin", datamodel.GetContent) go func() { _ = bu.Serve() }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } ================================================ FILE: examples/chi/main.go ================================================ package main import ( "log" "net/http" "os" "os/signal" "path/filepath" "strings" "time" _ "github.com/GoAdminGroup/go-admin/adapter/chi" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/themes/adminlte" "github.com/go-chi/chi" ) func main() { r := chi.NewRouter() eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, }, }, UrlPrefix: "admin", Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, Language: language.EN, IndexUrl: "/", Debug: true, ColorScheme: adminlte.ColorschemeSkinBlack, } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // eng.AddConfigFromJSON("../datamodel/config.json") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(r); err != nil { panic(err) } workDir, _ := os.Getwd() filesDir := filepath.Join(workDir, "uploads") FileServer(r, "/uploads", http.Dir(filesDir)) // you can custom your pages like: eng.HTML("GET", "/admin", datamodel.GetContent) go func() { _ = http.ListenAndServe(":3333", r) }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } // FileServer conveniently sets up a http.FileServer handler to serve // static files from a http.FileSystem. func FileServer(r chi.Router, path string, root http.FileSystem) { if strings.ContainsAny(path, "{}*") { panic("FileServer does not permit URL parameters.") } fs := http.StripPrefix(path, http.FileServer(root)) if path != "/" && path[len(path)-1] != '/' { r.Get(path, http.RedirectHandler(path+"/", http.StatusMovedPermanently).ServeHTTP) path += "/" } path += "*" r.Get(path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fs.ServeHTTP(w, r) })) } ================================================ FILE: examples/datamodel/authors.go ================================================ package datamodel import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template/types/form" ) // GetAuthorsTable return the model of table author. func GetAuthorsTable(ctx *context.Context) (authorsTable table.Table) { authorsTable = table.NewDefaultTable(ctx, table.DefaultConfig()) // connect your custom connection // authorsTable = table.NewDefaultTable(ctx, table.DefaultConfigWithDriverAndConnection("mysql", "admin")) info := authorsTable.GetInfo() info.AddField("ID", "id", db.Int).FieldSortable() info.AddField("First Name", "first_name", db.Varchar) info.AddField("Last Name", "last_name", db.Varchar) info.AddField("Email", "email", db.Varchar) info.AddField("Birthdate", "birthdate", db.Date) info.AddField("Added", "added", db.Timestamp) info.SetTable("authors").SetTitle("Authors").SetDescription("Authors") formList := authorsTable.GetForm() formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() formList.AddField("First Name", "first_name", db.Varchar, form.Text) formList.AddField("Last Name", "last_name", db.Varchar, form.Text) formList.AddField("Email", "email", db.Varchar, form.Text) formList.AddField("Birthdate", "birthdate", db.Date, form.Text) formList.AddField("Added", "added", db.Timestamp, form.Text) formList.SetTable("authors").SetTitle("Authors").SetDescription("Authors") return } ================================================ FILE: examples/datamodel/bootstrap.go ================================================ package datamodel ================================================ FILE: examples/datamodel/config.json ================================================ { "database": { "default": { "host": "127.0.0.1", "port": "3306", "user": "root", "pwd": "root", "name": "godmin", "max_idle_con": 50, "max_open_con": 150, "driver": "mysql" } }, "domain": "localhost", "prefix": "admin", "store": { "path": "./uploads", "prefix": "uploads" }, "language": "cn", "index": "/", "debug": true, "color_scheme": "skin-black" } ================================================ FILE: examples/datamodel/content.go ================================================ package datamodel import ( "html/template" "github.com/GoAdminGroup/go-admin/context" tmpl "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/go-admin/template/icon" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/themes/adminlte/components/chart_legend" "github.com/GoAdminGroup/themes/adminlte/components/description" "github.com/GoAdminGroup/themes/adminlte/components/infobox" "github.com/GoAdminGroup/themes/adminlte/components/productlist" "github.com/GoAdminGroup/themes/adminlte/components/progress_group" "github.com/GoAdminGroup/themes/adminlte/components/smallbox" ) // GetContent return the content of index page. func GetContent(ctx *context.Context) (types.Panel, error) { components := tmpl.Default(ctx) colComp := components.Col() /************************** * Info Box /**************************/ infobox1 := infobox.New(). SetText("CPU TRAFFIC"). SetColor("aqua"). SetNumber("100"). SetIcon("ion-ios-gear-outline"). GetContent() infobox2 := infobox.New(). SetText("Likes"). SetColor("red"). SetNumber("1030.00$"). SetIcon(icon.GooglePlus). GetContent() infobox3 := infobox.New(). SetText("Sales"). SetColor("green"). SetNumber("760"). SetIcon("ion-ios-cart-outline"). GetContent() infobox4 := infobox.New(). SetText("New Members"). SetColor("yellow"). SetNumber("2,349"). SetIcon("ion-ios-people-outline"). // svg is ok GetContent() var size = types.Size(6, 3, 0).XS(12) infoboxCol1 := colComp.SetSize(size).SetContent(infobox1).GetContent() infoboxCol2 := colComp.SetSize(size).SetContent(infobox2).GetContent() infoboxCol3 := colComp.SetSize(size).SetContent(infobox3).GetContent() infoboxCol4 := colComp.SetSize(size).SetContent(infobox4).GetContent() row1 := components.Row().SetContent(infoboxCol1 + infoboxCol2 + infoboxCol3 + infoboxCol4).GetContent() /************************** * Box /**************************/ table := components.Table().SetInfoList([]map[string]types.InfoItem{ { "Order ID": {Content: "OR9842"}, "Item": {Content: "Call of Duty IV"}, "Status": {Content: "shipped"}, "Popularity": {Content: "90%"}, }, { "Order ID": {Content: "OR9842"}, "Item": {Content: "Call of Duty IV"}, "Status": {Content: "shipped"}, "Popularity": {Content: "90%"}, }, { "Order ID": {Content: "OR9842"}, "Item": {Content: "Call of Duty IV"}, "Status": {Content: "shipped"}, "Popularity": {Content: "90%"}, }, { "Order ID": {Content: "OR9842"}, "Item": {Content: "Call of Duty IV"}, "Status": {Content: "shipped"}, "Popularity": {Content: "90%"}, }, }).SetThead(types.Thead{ {Head: "Order ID"}, {Head: "Item"}, {Head: "Status"}, {Head: "Popularity"}, }).GetContent() boxInfo := components.Box(). WithHeadBorder(). SetHeader("Latest Orders"). SetHeadColor("#f7f7f7"). SetBody(table). SetFooter(``). GetContent() tableCol := colComp.SetSize(types.SizeMD(8)).SetContent(row1 + boxInfo).GetContent() /************************** * Product List /**************************/ productList := productlist.New().SetData([]map[string]string{ { "img": "http://adminlte.io/themes/AdminLTE/dist/img/default-50x50.gif", "title": "GoAdmin", "has_tabel": "true", "labeltype": "warning", "label": "free", "description": `a framework help you build the dataviz system`, }, { "img": "http://adminlte.io/themes/AdminLTE/dist/img/default-50x50.gif", "title": "GoAdmin", "has_tabel": "true", "labeltype": "warning", "label": "free", "description": `a framework help you build the dataviz system`, }, { "img": "http://adminlte.io/themes/AdminLTE/dist/img/default-50x50.gif", "title": "GoAdmin", "has_tabel": "true", "labeltype": "warning", "label": "free", "description": `a framework help you build the dataviz system`, }, { "img": "http://adminlte.io/themes/AdminLTE/dist/img/default-50x50.gif", "title": "GoAdmin", "has_tabel": "true", "labeltype": "warning", "label": "free", "description": `a framework help you build the dataviz system`, }, }).GetContent() boxWarning := components.Box().SetTheme("warning").WithHeadBorder().SetHeader("Recently Added Products"). SetBody(productList). SetFooter(`View All Products`). GetContent() newsCol := colComp.SetSize(types.SizeMD(4)).SetContent(boxWarning).GetContent() row5 := components.Row().SetContent(tableCol + newsCol).GetContent() /************************** * Box /**************************/ line := chartjs.Line() lineChart := line. SetID("salechart"). SetHeight(180). SetTitle("Sales: 1 Jan, 2019 - 30 Jul, 2019"). SetLabels([]string{"January", "February", "March", "April", "May", "June", "July"}). AddDataSet("Electronics"). DSData([]float64{65, 59, 80, 81, 56, 55, 40}). DSFill(false). DSBorderColor("rgb(210, 214, 222)"). DSLineTension(0.1). AddDataSet("Digital Goods"). DSData([]float64{28, 48, 40, 19, 86, 27, 90}). DSFill(false). DSBorderColor("rgba(60,141,188,1)"). DSLineTension(0.1). GetContent() title := `

Goal Completion

` progressGroup := progress_group.New(). SetTitle("Add Products to Cart"). SetColor("#76b2d4"). SetDenominator(200). SetMolecular(160). SetPercent(80). GetContent() progressGroup1 := progress_group.New(). SetTitle("Complete Purchase"). SetColor("#f17c6e"). SetDenominator(400). SetMolecular(310). SetPercent(80). GetContent() progressGroup2 := progress_group.New(). SetTitle("Visit Premium Page"). SetColor("#ace0ae"). SetDenominator(800). SetMolecular(490). SetPercent(80). GetContent() progressGroup3 := progress_group.New(). SetTitle("Send Inquiries"). SetColor("#fdd698"). SetDenominator(500). SetMolecular(250). SetPercent(50). GetContent() boxInternalCol1 := colComp.SetContent(lineChart).SetSize(types.SizeMD(8)).GetContent() boxInternalCol2 := colComp. SetContent(template.HTML(title) + progressGroup + progressGroup1 + progressGroup2 + progressGroup3). SetSize(types.SizeMD(4)). GetContent() boxInternalRow := components.Row().SetContent(boxInternalCol1 + boxInternalCol2).GetContent() description1 := description.New(). SetPercent("17"). SetNumber("¥140,100"). SetTitle("TOTAL REVENUE"). SetArrow("up"). SetColor("green"). SetBorder("right"). GetContent() description2 := description.New(). SetPercent("2"). SetNumber("440,560"). SetTitle("TOTAL REVENUE"). SetArrow("down"). SetColor("red"). SetBorder("right"). GetContent() description3 := description.New(). SetPercent("12"). SetNumber("¥140,050"). SetTitle("TOTAL REVENUE"). SetArrow("up"). SetColor("green"). SetBorder("right"). GetContent() description4 := description.New(). SetPercent("1"). SetNumber("30943"). SetTitle("TOTAL REVENUE"). SetArrow("up"). SetColor("green"). GetContent() size2 := types.SizeXS(6).SM(3) boxInternalCol3 := colComp.SetContent(description1).SetSize(size2).GetContent() boxInternalCol4 := colComp.SetContent(description2).SetSize(size2).GetContent() boxInternalCol5 := colComp.SetContent(description3).SetSize(size2).GetContent() boxInternalCol6 := colComp.SetContent(description4).SetSize(size2).GetContent() boxInternalRow2 := components.Row().SetContent(boxInternalCol3 + boxInternalCol4 + boxInternalCol5 + boxInternalCol6).GetContent() box := components.Box().WithHeadBorder().SetHeader("Monthly Recap Report"). SetBody(boxInternalRow). SetFooter(boxInternalRow2). GetContent() boxcol := colComp.SetContent(box).SetSize(types.SizeMD(12)).GetContent() row2 := components.Row().SetContent(boxcol).GetContent() /************************** * Small Box /**************************/ smallbox1 := smallbox.New().SetColor("blue").SetIcon("ion-ios-gear-outline").SetUrl("/").SetTitle("new users").SetValue("345¥").GetContent() smallbox2 := smallbox.New().SetColor("yellow").SetIcon("ion-ios-cart-outline").SetUrl("/").SetTitle("new users").SetValue("80%").GetContent() smallbox3 := smallbox.New().SetColor("red").SetIcon("fa-user").SetUrl("/").SetTitle("new users").SetValue("645¥").GetContent() smallbox4 := smallbox.New().SetColor("green").SetIcon("ion-ios-cart-outline").SetUrl("/").SetTitle("new users").SetValue("889¥").GetContent() col1 := colComp.SetSize(size).SetContent(smallbox1).GetContent() col2 := colComp.SetSize(size).SetContent(smallbox2).GetContent() col3 := colComp.SetSize(size).SetContent(smallbox3).GetContent() col4 := colComp.SetSize(size).SetContent(smallbox4).GetContent() row3 := components.Row().SetContent(col1 + col2 + col3 + col4).GetContent() /************************** * Pie Chart /**************************/ pie := chartjs.Pie(). SetHeight(170). SetLabels([]string{"Navigator", "Opera", "Safari", "FireFox", "IE", "Chrome"}). SetID("pieChart"). AddDataSet("Chrome"). DSData([]float64{100, 300, 600, 400, 500, 700}). DSBackgroundColor([]chartjs.Color{ "rgb(255, 205, 86)", "rgb(54, 162, 235)", "rgb(255, 99, 132)", "rgb(255, 205, 86)", "rgb(54, 162, 235)", "rgb(255, 99, 132)", }). GetContent() legend := chart_legend.New().SetData([]map[string]string{ { "label": " Chrome", "color": "red", }, { "label": " IE", "color": "Green", }, { "label": " FireFox", "color": "yellow", }, { "label": " Sarafri", "color": "blue", }, { "label": " Opera", "color": "light-blue", }, { "label": " Navigator", "color": "gray", }, }).GetContent() boxDanger := components.Box().SetTheme("danger").WithHeadBorder().SetHeader("Browser Usage"). SetBody(components.Row(). SetContent(colComp.SetSize(types.SizeMD(8)). SetContent(pie). GetContent() + colComp.SetSize(types.SizeMD(4)). SetContent(legend). GetContent()).GetContent()). SetFooter(`

View All Users

`). GetContent() tabs := components.Tabs().SetData([]map[string]template.HTML{ { "title": "tabs1", "content": template.HTML(`How to use:

Exactly like the original bootstrap tabs except you should use the custom wrapper .nav-tabs-custom to achieve this style.

A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine. I am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.`), }, { "title": "tabs2", "content": template.HTML(` The European languages are members of the same family. Their separate existence is a myth. For science, music, sport, etc, Europe uses the same vocabulary. The languages only differ in their grammar, their pronunciation and their most common words. Everyone realizes why a new common language would be desirable: one could refuse to pay expensive translators. To achieve this, it would be necessary to have uniform grammar, pronunciation and more common words. If several languages coalesce, the grammar of the resulting language is more simple and regular than that of the individual languages. `), }, { "title": "tabs3", "content": template.HTML(` Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. `), }, }).GetContent() buttonTest := `` popupForm := `
` popup := components.Popup().SetID("exampleModal"). SetFooter("Save Change"). SetTitle("this is a popup"). SetBody(template.HTML(popupForm)). GetContent() col5 := colComp.SetSize(types.SizeMD(8)).SetContent(tabs + template.HTML(buttonTest)).GetContent() col6 := colComp.SetSize(types.SizeMD(4)).SetContent(boxDanger + popup).GetContent() row4 := components.Row().SetContent(col5 + col6).GetContent() return types.Panel{ Content: row3 + row2 + row5 + row4, Title: "Dashboard", Description: "dashboard example", }, nil } ================================================ FILE: examples/datamodel/goadmin_super_users.go ================================================ package datamodel import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template/types/form" ) func GetGoadminSuperUsersTable(ctx *context.Context) table.Table { goadminSuperUsers := table.NewDefaultTable(ctx, table.DefaultConfigWithDriver("mysql")) info := goadminSuperUsers.GetInfo().HideFilterArea() info.AddField("Id", "id", db.Int).FieldFilterable() info.AddField("Username", "username", db.Varchar) info.AddField("Password", "password", db.Varchar) info.AddField("Name", "name", db.Varchar) info.AddField("Avatar", "avatar", db.Varchar) info.AddField("Remember_token", "remember_token", db.Varchar) info.AddField("Created_at", "created_at", db.Timestamp) info.AddField("Updated_at", "updated_at", db.Timestamp) info.SetTable("goadmin_super_users").SetTitle("GoadminSuperUsers").SetDescription("GoadminSuperUsers") formList := goadminSuperUsers.GetForm() formList.AddField("Id", "id", db.Int, form.Default) formList.AddField("Username", "username", db.Varchar, form.Text) formList.AddField("Password", "password", db.Varchar, form.Password) formList.AddField("Name", "name", db.Varchar, form.Text) formList.AddField("Avatar", "avatar", db.Varchar, form.Text) formList.AddField("Remember_token", "remember_token", db.Varchar, form.Text) formList.AddField("Created_at", "created_at", db.Timestamp, form.Datetime) formList.AddField("Updated_at", "updated_at", db.Timestamp, form.Datetime) formList.SetTable("goadmin_super_users").SetTitle("GoadminSuperUsers").SetDescription("GoadminSuperUsers") return goadminSuperUsers } ================================================ FILE: examples/datamodel/mysql_types.go ================================================ package datamodel import ( "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template/types/form" ) // GetAllTypesTable return the model of table types. func GetAllTypesTable() table.Table { allTypesTable := table.NewDefaultTable(nil, table.DefaultConfigWithDriver("mysql")) info := allTypesTable.GetInfo() info.AddField("Id", "id", db.Int) info.AddField("Type_1", "type_1", db.Tinyint) info.AddField("Type_2", "type_2", db.Smallint) info.AddField("Type_3", "type_3", db.Mediumint) info.AddField("Type_4", "type_4", db.Bigint) info.AddField("Type_5", "type_5", db.Float) info.AddField("Type_6", "type_6", db.Double) info.AddField("Type_7", "type_7", db.Double) info.AddField("Type_8", "type_8", db.Double) info.AddField("Type_9", "type_9", db.Decimal) info.AddField("Type_10", "type_10", db.Bit) info.AddField("Type_11", "type_11", db.Tinyint) info.AddField("Type_12", "type_12", db.Tinyint) info.AddField("Type_13", "type_13", db.Decimal) info.AddField("Type_14", "type_14", db.Decimal) info.AddField("Type_15", "type_15", db.Decimal) info.AddField("Type_16", "type_16", db.Char) info.AddField("Type_17", "type_17", db.Varchar) info.AddField("Type_18", "type_18", db.Tinytext) info.AddField("Type_19", "type_19", db.Text) info.AddField("Type_20", "type_20", db.Mediumtext) info.AddField("Type_21", "type_21", db.Longtext) info.AddField("Type_22", "type_22", db.Tinyblob) info.AddField("Type_23", "type_23", db.Mediumblob) info.AddField("Type_24", "type_24", db.Blob) info.AddField("Type_25", "type_25", db.Longblob) info.AddField("Type_26", "type_26", db.Binary) info.AddField("Type_27", "type_27", db.Varbinary) info.AddField("Type_28", "type_28", db.Enum) info.AddField("Type_29", "type_29", db.Set) info.AddField("Type_30", "type_30", db.Date) info.AddField("Type_31", "type_31", db.Datetime) info.AddField("Type_32", "type_32", db.Timestamp) info.AddField("Type_33", "type_33", db.Time) info.AddField("Type_34", "type_34", db.Year) info.AddField("Type_35", "type_35", db.Geometry) info.AddField("Type_36", "type_36", db.Point) info.AddField("Type_39", "type_39", db.Multilinestring) info.AddField("Type_41", "type_41", db.Multipolygon) info.AddField("Type_37", "type_37", db.Linestring) info.AddField("Type_38", "type_38", db.Polygon) info.AddField("Type_40", "type_40", db.Multipoint) info.AddField("Type_42", "type_42", db.Geometrycollection) info.AddField("Type_50", "type_50", db.Double) info.AddField("Type_51", "type_51", db.JSON) info.SetTable("all_types").SetTitle("All_types").SetDescription("All_types") formList := allTypesTable.GetForm() formList.AddField("Id", "id", db.Int, form.Default) formList.AddField("Type_1", "type_1", db.Tinyint, form.Number) formList.AddField("Type_2", "type_2", db.Smallint, form.Number) formList.AddField("Type_3", "type_3", db.Mediumint, form.Number) formList.AddField("Type_4", "type_4", db.Bigint, form.Number) formList.AddField("Type_5", "type_5", db.Float, form.Text) formList.AddField("Type_6", "type_6", db.Double, form.Text) formList.AddField("Type_7", "type_7", db.Double, form.Text) formList.AddField("Type_8", "type_8", db.Double, form.Text) formList.AddField("Type_9", "type_9", db.Decimal, form.Text) formList.AddField("Type_10", "type_10", db.Bit, form.Text) formList.AddField("Type_11", "type_11", db.Tinyint, form.Number) formList.AddField("Type_12", "type_12", db.Tinyint, form.Number) formList.AddField("Type_13", "type_13", db.Decimal, form.Text) formList.AddField("Type_14", "type_14", db.Decimal, form.Text) formList.AddField("Type_15", "type_15", db.Decimal, form.Text) formList.AddField("Type_16", "type_16", db.Char, form.Text) formList.AddField("Type_17", "type_17", db.Varchar, form.Text) formList.AddField("Type_18", "type_18", db.Tinytext, form.RichText) formList.AddField("Type_19", "type_19", db.Text, form.RichText) formList.AddField("Type_20", "type_20", db.Mediumtext, form.RichText) formList.AddField("Type_21", "type_21", db.Longtext, form.RichText) formList.AddField("Type_22", "type_22", db.Tinyblob, form.Text) formList.AddField("Type_23", "type_23", db.Mediumblob, form.Text) formList.AddField("Type_24", "type_24", db.Blob, form.Text) formList.AddField("Type_25", "type_25", db.Longblob, form.Text) formList.AddField("Type_26", "type_26", db.Binary, form.Text) formList.AddField("Type_27", "type_27", db.Varbinary, form.Text) formList.AddField("Type_28", "type_28", db.Enum, form.Text) formList.AddField("Type_29", "type_29", db.Set, form.Text) formList.AddField("Type_30", "type_30", db.Date, form.Datetime) formList.AddField("Type_31", "type_31", db.Datetime, form.Datetime) formList.AddField("Type_32", "type_32", db.Timestamp, form.Datetime) formList.AddField("Type_33", "type_33", db.Time, form.Datetime) formList.AddField("Type_34", "type_34", db.Year, form.Datetime) formList.AddField("Type_35", "type_35", db.Geometry, form.Text) formList.AddField("Type_36", "type_36", db.Point, form.Text) formList.AddField("Type_39", "type_39", db.Multilinestring, form.Text) formList.AddField("Type_41", "type_41", db.Multipolygon, form.Text) formList.AddField("Type_37", "type_37", db.Linestring, form.Text) formList.AddField("Type_38", "type_38", db.Polygon, form.Text) formList.AddField("Type_40", "type_40", db.Multipoint, form.Text) formList.AddField("Type_42", "type_42", db.Geometrycollection, form.Text) formList.AddField("Type_50", "type_50", db.Double, form.Text) formList.AddField("Type_51", "type_51", db.JSON, form.Text) formList.SetTable("all_types").SetTitle("All_types").SetDescription("All_types") return allTypesTable } ================================================ FILE: examples/datamodel/posts.go ================================================ package datamodel import ( template2 "html/template" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/form" editType "github.com/GoAdminGroup/go-admin/template/types/table" ) // GetPostsTable return the model of table posts. func GetPostsTable(ctx *context.Context) (postsTable table.Table) { postsTable = table.NewDefaultTable(ctx, table.DefaultConfig().SetExportable(true)) info := postsTable.GetInfo() info.AddField("ID", "id", db.Int).FieldSortable() info.AddField("Title", "title", db.Varchar) info.AddField("AuthorID", "author_id", db.Varchar).FieldDisplay(func(value types.FieldModel) interface{} { return template.Default(ctx). Link(). SetURL("/admin/info/authors/detail?__goadmin_detail_pk=" + value.Value). SetContent(template2.HTML(value.Value)). OpenInNewTab(). SetTabTitle("Author Detail"). GetContent() }) info.AddField("AuthorName", "name", db.Varchar).FieldDisplay(func(value types.FieldModel) interface{} { first, _ := value.Row["authors_goadmin_join_first_name"].(string) last, _ := value.Row["authors_goadmin_join_last_name"].(string) return first + " " + last }) info.AddField("AuthorFirstName", "first_name", db.Varchar).FieldJoin(types.Join{ Field: "author_id", JoinField: "id", Table: "authors", }).FieldHide() info.AddField("AuthorLastName", "last_name", db.Varchar).FieldJoin(types.Join{ Field: "author_id", JoinField: "id", Table: "authors", }).FieldHide() info.AddField("Description", "description", db.Varchar) info.AddField("Content", "content", db.Varchar).FieldEditAble(editType.Textarea) info.AddField("Date", "date", db.Varchar) info.AddField("AuthorCreatedAt", "created_at", db.Varchar).FieldJoin(types.Join{ Field: "author_id", JoinField: "id", Table: "authors", }) info.AddField("Created_at", "created_at", db.Varchar).FieldFilterable() info.SetTable("posts").SetTitle("Posts").SetDescription("Posts") formList := postsTable.GetForm() formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() formList.AddField("Title", "title", db.Varchar, form.Text) formList.AddField("Description", "description", db.Varchar, form.Text) formList.AddField("Content", "content", db.Varchar, form.RichText).FieldEnableFileUpload() formList.AddField("Date", "date", db.Varchar, form.Datetime) formList.EnableAjax("Request Success", "Request Failed") formList.SetTable("posts").SetTitle("Posts").SetDescription("Posts") return } ================================================ FILE: examples/datamodel/tables.go ================================================ package datamodel import "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" // Generators is a map of table models. // // The key of generators is the prefix of table info url. // The corresponding value is the Form and TableName data. // // http://{{config.Domain}}:{{Port}}/{{config.Prefix}}/info/{{key}} // // example: // // "posts" => http://localhost:9033/admin/info/posts // "authors" => http://localhost:9033/admin/info/authors // var Generators = map[string]table.Generator{ "posts": GetPostsTable, "authors": GetAuthorsTable, } ================================================ FILE: examples/datamodel/user.go ================================================ package datamodel import ( "fmt" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/db" form2 "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/icon" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/action" "github.com/GoAdminGroup/go-admin/template/types/form" selection "github.com/GoAdminGroup/go-admin/template/types/form/select" editType "github.com/GoAdminGroup/go-admin/template/types/table" ) // GetUserTable return the model of table user. func GetUserTable(ctx *context.Context) (userTable table.Table) { userTable = table.NewDefaultTable(ctx, table.Config{ Driver: db.DriverMysql, CanAdd: true, Editable: true, Deletable: true, Exportable: true, Connection: table.DefaultConnectionName, PrimaryKey: table.PrimaryKey{ Type: db.Int, Name: table.DefaultPrimaryKeyName, }, }) info := userTable.GetInfo().SetFilterFormLayout(form.LayoutThreeCol) info.AddField("ID", "id", db.Int).FieldSortable() info.AddField("Name", "name", db.Varchar).FieldEditAble(editType.Text). FieldFilterable(types.FilterType{Operator: types.FilterOperatorLike}) info.AddField("Gender", "gender", db.Tinyint).FieldDisplay(func(model types.FieldModel) interface{} { if model.Value == "0" { return "men" } if model.Value == "1" { return "women" } return "unknown" }).FieldEditAble(editType.Switch).FieldEditOptions(types.FieldOptions{ {Value: "0", Text: "👦"}, {Value: "1", Text: "👧"}, }).FieldFilterable(types.FilterType{FormType: form.SelectSingle}).FieldFilterOptions(types.FieldOptions{ {Value: "0", Text: "men"}, {Value: "1", Text: "women"}, }) info.AddColumn("Personality", func(value types.FieldModel) interface{} { return "handsome" }) info.AddColumnButtons(ctx, "see more", types.GetColumnButton("see more", icon.Info, action.PopUp("/see/more/example", "see more", func(ctx *context.Context) (success bool, msg string, data interface{}) { return true, "ok", "

Detail

balabala

" }))) info.AddField("Phone", "phone", db.Varchar).FieldFilterable() info.AddField("City", "city", db.Varchar).FieldFilterable() info.AddField("Avatar", "avatar", db.Varchar).FieldDisplay(func(value types.FieldModel) interface{} { return template.Default(ctx).Image(). SetSrc(`//quick.go-admin.cn/demo/assets/dist/img/gopher_avatar.png`). SetHeight("120").SetWidth("120").WithModal().GetContent() }) info.AddField("CreatedAt", "created_at", db.Timestamp). FieldFilterable(types.FilterType{FormType: form.DatetimeRange}) info.AddField("UpdatedAt", "updated_at", db.Timestamp).FieldEditAble(editType.Datetime) info.AddActionButton(ctx, "google", action.Jump("https://google.com")) info.AddActionButton(ctx, "Audit", action.Ajax("/admin/audit", func(ctx *context.Context) (success bool, msg string, data interface{}) { fmt.Println("PostForm", ctx.PostForm()) return true, "success", "" })) info.AddActionButton(ctx, "Preview", action.PopUp("/admin/preview", "Preview", func(ctx *context.Context) (success bool, msg string, data interface{}) { return true, "", "

hello world

" })) info.AddButton(ctx, "jump", icon.User, action.JumpInNewTab("/admin/info/authors", "authors")) info.AddButton(ctx, "popup", icon.Terminal, action.PopUp("/admin/popup", "Popup Example", func(ctx *context.Context) (success bool, msg string, data interface{}) { return true, "", "

hello world

" })) info.AddButton(ctx, "iframe", icon.Tv, action.PopUpWithIframe("/admin/iframe", "Iframe Example", action.IframeData{Src: "/admin/info/authors"}, "900px", "560px")) info.AddButton(ctx, "form", icon.Folder, action.PopUpWithForm(action.PopUpData{ Id: "/admin/popup/form", Title: "Popup Form Example", Width: "900px", Height: "430px", }, func(panel *types.FormPanel) *types.FormPanel { panel.AddField("Name", "name", db.Varchar, form.Text) panel.AddField("Age", "age", db.Int, form.Number) panel.AddField("HomePage", "homepage", db.Varchar, form.Url).FieldDefault("http://google.com") panel.AddField("Email", "email", db.Varchar, form.Email).FieldDefault("xxxx@xxx.com") panel.AddField("Birthday", "birthday", db.Varchar, form.Date).FieldDefault("2010-09-03 18:09:05") panel.AddField("Time", "time", db.Varchar, form.Datetime).FieldDefault("2010-09-05") panel.EnableAjax("Request Success", "Request Failed") return panel }, "/admin/popup/form")) info.AddButton(ctx, "ajax", icon.Android, action.Ajax("/admin/ajax", func(ctx *context.Context) (success bool, msg string, data interface{}) { return true, "success", "" })) info.AddSelectBox(ctx, "gender", types.FieldOptions{ {Value: "0", Text: "men"}, {Value: "1", Text: "women"}, }, action.FieldFilter("gender")) info.SetTable("users").SetTitle("Users").SetDescription("Users") formList := userTable.GetForm() formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() formList.AddField("Ip", "ip", db.Varchar, form.Text) formList.AddField("Name", "name", db.Varchar, form.Text) formList.AddField("Gender", "gender", db.Tinyint, form.Radio). FieldOptions(types.FieldOptions{ {Text: "men", Value: "0"}, {Text: "women", Value: "1"}, }) formList.AddField("Country", "country", db.Tinyint, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: "China", Value: "0"}, {Text: "America", Value: "1"}, {Text: "England", Value: "2"}, {Text: "Canada", Value: "3"}, }).FieldDefault("0").FieldOnChooseAjax("city", "/choose/country", func(ctx *context.Context) (bool, string, interface{}) { country := ctx.FormValue("value") var data = make(selection.Options, 0) switch country { case "0": data = selection.Options{ {Text: "Beijing", ID: "beijing"}, {Text: "ShangHai", ID: "shangHai"}, {Text: "GuangZhou", ID: "guangZhou"}, {Text: "ShenZhen", ID: "shenZhen"}, } case "1": data = selection.Options{ {Text: "Los Angeles", ID: "los angeles"}, {Text: "Washington, dc", ID: "washington, dc"}, {Text: "New York", ID: "new york"}, {Text: "Las Vegas", ID: "las vegas"}, } case "2": data = selection.Options{ {Text: "London", ID: "london"}, {Text: "Cambridge", ID: "cambridge"}, {Text: "Manchester", ID: "manchester"}, {Text: "Liverpool", ID: "liverpool"}, } case "3": data = selection.Options{ {Text: "Vancouver", ID: "vancouver"}, {Text: "Toronto", ID: "toronto"}, } default: data = selection.Options{ {Text: "Beijing", ID: "beijing"}, {Text: "ShangHai", ID: "shangHai"}, {Text: "GuangZhou", ID: "guangZhou"}, {Text: "ShenZhen", ID: "shenZhen"}, } } return true, "ok", data }, "", `'phone':$(".phone").val(),`) formList.AddField("Phone", "phone", db.Varchar, form.Custom). FieldCustomContent(` `) formList.AddField("City", "city", db.Varchar, form.SelectSingle). FieldOptionInitFn(func(val types.FieldModel) types.FieldOptions { return types.FieldOptions{ {Value: val.Value, Text: val.Value, Selected: true}, } }).FieldOptions(types.FieldOptions{ {Text: "Beijing", Value: "beijing"}, {Text: "ShangHai", Value: "shanghai"}, {Text: "GuangZhou", Value: "guangzhou"}, {Text: "ShenZhen", Value: "shenzhen"}, }) formList.AddField("Custom Field", "role", db.Varchar, form.Text). FieldPostFilterFn(func(value types.PostFieldModel) interface{} { fmt.Println("user custom field", value) return "" }) formList.AddField("UpdatedAt", "updated_at", db.Timestamp, form.Default).FieldDisableWhenCreate() formList.AddField("CreatedAt", "created_at", db.Timestamp, form.Datetime).FieldDisableWhenCreate() userTable.GetForm().SetTabGroups(types. NewTabGroups("id", "ip", "name", "gender", "country", "city"). AddGroup("phone", "role", "created_at", "updated_at")). SetTabHeaders("profile1", "profile2") formList.SetTable("users").SetTitle("Users").SetDescription("Users") formList.SetPostHook(func(values form2.Values) error { fmt.Println("userTable.GetForm().PostHook", values) return nil }) return } ================================================ FILE: examples/echo/main.go ================================================ package main import ( "log" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/echo" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" _ "github.com/GoAdminGroup/themes/adminlte" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/labstack/echo/v4" ) func main() { e := echo.New() eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, }, }, UrlPrefix: "admin", IndexUrl: "/", Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, Debug: true, Language: language.CN, } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // eng.AddConfigFromJSON("../datamodel/config.json") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(e); err != nil { panic(err) } e.Static("/uploads", "./uploads") // you can custom your pages like: eng.HTML("GET", "/admin", datamodel.GetContent) // Start server go e.Logger.Fatal(e.Start(":1323")) quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } ================================================ FILE: examples/fasthttp/main.go ================================================ package main import ( "log" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/fasthttp" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" _ "github.com/GoAdminGroup/themes/adminlte" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/buaazp/fasthttprouter" "github.com/valyala/fasthttp" ) func main() { router := fasthttprouter.New() eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, }, }, UrlPrefix: "admin", IndexUrl: "/", Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, Debug: true, Language: language.CN, } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // eng.AddConfigFromJSON("../datamodel/config.json") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(router); err != nil { panic(err) } router.ServeFiles("/uploads/*filepath", "./uploads") eng.HTML("GET", "/admin", datamodel.GetContent) go func() { _ = fasthttp.ListenAndServe(":8897", router.Handler) }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } ================================================ FILE: examples/gear/main.go ================================================ package main import ( "log" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/gear" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" _ "github.com/GoAdminGroup/themes/sword" "github.com/teambition/gear" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/themes/adminlte" ) func main() { app := gear.New() e := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, //Driver: config.DriverSqlite, //File: "../datamodel/admin.db", }, }, Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, UrlPrefix: "admin", Language: language.CN, IndexUrl: "/", Debug: true, AccessAssetsLogOff: true, Animation: config.PageAnimation{ Type: "fadeInUp", }, ColorScheme: adminlte.ColorschemeSkinBlack, BootstrapFilePath: "./../datamodel/bootstrap.go", } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // e.AddConfigFromJSON("../datamodel/config.json") if err := e.AddConfig(&cfg). AddGenerators(datamodel.Generators). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddDisplayFilterXssJsFilter(). AddPlugins(examplePlugin). Use(app); err != nil { panic(err) } // customize your pages e.HTML("GET", "/admin", datamodel.GetContent) go func() { app.Start(":8099") }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") e.MysqlConnection().Close() } ================================================ FILE: examples/gf/main.go ================================================ package main import ( "log" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/gf" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/themes/adminlte" "github.com/gogf/gf/frame/g" ) func main() { s := g.Server() eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, //Driver: config.DriverSqlite, //File: "../datamodel/admin.db", }, }, UrlPrefix: "admin", Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, Language: language.CN, IndexUrl: "/", Debug: true, ColorScheme: adminlte.ColorschemeSkinBlack, } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // eng.AddConfigFromJSON("../datamodel/config.json") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(s); err != nil { panic(err) } s.AddStaticPath("/uploads", "./uploads") // customize your pages eng.HTML("GET", "/admin", datamodel.GetContent) s.SetPort(9033) go s.Run() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } ================================================ FILE: examples/gf2/main.go ================================================ package main import ( "log" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/gf2" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/themes/adminlte" "github.com/gogf/gf/v2/frame/g" ) func main() { s := g.Server() eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "123456", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, //Driver: config.DriverSqlite, //File: "../datamodel/admin.db", }, }, UrlPrefix: "admin", Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, Language: language.CN, IndexUrl: "/", Debug: true, ColorScheme: adminlte.ColorschemeSkinBlack, } template.AddComp(chartjs.NewChart()) examplePlugin := example.NewExample() if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssFilter(). AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(s); err != nil { panic(err) } s.AddStaticPath("/uploads", "./uploads") eng.HTML("GET", "/admin", datamodel.GetContent) s.SetPort(9033) go s.Run() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } ================================================ FILE: examples/gin/main.go ================================================ package main import ( "io/ioutil" "log" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/gin" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" _ "github.com/GoAdminGroup/themes/sword" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/themes/adminlte" "github.com/gin-gonic/gin" ) func main() { gin.SetMode(gin.ReleaseMode) gin.DefaultWriter = ioutil.Discard r := gin.New() e := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, //Driver: config.DriverSqlite, //File: "../datamodel/admin.db", }, }, UrlPrefix: "admin", Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, Language: language.CN, IndexUrl: "/", Debug: true, AccessAssetsLogOff: true, Animation: config.PageAnimation{ Type: "fadeInUp", }, ColorScheme: adminlte.ColorschemeSkinBlack, BootstrapFilePath: "./../datamodel/bootstrap.go", } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // e.AddConfigFromJSON("../datamodel/config.json") if err := e.AddConfig(&cfg). AddGenerators(datamodel.Generators). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddDisplayFilterXssJsFilter(). AddPlugins(examplePlugin). Use(r); err != nil { panic(err) } r.Static("/uploads", "./uploads") // customize your pages e.HTML("GET", "/admin", datamodel.GetContent) go func() { _ = r.Run(":9033") }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") e.MysqlConnection().Close() } ================================================ FILE: examples/gofiber/main.go ================================================ package main import ( "log" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/gofiber" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" _ "github.com/GoAdminGroup/themes/adminlte" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New(fiber.Config{ ServerHeader: "Fiber", }) eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, }, }, UrlPrefix: "admin", IndexUrl: "/", Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, Debug: true, Language: language.CN, } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // eng.AddConfigFromJSON("../datamodel/config.json") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(app); err != nil { panic(err) } eng.HTML("GET", "/admin", datamodel.GetContent) _ = app.Listen(":8897") quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } ================================================ FILE: examples/gorilla/main.go ================================================ package main import ( "log" "net/http" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/gorilla" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" _ "github.com/GoAdminGroup/themes/adminlte" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/gorilla/mux" ) func main() { app := mux.NewRouter() eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, }, }, Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, UrlPrefix: "admin", IndexUrl: "/", Debug: true, Language: language.EN, } // customize a plugin examplePlugin := example.NewExample() template.AddComp(chartjs.NewChart()) // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // eng.AddConfigFromJSON("../datamodel/config.json") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(app); err != nil { panic(err) } app.PathPrefix("/uploads/").Handler(http.StripPrefix("/uploads/", http.FileServer(http.Dir("./uploads")))) eng.HTML("GET", "/admin", datamodel.GetContent) go func() { _ = http.ListenAndServe(":9033", app) }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } ================================================ FILE: examples/iris/main.go ================================================ package main import ( "log" "os" "os/signal" "time" _ "github.com/GoAdminGroup/go-admin/adapter/iris" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" _ "github.com/GoAdminGroup/themes/adminlte" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/kataras/iris/v12" ) func main() { app := iris.Default() eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, }, }, UrlPrefix: "admin", Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, IndexUrl: "/", Debug: true, Language: language.CN, } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // eng.AddConfigFromJSON("../datamodel/config.json") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(app); err != nil { panic(err) } app.HandleDir("/uploads", "./uploads", iris.DirOptions{ IndexName: "/index.html", ShowList: false, }) // you can custom your pages like: eng.HTML("GET", "/admin", datamodel.GetContent) go func() { _ = app.Run(iris.Addr(":8099")) }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } ================================================ FILE: examples/nethttp/main.go ================================================ package main import ( "log" "net/http" "os" "os/signal" "path/filepath" "strings" "time" _ "github.com/GoAdminGroup/go-admin/adapter/nethttp" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" "github.com/GoAdminGroup/go-admin/engine" "github.com/GoAdminGroup/go-admin/examples/datamodel" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/example" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/themes/adminlte" ) func main() { r := http.NewServeMux() eng := engine.Default() cfg := config.Config{ Env: config.EnvLocal, Databases: config.DatabaseList{ "default": { Host: "127.0.0.1", Port: "3306", User: "root", Pwd: "root", Name: "godmin", MaxIdleConns: 50, MaxOpenConns: 150, ConnMaxLifetime: time.Hour, Driver: config.DriverMysql, }, }, UrlPrefix: "admin", Store: config.Store{ Path: "./uploads", Prefix: "uploads", }, Language: language.EN, IndexUrl: "/", Debug: true, ColorScheme: adminlte.ColorschemeSkinBlack, } template.AddComp(chartjs.NewChart()) // customize a plugin examplePlugin := example.NewExample() // load from golang.Plugin // // examplePlugin := plugins.LoadFromPlugin("../datamodel/example.so") // customize the login page // example: https://github.com/GoAdminGroup/demo.go-admin.cn/blob/master/main.go#L39 // // template.AddComp("login", datamodel.LoginPage) // load config from json file // // eng.AddConfigFromJSON("../datamodel/config.json") if err := eng.AddConfig(&cfg). AddGenerators(datamodel.Generators). AddDisplayFilterXssJsFilter(). // add generator, first parameter is the url prefix of table when visit. // example: // // "user" => http://localhost:9033/admin/info/user // AddGenerator("user", datamodel.GetUserTable). AddPlugins(examplePlugin). Use(r); err != nil { panic(err) } workDir, _ := os.Getwd() filesDir := filepath.Join(workDir, "uploads") FileServer(r, "/uploads", http.Dir(filesDir)) // you can custom your pages like: eng.HTML("GET", "/admin", datamodel.GetContent) go func() { _ = http.ListenAndServe(":3333", r) }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit log.Print("closing database connection") eng.MysqlConnection().Close() } // FileServer conveniently sets up a http.FileServer handler to serve // static files from a http.FileSystem. func FileServer(r *http.ServeMux, path string, root http.FileSystem) { if strings.ContainsAny(path, "{}*") { panic("FileServer does not permit URL parameters.") } fs := http.StripPrefix(path, http.FileServer(root)) if path != "/" && path[len(path)-1] != '/' { r.HandleFunc("GET "+path, http.RedirectHandler(path+"/", http.StatusMovedPermanently).ServeHTTP) path += "/" } path += "*" r.HandleFunc("GET "+path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fs.ServeHTTP(w, r) })) } ================================================ FILE: go.mod ================================================ module github.com/GoAdminGroup/go-admin go 1.22.10 require ( github.com/360EntSecGroup-Skylar/excelize v1.4.1 github.com/GoAdminGroup/html v0.0.1 github.com/GoAdminGroup/themes v0.0.48 github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e github.com/agiledragon/gomonkey v2.0.2+incompatible github.com/astaxie/beego v1.12.1 github.com/beego/beego/v2 v2.2.0 github.com/buaazp/fasthttprouter v0.1.1 github.com/denisenkom/go-mssqldb v0.0.0-20200206145737-bbfc9a55622e github.com/gavv/httpexpect v2.0.0+incompatible github.com/gin-gonic/gin v1.3.0 github.com/go-chi/chi v1.5.5 github.com/go-sql-driver/mysql v1.8.1 github.com/gobuffalo/buffalo v1.1.0 github.com/gofiber/fiber/v2 v2.52.4 github.com/gogf/gf v1.16.9 github.com/gogf/gf/v2 v2.6.4 github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.0 github.com/kataras/iris/v12 v12.2.10 github.com/labstack/echo/v4 v4.11.4 github.com/lib/pq v1.10.5 github.com/magiconair/properties v1.8.6 github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b github.com/sclevine/agouti v3.0.0+incompatible github.com/stretchr/testify v1.9.0 github.com/teambition/gear v1.27.3 github.com/valyala/fasthttp v1.52.0 go.uber.org/zap v1.19.1 golang.org/x/crypto v0.31.0 golang.org/x/text v0.21.0 gopkg.in/ini.v1 v1.67.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v2 v2.4.0 xorm.io/xorm v1.0.2 ) require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/BurntSushi/toml v1.3.2 // indirect github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect github.com/CloudyKit/jet/v6 v6.2.0 // indirect github.com/Joker/jade v1.1.3 // indirect github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect github.com/ajg/form v1.5.1 // indirect github.com/andybalholm/brotli v1.1.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 // indirect github.com/fatih/color v1.15.0 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect github.com/flosch/pongo2/v4 v4.0.2 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-http-utils/cookie v1.3.1 // indirect github.com/go-http-utils/negotiator v1.0.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gobuffalo/envy v1.10.2 // indirect github.com/gobuffalo/events v1.4.3 // indirect github.com/gobuffalo/flect v1.0.0 // indirect github.com/gobuffalo/github_flavored_markdown v1.1.3 // indirect github.com/gobuffalo/grift v1.5.2 // indirect github.com/gobuffalo/helpers v0.6.7 // indirect github.com/gobuffalo/logger v1.0.7 // indirect github.com/gobuffalo/meta v0.3.3 // indirect github.com/gobuffalo/nulls v0.4.2 // indirect github.com/gobuffalo/plush/v4 v4.1.18 // indirect github.com/gobuffalo/refresh v1.13.3 // indirect github.com/gobuffalo/tags/v3 v3.1.4 // indirect github.com/gobuffalo/validate/v3 v3.3.3 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 // indirect github.com/gomodule/redigo v2.0.0+incompatible // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/css v1.0.0 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.2.1 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/grokify/html-strip-tags-go v0.0.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/imkira/go-interpol v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/iris-contrib/schema v0.0.6 // indirect github.com/joho/godotenv v1.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kataras/blocks v0.0.8 // indirect github.com/kataras/golog v0.1.11 // indirect github.com/kataras/pio v0.0.13 // indirect github.com/kataras/sitemap v0.0.6 // indirect github.com/kataras/tunnel v0.0.4 // indirect github.com/klauspost/compress v1.17.6 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/mailgun/raymond/v2 v2.0.48 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/microcosm-cc/bluemonday v1.0.26 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/monoculum/formam v3.5.5+incompatible // indirect github.com/moul/http2curl v1.0.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.19.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/schollz/closestmatch v2.1.0+incompatible // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/smartystreets/goconvey v1.8.1 // indirect github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d // indirect github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect github.com/spf13/cobra v1.6.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/syndtr/goleveldb v1.0.0 // indirect github.com/tdewolff/minify/v2 v2.20.14 // indirect github.com/tdewolff/parse/v2 v2.7.8 // indirect github.com/teambition/trie-mux v1.5.2 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/valyala/tcplisten v1.0.0 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect github.com/yosssi/ace v0.0.5 // indirect github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/yudai/pp v2.0.1+incompatible // indirect go.opentelemetry.io/otel v1.14.0 // indirect go.opentelemetry.io/otel/sdk v1.14.0 // indirect go.opentelemetry.io/otel/trace v1.14.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.7.0 // indirect golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect golang.org/x/net v0.21.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/term v0.27.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/protobuf v1.32.0 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v8 v8.18.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect xorm.io/builder v0.3.7 // indirect ) replace github.com/ugorji/go => github.com/ugorji/go v1.2.11 ================================================ FILE: go.sum ================================================ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= github.com/360EntSecGroup-Skylar/excelize v1.4.1 h1:l55mJb6rkkaUzOpSsgEeKYtS6/0gHwBYyfo5Jcjv/Ks= github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= github.com/GoAdminGroup/html v0.0.1 h1:SdWNWl4OKPsvDk2GDp5ZKD6ceWoN8n4Pj6cUYxavUd0= github.com/GoAdminGroup/html v0.0.1/go.mod h1:A1laTJaOx8sQ64p2dE8IqtstDeCNBHEazrEp7hR5VvM= github.com/GoAdminGroup/themes v0.0.48 h1:OveEEoFBCBTU5kNicqnvs0e/pL6uZKNQU1RAP9kmNFA= github.com/GoAdminGroup/themes v0.0.48/go.mod h1:w/5P0WCmM8iv7DYE5scIT8AODYMoo6zj/bVlzAbgOaU= github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e h1:n+DcnTNkQnHlwpsrHoQtkrJIO7CBx029fw6oR4vIob4= github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e/go.mod h1:Bdzq+51GR4/0DIhaICZEOm+OHvXGwwB2trKZ8B4Y6eQ= github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM= github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw= github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/astaxie/beego v1.12.1 h1:dfpuoxpzLVgclveAXe4PyNKqkzgm5zF4tgF2B3kkM2I= github.com/astaxie/beego v1.12.1/go.mod h1:kPBWpSANNbSdIqOc8SUL9h+1oyBMZhROeYsXQDbidWQ= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/beego/beego/v2 v2.2.0 h1:x2yCNL9x74vqAXRdFBw5HCzB8AwownALpBWEOitivow= github.com/beego/beego/v2 v2.2.0/go.mod h1:kqiwel3TqpZHYtI08GWnleCtBc0LqtawsmfFDxY9POY= github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ= github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= github.com/buaazp/fasthttprouter v0.1.1 h1:4oAnN0C3xZjylvZJdP35cxfclyn4TYkW6Y+DSvS+h8Q= github.com/buaazp/fasthttprouter v0.1.1/go.mod h1:h/Ap5oRVLeItGKTVBb+heQPks+HdIUtGmI4H5WCYijM= github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 h1:LdXxtjzvZYhhUaonAaAKArG3pyC67kGL3YY+6hGG8G4= github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= github.com/couchbase/go-couchbase v0.0.0-20181122212707-3e9b6e1258bb/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U= github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= github.com/denisenkom/go-mssqldb v0.0.0-20200206145737-bbfc9a55622e h1:LzwWXEScfcTu7vUZNlDDWDARoSGEtvlDKK2BYHowNeE= github.com/denisenkom/go-mssqldb v0.0.0-20200206145737-bbfc9a55622e/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw= github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 h1:DddqAaWDpywytcG8w/qoQ5sAN8X12d3Z3koB0C3Rxsc= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.3.0 h1:kCmZyPklC0gVdL728E6Aj20uYBJV93nj/TkwBTKhFbs= github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE= github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw= github.com/go-http-utils/cookie v1.3.1 h1:GCdTeqVV5vDcjP7LrgYpH8pbt3dOYKS+Wrs7Jo3/k/w= github.com/go-http-utils/cookie v1.3.1/go.mod h1:ATl4rfG3bEemjiVa+8WIfgNcBUWdYBTasfXKjJ3Avt8= github.com/go-http-utils/negotiator v1.0.0 h1:Qp1zofD6Nw7KXApXa3pAjehP06Js0ILguEBCnHhZeVA= github.com/go-http-utils/negotiator v1.0.0/go.mod h1:mTQe1sH0XhdFkeDiWpCY3QSk7Apo5jwOlIwLWJbJe2c= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/buffalo v1.1.0 h1:6y1fUC47QWevaM1ImukJFHNgxiRIT+Y74VcP4ZQaz80= github.com/gobuffalo/buffalo v1.1.0/go.mod h1:lLsx9Y8bFYu9uvQyIEB3M0QA908ChHUPjwOGumZWARU= github.com/gobuffalo/envy v1.10.2 h1:EIi03p9c3yeuRCFPOKcSfajzkLb3hrRjEpHGI8I2Wo4= github.com/gobuffalo/envy v1.10.2/go.mod h1:qGAGwdvDsaEtPhfBzb3o0SfDea8ByGn9j8bKmVft9z8= github.com/gobuffalo/events v1.4.3 h1:JYDq7NbozP10zaN9Ijfem6Ozox2KacU2fU38RyquXM8= github.com/gobuffalo/events v1.4.3/go.mod h1:2BwfpV5X63t8xkUcVqIv4IbyAobJazRSVu1F1pgf3rc= github.com/gobuffalo/flect v0.3.0/go.mod h1:5pf3aGnsvqvCj50AVni7mJJF8ICxGZ8HomberC3pXLE= github.com/gobuffalo/flect v1.0.0 h1:eBFmskjXZgAOagiTXJH25Nt5sdFwNRcb8DKZsIsAUQI= github.com/gobuffalo/flect v1.0.0/go.mod h1:l9V6xSb4BlXwsxEMj3FVEub2nkdQjWhPvD8XTTlHPQc= github.com/gobuffalo/github_flavored_markdown v1.1.3 h1:rSMPtx9ePkFB22vJ+dH+m/EUBS8doQ3S8LeEXcdwZHk= github.com/gobuffalo/github_flavored_markdown v1.1.3/go.mod h1:IzgO5xS6hqkDmUh91BW/+Qxo/qYnvfzoz3A7uLkg77I= github.com/gobuffalo/grift v1.5.2 h1:mC0vHRs+nXz+JhkH3sv+rVnnTQRDXrUrOXOPYpgPjpo= github.com/gobuffalo/grift v1.5.2/go.mod h1:Uf/3T2AR1Vv+t84EPmxCjqQ8oyJwXs0FAoLMFUn/JVs= github.com/gobuffalo/helpers v0.6.7 h1:C9CedoRSfgWg2ZoIkVXgjI5kgmSpL34Z3qdnzpfNVd8= github.com/gobuffalo/helpers v0.6.7/go.mod h1:j0u1iC1VqlCaJEEVkZN8Ia3TEzfj/zoXANqyJExTMTA= github.com/gobuffalo/here v0.6.7/go.mod h1:vuCfanjqckTuRlqAitJz6QC4ABNnS27wLb816UhsPcc= github.com/gobuffalo/httptest v1.5.2 h1:GpGy520SfY1QEmyPvaqmznTpG4gEQqQ82HtHqyNEreM= github.com/gobuffalo/httptest v1.5.2/go.mod h1:FA23yjsWLGj92mVV74Qtc8eqluc11VqcWr8/C1vxt4g= github.com/gobuffalo/logger v1.0.7 h1:LTLwWelETXDYyqF/ASf0nxaIcdEOIJNxRokPcfI/xbU= github.com/gobuffalo/logger v1.0.7/go.mod h1:u40u6Bq3VVvaMcy5sRBclD8SXhBYPS0Qk95ubt+1xJM= github.com/gobuffalo/meta v0.3.3 h1:GwPWdbdnp4JrKASvMLa03OtmzISq7z/nE7T6aMqzoYM= github.com/gobuffalo/meta v0.3.3/go.mod h1:o4B099IUFUfK4555Guqxz1zHAqyuUQ/KtHXi8WvVeFE= github.com/gobuffalo/nulls v0.4.2 h1:GAqBR29R3oPY+WCC7JL9KKk9erchaNuV6unsOSZGQkw= github.com/gobuffalo/nulls v0.4.2/go.mod h1:EElw2zmBYafU2R9W4Ii1ByIj177wA/pc0JdjtD0EsH8= github.com/gobuffalo/plush/v4 v4.1.18 h1:bnPjdMTEUQHqj9TNX2Ck3mxEXYZa+0nrFMNM07kpX9g= github.com/gobuffalo/plush/v4 v4.1.18/go.mod h1:xi2tJIhFI4UdzIL8sxZtzGYOd2xbBpcFbLZlIPGGZhU= github.com/gobuffalo/refresh v1.13.3 h1:HYQlI6RiqWUf2yzCXvUHAYqm9M9/teVnox+mjzo/9rQ= github.com/gobuffalo/refresh v1.13.3/go.mod h1:NkzgLKZGk5suOvgvOD0/VALog0fH29Ib7fwym9JmRxA= github.com/gobuffalo/tags/v3 v3.1.4 h1:X/ydLLPhgXV4h04Hp2xlbI2oc5MDaa7eub6zw8oHjsM= github.com/gobuffalo/tags/v3 v3.1.4/go.mod h1:ArRNo3ErlHO8BtdA0REaZxijuWnWzF6PUXngmMXd2I0= github.com/gobuffalo/validate/v3 v3.3.3 h1:o7wkIGSvZBYBd6ChQoLxkz2y1pfmhbI4jNJYh6PuNJ4= github.com/gobuffalo/validate/v3 v3.3.3/go.mod h1:YC7FsbJ/9hW/VjQdmXPvFqvRis4vrRYFxr69WiNZw6g= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM= github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogf/gf v1.16.9 h1:Q803UmmRo59+Ws08sMVFOcd8oNpkSWL9vS33hlo/Cyk= github.com/gogf/gf v1.16.9/go.mod h1:8Q/kw05nlVRp+4vv7XASBsMe9L1tsVKiGoeP2AHnlkk= github.com/gogf/gf/v2 v2.6.4 h1:w7HXdH9mcTsn/aE13CkaDbRArmAL1KS3FuQqDi6u74Y= github.com/gogf/gf/v2 v2.6.4/go.mod h1:x2XONYcI4hRQ/4gMNbWHmZrNzSEIg20s2NULbzom5k0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 h1:k4Tw0nt6lwro3Uin8eqoET7MDA4JnT8YgbCjc/g5E3k= github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0= github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= github.com/kataras/iris/v12 v12.2.10 h1:rEJVM7qMoyhv8wpgkA1yGxibFcONE0jkJ70LFLibTAA= github.com/kataras/iris/v12 v12.2.10/go.mod h1:z4+E+kLMqZ7U4WtDsYfFnG7BjMTXLkdzMAXLVMLnMNs= github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8= github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ= github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50= github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/monoculum/formam v3.5.5+incompatible h1:iPl5csfEN96G2N2mGu8V/ZB62XLf9ySTpC8KRH6qXec= github.com/monoculum/formam v3.5.5+incompatible/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q= github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/psanford/memfs v0.0.0-20210214183328-a001468d78ef h1:NKxTG6GVGbfMXc2mIk+KphcH6hagbVXhcFkbTgYleTI= github.com/psanford/memfs v0.0.0-20210214183328-a001468d78ef/go.mod h1:tcaRap0jS3eifrEEllL6ZMd9dg8IlDpi2S1oARrQ+NI= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/sclevine/agouti v3.0.0+incompatible h1:8IBJS6PWz3uTlMP3YBIR5f+KAldcGuOeFkFbUWfBgK4= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik= github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg= github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg= github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tdewolff/minify/v2 v2.20.14 h1:sktSuVixRwk0ryQjqvKBu/uYS+MWmkwEFMEWtFZ+TdE= github.com/tdewolff/minify/v2 v2.20.14/go.mod h1:qnIJbnG2dSzk7LIa/UUwgN2OjS8ir6RRlqc0T/1q2xY= github.com/tdewolff/parse/v2 v2.7.8 h1:1cnVqa8L63xFkc2vfRsZTM6Qy35nJpTvQ2Uvdv3vbvs= github.com/tdewolff/parse/v2 v2.7.8/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= github.com/teambition/gear v1.27.3 h1:iWUOJYdBwxU+SZP5aZ2ZYR5FnRGmdgrMbbSpOCZo0go= github.com/teambition/gear v1.27.3/go.mod h1:d3Nmr6rRPnH5lYSK33W9IDhsaxp/8n14vRrUZu9dP9c= github.com/teambition/trie-mux v1.5.2 h1:ALTagFwKZXkn1vfSRlODlmoZg+NMeWAm4dyBPQI6a8w= github.com/teambition/trie-mux v1.5.2/go.mod h1:0Woh4KOHSN9bkJ66eWmLs8ltrEKw+fnZbFaHFfbMrtc= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0= github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg= go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs= go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI= xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= xorm.io/xorm v1.0.2 h1:kZlCh9rqd1AzGwWitcrEEqHE1h1eaZE/ujU5/2tWEtg= xorm.io/xorm v1.0.2/go.mod h1:o4vnEsQ5V2F1/WK6w4XTwmiWJeGj82tqjAnHe44wVHY= ================================================ FILE: modules/auth/auth.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package auth import ( "log" "sync" "github.com/GoAdminGroup/go-admin/modules/db/dialect" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/service" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" "golang.org/x/crypto/bcrypt" ) // Auth get the user model from Context. func Auth(ctx *context.Context) models.UserModel { return ctx.User().(models.UserModel) } // Check check the password and username and return the user model. func Check(password string, username string, conn db.Connection) (user models.UserModel, ok bool) { user = models.User().SetConn(conn).FindByUserName(username) if user.IsEmpty() { ok = false } else { if comparePassword(password, user.Password) { ok = true user = user.WithRoles().WithPermissions().WithMenus() user.UpdatePwd(EncodePassword([]byte(password))) } else { ok = false } } return } func comparePassword(comPwd, pwdHash string) bool { err := bcrypt.CompareHashAndPassword([]byte(pwdHash), []byte(comPwd)) return err == nil } // EncodePassword encode the password. func EncodePassword(pwd []byte) string { hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost) if err != nil { return "" } return string(hash) } // SetCookie set the cookie. func SetCookie(ctx *context.Context, user models.UserModel, conn db.Connection) error { ses, err := InitSession(ctx, conn) if err != nil { return err } return ses.Add("user_id", user.Id) } // DelCookie delete the cookie from Context. func DelCookie(ctx *context.Context, conn db.Connection) error { ses, err := InitSession(ctx, conn) if err != nil { return err } return ses.Clear() } type TokenService struct { tokens CSRFToken lock sync.Mutex conn db.Connection } func (s *TokenService) Name() string { return TokenServiceKey } func InitCSRFTokenSrv(conn db.Connection) (string, service.Service) { list, err := db.WithDriver(conn).Table("goadmin_session"). Where("values", "=", "__csrf_token__"). All() if db.CheckError(err, db.QUERY) { logger.Error("csrf token query from database error: ", err) } tokens := make(CSRFToken, len(list)) for i := 0; i < len(list); i++ { tokens[i] = list[i]["sid"].(string) } return TokenServiceKey, &TokenService{ tokens: tokens, conn: conn, } } const ( TokenServiceKey = "token_csrf_helper" ServiceKey = "auth" ) func GetTokenService(s interface{}) *TokenService { if srv, ok := s.(*TokenService); ok { return srv } log.Panicf("wrong service: %+v", s) return nil } // AddToken add the token to the CSRFToken. func (s *TokenService) AddToken() string { s.lock.Lock() defer s.lock.Unlock() tokenStr := modules.Uuid() s.tokens = append(s.tokens, tokenStr) _, err := db.WithDriver(s.conn).Table("goadmin_session").Insert(dialect.H{ "sid": tokenStr, "values": "__csrf_token__", }) if db.CheckError(err, db.INSERT) { logger.Error("csrf token insert into database error: ", err) } return tokenStr } // CheckToken check the given token with tokens in the CSRFToken, if exist // return true. func (s *TokenService) CheckToken(toCheckToken string) (ok bool) { defer func() { if ok { err := db.WithDriver(s.conn).Table("goadmin_session"). Where("sid", "=", toCheckToken). Where("values", "=", "__csrf_token__"). Delete() if db.CheckError(err, db.DELETE) { logger.Error("csrf token delete from database error: ", err) } } }() for i := 0; i < len(s.tokens); i++ { if (s.tokens)[i] == toCheckToken { s.tokens = append((s.tokens)[:i], (s.tokens)[i+1:]...) ok = true return } } item, err := db.WithDriver(s.conn).Table("goadmin_session"). Where("sid", "=", toCheckToken). Where("values", "=", "__csrf_token__"). First() if item != nil && err == nil { ok = true return } return } // CSRFToken is type of a csrf token list. type CSRFToken []string type Processor func(ctx *context.Context) (model models.UserModel, exist bool, msg string) type Service struct { P Processor } func (s *Service) Name() string { return "auth" } func GetService(s interface{}) *Service { if srv, ok := s.(*Service); ok { return srv } log.Panicf("wrong service: %+v", s) return nil } func NewService(processor Processor) *Service { return &Service{ P: processor, } } ================================================ FILE: modules/auth/auth_test.go ================================================ package auth import ( "testing" "github.com/stretchr/testify/assert" ) func TestEncodePassword(t *testing.T) { pwd := EncodePassword([]byte("123456")) assert.Equal(t, comparePassword("123456", pwd), true) } ================================================ FILE: modules/auth/middleware.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package auth import ( "net/http" "net/url" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/constant" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/page" "github.com/GoAdminGroup/go-admin/plugins/admin/models" template2 "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" ) // Invoker contains the callback functions which are used // in the route middleware. type Invoker struct { prefix string authFailCallback MiddlewareCallback permissionDenyCallback MiddlewareCallback conn db.Connection } // Middleware is the default auth middleware of plugins. func Middleware(conn db.Connection) context.Handler { return DefaultInvoker(conn).Middleware() } // DefaultInvoker return a default Invoker. func DefaultInvoker(conn db.Connection) *Invoker { return &Invoker{ prefix: config.Prefix(), authFailCallback: func(ctx *context.Context) { if ctx.Request.URL.Path == config.Url(config.GetLoginUrl()) { return } if ctx.Request.URL.Path == config.Url("/logout") { ctx.Write(302, map[string]string{ "Location": config.Url(config.GetLoginUrl()), }, ``) return } param := "" if ref := ctx.Referer(); ref != "" { param = "?ref=" + url.QueryEscape(ref) } u := config.Url(config.GetLoginUrl() + param) _, err := ctx.Request.Cookie(DefaultCookieKey) referer := ctx.Referer() if (ctx.Headers(constant.PjaxHeader) == "" && ctx.Method() != "GET") || err != nil || referer == "" { ctx.Write(302, map[string]string{ "Location": u, }, ``) } else { msg := language.Get("login overdue, please login again") ctx.HTML(http.StatusOK, ``) } }, permissionDenyCallback: func(rawCtx *context.Context) { if rawCtx.Headers(constant.PjaxHeader) == "" && rawCtx.Method() != "GET" { rawCtx.JSON(http.StatusForbidden, map[string]interface{}{ "code": http.StatusForbidden, "msg": language.Get(errors.PermissionDenied), }) } else { page.SetPageContent(rawCtx, Auth(rawCtx), func(ctx interface{}) (types.Panel, error) { return template2.WarningPanel(rawCtx, errors.PermissionDenied, template2.NoPermission403Page), nil }, conn) } }, conn: conn, } } // SetPrefix return the default Invoker with the given prefix. func SetPrefix(prefix string, conn db.Connection) *Invoker { i := DefaultInvoker(conn) i.prefix = prefix return i } // SetAuthFailCallback set the authFailCallback of Invoker. func (invoker *Invoker) SetAuthFailCallback(callback MiddlewareCallback) *Invoker { invoker.authFailCallback = callback return invoker } // SetPermissionDenyCallback set the permissionDenyCallback of Invoker. func (invoker *Invoker) SetPermissionDenyCallback(callback MiddlewareCallback) *Invoker { invoker.permissionDenyCallback = callback return invoker } // MiddlewareCallback is type of callback function. type MiddlewareCallback func(ctx *context.Context) // Middleware get the auth middleware from Invoker. func (invoker *Invoker) Middleware() context.Handler { return func(ctx *context.Context) { user, authOk, permissionOk := Filter(ctx, invoker.conn) if authOk && permissionOk { ctx.SetUserValue("user", user) ctx.Next() return } if !authOk { invoker.authFailCallback(ctx) ctx.Abort() return } if !permissionOk { ctx.SetUserValue("user", user) invoker.permissionDenyCallback(ctx) ctx.Abort() return } } } // Filter retrieve the user model from Context and check the permission // at the same time. func Filter(ctx *context.Context, conn db.Connection) (models.UserModel, bool, bool) { var ( id float64 ok bool user = models.User() ses, err = InitSession(ctx, conn) ) if err != nil { logger.ErrorCtx(ctx, "retrieve auth user failed %+v", err) return user, false, false } if id, ok = ses.Get("user_id").(float64); !ok { return user, false, false } user, ok = GetCurUserByID(int64(id), conn) if !ok { return user, false, false } return user, true, CheckPermissions(user, ctx.Request.URL.String(), ctx.Method(), ctx.PostForm()) } const defaultUserIDSesKey = "user_id" // GetUserID return the user id from the session. func GetUserID(sesKey string, conn db.Connection) int64 { id, err := GetSessionByKey(sesKey, defaultUserIDSesKey, conn) if err != nil { logger.Error("retrieve auth user failed", err) return -1 } if idFloat64, ok := id.(float64); ok { return int64(idFloat64) } return -1 } // GetCurUser return the user model. func GetCurUser(sesKey string, conn db.Connection) (user models.UserModel, ok bool) { if sesKey == "" { ok = false return } id := GetUserID(sesKey, conn) if id == -1 { ok = false return } return GetCurUserByID(id, conn) } // GetCurUserByID return the user model of given user id. func GetCurUserByID(id int64, conn db.Connection) (user models.UserModel, ok bool) { user = models.User().SetConn(conn).Find(id) if user.IsEmpty() { ok = false return } if user.Avatar == "" || config.GetStore().Prefix == "" { user.Avatar = "" } else { user.Avatar = config.GetStore().URL(user.Avatar) } user = user.WithRoles().WithPermissions().WithMenus() ok = user.HasMenu() return } // CheckPermissions check the permission of the user. func CheckPermissions(user models.UserModel, path, method string, param url.Values) bool { return user.CheckPermissionByUrlMethod(path, method, param) } ================================================ FILE: modules/auth/middleware_test.go ================================================ package auth import ( "net/url" "testing" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/stretchr/testify/assert" ) func TestCheckPermissions(t *testing.T) { config.Initialize(&config.Config{ UrlPrefix: "admin", }) user := models.UserModel{ Permissions: []models.PermissionModel{ { Name: "/", Slug: "/", HttpMethod: []string{"GET"}, HttpPath: []string{"/"}, }, { Name: "/info/user", Slug: "/", HttpMethod: []string{"GET"}, HttpPath: []string{"/info/user"}, }, { Name: "/info/user/edit", Slug: "/", HttpMethod: []string{"GET"}, HttpPath: []string{"/info/user/edit"}, }, { Name: "/info/normal_manager?id=2", Slug: "/", HttpMethod: []string{"GET"}, HttpPath: []string{"/info/normal_manager?id=2"}, }, { Name: "/info/normal_manager/edit?id=2", Slug: "/", HttpMethod: []string{"GET"}, HttpPath: []string{"/info/normal_manager/edit?id=2"}, }, { Name: "/info/user_list?user_type=10", Slug: "/", HttpMethod: []string{"GET"}, HttpPath: []string{"/info/user_list?user_type=10"}, }, { Name: "/info/user_list?user_type=20", Slug: "/", HttpMethod: []string{"GET"}, HttpPath: []string{"/info/user_list?user_type=20"}, }, { Name: "/delete/user", Slug: "/", HttpMethod: []string{"POST"}, HttpPath: []string{"/delete/user"}, }, }, } param := make(url.Values) assert.Equal(t, CheckPermissions(user, "/admin/", "GET", param), true) assert.Equal(t, CheckPermissions(user, "/admin", "GET", param), true) assert.Equal(t, CheckPermissions(user, "/", "GET", param), false) assert.Equal(t, CheckPermissions(user, "/admin", "POST", param), false) assert.Equal(t, CheckPermissions(user, "/admin/info/users", "GET", param), false) assert.Equal(t, CheckPermissions(user, "/admin/info/user", "GET", param), true) assert.Equal(t, CheckPermissions(user, "/admin/info/user", "get", param), true) assert.Equal(t, CheckPermissions(user, "/admin/info/normal_manager/edit?__goadmin_edit_pk=2&__columns=id,roles,created_at,updated_at", "get", param), true) assert.Equal(t, CheckPermissions(user, "/admin/info/normal_manager/edit?__goadmin_edit_pk=2", "get", param), true) assert.Equal(t, CheckPermissions(user, "/admin/info/normal_manager/edit?__goadmin_edit_pk=3&__columns=id,roles,created_at,updated_at", "get", param), false) assert.Equal(t, CheckPermissions(user, "/admin/info/normal_manager/edit?__columns=id,roles,created_at,updated_at&id=3", "get", param), false) assert.Equal(t, CheckPermissions(user, "/admin/info/user", "post", param), false) assert.Equal(t, CheckPermissions(user, "/admin/info/user/edit?id=3", "get", param), true) assert.Equal(t, CheckPermissions(user, "/admin/logout?j=asdf", "post", param), true) assert.Equal(t, CheckPermissions(user, "/admin/info/user_list?user_type=20", "get", param), true) assert.Equal(t, CheckPermissions(user, "/admin/info/user_list?__goadmin_edit_pk=3&user_type=20", "get", param), true) assert.Equal(t, CheckPermissions(user, "/admin/delete/user", "post", param), true) } ================================================ FILE: modules/auth/session.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package auth import ( "encoding/json" "net/http" "strconv" "time" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/db/dialect" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" ) const DefaultCookieKey = "go_admin_session" // NewDBDriver return the default PersistenceDriver. func newDBDriver(conn db.Connection) *DBDriver { return &DBDriver{ conn: conn, tableName: "goadmin_session", } } // PersistenceDriver is a driver of storing and getting the session info. type PersistenceDriver interface { Load(string) (map[string]interface{}, error) Update(sid string, values map[string]interface{}) error } // GetSessionByKey get the session value by key. func GetSessionByKey(sesKey, key string, conn db.Connection) (interface{}, error) { m, err := newDBDriver(conn).Load(sesKey) return m[key], err } // Session contains info of session. type Session struct { Expires time.Duration Cookie string Values map[string]interface{} Driver PersistenceDriver Sid string Context *context.Context } // Config wraps the Session info. type Config struct { Expires time.Duration Cookie string } // UpdateConfig update the Expires and Cookie of Session. func (ses *Session) UpdateConfig(config Config) { ses.Expires = config.Expires ses.Cookie = config.Cookie } // Get get the session value. func (ses *Session) Get(key string) interface{} { return ses.Values[key] } // Add add the session value of key. func (ses *Session) Add(key string, value interface{}) error { ses.Values[key] = value if err := ses.Driver.Update(ses.Sid, ses.Values); err != nil { return err } cookie := http.Cookie{ Name: ses.Cookie, Value: ses.Sid, MaxAge: config.GetSessionLifeTime(), Expires: time.Now().Add(ses.Expires), HttpOnly: true, Path: "/", } if config.GetDomain() != "" { cookie.Domain = config.GetDomain() } ses.Context.SetCookie(&cookie) return nil } // Clear clear a Session. func (ses *Session) Clear() error { ses.Values = map[string]interface{}{} return ses.Driver.Update(ses.Sid, ses.Values) } // UseDriver set the driver of the Session. func (ses *Session) UseDriver(driver PersistenceDriver) { ses.Driver = driver } // StartCtx return a Session from the given Context. func (ses *Session) StartCtx(ctx *context.Context) (*Session, error) { if cookie, err := ctx.Request.Cookie(ses.Cookie); err == nil && cookie.Value != "" { ses.Sid = cookie.Value valueFromDriver, err := ses.Driver.Load(cookie.Value) if err != nil { return nil, err } if len(valueFromDriver) > 0 { ses.Values = valueFromDriver } } else { ses.Sid = modules.Uuid() } ses.Context = ctx return ses, nil } // InitSession return the default Session. func InitSession(ctx *context.Context, conn db.Connection) (*Session, error) { sessions := new(Session) sessions.UpdateConfig(Config{ Expires: time.Second * time.Duration(config.GetSessionLifeTime()), Cookie: DefaultCookieKey, }) sessions.UseDriver(newDBDriver(conn)) sessions.Values = make(map[string]interface{}) return sessions.StartCtx(ctx) } // DBDriver is a driver which uses database as a persistence tool. type DBDriver struct { conn db.Connection tableName string } // Load implements the PersistenceDriver.Load. func (driver *DBDriver) Load(sid string) (map[string]interface{}, error) { sesModel, err := driver.table().Where("sid", "=", sid).First() if db.CheckError(err, db.QUERY) { return nil, err } if sesModel == nil { return map[string]interface{}{}, nil } var values map[string]interface{} err = json.Unmarshal([]byte(sesModel["values"].(string)), &values) return values, err } func (driver *DBDriver) deleteOverdueSession() { defer func() { if err := recover(); err != nil { logger.Error(err) panic(err) } }() var ( duration = strconv.Itoa(config.GetSessionLifeTime() + 1000) driverName = config.GetDatabases().GetDefault().Driver raw = `` ) if db.DriverPostgresql == driverName { raw = `extract(epoch from now()) - ` + duration + ` > extract(epoch from created_at)` } else if db.DriverMysql == driverName { raw = `unix_timestamp(created_at) < unix_timestamp() - ` + duration } else if db.DriverSqlite == driverName { raw = `strftime('%s', created_at) < strftime('%s', 'now') - ` + duration } else if db.DriverMssql == driverName { raw = `DATEDIFF(second, [created_at], GETDATE()) > ` + duration } else if db.DriverOceanBase == driverName { raw = `unix_timestamp(created_at) < unix_timestamp() - ` + duration } if raw != "" { _ = driver.table().WhereRaw(raw).Delete() } } // Update implements the PersistenceDriver.Update. func (driver *DBDriver) Update(sid string, values map[string]interface{}) error { go driver.deleteOverdueSession() if sid != "" { if len(values) == 0 { err := driver.table().Where("sid", "=", sid).Delete() if db.CheckError(err, db.DELETE) { return err } } valuesByte, err := json.Marshal(values) if err != nil { return err } sesValue := string(valuesByte) sesModel, _ := driver.table().Where("sid", "=", sid).First() if sesModel == nil { if !config.GetNoLimitLoginIP() { err = driver.table().Where("values", "=", sesValue).Delete() if db.CheckError(err, db.DELETE) { return err } } _, err := driver.table().Insert(dialect.H{ "values": sesValue, "sid": sid, }) if db.CheckError(err, db.INSERT) { return err } } else { _, err := driver.table(). Where("sid", "=", sid). Update(dialect.H{ "values": sesValue, }) if db.CheckError(err, db.UPDATE) { return err } } } return nil } func (driver *DBDriver) table() *db.SQL { return db.Table(driver.tableName).WithDriver(driver.conn) } ================================================ FILE: modules/collection/collection.go ================================================ package collection type Collection []map[string]interface{} // Where filters the collection by a given key / value pair. func (c Collection) Where(key string, values ...interface{}) Collection { var d = make([]map[string]interface{}, 0) if len(values) < 1 { for _, value := range c { if isTrue(value[key]) { d = append(d, value) } } } else if len(values) < 2 { for _, value := range c { if value[key] == values[0] { d = append(d, value) } } } else if values[0].(string) == "=" { for _, value := range c { if value[key] == values[1] { d = append(d, value) } } } return d } func (c Collection) Length() int { return len(c) } func (c Collection) FirstGet(key string) interface{} { return c[0][key] } func isTrue(a interface{}) bool { switch a := a.(type) { case uint: return a != uint(0) case uint8: return a != uint8(0) case uint16: return a != uint16(0) case uint32: return a != uint32(0) case uint64: return a != uint64(0) case int: return a != int(0) case int8: return a != int8(0) case int16: return a != int16(0) case int32: return a != int32(0) case int64: return a != int64(0) case float32: return a != float32(0) case float64: return a != float64(0) case string: return a != "" case bool: return a default: return false } } ================================================ FILE: modules/collection/collection_test.go ================================================ package collection ================================================ FILE: modules/config/config.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package config import ( "encoding/json" "fmt" "html/template" "os" "path/filepath" "reflect" "strconv" "strings" "sync" "sync/atomic" "time" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "gopkg.in/ini.v1" "gopkg.in/yaml.v2" ) // Database is a type of database connection config. // // Because a little difference of different database driver. // The Config has multiple options but may not be used. // Such as the sqlite driver only use the File option which // can be ignored when the driver is mysql. // // If the Dsn is configured, when driver is mysql/postgresql/ // mssql, the other configurations will be ignored, except for // MaxIdleConns and MaxOpenConns. type Database struct { Host string `json:"host,omitempty" yaml:"host,omitempty" ini:"host,omitempty"` Port string `json:"port,omitempty" yaml:"port,omitempty" ini:"port,omitempty"` User string `json:"user,omitempty" yaml:"user,omitempty" ini:"user,omitempty"` Pwd string `json:"pwd,omitempty" yaml:"pwd,omitempty" ini:"pwd,omitempty"` Name string `json:"name,omitempty" yaml:"name,omitempty" ini:"name,omitempty"` Driver string `json:"driver,omitempty" yaml:"driver,omitempty" ini:"driver,omitempty"` DriverMode string `json:"driver_mode,omitempty" yaml:"driver_mode,omitempty" ini:"driver_mode,omitempty"` File string `json:"file,omitempty" yaml:"file,omitempty" ini:"file,omitempty"` Dsn string `json:"dsn,omitempty" yaml:"dsn,omitempty" ini:"dsn,omitempty"` MaxIdleConns int `json:"max_idle_con,omitempty" yaml:"max_idle_con,omitempty" ini:"max_idle_con,omitempty"` MaxOpenConns int `json:"max_open_con,omitempty" yaml:"max_open_con,omitempty" ini:"max_open_con,omitempty"` ConnMaxLifetime time.Duration `json:"conn_max_life_time,omitempty" yaml:"conn_max_life_time,omitempty" ini:"conn_max_life_time,omitempty"` ConnMaxIdleTime time.Duration `json:"conn_max_idle_time,omitempty" yaml:"conn_max_idle_time,omitempty" ini:"conn_max_idle_time,omitempty"` Params map[string]string `json:"params,omitempty" yaml:"params,omitempty" ini:"params,omitempty"` } func (d Database) GetDSN() string { if d.Dsn != "" { return d.Dsn } if d.Driver == DriverMysql { return d.User + ":" + d.Pwd + "@tcp(" + d.Host + ":" + d.Port + ")/" + d.Name + d.ParamStr() } if d.Driver == DriverPostgresql { return fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s"+d.ParamStr(), d.Host, d.Port, d.User, d.Pwd, d.Name) } if d.Driver == DriverMssql { return fmt.Sprintf("user id=%s;password=%s;server=%s;port=%s;database=%s;"+d.ParamStr(), d.User, d.Pwd, d.Host, d.Port, d.Name) } if d.Driver == DriverSqlite { return d.File + d.ParamStr() } if d.Driver == DriverOceanBase { return d.User + ":" + d.Pwd + "@tcp(" + d.Host + ":" + d.Port + ")/" + d.Name + d.ParamStr() } return "" } func (d Database) ParamStr() string { p := "" if d.Params == nil { d.Params = make(map[string]string) } if d.Driver == DriverMysql || d.Driver == DriverSqlite || d.Driver == DriverOceanBase { if d.Driver == DriverMysql || d.Driver == DriverOceanBase { if _, ok := d.Params["charset"]; !ok { d.Params["charset"] = "utf8mb4" } } if len(d.Params) > 0 { p = "?" for k, v := range d.Params { p += k + "=" + v + "&" } p = p[:len(p)-1] } } if d.Driver == DriverMssql { if _, ok := d.Params["encrypt"]; !ok { d.Params["encrypt"] = "disable" } for k, v := range d.Params { p += k + "=" + v + ";" } p = p[:len(p)-1] } if d.Driver == DriverPostgresql { if _, ok := d.Params["sslmode"]; !ok { d.Params["sslmode"] = "disable" } p = " " for k, v := range d.Params { p += k + "=" + v + " " } p = p[:len(p)-1] } return p } // DatabaseList is a map of Database. type DatabaseList map[string]Database // GetDefault get the default Database. func (d DatabaseList) GetDefault() Database { return d["default"] } // Add add a Database to the DatabaseList. func (d DatabaseList) Add(key string, db Database) { d[key] = db } // GroupByDriver group the Databases with the drivers. func (d DatabaseList) GroupByDriver() map[string]DatabaseList { drivers := make(map[string]DatabaseList) for key, item := range d { if driverList, ok := drivers[item.Driver]; ok { driverList.Add(key, item) } else { drivers[item.Driver] = make(DatabaseList) drivers[item.Driver].Add(key, item) } } return drivers } func (d DatabaseList) JSON() string { return utils.JSON(d) } func (d DatabaseList) Copy() DatabaseList { var c = make(DatabaseList) for k, v := range d { c[k] = v } return c } func (d DatabaseList) Connections() []string { conns := make([]string, len(d)) count := 0 for key := range d { conns[count] = key count++ } return conns } func GetDatabaseListFromJSON(m string) DatabaseList { var d = make(DatabaseList) if m == "" { panic("wrong config") } _ = json.Unmarshal([]byte(m), &d) return d } const ( // EnvTest is a const value of test environment. EnvTest = "test" // EnvLocal is a const value of local environment. EnvLocal = "local" // EnvProd is a const value of production environment. EnvProd = "prod" // DriverMysql is a const value of mysql driver. DriverMysql = "mysql" // DriverSqlite is a const value of sqlite driver. DriverSqlite = "sqlite" // DriverPostgresql is a const value of postgresql driver. DriverPostgresql = "postgresql" // DriverMssql is a const value of mssql driver. DriverMssql = "mssql" // DriverOceanBase is a const value of mysql driver. DriverOceanBase = "oceanbase" ) // Store is the file store config. Path is the local store path. // and prefix is the url prefix used to visit it. type Store struct { Path string `json:"path,omitempty" yaml:"path,omitempty" ini:"path,omitempty"` Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty" ini:"prefix,omitempty"` } func (s Store) URL(suffix string) string { if len(suffix) > 4 && suffix[:4] == "http" { return suffix } if s.Prefix == "" { if suffix[0] == '/' { return suffix } return "/" + suffix } if s.Prefix[0] == '/' { if suffix[0] == '/' { return s.Prefix + suffix } return s.Prefix + "/" + suffix } if suffix[0] == '/' { if len(s.Prefix) > 4 && s.Prefix[:4] == "http" { return s.Prefix + suffix } return "/" + s.Prefix + suffix } if len(s.Prefix) > 4 && s.Prefix[:4] == "http" { return s.Prefix + "/" + suffix } return "/" + s.Prefix + "/" + suffix } func (s Store) JSON() string { if s.Path == "" && s.Prefix == "" { return "" } return utils.JSON(s) } func GetStoreFromJSON(m string) Store { var s Store if m == "" { return s } _ = json.Unmarshal([]byte(m), &s) return s } // Config type is the global config of goAdmin. It will be // initialized in the engine. type Config struct { // An map supports multi database connection. The first // element of Databases is the default connection. See the // file connection.go. Databases DatabaseList `json:"database,omitempty" yaml:"database,omitempty" ini:"database,omitempty"` // The application unique ID. Once generated, don't modify. AppID string `json:"app_id,omitempty" yaml:"app_id,omitempty" ini:"app_id,omitempty"` // The cookie domain used in the auth modules. see // the session.go. Domain string `json:"domain,omitempty" yaml:"domain,omitempty" ini:"domain,omitempty"` // Used to set as the localize language which show in the // interface. Language string `json:"language,omitempty" yaml:"language,omitempty" ini:"language,omitempty"` // The global url prefix. UrlPrefix string `json:"prefix,omitempty" yaml:"prefix,omitempty" ini:"prefix,omitempty"` // The theme name of template. Theme string `json:"theme,omitempty" yaml:"theme,omitempty" ini:"theme,omitempty"` // The path where files will be stored into. Store Store `json:"store,omitempty" yaml:"store,omitempty" ini:"store,omitempty"` // The title of web page. Title string `json:"title,omitempty" yaml:"title,omitempty" ini:"title,omitempty"` // Logo is the top text in the sidebar. Logo template.HTML `json:"logo,omitempty" yaml:"logo,omitempty" ini:"logo,omitempty"` // Mini-logo is the top text in the sidebar when folding. MiniLogo template.HTML `json:"mini_logo,omitempty" yaml:"mini_logo,omitempty" ini:"mini_logo,omitempty"` // The url redirect to after login. IndexUrl string `json:"index,omitempty" yaml:"index,omitempty" ini:"index,omitempty"` // Login page URL LoginUrl string `json:"login_url,omitempty" yaml:"login_url,omitempty" ini:"login_url,omitempty"` // Debug mode Debug bool `json:"debug,omitempty" yaml:"debug,omitempty" ini:"debug,omitempty"` // Env is the environment,which maybe local,test,prod. Env string `json:"env,omitempty" yaml:"env,omitempty" ini:"env,omitempty"` // Info log path. InfoLogPath string `json:"info_log,omitempty" yaml:"info_log,omitempty" ini:"info_log,omitempty"` // Error log path. ErrorLogPath string `json:"error_log,omitempty" yaml:"error_log,omitempty" ini:"error_log,omitempty"` // Access log path. AccessLogPath string `json:"access_log,omitempty" yaml:"access_log,omitempty" ini:"access_log,omitempty"` // Access assets log off AccessAssetsLogOff bool `json:"access_assets_log_off,omitempty" yaml:"access_assets_log_off,omitempty" ini:"access_assets_log_off,omitempty"` // Sql operator record log switch. SqlLog bool `json:"sql_log,omitempty" yaml:"sql_log,omitempty" ini:"sql_log,omitempty"` AccessLogOff bool `json:"access_log_off,omitempty" yaml:"access_log_off,omitempty" ini:"access_log_off,omitempty"` InfoLogOff bool `json:"info_log_off,omitempty" yaml:"info_log_off,omitempty" ini:"info_log_off,omitempty"` ErrorLogOff bool `json:"error_log_off,omitempty" yaml:"error_log_off,omitempty" ini:"error_log_off,omitempty"` Logger Logger `json:"logger,omitempty" yaml:"logger,omitempty" ini:"logger,omitempty"` // Color scheme. ColorScheme string `json:"color_scheme,omitempty" yaml:"color_scheme,omitempty" ini:"color_scheme,omitempty"` // Session valid time duration,units are seconds. Default 7200. SessionLifeTime int `json:"session_life_time,omitempty" yaml:"session_life_time,omitempty" ini:"session_life_time,omitempty"` // Assets visit link. AssetUrl string `json:"asset_url,omitempty" yaml:"asset_url,omitempty" ini:"asset_url,omitempty"` // File upload engine,default "local" FileUploadEngine FileUploadEngine `json:"file_upload_engine,omitempty" yaml:"file_upload_engine,omitempty" ini:"file_upload_engine,omitempty"` // Custom html in the tag head. CustomHeadHtml template.HTML `json:"custom_head_html,omitempty" yaml:"custom_head_html,omitempty" ini:"custom_head_html,omitempty"` // Custom html after body. CustomFootHtml template.HTML `json:"custom_foot_html,omitempty" yaml:"custom_foot_html,omitempty" ini:"custom_foot_html,omitempty"` // Footer Info html FooterInfo template.HTML `json:"footer_info,omitempty" yaml:"footer_info,omitempty" ini:"footer_info,omitempty"` // Login page title LoginTitle string `json:"login_title,omitempty" yaml:"login_title,omitempty" ini:"login_title,omitempty"` // Login page logo LoginLogo template.HTML `json:"login_logo,omitempty" yaml:"login_logo,omitempty" ini:"login_logo,omitempty"` // Auth user table AuthUserTable string `json:"auth_user_table,omitempty" yaml:"auth_user_table,omitempty" ini:"auth_user_table,omitempty"` // Extra config info Extra ExtraInfo `json:"extra,omitempty" yaml:"extra,omitempty" ini:"extra,omitempty"` // Page animation Animation PageAnimation `json:"animation,omitempty" yaml:"animation,omitempty" ini:"animation,omitempty"` // Limit login with different IPs NoLimitLoginIP bool `json:"no_limit_login_ip,omitempty" yaml:"no_limit_login_ip,omitempty" ini:"no_limit_login_ip,omitempty"` // When site off is true, website will be closed SiteOff bool `json:"site_off,omitempty" yaml:"site_off,omitempty" ini:"site_off,omitempty"` // Hide config center entrance flag HideConfigCenterEntrance bool `json:"hide_config_center_entrance,omitempty" yaml:"hide_config_center_entrance,omitempty" ini:"hide_config_center_entrance,omitempty"` // Prohibit config modification ProhibitConfigModification bool `json:"prohibit_config_modification,omitempty" yaml:"prohibit_config_modification,omitempty" ini:"prohibit_config_modification,omitempty"` // Hide app info entrance flag HideAppInfoEntrance bool `json:"hide_app_info_entrance,omitempty" yaml:"hide_app_info_entrance,omitempty" ini:"hide_app_info_entrance,omitempty"` // Hide tool entrance flag HideToolEntrance bool `json:"hide_tool_entrance,omitempty" yaml:"hide_tool_entrance,omitempty" ini:"hide_tool_entrance,omitempty"` HidePluginEntrance bool `json:"hide_plugin_entrance,omitempty" yaml:"hide_plugin_entrance,omitempty" ini:"hide_plugin_entrance,omitempty"` Custom404HTML template.HTML `json:"custom_404_html,omitempty" yaml:"custom_404_html,omitempty" ini:"custom_404_html,omitempty"` Custom403HTML template.HTML `json:"custom_403_html,omitempty" yaml:"custom_403_html,omitempty" ini:"custom_403_html,omitempty"` Custom500HTML template.HTML `json:"custom_500_html,omitempty" yaml:"custom_500_html,omitempty" ini:"custom_500_html,omitempty"` // Update Process Function UpdateProcessFn UpdateConfigProcessFn `json:"-" yaml:"-" ini:"-"` // Favicon string `json:"favicon,omitempty" yaml:"favicon,omitempty" ini:"favicon,omitempty"` // Is open admin plugin json api OpenAdminApi bool `json:"open_admin_api,omitempty" yaml:"open_admin_api,omitempty" ini:"open_admin_api,omitempty"` HideVisitorUserCenterEntrance bool `json:"hide_visitor_user_center_entrance,omitempty" yaml:"hide_visitor_user_center_entrance,omitempty" ini:"hide_visitor_user_center_entrance,omitempty"` ExcludeThemeComponents []string `json:"exclude_theme_components,omitempty" yaml:"exclude_theme_components,omitempty" ini:"exclude_theme_components,omitempty"` BootstrapFilePath string `json:"bootstrap_file_path,omitempty" yaml:"bootstrap_file_path,omitempty" ini:"bootstrap_file_path,omitempty"` GoModFilePath string `json:"go_mod_file_path,omitempty" yaml:"go_mod_file_path,omitempty" ini:"go_mod_file_path,omitempty"` AllowDelOperationLog bool `json:"allow_del_operation_log,omitempty" yaml:"allow_del_operation_log,omitempty" ini:"allow_del_operation_log,omitempty"` OperationLogOff bool `json:"operation_log_off,omitempty" yaml:"operation_log_off,omitempty" ini:"operation_log_off,omitempty"` AssetRootPath string `json:"asset_root_path,omitempty" yaml:"asset_root_path,omitempty" ini:"asset_root_path,omitempty"` URLFormat URLFormat `json:"url_format,omitempty" yaml:"url_format,omitempty" ini:"url_format,omitempty"` prefix string `json:"-" yaml:"-" ini:"-"` lock sync.RWMutex `json:"-" yaml:"-" ini:"-"` } type Logger struct { Encoder EncoderCfg `json:"encoder,omitempty" yaml:"encoder,omitempty" ini:"encoder,omitempty"` Rotate RotateCfg `json:"rotate,omitempty" yaml:"rotate,omitempty" ini:"rotate,omitempty"` Level int8 `json:"level,omitempty" yaml:"level,omitempty" ini:"level,omitempty"` } type EncoderCfg struct { TimeKey string `json:"time_key,omitempty" yaml:"time_key,omitempty" ini:"time_key,omitempty"` LevelKey string `json:"level_key,omitempty" yaml:"level_key,omitempty" ini:"level_key,omitempty"` NameKey string `json:"name_key,omitempty" yaml:"name_key,omitempty" ini:"name_key,omitempty"` CallerKey string `json:"caller_key,omitempty" yaml:"caller_key,omitempty" ini:"caller_key,omitempty"` MessageKey string `json:"message_key,omitempty" yaml:"message_key,omitempty" ini:"message_key,omitempty"` StacktraceKey string `json:"stacktrace_key,omitempty" yaml:"stacktrace_key,omitempty" ini:"stacktrace_key,omitempty"` Level string `json:"level,omitempty" yaml:"level,omitempty" ini:"level,omitempty"` Time string `json:"time,omitempty" yaml:"time,omitempty" ini:"time,omitempty"` Duration string `json:"duration,omitempty" yaml:"duration,omitempty" ini:"duration,omitempty"` Caller string `json:"caller,omitempty" yaml:"caller,omitempty" ini:"caller,omitempty"` Encoding string `json:"encoding,omitempty" yaml:"encoding,omitempty" ini:"encoding,omitempty"` } type RotateCfg struct { MaxSize int `json:"max_size,omitempty" yaml:"max_size,omitempty" ini:"max_size,omitempty"` MaxBackups int `json:"max_backups,omitempty" yaml:"max_backups,omitempty" ini:"max_backups,omitempty"` MaxAge int `json:"max_age,omitempty" yaml:"max_age,omitempty" ini:"max_age,omitempty"` Compress bool `json:"compress,omitempty" yaml:"compress,omitempty" ini:"compress,omitempty"` } type URLFormat struct { Info string `json:"info,omitempty" yaml:"info,omitempty" ini:"info,omitempty"` Detail string `json:"detail,omitempty" yaml:"detail,omitempty" ini:"detail,omitempty"` Create string `json:"create,omitempty" yaml:"create,omitempty" ini:"create,omitempty"` Delete string `json:"delete,omitempty" yaml:"delete,omitempty" ini:"delete,omitempty"` Export string `json:"export,omitempty" yaml:"export,omitempty" ini:"export,omitempty"` Edit string `json:"edit,omitempty" yaml:"edit,omitempty" ini:"edit,omitempty"` ShowEdit string `json:"show_edit,omitempty" yaml:"show_edit,omitempty" ini:"show_edit,omitempty"` ShowCreate string `json:"show_create,omitempty" yaml:"show_create,omitempty" ini:"show_create,omitempty"` Update string `json:"update,omitempty" yaml:"update,omitempty" ini:"update,omitempty"` } func (f URLFormat) SetDefault() URLFormat { f.Detail = utils.SetDefault(f.Detail, "", "/info/:__prefix/detail") f.ShowEdit = utils.SetDefault(f.ShowEdit, "", "/info/:__prefix/edit") f.ShowCreate = utils.SetDefault(f.ShowCreate, "", "/info/:__prefix/new") f.Edit = utils.SetDefault(f.Edit, "", "/edit/:__prefix") f.Create = utils.SetDefault(f.Create, "", "/new/:__prefix") f.Delete = utils.SetDefault(f.Delete, "", "/delete/:__prefix") f.Export = utils.SetDefault(f.Export, "", "/export/:__prefix") f.Info = utils.SetDefault(f.Info, "", "/info/:__prefix") f.Update = utils.SetDefault(f.Update, "", "/update/:__prefix") return f } type ExtraInfo map[string]interface{} type UpdateConfigProcessFn func(values form.Values) (form.Values, error) // see more: https://daneden.github.io/animate.css/ type PageAnimation struct { Type string `json:"type,omitempty" yaml:"type,omitempty" ini:"type,omitempty"` Duration float32 `json:"duration,omitempty" yaml:"duration,omitempty" ini:"duration,omitempty"` Delay float32 `json:"delay,omitempty" yaml:"delay,omitempty" ini:"delay,omitempty"` } func (p PageAnimation) JSON() string { if p.Type == "" { return "" } return utils.JSON(p) } // FileUploadEngine is a file upload engine. type FileUploadEngine struct { Name string `json:"name,omitempty" yaml:"name,omitempty" ini:"name,omitempty"` Config map[string]interface{} `json:"config,omitempty" yaml:"config,omitempty" ini:"config,omitempty"` } func (f FileUploadEngine) JSON() string { if f.Name == "" { return "" } if len(f.Config) == 0 { f.Config = nil } return utils.JSON(f) } func GetFileUploadEngineFromJSON(m string) FileUploadEngine { var f FileUploadEngine if m == "" { return f } _ = json.Unmarshal([]byte(m), &f) return f } // GetIndexURL get the index url with prefix. func (c *Config) GetIndexURL() string { index := c.Index() if index == "/" { return c.Prefix() } return c.Prefix() + index } // Url get url with the given suffix. func (c *Config) Url(suffix string) string { if c.prefix == "/" { return suffix } if suffix == "/" { return c.prefix } return c.prefix + suffix } // IsTestEnvironment check the environment if it is test. func (c *Config) IsTestEnvironment() bool { return c.Env == EnvTest } // IsLocalEnvironment check the environment if it is local. func (c *Config) IsLocalEnvironment() bool { return c.Env == EnvLocal } // IsProductionEnvironment check the environment if it is production. func (c *Config) IsProductionEnvironment() bool { return c.Env == EnvProd } // IsNotProductionEnvironment check the environment if it is not production. func (c *Config) IsNotProductionEnvironment() bool { return c.Env != EnvProd } func (c *Config) IsAllowConfigModification() bool { return !c.ProhibitConfigModification } // URLRemovePrefix remove prefix from the given url. func (c *Config) URLRemovePrefix(url string) string { if url == c.prefix { return "/" } if c.prefix == "/" { return url } return strings.Replace(url, c.prefix, "", 1) } // Index return the index url without prefix. func (c *Config) Index() string { if c.IndexUrl == "" { return "/" } if c.IndexUrl[0] != '/' { return "/" + c.IndexUrl } return c.IndexUrl } // Prefix return the prefix. func (c *Config) Prefix() string { return c.prefix } // AssertPrefix return the prefix of assert. func (c *Config) AssertPrefix() string { if c.prefix == "/" { return "" } return c.prefix } func (c *Config) AddUpdateProcessFn(fn UpdateConfigProcessFn) *Config { c.UpdateProcessFn = fn return c } // PrefixFixSlash return the prefix fix the slash error. func (c *Config) PrefixFixSlash() string { if c.UrlPrefix == "/" { return "" } if c.UrlPrefix != "" && c.UrlPrefix[0] != '/' { return "/" + c.UrlPrefix } return c.UrlPrefix } func (c *Config) Copy() *Config { c.lock.RLock() defer c.lock.RUnlock() var ( newCfg = new(Config) srcType = reflect.TypeOf(c).Elem() srcVal = reflect.ValueOf(c).Elem() distType = reflect.TypeOf(newCfg).Elem() distVal = reflect.ValueOf(newCfg).Elem() ) for i := 0; i < distType.NumField(); i++ { v := distVal.Field(i) if distType.Field(i).Type.String() == "config.DatabaseList" { newCfg.Databases = c.Databases.Copy() } else if v.CanInterface() { for j := 0; j < srcType.NumField(); j++ { if distType.Field(i).Name == srcType.Field(j).Name { v.Set(reflect.ValueOf(srcVal.Field(i).Interface())) break } } } } newCfg.prefix = c.prefix return newCfg } func (c *Config) ToMap() map[string]string { c.lock.RLock() defer c.lock.RUnlock() var ( m = make(map[string]string) rType = reflect.TypeOf(c).Elem() rVal = reflect.ValueOf(c).Elem() ) for i := 0; i < rType.NumField(); i++ { v := rVal.Field(i) if !v.CanInterface() { continue } t := rType.Field(i) keyName := t.Tag.Get("json") if keyName == "-" { continue } keyName = keyName[:len(keyName)-10] switch t.Type.Kind() { case reflect.Bool: m[keyName] = strconv.FormatBool(v.Bool()) case reflect.String: if keyName == "prefix" { keyName = "url_prefix" } else if keyName == "index" { keyName = "index_url" } else if keyName == "info_log" || keyName == "error_log" || keyName == "access_log" { keyName += "_path" } m[keyName] = v.String() case reflect.Int: m[keyName] = fmt.Sprintf("%d", v.Int()) case reflect.Struct: switch t.Type.String() { case "config.PageAnimation": m["animation_type"] = c.Animation.Type m["animation_duration"] = fmt.Sprintf("%.2f", c.Animation.Duration) m["animation_delay"] = fmt.Sprintf("%.2f", c.Animation.Delay) case "config.Logger": m["logger_rotate_max_size"] = strconv.Itoa(c.Logger.Rotate.MaxSize) m["logger_rotate_max_backups"] = strconv.Itoa(c.Logger.Rotate.MaxBackups) m["logger_rotate_max_age"] = strconv.Itoa(c.Logger.Rotate.MaxAge) m["logger_rotate_compress"] = strconv.FormatBool(c.Logger.Rotate.Compress) m["logger_encoder_time_key"] = c.Logger.Encoder.TimeKey m["logger_encoder_level_key"] = c.Logger.Encoder.LevelKey m["logger_encoder_name_key"] = c.Logger.Encoder.NameKey m["logger_encoder_caller_key"] = c.Logger.Encoder.CallerKey m["logger_encoder_message_key"] = c.Logger.Encoder.MessageKey m["logger_encoder_stacktrace_key"] = c.Logger.Encoder.StacktraceKey m["logger_encoder_level"] = c.Logger.Encoder.Level m["logger_encoder_time"] = c.Logger.Encoder.Time m["logger_encoder_duration"] = c.Logger.Encoder.Duration m["logger_encoder_caller"] = c.Logger.Encoder.Caller m["logger_encoder_encoding"] = c.Logger.Encoder.Encoding m["logger_level"] = strconv.Itoa(int(c.Logger.Level)) case "config.DatabaseList": m["databases"] = utils.JSON(v.Interface()) case "config.FileUploadEngine": m["file_upload_engine"] = c.FileUploadEngine.JSON() } case reflect.Map: if t.Type.String() == "config.ExtraInfo" { if len(c.Extra) == 0 { m["extra"] = "" } else { m["extra"] = utils.JSON(c.Extra) } } default: m[keyName] = utils.JSON(v.Interface()) } } return m } func (c *Config) Update(m map[string]string) error { c.lock.Lock() defer c.lock.Unlock() rType := reflect.TypeOf(c).Elem() rVal := reflect.ValueOf(c).Elem() for i := 0; i < rType.NumField(); i++ { v := rVal.Field(i) if !v.CanInterface() { continue } t := rType.Field(i) keyName := t.Tag.Get("json") if keyName == "-" { continue } keyName = keyName[:len(keyName)-10] switch t.Type.Kind() { case reflect.Bool: if mv, ok := m[keyName]; ok { v.Set(reflect.ValueOf(utils.ParseBool(mv))) } case reflect.String: if t.Type.String() == "template.HTML" { if mv, ok := m[keyName]; ok { v.Set(reflect.ValueOf(template.HTML(mv))) } continue } if keyName == "prefix" { keyName = "url_prefix" } else if keyName == "index" { keyName = "index_url" } else if keyName == "info_log" || keyName == "error_log" || keyName == "access_log" { keyName += "_path" } if mv, ok := m[keyName]; ok { if keyName == "info_log" || keyName == "error_log" || keyName == "access_log" { v.Set(reflect.ValueOf(utils.SetDefault(mv, v.String(), v.String()))) } else if keyName == "app_id" { v.Set(reflect.ValueOf(utils.SetDefault(mv, "", v.String()))) } else if keyName == "color_scheme" { if m["theme"] == "adminlte" { v.Set(reflect.ValueOf(mv)) } } else { v.Set(reflect.ValueOf(mv)) } } case reflect.Int: ses, _ := strconv.Atoi(m[keyName]) if ses != 0 { v.Set(reflect.ValueOf(ses)) } case reflect.Struct: switch t.Type.String() { case "config.PageAnimation": c.Animation.Type = m["animation_type"] c.Animation.Duration = utils.ParseFloat32(m["animation_duration"]) c.Animation.Delay = utils.ParseFloat32(m["animation_delay"]) case "config.Logger": c.Logger.Rotate.MaxSize, _ = strconv.Atoi(m["logger_rotate_max_size"]) c.Logger.Rotate.MaxBackups, _ = strconv.Atoi(m["logger_rotate_max_backups"]) c.Logger.Rotate.MaxAge, _ = strconv.Atoi(m["logger_rotate_max_age"]) c.Logger.Rotate.Compress = utils.ParseBool(m["logger_rotate_compress"]) c.Logger.Encoder.Encoding = m["logger_encoder_encoding"] loggerLevel, _ := strconv.Atoi(m["logger_level"]) c.Logger.Level = int8(loggerLevel) if c.Logger.Encoder.Encoding == "json" { c.Logger.Encoder.TimeKey = m["logger_encoder_time_key"] c.Logger.Encoder.LevelKey = m["logger_encoder_level_key"] c.Logger.Encoder.NameKey = m["logger_encoder_name_key"] c.Logger.Encoder.CallerKey = m["logger_encoder_caller_key"] c.Logger.Encoder.MessageKey = m["logger_encoder_message_key"] c.Logger.Encoder.StacktraceKey = m["logger_encoder_stacktrace_key"] c.Logger.Encoder.Level = m["logger_encoder_level"] c.Logger.Encoder.Time = m["logger_encoder_time"] c.Logger.Encoder.Duration = m["logger_encoder_duration"] c.Logger.Encoder.Caller = m["logger_encoder_caller"] } initLogger(c) case "config.FileUploadEngine": c.FileUploadEngine = GetFileUploadEngineFromJSON(m["file_upload_engine"]) } case reflect.Map: if t.Type.String() == "config.ExtraInfo" && m["extra"] != "" { var extra = make(map[string]interface{}) _ = json.Unmarshal([]byte(m["extra"]), &extra) c.Extra = extra } } } return nil } // eraseSens erase sensitive info. func (c *Config) EraseSens() *Config { for key := range c.Databases { c.Databases[key] = Database{ Driver: c.Databases[key].Driver, } } return c } var ( _global = new(Config) count uint32 initializeLock sync.Mutex ) // ReadFromJson read the Config from a JSON file. func ReadFromJson(path string) Config { jsonByte, err := os.ReadFile(path) if err != nil { panic(err) } var cfg Config err = json.Unmarshal(jsonByte, &cfg) if err != nil { panic(err) } return cfg } // ReadFromYaml read the Config from a YAML file. func ReadFromYaml(path string) Config { jsonByte, err := os.ReadFile(path) if err != nil { panic(err) } var cfg Config err = yaml.Unmarshal(jsonByte, &cfg) if err != nil { panic(err) } return cfg } // ReadFromINI read the Config from a INI file. func ReadFromINI(path string) Config { iniCfg, err := ini.Load(path) if err != nil { panic(err) } var cfg = Config{ Databases: make(DatabaseList), } err = iniCfg.MapTo(&cfg) if err != nil { panic(err) } for _, child := range iniCfg.ChildSections("database") { var d Database err = child.MapTo(&d) if err != nil { panic(err) } cfg.Databases[child.Name()[9:]] = d } return cfg } func SetDefault(cfg *Config) *Config { cfg.Title = utils.SetDefault(cfg.Title, "", "GoAdmin") cfg.LoginTitle = utils.SetDefault(cfg.LoginTitle, "", "GoAdmin") cfg.Logo = template.HTML(utils.SetDefault(string(cfg.Logo), "", "GoAdmin")) cfg.MiniLogo = template.HTML(utils.SetDefault(string(cfg.MiniLogo), "", "GA")) cfg.Theme = utils.SetDefault(cfg.Theme, "", "adminlte") cfg.IndexUrl = utils.SetDefault(cfg.IndexUrl, "", "/info/manager") cfg.LoginUrl = utils.SetDefault(cfg.LoginUrl, "", "/login") cfg.AuthUserTable = utils.SetDefault(cfg.AuthUserTable, "", "goadmin_users") cfg.ColorScheme = utils.SetDefault(cfg.ColorScheme, "", "skin-black") cfg.AssetRootPath = utils.SetDefault(cfg.AssetRootPath, "", "./public/") cfg.AssetRootPath = filepath.ToSlash(cfg.AssetRootPath) cfg.FileUploadEngine.Name = utils.SetDefault(cfg.FileUploadEngine.Name, "", "local") cfg.Env = utils.SetDefault(cfg.Env, "", EnvProd) if cfg.SessionLifeTime == 0 { // default two hours cfg.SessionLifeTime = 7200 } cfg.AppID = utils.Uuid(12) if cfg.UrlPrefix == "" { cfg.prefix = "/" } else if cfg.UrlPrefix[0] != '/' { cfg.prefix = "/" + cfg.UrlPrefix } else { cfg.prefix = cfg.UrlPrefix } cfg.URLFormat = cfg.URLFormat.SetDefault() return cfg } // Initialize initialize the config. func Initialize(cfg *Config) *Config { initializeLock.Lock() defer initializeLock.Unlock() if atomic.LoadUint32(&count) != 0 { panic("can not initialize config twice") } atomic.StoreUint32(&count, 1) initLogger(SetDefault(cfg)) _global = cfg return _global } func initLogger(cfg *Config) { logger.InitWithConfig(logger.Config{ InfoLogOff: cfg.InfoLogOff, ErrorLogOff: cfg.ErrorLogOff, AccessLogOff: cfg.AccessLogOff, SqlLogOpen: cfg.SqlLog, InfoLogPath: cfg.InfoLogPath, ErrorLogPath: cfg.ErrorLogPath, AccessLogPath: cfg.AccessLogPath, AccessAssetsLogOff: cfg.AccessAssetsLogOff, Rotate: logger.RotateCfg{ MaxSize: cfg.Logger.Rotate.MaxSize, MaxBackups: cfg.Logger.Rotate.MaxBackups, MaxAge: cfg.Logger.Rotate.MaxAge, Compress: cfg.Logger.Rotate.Compress, }, Encode: logger.EncoderCfg{ TimeKey: cfg.Logger.Encoder.TimeKey, LevelKey: cfg.Logger.Encoder.LevelKey, NameKey: cfg.Logger.Encoder.NameKey, CallerKey: cfg.Logger.Encoder.CallerKey, MessageKey: cfg.Logger.Encoder.MessageKey, StacktraceKey: cfg.Logger.Encoder.StacktraceKey, Level: cfg.Logger.Encoder.Level, Time: cfg.Logger.Encoder.Time, Duration: cfg.Logger.Encoder.Duration, Caller: cfg.Logger.Encoder.Caller, Encoding: cfg.Logger.Encoder.Encoding, }, Debug: cfg.Debug, Level: cfg.Logger.Level, }) } // AssertPrefix return the prefix of assert. func AssertPrefix() string { return _global.AssertPrefix() } // GetIndexURL get the index url with prefix. func GetIndexURL() string { return _global.GetIndexURL() } // IsProductionEnvironment check the environment if it is production. func IsProductionEnvironment() bool { return _global.IsProductionEnvironment() } // IsNotProductionEnvironment check the environment if it is not production. func IsNotProductionEnvironment() bool { return _global.IsNotProductionEnvironment() } // URLRemovePrefix remove prefix from the given url. func URLRemovePrefix(url string) string { return _global.URLRemovePrefix(url) } func Url(suffix string) string { return _global.Url(suffix) } func GetURLFormats() URLFormat { return _global.URLFormat } // Prefix return the prefix. func Prefix() string { return _global.prefix } // PrefixFixSlash return the prefix fix the slash error. func PrefixFixSlash() string { return _global.PrefixFixSlash() } // Get gets the config. func Get() *Config { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Copy().EraseSens() } // Getter methods // ============================ func GetDatabases() DatabaseList { var list = make(DatabaseList, len(_global.Databases)) for key := range _global.Databases { list[key] = Database{ Driver: _global.Databases[key].Driver, DriverMode: _global.Databases[key].DriverMode, } } return list } func GetDomain() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Domain } func GetLanguage() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Language } func GetAppID() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.AppID } func GetUrlPrefix() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.UrlPrefix } func GetOpenAdminApi() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.OpenAdminApi } func GetAllowDelOperationLog() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.AllowDelOperationLog } func GetOperationLogOff() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.OperationLogOff } func GetCustom500HTML() template.HTML { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Custom500HTML } func GetCustom404HTML() template.HTML { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Custom404HTML } func GetCustom403HTML() template.HTML { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Custom403HTML } func GetTheme() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Theme } func GetStore() Store { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Store } func GetTitle() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Title } func GetAssetRootPath() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.AssetRootPath } func GetLogo() template.HTML { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Logo } func GetSiteOff() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.SiteOff } func GetMiniLogo() template.HTML { _global.lock.RLock() defer _global.lock.RUnlock() return _global.MiniLogo } func GetIndexUrl() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.IndexUrl } func GetLoginUrl() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.LoginUrl } func GetDebug() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Debug } func GetEnv() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Env } func GetInfoLogPath() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.InfoLogPath } func GetErrorLogPath() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.ErrorLogPath } func GetAccessLogPath() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.AccessLogPath } func GetSqlLog() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.SqlLog } func GetAccessLogOff() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.AccessLogOff } func GetInfoLogOff() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.InfoLogOff } func GetErrorLogOff() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.ErrorLogOff } func GetColorScheme() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.ColorScheme } func GetSessionLifeTime() int { _global.lock.RLock() defer _global.lock.RUnlock() return _global.SessionLifeTime } func GetAssetUrl() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.AssetUrl } func GetFileUploadEngine() FileUploadEngine { _global.lock.RLock() defer _global.lock.RUnlock() return _global.FileUploadEngine } func GetCustomHeadHtml() template.HTML { _global.lock.RLock() defer _global.lock.RUnlock() return _global.CustomHeadHtml } func GetCustomFootHtml() template.HTML { _global.lock.RLock() defer _global.lock.RUnlock() return _global.CustomFootHtml } func GetFooterInfo() template.HTML { _global.lock.RLock() defer _global.lock.RUnlock() return _global.FooterInfo } func GetLoginTitle() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.LoginTitle } func GetLoginLogo() template.HTML { _global.lock.RLock() defer _global.lock.RUnlock() return _global.LoginLogo } func GetAuthUserTable() string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.AuthUserTable } func GetExtra() map[string]interface{} { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Extra } func GetAnimation() PageAnimation { _global.lock.RLock() defer _global.lock.RUnlock() return _global.Animation } func GetNoLimitLoginIP() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.NoLimitLoginIP } func GetHideVisitorUserCenterEntrance() bool { _global.lock.RLock() defer _global.lock.RUnlock() return _global.HideVisitorUserCenterEntrance } func GetExcludeThemeComponents() []string { _global.lock.RLock() defer _global.lock.RUnlock() return _global.ExcludeThemeComponents } type Service struct { C *Config } func (s *Service) Name() string { return "config" } func SrvWithConfig(c *Config) *Service { return &Service{c} } func GetService(s interface{}) *Config { if srv, ok := s.(*Service); ok { return srv.C } panic("wrong service") } ================================================ FILE: modules/config/config.ini ================================================ domain = localhost prefix = admin language = en index = / debug = true open_admin_api = true color_scheme = skin-black [database.default] host = 127.0.0.1 port = 5432 user = postgres pwd = root name = go-admin-test max_idle_con = 50 max_open_con = 150 driver = postgresql [store] path = ./uploads prefix = uploads ================================================ FILE: modules/config/config.yaml ================================================ --- database: default: host: 127.0.0.1 port: '1433' user: sa pwd: Aa123456 name: goadmin max_idle_con: 50 max_open_con: 150 driver: mssql domain: localhost prefix: admin store: path: "./uploads" prefix: uploads language: en index: "/" debug: true open_admin_api: true color_scheme: skin-black ================================================ FILE: modules/config/config_test.go ================================================ package config import ( "fmt" "reflect" "testing" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/stretchr/testify/assert" ) func TestConfig_GetIndexUrl(t *testing.T) { Initialize(&Config{ UrlPrefix: "admin", IndexUrl: "/", }) assert.Equal(t, Get().GetIndexURL(), "/admin") testSetCfg(&Config{ UrlPrefix: "/admin", IndexUrl: "/", }) assert.Equal(t, Get().GetIndexURL(), "/admin") testSetCfg(&Config{ UrlPrefix: "/admin", IndexUrl: "/", }) assert.Equal(t, Get().GetIndexURL(), "/admin") } func TestConfig_Index(t *testing.T) { testSetCfg(&Config{ UrlPrefix: "admin", IndexUrl: "/", }) assert.Equal(t, Get().Index(), "/") } func TestConfig_Prefix(t *testing.T) { testSetCfg(&Config{ UrlPrefix: "admin", IndexUrl: "/", }) assert.Equal(t, Get().Prefix(), "/admin") testSetCfg(&Config{ UrlPrefix: "/admin", IndexUrl: "/", }) assert.Equal(t, Get().Prefix(), "/admin") } func TestConfig_Url(t *testing.T) { testSetCfg(&Config{ UrlPrefix: "admin", IndexUrl: "/", }) assert.Equal(t, Get().Url("/info/user"), "/admin/info/user") testSetCfg(&Config{ UrlPrefix: "/admin", IndexUrl: "/", }) assert.Equal(t, Get().Url("/info/user"), "/admin/info/user") assert.Equal(t, Get().Url("/info/user") != "/admin/info/user/", true) } func TestConfig_UrlRemovePrefix(t *testing.T) { testSetCfg(&Config{ UrlPrefix: "/admin", IndexUrl: "/", }) assert.Equal(t, Get().URLRemovePrefix("/admin/info/user"), "/info/user") } func TestConfig_PrefixFixSlash(t *testing.T) { testSetCfg(&Config{ UrlPrefix: "/admin", IndexUrl: "/", }) assert.Equal(t, Get().PrefixFixSlash(), "/admin") testSetCfg(&Config{ UrlPrefix: "admin", IndexUrl: "/", }) assert.Equal(t, Get().PrefixFixSlash(), "/admin") } func TestSet(t *testing.T) { testSetCfg(&Config{Theme: "abc"}) testSetCfg(&Config{Theme: "bcd"}) assert.Equal(t, Get().Theme, "bcd") } func TestStore_URL(t *testing.T) { testSetCfg(&Config{ Store: Store{ Prefix: "/file", Path: "./uploads", }, }) assert.Equal(t, Get().Store.URL("/xxxxxx.png"), "/file/xxxxxx.png") testSetCfg(&Config{ Store: Store{ Prefix: "http://xxxxx.com/xxxx/file", Path: "./uploads", }, }) assert.Equal(t, Get().Store.URL("/xxxxxx.png"), "http://xxxxx.com/xxxx/file/xxxxxx.png") testSetCfg(&Config{ Store: Store{ Prefix: "/file", Path: "./uploads", }, }) assert.Equal(t, Get().Store.URL("http://xxxxx.com/xxxx/file/xxxx.png"), "http://xxxxx.com/xxxx/file/xxxx.png") } func TestDatabase_ParamStr(t *testing.T) { cfg := Database{ Driver: DriverMysql, Params: map[string]string{ "parseTime": "true", }, } assert.Equal(t, cfg.ParamStr(), "?charset=utf8mb4&parseTime=true") } func TestReadFromYaml(t *testing.T) { cfg := ReadFromYaml("./config.yaml") assert.Equal(t, cfg.Databases.GetDefault().Driver, "mssql") assert.Equal(t, cfg.Domain, "localhost") assert.Equal(t, cfg.UrlPrefix, "admin") assert.Equal(t, cfg.Store.Path, "./uploads") assert.Equal(t, cfg.IndexUrl, "/") assert.Equal(t, cfg.Debug, true) assert.Equal(t, cfg.OpenAdminApi, true) assert.Equal(t, cfg.ColorScheme, "skin-black") } func TestReadFromINI(t *testing.T) { cfg := ReadFromINI("./config.ini") assert.Equal(t, cfg.Databases.GetDefault().Driver, "postgresql") assert.Equal(t, cfg.Domain, "localhost") assert.Equal(t, cfg.UrlPrefix, "admin") assert.Equal(t, cfg.Store.Path, "./uploads") assert.Equal(t, cfg.IndexUrl, "/") assert.Equal(t, cfg.Debug, true) assert.Equal(t, cfg.OpenAdminApi, true) assert.Equal(t, cfg.ColorScheme, "skin-black") } func testSetCfg(cfg *Config) { count = 0 Initialize(cfg) } func TestUpdate(t *testing.T) { m := map[string]string{ "access_assets_log_off": `true`, "access_log_off": `false`, "access_log_path": "", "allow_del_operation_log": `false`, "animation": `{"type":"fadeInUp","duration":0,"delay":0}`, "animation_delay": `0.00`, "animation_duration": `0`, "animation_type": `fadeInUp`, "app_id": `70rv3KwjwjXE`, "asset_root_path": `./public/`, "asset_url": "", "auth_user_table": `goadmin_users`, "bootstrap_file_path": `./../datamodel/bootstrap.go`, "color_scheme": `skin-black`, "custom_403_html": "", "custom_404_html": "", "custom_500_html": "", "custom_foot_html": "", "custom_head_html": ` `, "databases": `{"default":{"host":"127.0.0.1","port":"3306","user":"root","pwd":"root","name":"godmin","max_idle_con":50,"max_open_con":150,"driver":"mysql","file":"","dsn":""}}`, "debug": `true`, "domain": "", "env": `test`, "error_log_off": `false`, "error_log_path": "", "exclude_theme_components": `null`, "extra": "", "file_upload_engine": `{"name":"local","config":null}`, "footer_info": "", "go_mod_file_path": "", "hide_app_info_entrance": `false`, "hide_config_center_entrance": `false`, "hide_plugin_entrance": `false`, "hide_tool_entrance": `false`, "hide_visitor_user_center_entrance": `false`, "index_url": `/`, "info_log_off": `false`, "info_log_path": "", "language": `zh`, "logger_encoder_caller": `full`, "logger_encoder_caller_key": `caller`, "logger_encoder_duration": `string`, "logger_encoder_encoding": `console`, "logger_encoder_level": `capitalColor`, "logger_encoder_level_key": `level`, "logger_encoder_message_key": `msg`, "logger_encoder_name_key": `logger`, "logger_encoder_stacktrace_key": `stacktrace`, "logger_encoder_time": `iso8601`, "logger_encoder_time_key": `ts`, "logger_level": `0`, "logger_rotate_compress": `false`, "logger_rotate_max_age": `30`, "logger_rotate_max_backups": `5`, "logger_rotate_max_size": `10`, "login_logo": "", "login_title": `GoAdmin`, "login_url": `/login`, "logo": `GoAdmin`, "mini_logo": `GA`, "no_limit_login_ip": `false`, "open_admin_api": `false`, "operation_log_off": `false`, "plugin_file_path": `/go/src/github.com/GoAdminGroup/go-admin/examples/gin/plugins.go`, "session_life_time": `7200`, "site_off": `false`, "sql_log": `true`, "store": `{"path":"./uploads","prefix":"uploads"}`, "theme": `sword`, "title": `GoAdmin`, "url_prefix": `admin`, } c := &Config{} c2 := &Config{} if c.Update(m) == nil { if c.Language != c2.Language || c.Domain != c2.Domain || c.Theme != c2.Theme || c.Title != c2.Title || c.Logo != c2.Logo || c.MiniLogo != c2.MiniLogo || c.Debug != c2.Debug || c.SiteOff != c2.SiteOff || c.AccessLogOff != c2.AccessLogOff || c.InfoLogOff != c2.InfoLogOff || c.ErrorLogOff != c2.ErrorLogOff || c.AccessAssetsLogOff != c2.AccessAssetsLogOff || c.InfoLogPath != c2.InfoLogPath || c.ErrorLogPath != c2.ErrorLogPath || c.AccessLogPath != c2.AccessLogPath || c.SqlLog != c2.SqlLog || c.Logger.Rotate.MaxSize != c2.Logger.Rotate.MaxSize || c.Logger.Rotate.MaxBackups != c2.Logger.Rotate.MaxBackups || c.Logger.Rotate.MaxAge != c2.Logger.Rotate.MaxAge || c.Logger.Rotate.Compress != c2.Logger.Rotate.Compress || c.Logger.Encoder.Encoding != c2.Logger.Encoder.Encoding || c.Logger.Level != c2.Logger.Level || c.Logger.Encoder.TimeKey != c2.Logger.Encoder.TimeKey || c.Logger.Encoder.LevelKey != c2.Logger.Encoder.LevelKey || c.Logger.Encoder.NameKey != c2.Logger.Encoder.NameKey || c.Logger.Encoder.CallerKey != c2.Logger.Encoder.CallerKey || c.Logger.Encoder.MessageKey != c2.Logger.Encoder.MessageKey || c.Logger.Encoder.StacktraceKey != c2.Logger.Encoder.StacktraceKey || c.Logger.Encoder.Level != c2.Logger.Encoder.Level || c.Logger.Encoder.Time != c2.Logger.Encoder.Time || c.Logger.Encoder.Duration != c2.Logger.Encoder.Duration || c.Logger.Encoder.Caller != c2.Logger.Encoder.Caller || c.ColorScheme != c2.ColorScheme || c.SessionLifeTime != c2.SessionLifeTime || c.CustomHeadHtml != c2.CustomHeadHtml || c.CustomFootHtml != c2.CustomFootHtml || c.Custom404HTML != c2.Custom404HTML || c.Custom403HTML != c2.Custom403HTML || c.Custom500HTML != c2.Custom500HTML || c.BootstrapFilePath != c2.BootstrapFilePath || c.GoModFilePath != c2.GoModFilePath || c.FooterInfo != c2.FooterInfo || c.LoginTitle != c2.LoginTitle || c.AssetUrl != c2.AssetUrl || c.LoginLogo != c2.LoginLogo || c.NoLimitLoginIP != c2.NoLimitLoginIP || c.AllowDelOperationLog != c2.AllowDelOperationLog || c.OperationLogOff != c2.OperationLogOff || c.HideConfigCenterEntrance != c2.HideConfigCenterEntrance || c.HideAppInfoEntrance != c2.HideAppInfoEntrance || c.HideToolEntrance != c2.HideToolEntrance || c.HidePluginEntrance != c2.HidePluginEntrance || c.FileUploadEngine.Name != c2.FileUploadEngine.Name || c.Animation.Type != c2.Animation.Type || c.Animation.Duration != c2.Animation.Duration || c.Animation.Delay != c2.Animation.Delay || !reflect.DeepEqual(c.Extra, c2.Extra) { panic("c.Extra") } } } func TestToMap(t *testing.T) { c := &Config{ UrlPrefix: "/admin", IndexUrl: "/", MiniLogo: "", Animation: PageAnimation{ Type: "12313213", }, SessionLifeTime: 40, ExcludeThemeComponents: []string{"asdfas", "sadfasf"}, } m := c.ToMap() fmt.Println(m) fmt.Println(m["prefix"], m["animation_type"], m["mini_logo"]) arr := []string{ "language", "databases", "domain", "url_prefix", "theme", "store", "title", "logo", "mini_logo", "index_url", "site_off", "login_url", "debug", "env", "open_admin_api", "hide_visitor_user_center_entrance", "info_log_path", "error_log_path", "access_log_path", "sql_log", "access_log_off", "info_log_off", "error_log_off", "access_assets_log_off", "logger_rotate_max_size", "logger_rotate_max_backups", "logger_rotate_max_age", "logger_rotate_compress", "logger_encoder_time_key", "logger_encoder_level_key", "logger_encoder_name_key", "logger_encoder_caller_key", "logger_encoder_message_key", "logger_encoder_stacktrace_key", "logger_encoder_level", "logger_encoder_time", "logger_encoder_duration", "logger_encoder_caller", "logger_encoder_encoding", "logger_level", "color_scheme", "session_life_time", "asset_url", "file_upload_engine", "custom_head_html", "custom_foot_html", "custom_404_html", "custom_403_html", "custom_500_html", "bootstrap_file_path", "go_mod_file_path", "footer_info", "app_id", "login_title", "login_logo", "auth_user_table", "exclude_theme_components", "extra", "animation_type", "animation_duration", "animation_delay", "no_limit_login_ip", "allow_del_operation_log", "operation_log_off", "hide_config_center_entrance", "hide_app_info_entrance", "hide_tool_entrance", "hide_plugin_entrance", "asset_root_path", } for key := range m { if !utils.InArray(arr, key) { panic(key) } } fmt.Println(len(arr), len(m)) } ================================================ FILE: modules/constant/constant.go ================================================ package constant const ( // PjaxHeader is default pjax http header key. PjaxHeader = "X-PJAX" // PjaxUrlHeader is default pjax url http header key. PjaxUrlHeader = "X-PJAX-Url" // Title is default title of the project. Title = "GoAdmin" ContextNodeNeedAuth = "need_auth" IframeKey = "__goadmin_iframe" IframeIDKey = "__goadmin_iframe_id" ) ================================================ FILE: modules/db/base.go ================================================ package db import ( "database/sql" "errors" "sync" "github.com/GoAdminGroup/go-admin/modules/config" "xorm.io/xorm" ) // Base is a common Connection. type Base struct { DbList map[string]*sql.DB Once sync.Once Configs config.DatabaseList } // Close implements the method Connection.Close. func (db *Base) Close() []error { errs := make([]error, 0) for _, d := range db.DbList { errs = append(errs, d.Close()) } return errs } // GetDB implements the method Connection.GetDB. func (db *Base) GetDB(key string) *sql.DB { return db.DbList[key] } func (db *Base) CreateDB(name string, beans ...interface{}) error { cfg := db.GetConfig(name) if cfg.Driver == "" { return errors.New("wrong connection name") } engine, err := xorm.NewEngine(cfg.Driver, cfg.GetDSN()) if err != nil { return err } defer func() { _ = engine.Close() }() err = engine.Sync(beans...) if err != nil { return err } return nil } func (db *Base) GetConfig(name string) config.Database { return db.Configs[name] } ================================================ FILE: modules/db/connection.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package db import ( "database/sql" "fmt" "strings" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/service" ) const ( // DriverMysql is a const value of mysql driver. DriverMysql = "mysql" // DriverSqlite is a const value of sqlite driver. DriverSqlite = "sqlite" // DriverPostgresql is a const value of postgresql driver. DriverPostgresql = "postgresql" // DriverMssql is a const value of mssql driver. DriverMssql = "mssql" // DriverOceanBase is a const value of oceanbase driver. DriverOceanBase = "oceanbase" ) // Connection is a connection handler of database. type Connection interface { // Query is the query method of sql. Query(query string, args ...interface{}) ([]map[string]interface{}, error) // Exec is the exec method of sql. Exec(query string, args ...interface{}) (sql.Result, error) // QueryWithConnection is the query method with given connection of sql. QueryWithConnection(conn, query string, args ...interface{}) ([]map[string]interface{}, error) QueryWithTx(tx *sql.Tx, query string, args ...interface{}) ([]map[string]interface{}, error) QueryWith(tx *sql.Tx, conn, query string, args ...interface{}) ([]map[string]interface{}, error) // ExecWithConnection is the exec method with given connection of sql. ExecWithConnection(conn, query string, args ...interface{}) (sql.Result, error) ExecWithTx(tx *sql.Tx, query string, args ...interface{}) (sql.Result, error) ExecWith(tx *sql.Tx, conn, query string, args ...interface{}) (sql.Result, error) BeginTxWithReadUncommitted() *sql.Tx BeginTxWithReadCommitted() *sql.Tx BeginTxWithRepeatableRead() *sql.Tx BeginTx() *sql.Tx BeginTxWithLevel(level sql.IsolationLevel) *sql.Tx BeginTxWithReadUncommittedAndConnection(conn string) *sql.Tx BeginTxWithReadCommittedAndConnection(conn string) *sql.Tx BeginTxWithRepeatableReadAndConnection(conn string) *sql.Tx BeginTxAndConnection(conn string) *sql.Tx BeginTxWithLevelAndConnection(conn string, level sql.IsolationLevel) *sql.Tx // InitDB initialize the database connections. InitDB(cfg map[string]config.Database) Connection // GetName get the connection name. Name() string Close() []error GetDelimiter() string GetDelimiter2() string GetDelimiters() []string GetDB(key string) *sql.DB GetConfig(name string) config.Database CreateDB(name string, beans ...interface{}) error } // GetConnectionByDriver return the Connection by given driver name. func GetConnectionByDriver(driver string) Connection { switch driver { case "mysql": return GetMysqlDB() case "mssql": return GetMssqlDB() case "sqlite": return GetSqliteDB() case "postgresql": return GetPostgresqlDB() case "oceanbase": return GetOceanBaseDB() default: panic("driver not found!") } } func GetConnectionFromService(srv interface{}) Connection { if v, ok := srv.(Connection); ok { return v } panic("wrong service") } func GetConnection(srvs service.List) Connection { if v, ok := srvs.Get(config.GetDatabases().GetDefault().Driver).(Connection); ok { return v } panic("wrong service") } func GetAggregationExpression(driver, field, headField, delimiter string) string { switch driver { case "postgresql": return fmt.Sprintf("string_agg(%s::character varying, '%s') as %s", field, delimiter, headField) case "mysql": return fmt.Sprintf("group_concat(%s separator '%s') as %s", field, delimiter, headField) case "sqlite": return fmt.Sprintf("group_concat(%s, '%s') as %s", field, delimiter, headField) case "mssql": return fmt.Sprintf("string_agg(%s, '%s') as [%s]", field, delimiter, headField) case "oceanbase": return fmt.Sprintf("group_concat(%s separator '%s') as %s", field, delimiter, headField) default: panic("wrong driver") } } const ( INSERT = 0 DELETE = 1 UPDATE = 2 QUERY = 3 ) var ignoreErrors = [...][]string{ // insert { "LastInsertId is not supported", "There is no generated identity value", "LastInsertId is not supported by this driver", }, // delete { "no affect", }, // update { "LastInsertId is not supported", "There is no generated identity value", "no affect", "LastInsertId is not supported by this driver", }, // query { "LastInsertId is not supported", "There is no generated identity value", "no affect", "out of index", "LastInsertId is not supported by this driver", }, } func CheckError(err error, t int) bool { if err == nil { return false } for _, msg := range ignoreErrors[t] { if strings.Contains(err.Error(), msg) { return false } } return true } ================================================ FILE: modules/db/converter.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package db import ( "database/sql" ) // SetColVarType set the column type. func SetColVarType(colVar *[]interface{}, i int, typeName string) { dt := DT(typeName) switch { case Contains(dt, BoolTypeList): var s sql.NullBool (*colVar)[i] = &s case Contains(dt, IntTypeList): var s sql.NullInt64 (*colVar)[i] = &s case Contains(dt, FloatTypeList): var s sql.NullFloat64 (*colVar)[i] = &s case Contains(dt, UintTypeList): var s []uint8 (*colVar)[i] = &s case Contains(dt, StringTypeList): var s sql.NullString (*colVar)[i] = &s default: var s interface{} (*colVar)[i] = &s } } // SetResultValue set the result value. func SetResultValue(result *map[string]interface{}, index string, colVar interface{}, typeName string) { dt := DT(typeName) switch { case Contains(dt, BoolTypeList): temp := *(colVar.(*sql.NullBool)) if temp.Valid { (*result)[index] = temp.Bool } else { (*result)[index] = nil } case Contains(dt, IntTypeList): temp := *(colVar.(*sql.NullInt64)) if temp.Valid { (*result)[index] = temp.Int64 } else { (*result)[index] = nil } case Contains(dt, FloatTypeList): temp := *(colVar.(*sql.NullFloat64)) if temp.Valid { (*result)[index] = temp.Float64 } else { (*result)[index] = nil } case Contains(dt, UintTypeList): (*result)[index] = *(colVar.(*[]uint8)) case Contains(dt, StringTypeList): temp := *(colVar.(*sql.NullString)) if temp.Valid { (*result)[index] = temp.String } else { (*result)[index] = nil } default: if colVar2, ok := colVar.(*interface{}); ok { if colVar, ok = (*colVar2).(int64); ok { (*result)[index] = colVar } else if colVar, ok = (*colVar2).(string); ok { (*result)[index] = colVar } else if colVar, ok = (*colVar2).(float64); ok { (*result)[index] = colVar } else if colVar, ok = (*colVar2).([]uint8); ok { (*result)[index] = colVar } else { (*result)[index] = colVar } } } } ================================================ FILE: modules/db/dialect/common.go ================================================ package dialect import "fmt" type commonDialect struct { delimiter string delimiter2 string } func (c commonDialect) Insert(comp *SQLComponent) string { comp.prepareInsert(c.delimiter, c.delimiter2) return comp.Statement } func (c commonDialect) Delete(comp *SQLComponent) string { comp.Statement = "delete from " + c.WrapTableName(comp) + comp.getWheres(c.delimiter, c.delimiter2) return comp.Statement } func (c commonDialect) Update(comp *SQLComponent) string { comp.prepareUpdate(c.delimiter, c.delimiter2) return comp.Statement } func (c commonDialect) Count(comp *SQLComponent) string { comp.prepareUpdate(c.delimiter, c.delimiter2) return comp.Statement } func (c commonDialect) Select(comp *SQLComponent) string { comp.Statement = "select " + comp.getFields(c.delimiter, c.delimiter2) + " from " + c.WrapTableName(comp) + comp.getJoins(c.delimiter, c.delimiter2) + comp.getWheres(c.delimiter, c.delimiter2) + comp.getGroupBy() + comp.getOrderBy() + comp.getLimit() + comp.getOffset() return comp.Statement } func (c commonDialect) ShowColumns(table string) string { return fmt.Sprintf("select * from information_schema.columns where table_name = '%s'", table) } func (c commonDialect) GetName() string { return "common" } func (c commonDialect) WrapTableName(comp *SQLComponent) string { return c.delimiter + comp.TableName + c.delimiter2 } func (c commonDialect) ShowTables() string { return "show tables" } func (c commonDialect) ShowColumnsWithComment(schema, table string) string { return "" } func (c commonDialect) GetDelimiter() string { return c.delimiter } func (c commonDialect) GetDelimiter2() string { return c.delimiter2 } func (c commonDialect) GetDelimiters() []string { return []string{c.delimiter, c.delimiter2} } ================================================ FILE: modules/db/dialect/dialect.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package dialect import ( "strings" "github.com/GoAdminGroup/go-admin/modules/config" ) // Dialect is methods set of different driver. type Dialect interface { // GetName get dialect's name GetName() string // ShowColumns show columns of specified table ShowColumns(table string) string // ShowColumnsWithComment show columns with coment of specified table ShowColumnsWithComment(schema, table string) string // ShowTables show tables of database ShowTables() string // Insert Insert(comp *SQLComponent) string // Delete Delete(comp *SQLComponent) string // Update Update(comp *SQLComponent) string // Select Select(comp *SQLComponent) string // GetDelimiter return the delimiter of Dialect. GetDelimiter() string } // GetDialect return the default Dialect. func GetDialect() Dialect { return GetDialectByDriver(config.GetDatabases().GetDefault().Driver) } // GetDialectByDriver return the Dialect of given driver. func GetDialectByDriver(driver string) Dialect { switch driver { case "mysql": return mysql{ commonDialect: commonDialect{delimiter: "`", delimiter2: "`"}, } case "mssql": return mssql{ commonDialect: commonDialect{delimiter: "[", delimiter2: "]"}, } case "postgresql": return postgresql{ commonDialect: commonDialect{delimiter: `"`, delimiter2: `"`}, } case "sqlite": return sqlite{ commonDialect: commonDialect{delimiter: "`", delimiter2: "`"}, } case "oceanbase": return oceanbase{ commonDialect: commonDialect{delimiter: "`", delimiter2: "`"}, } default: return commonDialect{delimiter: "`", delimiter2: "`"} } } // H is a shorthand of map. type H map[string]interface{} // SQLComponent is a sql components set. type SQLComponent struct { Fields []string Functions []string TableName string Wheres []Where Leftjoins []Join Args []interface{} Order string Offset string Limit string WhereRaws string UpdateRaws []RawUpdate Group string Statement string Values H } // Where contains the operation and field. type Where struct { Operation string Field string Qmark string } // Join contains the table and field and operation. type Join struct { Table string FieldA string Operation string FieldB string } // RawUpdate contains the expression and arguments. type RawUpdate struct { Expression string Args []interface{} } // ******************************* // internal help function // ******************************* func (sql *SQLComponent) getLimit() string { if sql.Limit == "" { return "" } return " limit " + sql.Limit + " " } func (sql *SQLComponent) getOffset() string { if sql.Offset == "" { return "" } return " offset " + sql.Offset + " " } func (sql *SQLComponent) getOrderBy() string { if sql.Order == "" { return "" } return " order by " + sql.Order + " " } func (sql *SQLComponent) getGroupBy() string { if sql.Group == "" { return "" } return " group by " + sql.Group + " " } func (sql *SQLComponent) getJoins(delimiter, delimiter2 string) string { if len(sql.Leftjoins) == 0 { return "" } joins := "" for _, join := range sql.Leftjoins { joins += " left join " + wrap(delimiter, delimiter2, join.Table) + " on " + sql.processLeftJoinField(join.FieldA, delimiter, delimiter2) + " " + join.Operation + " " + sql.processLeftJoinField(join.FieldB, delimiter, delimiter2) + " " } return joins } func (sql *SQLComponent) processLeftJoinField(field, delimiter, delimiter2 string) string { arr := strings.Split(field, ".") if len(arr) > 0 { return delimiter + arr[0] + delimiter2 + "." + delimiter + arr[1] + delimiter2 } return field } func (sql *SQLComponent) getFields(delimiter, delimiter2 string) string { if len(sql.Fields) == 0 { return "*" } fields := "" if len(sql.Leftjoins) == 0 { for k, field := range sql.Fields { if sql.Functions[k] != "" { fields += sql.Functions[k] + "(" + wrap(delimiter, delimiter2, field) + ")," } else { fields += wrap(delimiter, delimiter2, field) + "," } } } else { for _, field := range sql.Fields { arr := strings.Split(field, ".") if len(arr) > 1 { fields += wrap(delimiter, delimiter2, arr[0]) + "." + wrap(delimiter, delimiter2, arr[1]) + "," } else { fields += wrap(delimiter, delimiter2, field) + "," } } } return fields[:len(fields)-1] } func wrap(delimiter, delimiter2, field string) string { if field == "*" { return "*" } return delimiter + field + delimiter2 } func (sql *SQLComponent) getWheres(delimiter, delimiter2 string) string { if len(sql.Wheres) == 0 { if sql.WhereRaws != "" { return " where " + sql.WhereRaws } return "" } wheres := " where " var arr []string for _, where := range sql.Wheres { arr = strings.Split(where.Field, ".") if len(arr) > 1 { wheres += arr[0] + "." + wrap(delimiter, delimiter2, arr[1]) + " " + where.Operation + " " + where.Qmark + " and " } else { wheres += wrap(delimiter, delimiter2, where.Field) + " " + where.Operation + " " + where.Qmark + " and " } } if sql.WhereRaws != "" { return wheres + sql.WhereRaws } return wheres[:len(wheres)-5] } func (sql *SQLComponent) prepareUpdate(delimiter, delimiter2 string) { fields := "" args := make([]interface{}, 0) if len(sql.Values) != 0 { for key, value := range sql.Values { fields += wrap(delimiter, delimiter2, key) + " = ?, " args = append(args, value) } if len(sql.UpdateRaws) == 0 { fields = fields[:len(fields)-2] } else { for i := 0; i < len(sql.UpdateRaws); i++ { if i == len(sql.UpdateRaws)-1 { fields += sql.UpdateRaws[i].Expression + " " } else { fields += sql.UpdateRaws[i].Expression + "," } args = append(args, sql.UpdateRaws[i].Args...) } } sql.Args = append(args, sql.Args...) } else { if len(sql.UpdateRaws) == 0 { panic("prepareUpdate: wrong parameter") } else { for i := 0; i < len(sql.UpdateRaws); i++ { if i == len(sql.UpdateRaws)-1 { fields += sql.UpdateRaws[i].Expression + " " } else { fields += sql.UpdateRaws[i].Expression + "," } args = append(args, sql.UpdateRaws[i].Args...) } } sql.Args = append(args, sql.Args...) } sql.Statement = "update " + delimiter + sql.TableName + delimiter2 + " set " + fields + sql.getWheres(delimiter, delimiter2) } func (sql *SQLComponent) prepareInsert(delimiter, delimiter2 string) { fields := " (" quesMark := "(" for key, value := range sql.Values { fields += wrap(delimiter, delimiter2, key) + "," quesMark += "?," sql.Args = append(sql.Args, value) } fields = fields[:len(fields)-1] + ")" quesMark = quesMark[:len(quesMark)-1] + ")" sql.Statement = "insert into " + delimiter + sql.TableName + delimiter2 + fields + " values " + quesMark } ================================================ FILE: modules/db/dialect/mssql.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package dialect import "fmt" type mssql struct { commonDialect } func (mssql) GetName() string { return "mssql" } func (mssql) ShowColumnsWithComment(schema, table string) string { return fmt.Sprintf("select column_name, data_type from information_schema.columns where table_name = '%s'", table) } func (mssql) ShowColumns(table string) string { return fmt.Sprintf("select column_name, data_type from information_schema.columns where table_name = '%s'", table) } func (mssql) ShowTables() string { return "select * from information_schema.TABLES" } ================================================ FILE: modules/db/dialect/mysql.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package dialect type mysql struct { commonDialect } func (mysql) GetName() string { return "mysql" } func (mysql) ShowColumnsWithComment(schema, table string) string { return `SELECT COLUMN_NAME Field, DATA_TYPE Type, IS_NULLABLE 'Null', COLUMN_KEY 'Key', COLUMN_DEFAULT 'Default', EXTRA Extra, COLUMN_COMMENT Comment FROM information_schema.COLUMNS WHERE table_name = '` + table + `' AND table_schema = '` + schema + `'` } func (mysql) ShowColumns(table string) string { return "show columns in " + table } func (mysql) ShowTables() string { return "show tables" } ================================================ FILE: modules/db/dialect/oceanbase.go ================================================ package dialect type oceanbase struct { commonDialect } func (oceanbase) GetName() string { return "oceanbase" } func (oceanbase) ShowColumnsWithComment(schema, table string) string { return "show columns in " + table } func (oceanbase) ShowColumns(table string) string { return "show columns in " + table } func (oceanbase) ShowTables() string { return "show tables" } ================================================ FILE: modules/db/dialect/postgresql.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package dialect import ( "fmt" "strings" ) type postgresql struct { commonDialect } func (postgresql) GetName() string { return "postgresql" } func (postgresql) ShowColumnsWithComment(schema, table string) string { tableArr := strings.Split(table, "\".\"") if len(tableArr) > 1 { return fmt.Sprintf("select * from information_schema.columns where table_name = '%s' and table_schema = '%s'", tableArr[1], tableArr[0]) } else { return fmt.Sprintf("select * from information_schema.columns where table_name = '%s'", table) } } func (postgresql) ShowTables() string { return "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema';" } func (postgresql) ShowColumns(table string) string { tableArr := strings.Split(table, "\".\"") if len(tableArr) > 1 { return fmt.Sprintf("select * from information_schema.columns where table_name = '%s' and table_schema = '%s'", tableArr[1], tableArr[0]) } else { return fmt.Sprintf("select * from information_schema.columns where table_name = '%s'", table) } } ================================================ FILE: modules/db/dialect/sqlite.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package dialect type sqlite struct { commonDialect } func (sqlite) GetName() string { return "sqlite" } func (sqlite) ShowColumnsWithComment(schema, table string) string { return "PRAGMA table_info(" + table + ");" } func (sqlite) ShowColumns(table string) string { return "PRAGMA table_info(" + table + ");" } func (sqlite) ShowTables() string { return "SELECT name as tablename FROM sqlite_master WHERE type ='table'" } ================================================ FILE: modules/db/drivers/mssql/mssql.go ================================================ package mssql import _ "github.com/denisenkom/go-mssqldb" // Import the mssql driver. ================================================ FILE: modules/db/drivers/mysql/mysql.go ================================================ package mysql import _ "github.com/go-sql-driver/mysql" // Import the mysql driver. ================================================ FILE: modules/db/drivers/oceanbase/oceanbase.go ================================================ package oceanbase //oceanbase-ce can use mysql driver import _ "github.com/go-sql-driver/mysql" // Import the mysql driver. ================================================ FILE: modules/db/drivers/postgres/postgres.go ================================================ package postgres import _ "github.com/lib/pq" // Import the postgresql driver. ================================================ FILE: modules/db/drivers/sqlite/sqlite.go ================================================ package sqlite import _ "github.com/mattn/go-sqlite3" // Import the sqlite driver. ================================================ FILE: modules/db/mssql.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package db import ( "database/sql" "fmt" "regexp" "strconv" "strings" "github.com/GoAdminGroup/go-admin/modules/config" ) // Mssql is a Connection of mssql. type Mssql struct { Base } // GetMssqlDB return the global mssql connection. func GetMssqlDB() *Mssql { return &Mssql{ Base: Base{ DbList: make(map[string]*sql.DB), }, } } // GetDelimiter implements the method Connection.GetDelimiter. func (db *Mssql) GetDelimiter() string { return "[" } // GetDelimiter2 implements the method Connection.GetDelimiter2. func (db *Mssql) GetDelimiter2() string { return "]" } // GetDelimiters implements the method Connection.GetDelimiters. func (db *Mssql) GetDelimiters() []string { return []string{"[", "]"} } // Name implements the method Connection.Name. func (db *Mssql) Name() string { return "mssql" } // TODO: 整理优化 func replaceStringFunc(pattern, src string, rpl func(s string) string) (string, error) { r, err := regexp.Compile(pattern) if err != nil { return "", err } bytes := r.ReplaceAllFunc([]byte(src), func(bytes []byte) []byte { return []byte(rpl(string(bytes))) }) return string(bytes), nil } func replace(pattern string, replace, src []byte) ([]byte, error) { r, err := regexp.Compile(pattern) if err != nil { return nil, err } return r.ReplaceAll(src, replace), nil } func replaceString(pattern, rep, src string) (string, error) { r, e := replace(pattern, []byte(rep), []byte(src)) return string(r), e } func matchAllString(pattern string, src string) ([][]string, error) { r, err := regexp.Compile(pattern) if err != nil { return nil, err } return r.FindAllStringSubmatch(src, -1), nil } func isMatch(pattern string, src []byte) bool { r, err := regexp.Compile(pattern) if err != nil { return false } return r.Match(src) } func isMatchString(pattern string, src string) bool { return isMatch(pattern, []byte(src)) } func matchString(pattern string, src string) ([]string, error) { r, err := regexp.Compile(pattern) if err != nil { return nil, err } return r.FindStringSubmatch(src), nil } // 从Gf框架复制 // 在执行sql之前对sql进行进一步处理 func (db *Mssql) handleSqlBeforeExec(query string) string { index := 0 str, _ := replaceStringFunc("\\?", query, func(s string) string { index++ return fmt.Sprintf("@p%d", index) }) str, _ = replaceString("\"", "", str) return db.parseSql(str) } //将MYSQL的SQL语法转换为MSSQL的语法 //1.由于mssql不支持limit写法所以需要对mysql中的limit用法做转换 func (db *Mssql) parseSql(sql string) string { //下面的正则表达式匹配出SELECT和INSERT的关键字后分别做不同的处理,如有LIMIT则将LIMIT的关键字也匹配出 patten := `^\s*(?i)(SELECT)|(LIMIT\s*(\d+)\s*,\s*(\d+))` if !isMatchString(patten, sql) { //fmt.Println("not matched..") return sql } res, err := matchAllString(patten, sql) if err != nil { //fmt.Println("MatchString error.", err) return "" } index := 0 keyword := strings.TrimSpace(res[index][0]) keyword = strings.ToUpper(keyword) index++ switch keyword { case "SELECT": //不含LIMIT关键字则不处理 if len(res) < 2 || (!strings.HasPrefix(res[index][0], "LIMIT") && !strings.HasPrefix(res[index][0], "limit")) { break } //不含LIMIT则不处理 if !isMatchString("((?i)SELECT)(.+)((?i)LIMIT)", sql) { break } //判断SQL中是否含有order by selectStr := "" orderbyStr := "" haveOrderby := isMatchString("((?i)SELECT)(.+)((?i)ORDER BY)", sql) if haveOrderby { //取order by 前面的字符串 queryExpr, _ := matchString("((?i)SELECT)(.+)((?i)ORDER BY)", sql) if len(queryExpr) != 4 || !strings.EqualFold(queryExpr[1], "SELECT") || !strings.EqualFold(queryExpr[3], "ORDER BY") { break } selectStr = queryExpr[2] //取order by表达式的值 orderbyExpr, _ := matchString("((?i)ORDER BY)(.+)((?i)LIMIT)", sql) if len(orderbyExpr) != 4 || !strings.EqualFold(orderbyExpr[1], "ORDER BY") || !strings.EqualFold(orderbyExpr[3], "LIMIT") { break } orderbyStr = orderbyExpr[2] } else { queryExpr, _ := matchString("((?i)SELECT)(.+)((?i)LIMIT)", sql) if len(queryExpr) != 4 || !strings.EqualFold(queryExpr[1], "SELECT") || !strings.EqualFold(queryExpr[3], "LIMIT") { break } selectStr = queryExpr[2] } //取limit后面的取值范围 first, limit := 0, 0 for i := 1; i < len(res[index]); i++ { if strings.TrimSpace(res[index][i]) == "" { continue } if strings.HasPrefix(res[index][i], "LIMIT") || strings.HasPrefix(res[index][i], "limit") { first, _ = strconv.Atoi(res[index][i+1]) limit, _ = strconv.Atoi(res[index][i+2]) break } } if haveOrderby { sql = fmt.Sprintf("SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY %s) as ROWNUMBER_, %s ) as TMP_ WHERE TMP_.ROWNUMBER_ > %d AND TMP_.ROWNUMBER_ <= %d", orderbyStr, selectStr, first, limit) } else { if first == 0 { first = limit } else { first = limit - first } sql = fmt.Sprintf("SELECT * FROM (SELECT TOP %d * FROM (SELECT TOP %d %s) as TMP1_ ) as TMP2_ ", first, limit, selectStr) } default: } return sql } // QueryWithConnection implements the method Connection.QueryWithConnection. func (db *Mssql) QueryWithConnection(con string, query string, args ...interface{}) ([]map[string]interface{}, error) { query = db.handleSqlBeforeExec(query) return CommonQuery(db.DbList[con], query, args...) } // ExecWithConnection implements the method Connection.ExecWithConnection. func (db *Mssql) ExecWithConnection(con string, query string, args ...interface{}) (sql.Result, error) { query = db.handleSqlBeforeExec(query) return CommonExec(db.DbList[con], query, args...) } // Query implements the method Connection.Query. func (db *Mssql) Query(query string, args ...interface{}) ([]map[string]interface{}, error) { query = db.handleSqlBeforeExec(query) return CommonQuery(db.DbList["default"], query, args...) } // Exec implements the method Connection.Exec. func (db *Mssql) Exec(query string, args ...interface{}) (sql.Result, error) { query = db.handleSqlBeforeExec(query) return CommonExec(db.DbList["default"], query, args...) } func (db *Mssql) QueryWith(tx *sql.Tx, conn, query string, args ...interface{}) ([]map[string]interface{}, error) { if tx != nil { return db.QueryWithTx(tx, query, args...) } return db.QueryWithConnection(conn, query, args...) } func (db *Mssql) ExecWith(tx *sql.Tx, conn, query string, args ...interface{}) (sql.Result, error) { if tx != nil { return db.ExecWithTx(tx, query, args...) } return db.ExecWithConnection(conn, query, args...) } // InitDB implements the method Connection.InitDB. func (db *Mssql) InitDB(cfgs map[string]config.Database) Connection { db.Configs = cfgs db.Once.Do(func() { for conn, cfg := range cfgs { sqlDB, err := sql.Open("sqlserver", cfg.GetDSN()) if sqlDB == nil { panic("invalid connection") } if err != nil { _ = sqlDB.Close() panic(err.Error()) } sqlDB.SetMaxIdleConns(cfg.MaxIdleConns) sqlDB.SetMaxOpenConns(cfg.MaxOpenConns) sqlDB.SetConnMaxLifetime(cfg.ConnMaxLifetime) sqlDB.SetConnMaxIdleTime(cfg.ConnMaxIdleTime) db.DbList[conn] = sqlDB if err := sqlDB.Ping(); err != nil { panic(err) } } }) return db } // BeginTxWithReadUncommitted starts a transaction with level LevelReadUncommitted. func (db *Mssql) BeginTxWithReadUncommitted() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelReadUncommitted) } // BeginTxWithReadCommitted starts a transaction with level LevelReadCommitted. func (db *Mssql) BeginTxWithReadCommitted() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelReadCommitted) } // BeginTxWithRepeatableRead starts a transaction with level LevelRepeatableRead. func (db *Mssql) BeginTxWithRepeatableRead() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelRepeatableRead) } // BeginTx starts a transaction with level LevelDefault. func (db *Mssql) BeginTx() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelDefault) } // BeginTxWithLevel starts a transaction with given transaction isolation level. func (db *Mssql) BeginTxWithLevel(level sql.IsolationLevel) *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], level) } // BeginTxWithReadUncommittedAndConnection starts a transaction with level LevelReadUncommitted and connection. func (db *Mssql) BeginTxWithReadUncommittedAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelReadUncommitted) } // BeginTxWithReadCommittedAndConnection starts a transaction with level LevelReadCommitted and connection. func (db *Mssql) BeginTxWithReadCommittedAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelReadCommitted) } // BeginTxWithRepeatableReadAndConnection starts a transaction with level LevelRepeatableRead and connection. func (db *Mssql) BeginTxWithRepeatableReadAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelRepeatableRead) } // BeginTxAndConnection starts a transaction with level LevelDefault and connection. func (db *Mssql) BeginTxAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelDefault) } // BeginTxWithLevelAndConnection starts a transaction with given transaction isolation level and connection. func (db *Mssql) BeginTxWithLevelAndConnection(conn string, level sql.IsolationLevel) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], level) } // QueryWithTx is query method within the transaction. func (db *Mssql) QueryWithTx(tx *sql.Tx, query string, args ...interface{}) ([]map[string]interface{}, error) { query = db.handleSqlBeforeExec(query) return CommonQueryWithTx(tx, query, args...) } // ExecWithTx is exec method within the transaction. func (db *Mssql) ExecWithTx(tx *sql.Tx, query string, args ...interface{}) (sql.Result, error) { query = db.handleSqlBeforeExec(query) return CommonExecWithTx(tx, query, args...) } ================================================ FILE: modules/db/mysql.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package db import ( "database/sql" "github.com/GoAdminGroup/go-admin/modules/config" ) // SQLTx is an in-progress database transaction. type SQLTx struct { Tx *sql.Tx } // Mysql is a Connection of mysql. type Mysql struct { Base } // GetMysqlDB return the global mysql connection. func GetMysqlDB() *Mysql { return &Mysql{ Base: Base{ DbList: make(map[string]*sql.DB), }, } } // Name implements the method Connection.Name. func (db *Mysql) Name() string { return "mysql" } // GetDelimiter implements the method Connection.GetDelimiter. func (db *Mysql) GetDelimiter() string { return "`" } // GetDelimiter2 implements the method Connection.GetDelimiter2. func (db *Mysql) GetDelimiter2() string { return "`" } // GetDelimiters implements the method Connection.GetDelimiters. func (db *Mysql) GetDelimiters() []string { return []string{"`", "`"} } // InitDB implements the method Connection.InitDB. func (db *Mysql) InitDB(cfgs map[string]config.Database) Connection { db.Configs = cfgs db.Once.Do(func() { for conn, cfg := range cfgs { sqlDB, err := sql.Open("mysql", cfg.GetDSN()) if err != nil { if sqlDB != nil { _ = sqlDB.Close() } panic(err) } // Largest set up the database connection reduce time wait sqlDB.SetMaxIdleConns(cfg.MaxIdleConns) sqlDB.SetMaxOpenConns(cfg.MaxOpenConns) sqlDB.SetConnMaxLifetime(cfg.ConnMaxLifetime) sqlDB.SetConnMaxIdleTime(cfg.ConnMaxIdleTime) db.DbList[conn] = sqlDB if err := sqlDB.Ping(); err != nil { panic(err) } } }) return db } // QueryWithConnection implements the method Connection.QueryWithConnection. func (db *Mysql) QueryWithConnection(con string, query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQuery(db.DbList[con], query, args...) } // ExecWithConnection implements the method Connection.ExecWithConnection. func (db *Mysql) ExecWithConnection(con string, query string, args ...interface{}) (sql.Result, error) { return CommonExec(db.DbList[con], query, args...) } // Query implements the method Connection.Query. func (db *Mysql) Query(query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQuery(db.DbList["default"], query, args...) } // Exec implements the method Connection.Exec. func (db *Mysql) Exec(query string, args ...interface{}) (sql.Result, error) { return CommonExec(db.DbList["default"], query, args...) } // QueryWithTx is query method within the transaction. func (db *Mysql) QueryWithTx(tx *sql.Tx, query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQueryWithTx(tx, query, args...) } // ExecWithTx is exec method within the transaction. func (db *Mysql) ExecWithTx(tx *sql.Tx, query string, args ...interface{}) (sql.Result, error) { return CommonExecWithTx(tx, query, args...) } func (db *Mysql) QueryWith(tx *sql.Tx, conn, query string, args ...interface{}) ([]map[string]interface{}, error) { if tx != nil { return db.QueryWithTx(tx, query, args...) } return db.QueryWithConnection(conn, query, args...) } func (db *Mysql) ExecWith(tx *sql.Tx, conn, query string, args ...interface{}) (sql.Result, error) { if tx != nil { return db.ExecWithTx(tx, query, args...) } return db.ExecWithConnection(conn, query, args...) } // BeginTxWithReadUncommitted starts a transaction with level LevelReadUncommitted. func (db *Mysql) BeginTxWithReadUncommitted() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelReadUncommitted) } // BeginTxWithReadCommitted starts a transaction with level LevelReadCommitted. func (db *Mysql) BeginTxWithReadCommitted() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelReadCommitted) } // BeginTxWithRepeatableRead starts a transaction with level LevelRepeatableRead. func (db *Mysql) BeginTxWithRepeatableRead() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelRepeatableRead) } // BeginTx starts a transaction with level LevelDefault. func (db *Mysql) BeginTx() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelDefault) } // BeginTxWithLevel starts a transaction with given transaction isolation level. func (db *Mysql) BeginTxWithLevel(level sql.IsolationLevel) *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], level) } // BeginTxWithReadUncommittedAndConnection starts a transaction with level LevelReadUncommitted and connection. func (db *Mysql) BeginTxWithReadUncommittedAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelReadUncommitted) } // BeginTxWithReadCommittedAndConnection starts a transaction with level LevelReadCommitted and connection. func (db *Mysql) BeginTxWithReadCommittedAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelReadCommitted) } // BeginTxWithRepeatableReadAndConnection starts a transaction with level LevelRepeatableRead and connection. func (db *Mysql) BeginTxWithRepeatableReadAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelRepeatableRead) } // BeginTxAndConnection starts a transaction with level LevelDefault and connection. func (db *Mysql) BeginTxAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelDefault) } // BeginTxWithLevelAndConnection starts a transaction with given transaction isolation level and connection. func (db *Mysql) BeginTxWithLevelAndConnection(conn string, level sql.IsolationLevel) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], level) } ================================================ FILE: modules/db/oceanbase.go ================================================ package db import ( "database/sql" "github.com/GoAdminGroup/go-admin/modules/config" ) // OceanBase is a Connection of OceanBase. type OceanBase struct { Base } // GetOceanBaseDB return the global OceanBase connection. func GetOceanBaseDB() *OceanBase { return &OceanBase{ Base: Base{ DbList: make(map[string]*sql.DB), }, } } // Name implements the method Connection.Name. func (db *OceanBase) Name() string { return "OceanBase" } // GetDelimiter implements the method Connection.GetDelimiter. func (db *OceanBase) GetDelimiter() string { return "`" } // GetDelimiter2 implements the method Connection.GetDelimiter2. func (db *OceanBase) GetDelimiter2() string { return "`" } // GetDelimiters implements the method Connection.GetDelimiters. func (db *OceanBase) GetDelimiters() []string { return []string{"`", "`"} } // InitDB implements the method Connection.InitDB. func (db *OceanBase) InitDB(cfgs map[string]config.Database) Connection { db.Configs = cfgs db.Once.Do(func() { for conn, cfg := range cfgs { sqlDB, err := sql.Open("mysql", cfg.GetDSN()) if err != nil { if sqlDB != nil { _ = sqlDB.Close() } panic(err) } // Largest set up the database connection reduce time wait sqlDB.SetMaxIdleConns(cfg.MaxIdleConns) sqlDB.SetMaxOpenConns(cfg.MaxOpenConns) sqlDB.SetConnMaxLifetime(cfg.ConnMaxLifetime) sqlDB.SetConnMaxIdleTime(cfg.ConnMaxIdleTime) db.DbList[conn] = sqlDB if err := sqlDB.Ping(); err != nil { panic(err) } } }) return db } // QueryWithConnection implements the method Connection.QueryWithConnection. func (db *OceanBase) QueryWithConnection(con string, query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQuery(db.DbList[con], query, args...) } // ExecWithConnection implements the method Connection.ExecWithConnection. func (db *OceanBase) ExecWithConnection(con string, query string, args ...interface{}) (sql.Result, error) { return CommonExec(db.DbList[con], query, args...) } // Query implements the method Connection.Query. func (db *OceanBase) Query(query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQuery(db.DbList["default"], query, args...) } // Exec implements the method Connection.Exec. func (db *OceanBase) Exec(query string, args ...interface{}) (sql.Result, error) { return CommonExec(db.DbList["default"], query, args...) } // QueryWithTx is query method within the transaction. func (db *OceanBase) QueryWithTx(tx *sql.Tx, query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQueryWithTx(tx, query, args...) } // ExecWithTx is exec method within the transaction. func (db *OceanBase) ExecWithTx(tx *sql.Tx, query string, args ...interface{}) (sql.Result, error) { return CommonExecWithTx(tx, query, args...) } func (db *OceanBase) QueryWith(tx *sql.Tx, conn, query string, args ...interface{}) ([]map[string]interface{}, error) { if tx != nil { return db.QueryWithTx(tx, query, args...) } return db.QueryWithConnection(conn, query, args...) } func (db *OceanBase) ExecWith(tx *sql.Tx, conn, query string, args ...interface{}) (sql.Result, error) { if tx != nil { return db.ExecWithTx(tx, query, args...) } return db.ExecWithConnection(conn, query, args...) } // BeginTxWithReadUncommitted starts a transaction with level LevelReadUncommitted. func (db *OceanBase) BeginTxWithReadUncommitted() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelReadUncommitted) } // BeginTxWithReadCommitted starts a transaction with level LevelReadCommitted. func (db *OceanBase) BeginTxWithReadCommitted() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelReadCommitted) } // BeginTxWithRepeatableRead starts a transaction with level LevelRepeatableRead. func (db *OceanBase) BeginTxWithRepeatableRead() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelRepeatableRead) } // BeginTx starts a transaction with level LevelDefault. func (db *OceanBase) BeginTx() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelDefault) } // BeginTxWithLevel starts a transaction with given transaction isolation level. func (db *OceanBase) BeginTxWithLevel(level sql.IsolationLevel) *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], level) } // BeginTxWithReadUncommittedAndConnection starts a transaction with level LevelReadUncommitted and connection. func (db *OceanBase) BeginTxWithReadUncommittedAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelReadUncommitted) } // BeginTxWithReadCommittedAndConnection starts a transaction with level LevelReadCommitted and connection. func (db *OceanBase) BeginTxWithReadCommittedAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelReadCommitted) } // BeginTxWithRepeatableReadAndConnection starts a transaction with level LevelRepeatableRead and connection. func (db *OceanBase) BeginTxWithRepeatableReadAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelRepeatableRead) } // BeginTxAndConnection starts a transaction with level LevelDefault and connection. func (db *OceanBase) BeginTxAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelDefault) } // BeginTxWithLevelAndConnection starts a transaction with given transaction isolation level and connection. func (db *OceanBase) BeginTxWithLevelAndConnection(conn string, level sql.IsolationLevel) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], level) } ================================================ FILE: modules/db/performer.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package db import ( "context" "database/sql" "regexp" "strings" ) // CommonQuery is a common method of query. func CommonQuery(db *sql.DB, query string, args ...interface{}) ([]map[string]interface{}, error) { rs, err := db.Query(query, args...) if err != nil { return nil, err } defer func() { if rs != nil { _ = rs.Close() } }() col, colErr := rs.Columns() if colErr != nil { return nil, colErr } typeVal, err := rs.ColumnTypes() if err != nil { return nil, err } // TODO: regular expressions for sqlite, use the dialect module // tell the drive to reduce the performance loss results := make([]map[string]interface{}, 0) r, _ := regexp.Compile(`\\((.*)\\)`) for rs.Next() { var colVar = make([]interface{}, len(col)) for i := 0; i < len(col); i++ { typeName := strings.ToUpper(r.ReplaceAllString(typeVal[i].DatabaseTypeName(), "")) SetColVarType(&colVar, i, typeName) } result := make(map[string]interface{}) if scanErr := rs.Scan(colVar...); scanErr != nil { return nil, scanErr } for j := 0; j < len(col); j++ { typeName := strings.ToUpper(r.ReplaceAllString(typeVal[j].DatabaseTypeName(), "")) SetResultValue(&result, col[j], colVar[j], typeName) } results = append(results, result) } if err := rs.Err(); err != nil { return nil, err } return results, nil } // CommonExec is a common method of exec. func CommonExec(db *sql.DB, query string, args ...interface{}) (sql.Result, error) { rs, err := db.Exec(query, args...) if err != nil { return nil, err } return rs, nil } // CommonQueryWithTx is a common method of query. func CommonQueryWithTx(tx *sql.Tx, query string, args ...interface{}) ([]map[string]interface{}, error) { rs, err := tx.Query(query, args...) if err != nil { panic(err) } defer func() { if rs != nil { _ = rs.Close() } }() col, colErr := rs.Columns() if colErr != nil { return nil, colErr } typeVal, err := rs.ColumnTypes() if err != nil { return nil, err } // TODO: regular expressions for sqlite, use the dialect module // tell the drive to reduce the performance loss results := make([]map[string]interface{}, 0) r, _ := regexp.Compile(`\\((.*)\\)`) for rs.Next() { var colVar = make([]interface{}, len(col)) for i := 0; i < len(col); i++ { typeName := strings.ToUpper(r.ReplaceAllString(typeVal[i].DatabaseTypeName(), "")) SetColVarType(&colVar, i, typeName) } result := make(map[string]interface{}) if scanErr := rs.Scan(colVar...); scanErr != nil { return nil, scanErr } for j := 0; j < len(col); j++ { typeName := strings.ToUpper(r.ReplaceAllString(typeVal[j].DatabaseTypeName(), "")) SetResultValue(&result, col[j], colVar[j], typeName) } results = append(results, result) } if err := rs.Err(); err != nil { return nil, err } return results, nil } // CommonExecWithTx is a common method of exec. func CommonExecWithTx(tx *sql.Tx, query string, args ...interface{}) (sql.Result, error) { rs, err := tx.Exec(query, args...) if err != nil { return nil, err } return rs, nil } // CommonBeginTxWithLevel starts a transaction with given transaction isolation level and db connection. func CommonBeginTxWithLevel(db *sql.DB, level sql.IsolationLevel) *sql.Tx { tx, err := db.BeginTx(context.Background(), &sql.TxOptions{Isolation: level}) if err != nil { panic(err) } return tx } ================================================ FILE: modules/db/postgresql.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package db import ( "database/sql" "strconv" "strings" "github.com/GoAdminGroup/go-admin/modules/config" ) // Postgresql is a Connection of postgresql. type Postgresql struct { Base } // GetPostgresqlDB return the global postgresql connection. func GetPostgresqlDB() *Postgresql { return &Postgresql{ Base: Base{ DbList: make(map[string]*sql.DB), }, } } // Name implements the method Connection.Name. func (db *Postgresql) Name() string { return "postgresql" } // GetDelimiter implements the method Connection.GetDelimiter. func (db *Postgresql) GetDelimiter() string { return `"` } // GetDelimiter2 implements the method Connection.GetDelimiter2. func (db *Postgresql) GetDelimiter2() string { return `"` } // GetDelimiters implements the method Connection.GetDelimiters. func (db *Postgresql) GetDelimiters() []string { return []string{`"`, `"`} } // QueryWithConnection implements the method Connection.QueryWithConnection. func (db *Postgresql) QueryWithConnection(con string, query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQuery(db.DbList[con], filterQuery(query), args...) } // ExecWithConnection implements the method Connection.ExecWithConnection. func (db *Postgresql) ExecWithConnection(con string, query string, args ...interface{}) (sql.Result, error) { return CommonExec(db.DbList[con], filterQuery(query), args...) } // Query implements the method Connection.Query. func (db *Postgresql) Query(query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQuery(db.DbList["default"], filterQuery(query), args...) } // Exec implements the method Connection.Exec. func (db *Postgresql) Exec(query string, args ...interface{}) (sql.Result, error) { return CommonExec(db.DbList["default"], filterQuery(query), args...) } func (db *Postgresql) QueryWith(tx *sql.Tx, conn, query string, args ...interface{}) ([]map[string]interface{}, error) { if tx != nil { return db.QueryWithTx(tx, query, args...) } return db.QueryWithConnection(conn, query, args...) } func (db *Postgresql) ExecWith(tx *sql.Tx, conn, query string, args ...interface{}) (sql.Result, error) { if tx != nil { return db.ExecWithTx(tx, query, args...) } return db.ExecWithConnection(conn, query, args...) } func filterQuery(query string) string { queCount := strings.Count(query, "?") for i := 1; i < queCount+1; i++ { query = strings.Replace(query, "?", "$"+strconv.Itoa(i), 1) } query = strings.ReplaceAll(query, "`", "") // TODO: add " to the keyword return strings.ReplaceAll(query, "by order ", `by "order" `) } // InitDB implements the method Connection.InitDB. func (db *Postgresql) InitDB(cfgList map[string]config.Database) Connection { db.Configs = cfgList db.Once.Do(func() { for conn, cfg := range cfgList { sqlDB, err := sql.Open("postgres", cfg.GetDSN()) if err != nil { if sqlDB != nil { _ = sqlDB.Close() } panic(err) } sqlDB.SetMaxIdleConns(cfg.MaxIdleConns) sqlDB.SetMaxOpenConns(cfg.MaxOpenConns) sqlDB.SetConnMaxLifetime(cfg.ConnMaxLifetime) sqlDB.SetConnMaxIdleTime(cfg.ConnMaxIdleTime) db.DbList[conn] = sqlDB if err := sqlDB.Ping(); err != nil { panic(err) } } }) return db } // BeginTxWithReadUncommitted starts a transaction with level LevelReadUncommitted. func (db *Postgresql) BeginTxWithReadUncommitted() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelReadUncommitted) } // BeginTxWithReadCommitted starts a transaction with level LevelReadCommitted. func (db *Postgresql) BeginTxWithReadCommitted() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelReadCommitted) } // BeginTxWithRepeatableRead starts a transaction with level LevelRepeatableRead. func (db *Postgresql) BeginTxWithRepeatableRead() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelRepeatableRead) } // BeginTx starts a transaction with level LevelDefault. func (db *Postgresql) BeginTx() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelDefault) } // BeginTxWithLevel starts a transaction with given transaction isolation level. func (db *Postgresql) BeginTxWithLevel(level sql.IsolationLevel) *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], level) } // BeginTxWithReadUncommittedAndConnection starts a transaction with level LevelReadUncommitted and connection. func (db *Postgresql) BeginTxWithReadUncommittedAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelReadUncommitted) } // BeginTxWithReadCommittedAndConnection starts a transaction with level LevelReadCommitted and connection. func (db *Postgresql) BeginTxWithReadCommittedAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelReadCommitted) } // BeginTxWithRepeatableReadAndConnection starts a transaction with level LevelRepeatableRead and connection. func (db *Postgresql) BeginTxWithRepeatableReadAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelRepeatableRead) } // BeginTxAndConnection starts a transaction with level LevelDefault and connection. func (db *Postgresql) BeginTxAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelDefault) } // BeginTxWithLevelAndConnection starts a transaction with given transaction isolation level and connection. func (db *Postgresql) BeginTxWithLevelAndConnection(conn string, level sql.IsolationLevel) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], level) } // QueryWithTx is query method within the transaction. func (db *Postgresql) QueryWithTx(tx *sql.Tx, query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQueryWithTx(tx, filterQuery(query), args...) } // ExecWithTx is exec method within the transaction. func (db *Postgresql) ExecWithTx(tx *sql.Tx, query string, args ...interface{}) (sql.Result, error) { return CommonExecWithTx(tx, filterQuery(query), args...) } ================================================ FILE: modules/db/sqlite.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package db import ( "database/sql" "github.com/GoAdminGroup/go-admin/modules/config" ) // Sqlite is a Connection of sqlite. type Sqlite struct { Base } // GetSqliteDB return the global sqlite connection. func GetSqliteDB() *Sqlite { return &Sqlite{ Base: Base{ DbList: make(map[string]*sql.DB), }, } } // Name implements the method Connection.Name. func (db *Sqlite) Name() string { return "sqlite" } // GetDelimiter implements the method Connection.GetDelimiter. func (db *Sqlite) GetDelimiter() string { return "`" } // GetDelimiter2 implements the method Connection.GetDelimiter2. func (db *Sqlite) GetDelimiter2() string { return "`" } // GetDelimiters implements the method Connection.GetDelimiters. func (db *Sqlite) GetDelimiters() []string { return []string{"`", "`"} } // QueryWithConnection implements the method Connection.QueryWithConnection. func (db *Sqlite) QueryWithConnection(con string, query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQuery(db.DbList[con], query, args...) } // ExecWithConnection implements the method Connection.ExecWithConnection. func (db *Sqlite) ExecWithConnection(con string, query string, args ...interface{}) (sql.Result, error) { return CommonExec(db.DbList[con], query, args...) } // Query implements the method Connection.Query. func (db *Sqlite) Query(query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQuery(db.DbList["default"], query, args...) } // Exec implements the method Connection.Exec. func (db *Sqlite) Exec(query string, args ...interface{}) (sql.Result, error) { return CommonExec(db.DbList["default"], query, args...) } func (db *Sqlite) QueryWith(tx *sql.Tx, conn, query string, args ...interface{}) ([]map[string]interface{}, error) { if tx != nil { return db.QueryWithTx(tx, query, args...) } return db.QueryWithConnection(conn, query, args...) } func (db *Sqlite) ExecWith(tx *sql.Tx, conn, query string, args ...interface{}) (sql.Result, error) { if tx != nil { return db.ExecWithTx(tx, query, args...) } return db.ExecWithConnection(conn, query, args...) } // InitDB implements the method Connection.InitDB. func (db *Sqlite) InitDB(cfgList map[string]config.Database) Connection { db.Configs = cfgList db.Once.Do(func() { for conn, cfg := range cfgList { sqlDB, err := sql.Open("sqlite3", cfg.GetDSN()) if err != nil { panic(err) } sqlDB.SetMaxIdleConns(cfg.MaxIdleConns) sqlDB.SetMaxOpenConns(cfg.MaxOpenConns) sqlDB.SetConnMaxLifetime(cfg.ConnMaxLifetime) sqlDB.SetConnMaxIdleTime(cfg.ConnMaxIdleTime) db.DbList[conn] = sqlDB if err := sqlDB.Ping(); err != nil { panic(err) } } }) return db } // BeginTxWithReadUncommitted starts a transaction with level LevelReadUncommitted. func (db *Sqlite) BeginTxWithReadUncommitted() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelReadUncommitted) } // BeginTxWithReadCommitted starts a transaction with level LevelReadCommitted. func (db *Sqlite) BeginTxWithReadCommitted() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelReadCommitted) } // BeginTxWithRepeatableRead starts a transaction with level LevelRepeatableRead. func (db *Sqlite) BeginTxWithRepeatableRead() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelRepeatableRead) } // BeginTx starts a transaction with level LevelDefault. func (db *Sqlite) BeginTx() *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], sql.LevelDefault) } // BeginTxWithLevel starts a transaction with given transaction isolation level. func (db *Sqlite) BeginTxWithLevel(level sql.IsolationLevel) *sql.Tx { return CommonBeginTxWithLevel(db.DbList["default"], level) } // BeginTxWithReadUncommittedAndConnection starts a transaction with level LevelReadUncommitted and connection. func (db *Sqlite) BeginTxWithReadUncommittedAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelReadUncommitted) } // BeginTxWithReadCommittedAndConnection starts a transaction with level LevelReadCommitted and connection. func (db *Sqlite) BeginTxWithReadCommittedAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelReadCommitted) } // BeginTxWithRepeatableReadAndConnection starts a transaction with level LevelRepeatableRead and connection. func (db *Sqlite) BeginTxWithRepeatableReadAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelRepeatableRead) } // BeginTxAndConnection starts a transaction with level LevelDefault and connection. func (db *Sqlite) BeginTxAndConnection(conn string) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], sql.LevelDefault) } // BeginTxWithLevelAndConnection starts a transaction with given transaction isolation level and connection. func (db *Sqlite) BeginTxWithLevelAndConnection(conn string, level sql.IsolationLevel) *sql.Tx { return CommonBeginTxWithLevel(db.DbList[conn], level) } // QueryWithTx is query method within the transaction. func (db *Sqlite) QueryWithTx(tx *sql.Tx, query string, args ...interface{}) ([]map[string]interface{}, error) { return CommonQueryWithTx(tx, query, args...) } // ExecWithTx is exec method within the transaction. func (db *Sqlite) ExecWithTx(tx *sql.Tx, query string, args ...interface{}) (sql.Result, error) { return CommonExecWithTx(tx, query, args...) } ================================================ FILE: modules/db/statement.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package db import ( dbsql "database/sql" "errors" "regexp" "strconv" "strings" "sync" "github.com/GoAdminGroup/go-admin/modules/db/dialect" "github.com/GoAdminGroup/go-admin/modules/logger" ) // SQL wraps the Connection and driver dialect methods. type SQL struct { dialect.SQLComponent diver Connection dialect dialect.Dialect conn string tx *dbsql.Tx } // SQLPool is a object pool of SQL. var SQLPool = sync.Pool{ New: func() interface{} { return &SQL{ SQLComponent: dialect.SQLComponent{ Fields: make([]string, 0), TableName: "", Args: make([]interface{}, 0), Wheres: make([]dialect.Where, 0), Leftjoins: make([]dialect.Join, 0), UpdateRaws: make([]dialect.RawUpdate, 0), WhereRaws: "", Order: "", Group: "", Limit: "", }, diver: nil, dialect: nil, } }, } // H is a shorthand of map. type H map[string]interface{} // newSQL get a new SQL from SQLPool. func newSQL() *SQL { return SQLPool.Get().(*SQL) } // ******************************* // process method // ******************************* // TableName return a SQL with given table and default connection. func Table(table string) *SQL { sql := newSQL() sql.TableName = table sql.conn = "default" return sql } // WithDriver return a SQL with given driver. func WithDriver(conn Connection) *SQL { sql := newSQL() sql.diver = conn sql.dialect = dialect.GetDialectByDriver(conn.Name()) sql.conn = "default" return sql } // WithDriverAndConnection return a SQL with given driver and connection name. func WithDriverAndConnection(connName string, conn Connection) *SQL { sql := newSQL() sql.diver = conn sql.dialect = dialect.GetDialectByDriver(conn.Name()) sql.conn = connName return sql } // WithDriver return a SQL with given driver. func (sql *SQL) WithDriver(conn Connection) *SQL { sql.diver = conn sql.dialect = dialect.GetDialectByDriver(conn.Name()) return sql } // WithConnection set the connection name of SQL. func (sql *SQL) WithConnection(conn string) *SQL { sql.conn = conn return sql } // WithTx set the database transaction object of SQL. func (sql *SQL) WithTx(tx *dbsql.Tx) *SQL { sql.tx = tx return sql } // TableName set table of SQL. func (sql *SQL) Table(table string) *SQL { sql.clean() sql.TableName = table return sql } // Select set select fields. func (sql *SQL) Select(fields ...string) *SQL { sql.Fields = fields sql.Functions = make([]string, len(fields)) reg, _ := regexp.Compile(`(.*?)\((.*?)\)`) for k, field := range fields { res := reg.FindAllStringSubmatch(field, -1) if len(res) > 0 && len(res[0]) > 2 { sql.Functions[k] = res[0][1] sql.Fields[k] = res[0][2] } } return sql } // OrderBy set order fields. func (sql *SQL) OrderBy(fields ...string) *SQL { if len(fields) == 0 { panic("wrong order field") } for i := 0; i < len(fields); i++ { if i == len(fields)-2 { sql.Order += " " + sql.wrap(fields[i]) + " " + fields[i+1] return sql } sql.Order += " " + sql.wrap(fields[i]) + " and " } return sql } // OrderByRaw set order by. func (sql *SQL) OrderByRaw(order string) *SQL { if order != "" { sql.Order += " " + order } return sql } func (sql *SQL) GroupBy(fields ...string) *SQL { if len(fields) == 0 { panic("wrong group by field") } for i := 0; i < len(fields); i++ { if i == len(fields)-1 { sql.Group += " " + sql.wrap(fields[i]) } else { sql.Group += " " + sql.wrap(fields[i]) + "," } } return sql } // GroupByRaw set group by. func (sql *SQL) GroupByRaw(group string) *SQL { if group != "" { sql.Group += " " + group } return sql } // Skip set offset value. func (sql *SQL) Skip(offset int) *SQL { sql.Offset = strconv.Itoa(offset) return sql } // Take set limit value. func (sql *SQL) Take(take int) *SQL { sql.Limit = strconv.Itoa(take) return sql } // Where add the where operation and argument value. func (sql *SQL) Where(field string, operation string, arg interface{}) *SQL { sql.Wheres = append(sql.Wheres, dialect.Where{ Field: field, Operation: operation, Qmark: "?", }) sql.Args = append(sql.Args, arg) return sql } // WhereIn add the where operation of "in" and argument values. func (sql *SQL) WhereIn(field string, arg []interface{}) *SQL { if len(arg) == 0 { panic("wrong parameter") } sql.Wheres = append(sql.Wheres, dialect.Where{ Field: field, Operation: "in", Qmark: "(" + strings.Repeat("?,", len(arg)-1) + "?)", }) sql.Args = append(sql.Args, arg...) return sql } // WhereNotIn add the where operation of "not in" and argument values. func (sql *SQL) WhereNotIn(field string, arg []interface{}) *SQL { if len(arg) == 0 { panic("wrong parameter") } sql.Wheres = append(sql.Wheres, dialect.Where{ Field: field, Operation: "not in", Qmark: "(" + strings.Repeat("?,", len(arg)-1) + "?)", }) sql.Args = append(sql.Args, arg...) return sql } // Find query the sql result with given id assuming that primary key name is "id". func (sql *SQL) Find(arg interface{}) (map[string]interface{}, error) { return sql.Where("id", "=", arg).First() } // Count query the count of query results. func (sql *SQL) Count() (int64, error) { var ( res map[string]interface{} err error driver = sql.diver.Name() ) if res, err = sql.Select("count(*)").First(); err != nil { return 0, err } if driver == DriverPostgresql { return res["count"].(int64), nil } else if driver == DriverMssql { return res[""].(int64), nil } return res["count(*)"].(int64), nil } // Sum sum the value of given field. func (sql *SQL) Sum(field string) (float64, error) { var ( res map[string]interface{} err error key = "sum(" + sql.wrap(field) + ")" ) if res, err = sql.Select("sum(" + field + ")").First(); err != nil { return 0, err } if res == nil { return 0, nil } if r, ok := res[key].(float64); ok { return r, nil } else if r, ok := res[key].([]uint8); ok { return strconv.ParseFloat(string(r), 64) } else { return 0, nil } } // Max find the maximal value of given field. func (sql *SQL) Max(field string) (interface{}, error) { var ( res map[string]interface{} err error key = "max(" + sql.wrap(field) + ")" ) if res, err = sql.Select("max(" + field + ")").First(); err != nil { return 0, err } if res == nil { return 0, nil } return res[key], nil } // Min find the minimal value of given field. func (sql *SQL) Min(field string) (interface{}, error) { var ( res map[string]interface{} err error key = "min(" + sql.wrap(field) + ")" ) if res, err = sql.Select("min(" + field + ")").First(); err != nil { return 0, err } if res == nil { return 0, nil } return res[key], nil } // Avg find the average value of given field. func (sql *SQL) Avg(field string) (interface{}, error) { var ( res map[string]interface{} err error key = "avg(" + sql.wrap(field) + ")" ) if res, err = sql.Select("avg(" + field + ")").First(); err != nil { return 0, err } if res == nil { return 0, nil } return res[key], nil } // WhereRaw set WhereRaws and arguments. func (sql *SQL) WhereRaw(raw string, args ...interface{}) *SQL { sql.WhereRaws = raw sql.Args = append(sql.Args, args...) return sql } // UpdateRaw set UpdateRaw. func (sql *SQL) UpdateRaw(raw string, args ...interface{}) *SQL { sql.UpdateRaws = append(sql.UpdateRaws, dialect.RawUpdate{ Expression: raw, Args: args, }) return sql } // LeftJoin add a left join info. func (sql *SQL) LeftJoin(table string, fieldA string, operation string, fieldB string) *SQL { sql.Leftjoins = append(sql.Leftjoins, dialect.Join{ FieldA: fieldA, FieldB: fieldB, Table: table, Operation: operation, }) return sql } // ******************************* // Transaction method // ******************************* // TxFn is the transaction callback function. type TxFn func(tx *dbsql.Tx) (error, map[string]interface{}) // WithTransaction call the callback function within the transaction and // catch the error. func (sql *SQL) WithTransaction(fn TxFn) (res map[string]interface{}, err error) { tx := sql.diver.BeginTxAndConnection(sql.conn) defer func() { if p := recover(); p != nil { // a panic occurred, rollback and repanic _ = tx.Rollback() panic(p) } else if err != nil { // something went wrong, rollback _ = tx.Rollback() } else { // all good, commit err = tx.Commit() } }() err, res = fn(tx) return } // WithTransactionByLevel call the callback function within the transaction // of given transaction level and catch the error. func (sql *SQL) WithTransactionByLevel(level dbsql.IsolationLevel, fn TxFn) (res map[string]interface{}, err error) { tx := sql.diver.BeginTxWithLevelAndConnection(sql.conn, level) defer func() { if p := recover(); p != nil { // a panic occurred, rollback and repanic _ = tx.Rollback() panic(p) } else if err != nil { // something went wrong, rollback _ = tx.Rollback() } else { // all good, commit err = tx.Commit() } }() err, res = fn(tx) return } // ******************************* // terminal method // ------------------------------- // sql args order: // update ... => where ... // ******************************* // First query the result and return the first row. func (sql *SQL) First() (map[string]interface{}, error) { defer RecycleSQL(sql) sql.dialect.Select(&sql.SQLComponent) res, err := sql.diver.QueryWith(sql.tx, sql.conn, sql.Statement, sql.Args...) if err != nil { return nil, err } if len(res) < 1 { return nil, errors.New("out of index") } return res[0], nil } // All query all the result and return. func (sql *SQL) All() ([]map[string]interface{}, error) { defer RecycleSQL(sql) sql.dialect.Select(&sql.SQLComponent) return sql.diver.QueryWith(sql.tx, sql.conn, sql.Statement, sql.Args...) } // ShowColumns show columns info. func (sql *SQL) ShowColumns() ([]map[string]interface{}, error) { defer RecycleSQL(sql) return sql.diver.QueryWithConnection(sql.conn, sql.dialect.ShowColumns(sql.TableName)) } // ShowColumnsWithComment show columns info. func (sql *SQL) ShowColumnsWithComment(database string) ([]map[string]interface{}, error) { defer RecycleSQL(sql) return sql.diver.QueryWithConnection(sql.conn, sql.dialect.ShowColumnsWithComment(database, sql.TableName)) } // ShowTables show table info. func (sql *SQL) ShowTables() ([]string, error) { defer RecycleSQL(sql) models, err := sql.diver.QueryWithConnection(sql.conn, sql.dialect.ShowTables()) if err != nil { return []string{}, err } tables := make([]string, 0) if len(models) == 0 { return tables, nil } key := "Tables_in_" + sql.TableName if sql.diver.Name() == DriverPostgresql || sql.diver.Name() == DriverSqlite { key = "tablename" } else if sql.diver.Name() == DriverMssql { key = "TABLE_NAME" } else if _, ok := models[0][key].(string); !ok { key = "Tables_in_" + strings.ToLower(sql.TableName) } for i := 0; i < len(models); i++ { // skip sqlite system tables if sql.diver.Name() == DriverSqlite && models[i][key].(string) == "sqlite_sequence" { continue } tables = append(tables, models[i][key].(string)) } return tables, nil } // Update exec the update method of given key/value pairs. func (sql *SQL) Update(values dialect.H) (int64, error) { defer RecycleSQL(sql) sql.Values = values sql.dialect.Update(&sql.SQLComponent) res, err := sql.diver.ExecWith(sql.tx, sql.conn, sql.Statement, sql.Args...) if err != nil { return 0, err } if affectRow, _ := res.RowsAffected(); affectRow < 1 { return 0, errors.New("no affect row") } return res.LastInsertId() } // Delete exec the delete method. func (sql *SQL) Delete() error { defer RecycleSQL(sql) sql.dialect.Delete(&sql.SQLComponent) res, err := sql.diver.ExecWith(sql.tx, sql.conn, sql.Statement, sql.Args...) if err != nil { return err } if affectRow, _ := res.RowsAffected(); affectRow < 1 { return errors.New("no affect row") } return nil } // Exec exec the exec method. func (sql *SQL) Exec() (int64, error) { defer RecycleSQL(sql) sql.dialect.Update(&sql.SQLComponent) res, err := sql.diver.ExecWith(sql.tx, sql.conn, sql.Statement, sql.Args...) if err != nil { return 0, err } if affectRow, _ := res.RowsAffected(); affectRow < 1 { return 0, errors.New("no affect row") } return res.LastInsertId() } const postgresInsertCheckTableName = "goadmin_menu|goadmin_permissions|goadmin_roles|goadmin_users" // Insert exec the insert method of given key/value pairs. func (sql *SQL) Insert(values dialect.H) (int64, error) { defer RecycleSQL(sql) sql.Values = values sql.dialect.Insert(&sql.SQLComponent) if sql.diver.Name() == DriverPostgresql && (strings.Contains(postgresInsertCheckTableName, sql.TableName)) { resMap, err := sql.diver.QueryWith(sql.tx, sql.conn, sql.Statement+" RETURNING id", sql.Args...) if err != nil { // Fixed java h2 database postgresql mode _, err := sql.diver.QueryWith(sql.tx, sql.conn, sql.Statement, sql.Args...) if err != nil { return 0, err } res, err := sql.diver.QueryWithConnection(sql.conn, `SELECT max("id") as "id" FROM "`+sql.TableName+`"`) if err != nil { return 0, err } if len(res) != 0 { return res[0]["id"].(int64), nil } return 0, err } if len(resMap) == 0 { return 0, errors.New("no affect row") } return resMap[0]["id"].(int64), nil } res, err := sql.diver.ExecWith(sql.tx, sql.conn, sql.Statement, sql.Args...) if err != nil { return 0, err } if affectRow, _ := res.RowsAffected(); affectRow < 1 { return 0, errors.New("no affect row") } return res.LastInsertId() } func (sql *SQL) wrap(field string) string { return sql.diver.GetDelimiter() + field + sql.diver.GetDelimiter2() } func (sql *SQL) clean() { sql.Functions = make([]string, 0) sql.Group = "" sql.Values = make(map[string]interface{}) sql.Fields = make([]string, 0) sql.TableName = "" sql.Wheres = make([]dialect.Where, 0) sql.Leftjoins = make([]dialect.Join, 0) sql.Args = make([]interface{}, 0) sql.Order = "" sql.Offset = "" sql.Limit = "" sql.WhereRaws = "" sql.UpdateRaws = make([]dialect.RawUpdate, 0) sql.Statement = "" } // RecycleSQL clear the SQL and put into the pool. func RecycleSQL(sql *SQL) { logger.LogSQL(sql.Statement, sql.Args) sql.clean() sql.conn = "" sql.diver = nil sql.tx = nil sql.dialect = nil SQLPool.Put(sql) } ================================================ FILE: modules/db/statement_mssql_test.go ================================================ package db import ( "testing" "github.com/GoAdminGroup/go-admin/modules/config" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" ) var driverTestMssqlConn Connection func InitMssql() { driverTestMssqlConn = testConn(DriverMssql, config.Database{ Host: "127.0.0.1", Port: "1433", User: "sa", Pwd: "Aa123456", Name: "goadmin", }) } func TestMssqlSQL_WhereIn(t *testing.T) { testSQLWhereIn(t, driverTestMssqlConn) } func TestMssqlSQL_Count(t *testing.T) { testSQLCount(t, driverTestMssqlConn) } func TestMssqlSQL_Select(t *testing.T) { testSQLSelect(t, driverTestMssqlConn) } func TestMssqlSQL_OrderBy(t *testing.T) { testSQLOrderBy(t, driverTestMssqlConn) } func TestMssqlSQL_GroupBy(t *testing.T) { testSQLGroupBy(t, driverTestMssqlConn) } func TestMssqlSQL_Skip(t *testing.T) { testSQLSkip(t, driverTestMssqlConn) } func TestMssqlSQL_Take(t *testing.T) { testSQLTake(t, driverTestMssqlConn) } func TestMssqlSQL_Where(t *testing.T) { testSQLWhere(t, driverTestMssqlConn) } func TestMssqlSQL_WhereNotIn(t *testing.T) { testSQLWhereNotIn(t, driverTestMssqlConn) } func TestMssqlSQL_Find(t *testing.T) { testSQLFind(t, driverTestMssqlConn) } func TestMssqlSQL_Sum(t *testing.T) { testSQLSum(t, driverTestMssqlConn) } func TestMssqlSQL_Max(t *testing.T) { testSQLMax(t, driverTestMssqlConn) } func TestMssqlSQL_Min(t *testing.T) { testSQLMin(t, driverTestMssqlConn) } func TestMssqlSQL_Avg(t *testing.T) { testSQLAvg(t, driverTestMssqlConn) } func TestMssqlSQL_WhereRaw(t *testing.T) { testSQLWhereRaw(t, driverTestMssqlConn) } func TestMssqlSQL_UpdateRaw(t *testing.T) { testSQLUpdateRaw(t, driverTestMssqlConn) } func TestMssqlSQL_LeftJoin(t *testing.T) { testSQLLeftJoin(t, driverTestMssqlConn) } func TestMssqlSQL_WithTransaction(t *testing.T) { testSQLWithTransaction(t, driverTestMssqlConn) } func TestMssqlSQL_WithTransactionByLevel(t *testing.T) { testSQLWithTransactionByLevel(t, driverTestMssqlConn) } func TestMssqlSQL_First(t *testing.T) { testSQLFirst(t, driverTestMssqlConn) } func TestMssqlSQL_All(t *testing.T) { testSQLAll(t, driverTestMssqlConn) } func TestMssqlSQL_ShowColumns(t *testing.T) { testSQLShowColumns(t, driverTestMssqlConn) } func TestMssqlSQL_ShowTables(t *testing.T) { testSQLShowTables(t, driverTestMssqlConn) } func TestMssqlSQL_Update(t *testing.T) { testSQLUpdate(t, driverTestMssqlConn) } func TestMssqlSQL_Delete(t *testing.T) { testSQLDelete(t, driverTestMssqlConn) } func TestMssqlSQL_Exec(t *testing.T) { testSQLExec(t, driverTestMssqlConn) } func TestMssqlSQL_Insert(t *testing.T) { testSQLInsert(t, driverTestMssqlConn) } func TestMssqlSQL_Wrap(t *testing.T) { testSQLWrap(t, driverTestMssqlConn) } ================================================ FILE: modules/db/statement_mysql_test.go ================================================ package db import ( "fmt" "os/exec" "testing" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" ) var driverTestMysqlConn Connection const ( driverTestDBName = "go-admin-statement-test" ) func InitMysql() { c := testConnDSN(DriverMysql, fmt.Sprintf("root:root@tcp(127.0.0.1:3306)/%s", driverTestDBName)) _, err := c.Exec(fmt.Sprintf("create database if not exists `%s`", driverTestDBName)) if err != nil { panic(err) } cmd := exec.Command("mysql", "-u", "root", "-proot", driverTestDBName, "-e", "source "+testCurrentPath()+"/../../data/admin.sql") err = cmd.Run() if err != nil { panic(err) } driverTestMysqlConn = testConnDSN(DriverMysql, fmt.Sprintf("root:root@tcp(127.0.0.1:3306)/%s", driverTestDBName)) } func TestMysqlSQL_WhereIn(t *testing.T) { testSQLWhereIn(t, driverTestMysqlConn) } func TestMysqlSQL_Count(t *testing.T) { testSQLCount(t, driverTestMysqlConn) } func TestMysqlSQL_Select(t *testing.T) { testSQLSelect(t, driverTestMysqlConn) } func TestMysqlSQL_OrderBy(t *testing.T) { testSQLOrderBy(t, driverTestMysqlConn) } func TestMysqlSQL_GroupBy(t *testing.T) { testSQLGroupBy(t, driverTestMysqlConn) } func TestMysqlSQL_Skip(t *testing.T) { testSQLSkip(t, driverTestMysqlConn) } func TestMysqlSQL_Take(t *testing.T) { testSQLTake(t, driverTestMysqlConn) } func TestMysqlSQL_Where(t *testing.T) { testSQLWhere(t, driverTestMysqlConn) } func TestMysqlSQL_WhereNotIn(t *testing.T) { testSQLWhereNotIn(t, driverTestMysqlConn) } func TestMysqlSQL_Find(t *testing.T) { testSQLFind(t, driverTestMysqlConn) } func TestMysqlSQL_Sum(t *testing.T) { testSQLSum(t, driverTestMysqlConn) } func TestMysqlSQL_Max(t *testing.T) { testSQLMax(t, driverTestMysqlConn) } func TestMysqlSQL_Min(t *testing.T) { testSQLMin(t, driverTestMysqlConn) } func TestMysqlSQL_Avg(t *testing.T) { testSQLAvg(t, driverTestMysqlConn) } func TestMysqlSQL_WhereRaw(t *testing.T) { testSQLWhereRaw(t, driverTestMysqlConn) } func TestMysqlSQL_UpdateRaw(t *testing.T) { testSQLUpdateRaw(t, driverTestMysqlConn) } func TestMysqlSQL_LeftJoin(t *testing.T) { testSQLLeftJoin(t, driverTestMysqlConn) } func TestMysqlSQL_WithTransaction(t *testing.T) { testSQLWithTransaction(t, driverTestMysqlConn) } func TestMysqlSQL_WithTransactionByLevel(t *testing.T) { testSQLWithTransactionByLevel(t, driverTestMysqlConn) } func TestMysqlSQL_First(t *testing.T) { testSQLFirst(t, driverTestMysqlConn) } func TestMysqlSQL_All(t *testing.T) { testSQLAll(t, driverTestMysqlConn) } func TestMysqlSQL_ShowColumns(t *testing.T) { testSQLShowColumns(t, driverTestMysqlConn) } func TestMysqlSQL_ShowTables(t *testing.T) { testSQLShowTables(t, driverTestMysqlConn) } func TestMysqlSQL_Update(t *testing.T) { testSQLUpdate(t, driverTestMysqlConn) } func TestMysqlSQL_Delete(t *testing.T) { testSQLDelete(t, driverTestMysqlConn) } func TestMysqlSQL_Exec(t *testing.T) { testSQLExec(t, driverTestMysqlConn) } func TestMysqlSQL_Insert(t *testing.T) { testSQLInsert(t, driverTestMysqlConn) } func TestMysqlSQL_Wrap(t *testing.T) { testSQLWrap(t, driverTestMysqlConn) } ================================================ FILE: modules/db/statement_postgresql_test.go ================================================ package db import ( "fmt" "os" "os/exec" "path" "testing" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" ) var driverTestPgConn Connection func InitPostgresql() { cmd := exec.Command("createdb -p 5433 -U postgres " + driverTestDBName) cmd.Env = os.Environ() cmd.Env = append(cmd.Env, "PGPASSWORD=root") _ = cmd.Run() cmd = exec.Command("psql", "-h", "localhost", "-U", "root", "-proot", "-d", driverTestDBName, "-f", path.Dir(path.Dir(testCurrentPath()))+"/data/admin.pgsql") cmd.Env = os.Environ() cmd.Env = append(cmd.Env, "PGPASSWORD=root") err := cmd.Run() if err != nil { panic(err) } driverTestPgConn = testConnDSN(DriverPostgresql, fmt.Sprintf("host=127.0.0.1 port=5433 user=postgres "+ "password=root dbname=%s sslmode=disable", driverTestDBName)) } func TestPgSQL_WhereIn(t *testing.T) { testSQLWhereIn(t, driverTestPgConn) } func TestPgSQL_Count(t *testing.T) { testSQLCount(t, driverTestPgConn) } func TestPgSQL_Select(t *testing.T) { testSQLSelect(t, driverTestPgConn) } func TestPgSQL_OrderBy(t *testing.T) { testSQLOrderBy(t, driverTestPgConn) } func TestPgSQL_GroupBy(t *testing.T) { testSQLGroupBy(t, driverTestPgConn) } func TestPgSQL_Skip(t *testing.T) { testSQLSkip(t, driverTestPgConn) } func TestPgSQL_Take(t *testing.T) { testSQLTake(t, driverTestPgConn) } func TestPgSQL_Where(t *testing.T) { testSQLWhere(t, driverTestPgConn) } func TestPgSQL_WhereNotIn(t *testing.T) { testSQLWhereNotIn(t, driverTestPgConn) } func TestPgSQL_Find(t *testing.T) { testSQLFind(t, driverTestPgConn) } func TestPgSQL_Sum(t *testing.T) { testSQLSum(t, driverTestPgConn) } func TestPgSQL_Max(t *testing.T) { testSQLMax(t, driverTestPgConn) } func TestPgSQL_Min(t *testing.T) { testSQLMin(t, driverTestPgConn) } func TestPgSQL_Avg(t *testing.T) { testSQLAvg(t, driverTestPgConn) } func TestPgSQL_WhereRaw(t *testing.T) { testSQLWhereRaw(t, driverTestPgConn) } func TestPgSQL_UpdateRaw(t *testing.T) { testSQLUpdateRaw(t, driverTestPgConn) } func TestPgSQL_LeftJoin(t *testing.T) { testSQLLeftJoin(t, driverTestPgConn) } func TestPgSQL_WithTransaction(t *testing.T) { testSQLWithTransaction(t, driverTestPgConn) } func TestPgSQL_WithTransactionByLevel(t *testing.T) { testSQLWithTransactionByLevel(t, driverTestPgConn) } func TestPgSQL_First(t *testing.T) { testSQLFirst(t, driverTestPgConn) } func TestPgSQL_All(t *testing.T) { testSQLAll(t, driverTestPgConn) } func TestPgSQL_ShowColumns(t *testing.T) { testSQLShowColumns(t, driverTestPgConn) } func TestPgSQL_ShowTables(t *testing.T) { testSQLShowTables(t, driverTestPgConn) } func TestPgSQL_Update(t *testing.T) { testSQLUpdate(t, driverTestPgConn) } func TestPgSQL_Delete(t *testing.T) { testSQLDelete(t, driverTestPgConn) } func TestPgSQL_Exec(t *testing.T) { testSQLExec(t, driverTestPgConn) } func TestPgSQL_Insert(t *testing.T) { testSQLInsert(t, driverTestPgConn) } func TestPgSQL_Wrap(t *testing.T) { testSQLWrap(t, driverTestPgConn) } ================================================ FILE: modules/db/statement_sqlite_test.go ================================================ package db import ( "testing" "github.com/GoAdminGroup/go-admin/modules/config" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" ) var driverTestSQLiteConn Connection func InitSqlite() { driverTestSQLiteConn = testConn(DriverSqlite, config.Database{File: "/admin.db"}) } func TestSQLiteSQL_WhereIn(t *testing.T) { testSQLWhereIn(t, driverTestSQLiteConn) } func TestSQLiteSQL_Count(t *testing.T) { testSQLCount(t, driverTestSQLiteConn) } func TestSQLiteSQL_Select(t *testing.T) { testSQLSelect(t, driverTestSQLiteConn) } func TestSQLiteSQL_OrderBy(t *testing.T) { testSQLOrderBy(t, driverTestSQLiteConn) } func TestSQLiteSQL_GroupBy(t *testing.T) { testSQLGroupBy(t, driverTestSQLiteConn) } func TestSQLiteSQL_Skip(t *testing.T) { testSQLSkip(t, driverTestSQLiteConn) } func TestSQLiteSQL_Take(t *testing.T) { testSQLTake(t, driverTestSQLiteConn) } func TestSQLiteSQL_Where(t *testing.T) { testSQLWhere(t, driverTestSQLiteConn) } func TestSQLiteSQL_WhereNotIn(t *testing.T) { testSQLWhereNotIn(t, driverTestSQLiteConn) } func TestSQLiteSQL_Find(t *testing.T) { testSQLFind(t, driverTestSQLiteConn) } func TestSQLiteSQL_Sum(t *testing.T) { testSQLSum(t, driverTestSQLiteConn) } func TestSQLiteSQL_Max(t *testing.T) { testSQLMax(t, driverTestSQLiteConn) } func TestSQLiteSQL_Min(t *testing.T) { testSQLMin(t, driverTestSQLiteConn) } func TestSQLiteSQL_Avg(t *testing.T) { testSQLAvg(t, driverTestSQLiteConn) } func TestSQLiteSQL_WhereRaw(t *testing.T) { testSQLWhereRaw(t, driverTestSQLiteConn) } func TestSQLiteSQL_UpdateRaw(t *testing.T) { testSQLUpdateRaw(t, driverTestSQLiteConn) } func TestSQLiteSQL_LeftJoin(t *testing.T) { testSQLLeftJoin(t, driverTestSQLiteConn) } func TestSQLiteSQL_WithTransaction(t *testing.T) { testSQLWithTransaction(t, driverTestSQLiteConn) } func TestSQLiteSQL_WithTransactionByLevel(t *testing.T) { testSQLWithTransactionByLevel(t, driverTestSQLiteConn) } func TestSQLiteSQL_First(t *testing.T) { testSQLFirst(t, driverTestSQLiteConn) } func TestSQLiteSQL_All(t *testing.T) { testSQLAll(t, driverTestSQLiteConn) } func TestSQLiteSQL_ShowColumns(t *testing.T) { testSQLShowColumns(t, driverTestSQLiteConn) } func TestSQLiteSQL_ShowTables(t *testing.T) { testSQLShowTables(t, driverTestSQLiteConn) } func TestSQLiteSQL_Update(t *testing.T) { testSQLUpdate(t, driverTestSQLiteConn) } func TestSQLiteSQL_Delete(t *testing.T) { testSQLDelete(t, driverTestSQLiteConn) } func TestSQLiteSQL_Exec(t *testing.T) { testSQLExec(t, driverTestSQLiteConn) } func TestSQLiteSQL_Insert(t *testing.T) { testSQLInsert(t, driverTestSQLiteConn) } func TestSQLiteSQL_Wrap(t *testing.T) { testSQLWrap(t, driverTestSQLiteConn) } ================================================ FILE: modules/db/statement_test.go ================================================ package db import ( "database/sql" "testing" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" "github.com/magiconair/properties/assert" ) func testSQLWhereIn(t *testing.T, conn Connection) { item, _ := WithDriver(conn).Table("goadmin_users").WhereIn("id", []interface{}{"1", "2"}).First() assert.Equal(t, len(item), 2) _, _ = WithDriver(conn).WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) { item, _ := WithDriver(conn).WithTx(tx).Table("goadmin_users").WhereIn("id", []interface{}{"1", "2"}).All() assert.Equal(t, len(item), 2) return nil, nil }) } func testSQLCount(t *testing.T, conn Connection) { count, _ := WithDriver(conn).Table("goadmin_users").Count() assert.Equal(t, count, int64(2)) } // TODO func testSQLSelect(t *testing.T, conn Connection) {} // TODO func testSQLOrderBy(t *testing.T, conn Connection) {} // TODO func testSQLGroupBy(t *testing.T, conn Connection) {} // TODO func testSQLSkip(t *testing.T, conn Connection) {} // TODO func testSQLTake(t *testing.T, conn Connection) {} // TODO func testSQLWhere(t *testing.T, conn Connection) {} // TODO func testSQLWhereNotIn(t *testing.T, conn Connection) {} // TODO func testSQLFind(t *testing.T, conn Connection) {} // TODO func testSQLSum(t *testing.T, conn Connection) {} // TODO func testSQLMax(t *testing.T, conn Connection) {} // TODO func testSQLMin(t *testing.T, conn Connection) {} // TODO func testSQLAvg(t *testing.T, conn Connection) {} // TODO func testSQLWhereRaw(t *testing.T, conn Connection) {} // TODO func testSQLUpdateRaw(t *testing.T, conn Connection) {} // TODO func testSQLLeftJoin(t *testing.T, conn Connection) {} // TODO func testSQLWithTransaction(t *testing.T, conn Connection) {} // TODO func testSQLWithTransactionByLevel(t *testing.T, conn Connection) {} // TODO func testSQLFirst(t *testing.T, conn Connection) {} // TODO func testSQLAll(t *testing.T, conn Connection) {} // TODO func testSQLShowColumns(t *testing.T, conn Connection) {} // TODO func testSQLShowTables(t *testing.T, conn Connection) {} // TODO func testSQLUpdate(t *testing.T, conn Connection) {} // TODO func testSQLDelete(t *testing.T, conn Connection) {} // TODO func testSQLExec(t *testing.T, conn Connection) {} // TODO func testSQLInsert(t *testing.T, conn Connection) {} // TODO func testSQLWrap(t *testing.T, conn Connection) {} ================================================ FILE: modules/db/types.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package db import ( "fmt" "html/template" "strconv" ) // DatabaseType is the database field type. type DatabaseType string const ( // ================================= // integer // ================================= Int DatabaseType = "INT" Tinyint DatabaseType = "TINYINT" Mediumint DatabaseType = "MEDIUMINT" Smallint DatabaseType = "SMALLINT" Bigint DatabaseType = "BIGINT" Bit DatabaseType = "BIT" Int8 DatabaseType = "INT8" Int4 DatabaseType = "INT4" Int2 DatabaseType = "INT2" Integer DatabaseType = "INTEGER" Numeric DatabaseType = "NUMERIC" Smallserial DatabaseType = "SMALLSERIAL" Serial DatabaseType = "SERIAL" Bigserial DatabaseType = "BIGSERIAL" Money DatabaseType = "MONEY" // ================================= // float // ================================= Real DatabaseType = "REAL" Float DatabaseType = "FLOAT" Float4 DatabaseType = "FLOAT4" Float8 DatabaseType = "FLOAT8" Double DatabaseType = "DOUBLE" Decimal DatabaseType = "DECIMAL" Doubleprecision DatabaseType = "DOUBLEPRECISION" // ================================= // string // ================================= Date DatabaseType = "DATE" Time DatabaseType = "TIME" Year DatabaseType = "YEAR" Datetime DatabaseType = "DATETIME" Timestamp DatabaseType = "TIMESTAMP" Text DatabaseType = "TEXT" Longtext DatabaseType = "LONGTEXT" Mediumtext DatabaseType = "MEDIUMTEXT" Tinytext DatabaseType = "TINYTEXT" Varchar DatabaseType = "VARCHAR" Char DatabaseType = "CHAR" Bpchar DatabaseType = "BPCHAR" JSON DatabaseType = "JSON" Blob DatabaseType = "BLOB" Tinyblob DatabaseType = "TINYBLOB" Mediumblob DatabaseType = "MEDIUMBLOB" Longblob DatabaseType = "LONGBLOB" Interval DatabaseType = "INTERVAL" Boolean DatabaseType = "BOOLEAN" Bool DatabaseType = "BOOL" Point DatabaseType = "POINT" Line DatabaseType = "LINE" Lseg DatabaseType = "LSEG" Box DatabaseType = "BOX" Path DatabaseType = "PATH" Polygon DatabaseType = "POLYGON" Circle DatabaseType = "CIRCLE" Cidr DatabaseType = "CIDR" Inet DatabaseType = "INET" Macaddr DatabaseType = "MACADDR" Character DatabaseType = "CHARACTER" Varyingcharacter DatabaseType = "VARYINGCHARACTER" Nchar DatabaseType = "NCHAR" Nativecharacter DatabaseType = "NATIVECHARACTER" Nvarchar DatabaseType = "NVARCHAR" Clob DatabaseType = "CLOB" Binary DatabaseType = "BINARY" Varbinary DatabaseType = "VARBINARY" Enum DatabaseType = "ENUM" Set DatabaseType = "SET" Geometry DatabaseType = "GEOMETRY" Multilinestring DatabaseType = "MULTILINESTRING" Multipolygon DatabaseType = "MULTIPOLYGON" Linestring DatabaseType = "LINESTRING" Multipoint DatabaseType = "MULTIPOINT" Geometrycollection DatabaseType = "GEOMETRYCOLLECTION" Name DatabaseType = "NAME" UUID DatabaseType = "UUID" Timestamptz DatabaseType = "TIMESTAMPTZ" Timetz DatabaseType = "TIMETZ" ) // DT turn the string value into DatabaseType. func DT(s string) DatabaseType { return DatabaseType(s) } // GetDTAndCheck check the DatabaseType. func GetDTAndCheck(s string) DatabaseType { ss := DatabaseType(s) if !Contains(ss, BoolTypeList) && !Contains(ss, IntTypeList) && !Contains(ss, FloatTypeList) && !Contains(ss, UintTypeList) && !Contains(ss, StringTypeList) { panic("wrong type: " + s) } return ss } var ( // StringTypeList is a DatabaseType list of string. StringTypeList = []DatabaseType{Date, Time, Year, Datetime, Timestamptz, Timestamp, Timetz, Varchar, Char, Mediumtext, Longtext, Tinytext, Text, JSON, Blob, Tinyblob, Mediumblob, Longblob, Interval, Point, Bpchar, Line, Lseg, Box, Path, Polygon, Circle, Cidr, Inet, Macaddr, Character, Varyingcharacter, Nchar, Nativecharacter, Nvarchar, Clob, Binary, Varbinary, Enum, Set, Geometry, Multilinestring, Multipolygon, Linestring, Multipoint, Geometrycollection, Name, UUID, Timestamptz, Name, UUID, Inet} // BoolTypeList is a DatabaseType list of bool. BoolTypeList = []DatabaseType{Bool, Boolean} // IntTypeList is a DatabaseType list of integer. IntTypeList = []DatabaseType{Int4, Int2, Int8, Int, Tinyint, Mediumint, Smallint, Smallserial, Serial, Bigserial, Integer, Bigint} // FloatTypeList is a DatabaseType list of float. FloatTypeList = []DatabaseType{Float, Float4, Float8, Double, Real, Doubleprecision} // UintTypeList is a DatabaseType list of uint. UintTypeList = []DatabaseType{Decimal, Bit, Money, Numeric} ) // Contains check the given DatabaseType is in the list or not. func Contains(v DatabaseType, a []DatabaseType) bool { for _, i := range a { if i == v { return true } } return false } // Value is a string. type Value string // ToInt64 turn the string to a int64. func (v Value) ToInt64() int64 { value, err := strconv.ParseInt(string(v), 10, 64) if err != nil { panic("wrong value") } return value } // String return the string value. func (v Value) String() string { return string(v) } // HTML return the template.HTML value. func (v Value) HTML() template.HTML { return template.HTML(v) } func GetValueFromDatabaseType(typ DatabaseType, value interface{}, json bool) Value { if json { return GetValueFromJSONOfDatabaseType(typ, value) } else { return GetValueFromSQLOfDatabaseType(typ, value) } } // GetValueFromDatabaseType return Value of given DatabaseType and interface. func GetValueFromSQLOfDatabaseType(typ DatabaseType, value interface{}) Value { switch { case Contains(typ, StringTypeList): if v, ok := value.(string); ok { return Value(v) } if v2, ok2 := value.([]byte); ok2 { return Value(string(v2)) } return "" case Contains(typ, BoolTypeList): if v, ok := value.(bool); ok { if v { return "true" } return "false" } if v, ok := value.(int64); ok { if v == 0 { return "false" } return "true" } return "false" case Contains(typ, IntTypeList): if v, ok := value.(int64); ok { return Value(fmt.Sprintf("%d", v)) } return "0" case Contains(typ, FloatTypeList): if v, ok := value.(float64); ok { return Value(fmt.Sprintf("%f", v)) } return "0" case Contains(typ, UintTypeList): if v, ok := value.([]uint8); ok { return Value(string(v)) } return "0" } panic("wrong type:" + string(typ)) } // GetValueFromJSONOfDatabaseType return Value of given DatabaseType and interface from JSON string value. func GetValueFromJSONOfDatabaseType(typ DatabaseType, value interface{}) Value { switch { case Contains(typ, StringTypeList): if v, ok := value.(string); ok { return Value(v) } return "" case Contains(typ, BoolTypeList): if v, ok := value.(bool); ok { if v { return "true" } return "false" } return "false" case Contains(typ, IntTypeList): if v, ok := value.(float64); ok { return Value(fmt.Sprintf("%d", int64(v))) } return Value(fmt.Sprintf("%d", value)) case Contains(typ, FloatTypeList): return Value(fmt.Sprintf("%f", value)) case Contains(typ, UintTypeList): if v, ok := value.([]uint8); ok { return Value(string(v)) } return "0" } panic("wrong type:" + string(typ)) } ================================================ FILE: modules/db/types_test.go ================================================ package db import ( "fmt" "os" "regexp" "strings" "testing" "time" "github.com/GoAdminGroup/go-admin/modules/config" _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" "github.com/magiconair/properties/assert" ) const ( typeTestdbName = "go-admin-type-test" typeTesttableName = "all_types" typeTestpostgresCreateSql = `CREATE TABLE public.%s ( id integer NOT NULL, type_1 smallint, type_2 bigint, type_3 numeric, type_4 real, type_5 double precision, type_6 smallint NOT NULL DEFAULT nextval('all_types_type_6_seq'::regclass), type_7 integer NOT NULL DEFAULT nextval('all_types_type_7_seq'::regclass), type_8 bigint NOT NULL DEFAULT nextval('all_types_type_8_seq'::regclass), type_9 money, type_10 character varying COLLATE pg_catalog."default", type_11 character(1) COLLATE pg_catalog."default", type_12 text COLLATE pg_catalog."default", type_13 timestamp with time zone, type_14 time with time zone, type_15 date, type_16 timestamp without time zone, type_17 interval, type_18 point, type_19 line, type_20 lseg, type_21 box, type_22 path, type_23 polygon, type_24 circle, type_25 cidr, type_26 inet, type_27 macaddr, type_28 boolean, CONSTRAINT all_types_pkey PRIMARY KEY (id) ) WITH ( OIDS = FALSE ) TABLESPACE pg_default; ALTER TABLE public.all_types OWNER to postgres;` ) func TestMysqlGetTypeFromString(t *testing.T) { conn := testConnDSN(DriverMysql, fmt.Sprintf("root:root@tcp(127.0.0.1:3306)/%s", typeTestdbName)) _, err := conn.Exec(fmt.Sprintf("create database if not exists `%s`", typeTestdbName)) assert.Equal(t, err, nil) _, err = conn.Exec(fmt.Sprintf("DROP TABLE IF EXISTS `%s`;", typeTesttableName)) assert.Equal(t, err, nil) _, err = conn.Exec(fmt.Sprintf(`CREATE TABLE `+"`"+`%s`+"`"+` ( id int(11) unsigned NOT NULL AUTO_INCREMENT, `+testDelimiter("type_1")+` tinyint(11) DEFAULT NULL, `+testDelimiter("type_2")+` smallint(11) DEFAULT NULL, `+testDelimiter("type_3")+` mediumint(11) DEFAULT NULL, `+testDelimiter("type_4")+` bigint(11) DEFAULT NULL, `+testDelimiter("type_5")+` float DEFAULT NULL, `+testDelimiter("type_6")+` double(5,3) DEFAULT NULL, `+testDelimiter("type_7")+` double DEFAULT NULL, `+testDelimiter("type_8")+` double(5,3) DEFAULT NULL, `+testDelimiter("type_9")+` decimal(11,0) DEFAULT NULL, `+testDelimiter("type_10")+` bit(11) DEFAULT NULL, `+testDelimiter("type_11")+` tinyint(1) DEFAULT NULL, `+testDelimiter("type_12")+` tinyint(1) DEFAULT NULL, `+testDelimiter("type_13")+` decimal(10,5) DEFAULT NULL, `+testDelimiter("type_14")+` decimal(10,0) DEFAULT NULL, `+testDelimiter("type_15")+` decimal(10,0) DEFAULT NULL, `+testDelimiter("type_16")+` char(11) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `+testDelimiter("type_17")+` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `+testDelimiter("type_18")+` tinytext COLLATE utf8mb4_unicode_ci, `+testDelimiter("type_19")+` text COLLATE utf8mb4_unicode_ci, `+testDelimiter("type_20")+` mediumtext COLLATE utf8mb4_unicode_ci, `+testDelimiter("type_21")+` longtext COLLATE utf8mb4_unicode_ci, `+testDelimiter("type_22")+` tinyblob, `+testDelimiter("type_23")+` mediumblob, `+testDelimiter("type_24")+` blob, `+testDelimiter("type_25")+` longblob, `+testDelimiter("type_26")+` binary(1) DEFAULT NULL, `+testDelimiter("type_27")+` varbinary(1) DEFAULT NULL, `+testDelimiter("type_28")+` enum('RED','GREEN','BLUE') COLLATE utf8mb4_unicode_ci DEFAULT NULL, `+testDelimiter("type_29")+` set('RED','GREEN','BLUE') COLLATE utf8mb4_unicode_ci DEFAULT NULL, `+testDelimiter("type_30")+` date DEFAULT NULL, `+testDelimiter("type_31")+` datetime DEFAULT NULL, `+testDelimiter("type_32")+` timestamp NULL DEFAULT NULL, `+testDelimiter("type_33")+` time DEFAULT NULL, `+testDelimiter("type_34")+` year(4) DEFAULT NULL, `+testDelimiter("type_35")+` geometry DEFAULT NULL, `+testDelimiter("type_36")+` point DEFAULT NULL, `+testDelimiter("type_39")+` multilinestring DEFAULT NULL, `+testDelimiter("type_41")+` multipolygon DEFAULT NULL, `+testDelimiter("type_37")+` linestring DEFAULT NULL, `+testDelimiter("type_38")+` polygon DEFAULT NULL, `+testDelimiter("type_40")+` multipoint DEFAULT NULL, `+testDelimiter("type_42")+` geometrycollection DEFAULT NULL, `+testDelimiter("type_50")+` double(5,2) DEFAULT NULL, `+testDelimiter("type_51")+` json DEFAULT NULL, PRIMARY KEY (`+"`"+`id`+"`"+`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;`, typeTesttableName)) assert.Equal(t, err, nil) _, err = conn.Exec(`INSERT INTO ` + testDelimiter(typeTesttableName) + ` (id, type_1, type_2, type_3, type_4, type_5, type_6, type_7, type_8, type_9, type_10, type_11, type_12, type_13, type_14, type_15, type_16, type_17, type_18, type_19, type_20, type_21, type_22, type_23, type_24, type_25, type_26, type_27, type_28, type_29, type_30, type_31, type_32, type_33, type_34, type_35, type_36, type_39, type_41, type_37, type_38, type_40, type_42, type_50, type_51) VALUES (1, 1, 1, 1, 1, 1, 1.000, 1, 1.000, 1, 0, 1, 1, 1.00000, 1, 1, '1', '1', '1', '1', '1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2001', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);`) assert.Equal(t, err, nil) typeField := "Type" fieldField := "Field" conn = testConnDSN(DriverMysql, fmt.Sprintf("root:root@tcp(127.0.0.1:3306)/%s?charset=utf8mb4", typeTestdbName)) config.Initialize(&config.Config{ SqlLog: true, }) columnsModel, _ := WithDriver(conn).Table(typeTesttableName).ShowColumns() item, err := WithDriver(conn).Table(typeTesttableName).First() for _, model := range columnsModel { fieldTypeName := strings.ToUpper(testGetType(model[typeField].(string))) GetDTAndCheck(fieldTypeName) GetValueFromSQLOfDatabaseType(DatabaseType(fieldTypeName), item[model[fieldField].(string)]) } assert.Equal(t, err, nil) } func TestPostgresqlGetTypeFromString(t *testing.T) { // pg 11 testPG(t, "5433") // pg 12 //testPG(t, "5434") } func testPG(t *testing.T, port string) { connStatement := "host=127.0.0.1 port=" + port + " user=postgres password=root dbname=%s sslmode=disable" conn := testConnDSN(DriverPostgresql, fmt.Sprintf(connStatement, typeTestdbName)) fmt.Println("creating database") _, err := conn.Exec(fmt.Sprintf(`SELECT 'CREATE DATABASE %s' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '%s')`, typeTestdbName, typeTestdbName)) assert.Equal(t, err, nil) fmt.Println("drop table") _, err = conn.Exec(fmt.Sprintf("DROP TABLE IF EXISTS `%s`;", typeTesttableName)) assert.Equal(t, err, nil) fmt.Println("create sequence all_types_type_6_seq") _, err = conn.Exec(`CREATE SEQUENCE IF NOT EXISTS public.all_types_type_6_seq START 1;`) assert.Equal(t, err, nil) fmt.Println("create sequence all_types_type_7_seq") _, err = conn.Exec(`CREATE SEQUENCE IF NOT EXISTS public.all_types_type_7_seq START 1;`) assert.Equal(t, err, nil) fmt.Println("create sequence all_types_type_8_seq") _, err = conn.Exec(`CREATE SEQUENCE IF NOT EXISTS public.all_types_type_8_seq START 1;`) assert.Equal(t, err, nil) fmt.Println("create table") _, err = conn.Exec(fmt.Sprintf(typeTestpostgresCreateSql, typeTesttableName)) assert.Equal(t, err, nil) fmt.Println("insert data") _, err = conn.Exec(`INSERT INTO public.` + typeTesttableName + `( id, type_1, type_2, type_3, type_4, type_5, type_6, type_7, type_8, type_9, type_10, type_11, type_12, type_13, type_14, type_15, type_16, type_17, type_18, type_19, type_20, type_21, type_22, type_23, type_24, type_25, type_26, type_27, type_28) VALUES (1, 1, 1, 0.3, 1, 1, 1, 1, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'n');`) assert.Equal(t, err, nil) typeField := "udt_name" fieldField := "column_name" conn = testConnDSN(DriverPostgresql, fmt.Sprintf(connStatement, typeTestdbName)) config.Initialize(&config.Config{ SqlLog: true, }) columnsModel, _ := WithDriver(conn).Table(typeTesttableName).ShowColumns() item, err := WithDriver(conn).Table(typeTesttableName).First() for _, model := range columnsModel { fieldTypeName := strings.ToUpper(testGetType(model[typeField].(string))) fmt.Println("fieldTypeName", fieldTypeName) GetDTAndCheck(fieldTypeName) fmt.Println(model[fieldField].(string), GetValueFromSQLOfDatabaseType(DatabaseType(fieldTypeName), item[model[fieldField].(string)])) } assert.Equal(t, err, nil) } // ******************************* // test helper methods // ******************************* func testGetType(typeName string) string { r, _ := regexp.Compile(`\((.*?)\)`) typeName = r.ReplaceAllString(typeName, "") return strings.ToLower(strings.ReplaceAll(typeName, " unsigned", "")) } func testConnDSN(driver, dsn string) Connection { return GetConnectionByDriver(driver).InitDB(map[string]config.Database{ "default": {Dsn: dsn}, }) } func testConn(driver string, cfg config.Database) Connection { cfg.Driver = driver cfg.MaxIdleConns = 10 cfg.MaxOpenConns = 80 cfg.ConnMaxLifetime = time.Hour cfg.ConnMaxIdleTime = 0 return GetConnectionByDriver(driver).InitDB(map[string]config.Database{ "default": cfg, }) } func testDelimiter(s string) string { return "`" + s + "`" } func testCurrentPath() string { dir, err := os.Getwd() if err != nil { panic(err) } return dir } ================================================ FILE: modules/errors/error.go ================================================ package errors import ( "errors" "html/template" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/template/icon" ) var ( Msg string MsgHTML template.HTML MsgWithIcon template.HTML ) const ( PermissionDenied = "permission denied" WrongID = "wrong id" OperationNotAllow = "operation not allow" EditFailWrongToken = "edit fail, wrong token" CreateFailWrongToken = "create fail, wrong token" NoPermission = "no permission" SiteOff = "site is off" ) func WrongPK(pk string) string { return "wrong " + pk } func Init() { Msg = language.Get("error") MsgHTML = language.GetFromHtml("error") MsgWithIcon = icon.Icon(icon.Warning, 2) + MsgHTML + `!` PageError404 = errors.New(language.Get("not found")) PageError500 = errors.New(language.Get("internal error")) PageError403 = errors.New(language.Get("permission denied")) PageError401 = errors.New(language.Get("unauthorized")) } type PageError error var ( PageError404 PageError PageError500 PageError PageError403 PageError PageError401 PageError ) ================================================ FILE: modules/file/file.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package file import ( "fmt" "io" "mime/multipart" "os" "path" "sync" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" ) // Uploader is a file uploader which contains the method Upload. type Uploader interface { Upload(*multipart.Form) error } // UploaderGenerator is a function return an Uploader. type UploaderGenerator func() Uploader var uploaderList = map[string]UploaderGenerator{ "local": GetLocalFileUploader, } var upMu sync.Mutex // AddUploader makes a uploader generator available by the provided theme name. // If Add is called twice with the same name or if uploader is nil, // it panics. func AddUploader(name string, up UploaderGenerator) { upMu.Lock() defer upMu.Unlock() if up == nil { panic("uploader generator is nil") } if _, dup := uploaderList[name]; dup { panic("add uploader generator twice " + name) } uploaderList[name] = up } // GetFileEngine return the Uploader of given name. func GetFileEngine(name string) Uploader { if up, ok := uploaderList[name]; ok { return up() } panic("wrong uploader name") } // UploadFun is a function to process the uploading logic. type UploadFun func(*multipart.FileHeader, string) (string, error) // Upload receive the return value of given UploadFun and put them into the form. func Upload(c UploadFun, form *multipart.Form) error { var ( suffix string filename string ) for k := range form.File { for _, fileObj := range form.File[k] { suffix = path.Ext(fileObj.Filename) filename = modules.Uuid() + suffix pathStr, err := c(fileObj, filename) if err != nil { return err } form.Value[k] = append(form.Value[k], pathStr) form.Value[k+"_size"] = append(form.Value[k+"_size"], fmt.Sprintf("%d", fileObj.Size)) } } return nil } // SaveMultipartFile used in a local Uploader which help to save file in the local path. func SaveMultipartFile(fh *multipart.FileHeader, path string) error { f, err := fh.Open() if err != nil { return err } if ff, ok := f.(*os.File); ok { // Windows can't rename files that are opened. if err := f.Close(); err != nil { return err } // If renaming fails we try the normal copying method. // Renaming could fail if the files are on different devices. if os.Rename(ff.Name(), path) == nil { return nil } // Reopen f for the code below. f, err = fh.Open() if err != nil { return err } } defer func() { if err2 := f.Close(); err2 != nil { err = err2 } }() ff, err := os.Create(path) if err != nil { return err } defer func() { if err2 := ff.Close(); err2 != nil { err = err2 } }() _, err = copyZeroAlloc(ff, f) return err } func copyZeroAlloc(w io.Writer, r io.Reader) (int64, error) { buf := copyBufPool.Get().([]byte) n, err := io.CopyBuffer(w, r, buf) copyBufPool.Put(buf) return n, err } var copyBufPool = sync.Pool{ New: func() interface{} { return make([]byte, 4096) }, } ================================================ FILE: modules/file/local.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package file import ( "mime/multipart" "github.com/GoAdminGroup/go-admin/modules/config" ) // LocalFileUploader is an Uploader of local file engine. type LocalFileUploader struct { BasePath string } // GetLocalFileUploader return the default Uploader. func GetLocalFileUploader() Uploader { return &LocalFileUploader{ config.GetStore().Path, } } // Upload implements the Uploader.Upload. func (local *LocalFileUploader) Upload(form *multipart.Form) error { return Upload(func(fileObj *multipart.FileHeader, filename string) (string, error) { if err := SaveMultipartFile(fileObj, (*local).BasePath+"/"+filename); err != nil { return "", err } return filename, nil }, form) } ================================================ FILE: modules/language/cn.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package language import "strings" var cn = LangSet{ "managers": "管理员", "managers manage": "管理员管理", "name": "用户名", "nickname": "昵称", "role": "角色", "createdat": "创建时间", "updatedat": "更新时间", "path": "路径", "submit": "提交", "filter": "筛选", "new": "新建", "export": "导出", "action": "操作", "toggle dropdown": "下拉", "delete": "删除", "refresh": "刷新", "back": "返回", "reset": "重置", "save": "保存", "edit": "编辑", "expand": "展开", "collapse": "折叠", "online": "在线", "setting": "设置", "sign out": "登出", "home": "首页", "all": "全部", "more": "更多", "browse": "打开", "remove": "移除", "permission manage": "权限管理", "menus": "菜单", "menus manage": "菜单管理", "roles manage": "角色管理", "operation log": "操作日志", "method": "方法", "input": "输入", "operation": "操作", "menu name": "菜单名", "reload succeeded": "加载成功", "search": "搜索", "permission denied": "没有权限", "error": "错误", "success": "成功", "fail": "失败", "current page": "当前页", "goadmin is now running. \nrunning in \"debug\" mode. switch to \"release\" mode in production.\n\n": "GoAdmin 启动成功。\n目前处于 \"debug\" 模式。请在生产环境中切换为 \"release\" 模式。\n\n", "wrong goadmin version, theme %s required goadmin version are %s": "错误的 GoAdmin 版本,当前主题 %s 需要 GoAdmin 版本为 %s", "wrong theme version, goadmin %s required version of theme %s is %s": "错误的主题版本, GoAdmin %s 需要主题 %s 的版本为 %s", "adapter is nil, import the default adapter or use addadapter method add the adapter": "适配器为空,请先 import 对应的适配器或使用 AddAdapter 方法引入", "are you sure to delete": "你确定要删除吗?", "yes": "确定", "confirm": "确认", "got it": "知道了", "cancel": "取消", "refresh succeeded": "刷新成功", "delete succeed": "删除成功", "edit fail": "编辑失败", "create fail": "新增失败", "delete fail": "删除失败", "confirm password": "确认密码", "all method if empty": "为空默认为所有方法", "detail": "详情", "query time": "查询时间", "avatar": "头像", "password": "密码", "username": "用户名", "slug": "标志", "permission": "权限", "userid": "用户ID", "content": "内容", "parent": "父级", "icon": "图标", "uri": "路径", "close": "关闭", "login": "登录", "login fail": "登录失败", "admin": "管理", "user": "用户", "users": "用户", "roles": "角色", "menu": "菜单", "dashboard": "仪表盘", "continue editing": "继续编辑", "continue creating": "继续新增", "username and password can not be empty": "用户名密码不能为空", "operation not allow": "不允许的操作", "password does not match": "密码不一致", "should be unique": "需要保证唯一", "slug exists": "标志已经存在了", "no corresponding options?": "没找到对应选项?", "create here.": "在这里新建一个。", "use for login": "用于登录", "use to display": "用来展示", "a path a line, without global prefix": "一行一个路径,换行输入新路径,路径不包含全局路由前缀", "slug or http_path or name should not be empty": "标志或路径或权限名不能为空", "no roles": "无角色", "no permission": "没有权限", "fixed the sidebar": "固定侧边栏", "enter fullscreen": "进入全屏", "exit fullscreen": "退出全屏", "wrong captcha": "错误的验证码", "modify success": "修改成功", "not found": "找不到记录", "internal error": "系统内部错误", "unauthorized": "未认证", "login overdue, please login again": "登录信息过期,请重新登录", "login info": "登录信息", "initialize configuration": "初始化配置", "initialize navigation buttons": "初始化导航栏按钮", "initialize plugins": "初始化插件", "initialize database connections": "初始化数据库连接", "initialize success": "初始化成功🍺🍺", "plugins": "插件", "plugin store": "插件商店", "get more plugins": "获取更多插件", "uninstalled": "未安装", "plugin setting": "插件设置", "view": "查看", "del": "删除", "showing %s to %s of %s entries": "显示第 %s 到第 %s 条记录,总共 %s 条记录", "second": "秒", "seconds": "秒", "minute": "分", "minutes": "分", "hour": "小时", "hours": "小时", "day": "天", "days": "天", "week": "周", "weeks": "周", "month": "月", "months": "月", "year": "年", "years": "年", "site setting": "网站设置", "config.site setting": "网站设置", "config.domain": "网站域名", "config.language": "网站语言", "config.url prefix": "URL前缀", "config.theme": "主题", "config.title": "标题", "config.index url": "首页URL", "config.login url": "登录URL", "config.env": "开发环境", "config.color scheme": "颜色主题", "config.cdn url": "cdn资源URL", "config.login title": "登录标题", "config.auth user table": "登录用户表", "config.extra": "额外配置", "config.store": "文件存储设置", "config.databases": "数据库设置", "config.general": "通用", "config.log": "日志", "config.custom": "定制", "config.debug": "Debug模式", "config.site off": "关闭网站", "config.true": "是", "config.false": "否", "config.test": "测试环境", "config.prod": "生产环境", "config.local": "本地环境", "config.logo": "Logo", "config.mini logo": "Mini Logo", "config.session life time": "Session时长", "config.bootstrap file path": "插件文件路径", "config.go mod file path": "go.mod文件路径", "config.custom head html": "自定义Head HTML", "config.custom foot html": "自定义Foot HTML", "config.custom 404 html": "自定义404页面", "config.custom 403 html": "自定义403页面", "config.custom 500 html": "自定义500页面", "config.hide config center entrance": "隐藏配置中心入口", "config.hide app info entrance": "隐藏应用信息入口", "config.hide tool entrance": "隐藏工具入口", "config.hide plugin entrance": "隐藏插件列表入口", "config.footer info": "自定义底部信息", "config.login logo": "登录Logo", "config.no limit login ip": "取消限制多IP登录", "config.operation log off": "关闭操作日志", "config.allow delete operation log": "允许删除操作日志", "config.animation type": "动画类型", "config.animation duration": "动画间隔(秒)", "config.animation delay": "动画延迟(秒)", "config.file upload engine": "文件上传引擎", "config.logger rotate": "日志切割设置", "config.logger rotate max size": "存储最大文件大小(m)", "config.logger rotate max backups": "存储最多文件数", "config.logger rotate max age": "最长存储时间(天)", "config.logger rotate compress": "压缩", "config.info log path": "信息日志存储路径", "config.error log path": "错误日志存储路径", "config.access log path": "访问日志存储路径", "config.info log off": "关闭信息日志", "config.error log off": "关闭错误日志", "config.access log off": "关闭访问日志", "config.access assets log off": "关闭静态资源访问日志", "config.sql log on": "打开SQL日志", "config.log level": "日志级别", "config.logger rotate encoder": "日志encoder设置", "config.logger rotate encoder time key": "Time Key", "config.logger rotate encoder level key": "Level Key", "config.logger rotate encoder name key": "Name Key", "config.logger rotate encoder caller key": "Caller Key", "config.logger rotate encoder message key": "Message Key", "config.logger rotate encoder stacktrace key": "Stacktrace Key", "config.logger rotate encoder level": "Level字段编码", "config.logger rotate encoder time": "Time字段编码", "config.logger rotate encoder duration": "Duration字段编码", "config.logger rotate encoder caller": "Caller字段编码", "config.logger rotate encoder encoding": "输出格式", "config.capital": "大写", "config.capitalcolor": "大写带颜色", "config.lowercase": "小写", "config.lowercasecolor": "小写带颜色", "config.seconds": "秒", "config.nanosecond": "纳秒", "config.microsecond": "微秒", "config.millisecond": "毫秒", "config.full path": "完整路径", "config.short path": "简短路径", "config.do not modify when you have not set up all assets": "不要修改,当你还没有设置好所有资源文件的时候", "config.it will work when theme is adminlte": "当主题为adminlte时生效", "config.must bigger than 900 seconds": "必须大于900秒", "config.language." + CN: "中文", "config.language." + EN: "英文", "config.language." + JP: "日文", "config.language." + strings.ToLower(TC): "繁体中文", "config.language." + PTBR: "Brazilian Portuguese", "config.language." + RU: "Русский", "config.modify site config": "修改网站配置", "config.modify site config success": "修改网站配置成功", "config.modify site config fail": "修改网站配置失败", "site info": "运行信息", "system.site info": "运行信息", "system.application": "应用信息", "system.application run": "应用运行信息", "system.system": "系统信息", "system.process_id": "进程ID", "system.golang_version": "Golang版本", "system.server_uptime": "服务运行时间", "system.current_goroutine": "当前 Goroutines 数量", "system.current_memory_usage": "当前内存使用量", "system.total_memory_allocated": "所有被分配的内存", "system.memory_obtained": "内存占用量", "system.pointer_lookup_times": "指针查找次数", "system.memory_allocate_times": "内存分配次数", "system.memory_free_times": "内存释放次数", "system.current_heap_usage": "当前 Heap 内存使用量", "system.heap_memory_obtained": "Heap 内存占用量", "system.heap_memory_idle": "Heap 内存空闲量", "system.heap_memory_in_use": "正在使用的 Heap 内存", "system.heap_memory_released": "被释放的 Heap 内存", "system.heap_objects": "Heap 对象数量", "system.bootstrap_stack_usage": "启动 Stack 使用量", "system.stack_memory_obtained": "被分配的 Stack 内存", "system.mspan_structures_usage": "MSpan 结构内存使用量", "system.mspan_structures_obtained": "被分配的 MSpan 结构内存", "system.mcache_structures_usage": "MCache 结构内存使用量", "system.mcache_structures_obtained": "被分配的 MCache 结构内存", "system.profiling_bucket_hash_table_obtained": "被分配的剖析哈希表内存", "system.gc_metadata_obtained": "被分配的 GC 元数据内存", "system.other_system_allocation_obtained": "其它被分配的系统内存", "system.next_gc_recycle": "下次 GC 内存回收量", "system.last_gc_time": "距离上次 GC 时间", "system.total_gc_time": "GC 执行时间总量", "system.total_gc_pause": "GC 暂停时间总量", "system.last_gc_pause": "上次 GC 暂停时间", "system.gc_times": "GC 执行次数", "system.cpu_logical_core": "cpu逻辑核数", "system.cpu_core": "cpu物理核数", "system.os_platform": "系统平台", "system.os_family": "系统家族", "system.os_version": "系统版本", "system.load1": "1分钟内负载", "system.load5": "5分钟内负载", "system.load15": "15分钟内负载", "system.mem_total": "总内存", "system.mem_available": "可用内存", "system.mem_used": "使用内存", "system.app_name": "应用名", "system.go_admin_version": "应用版本", "system.theme_name": "主题", "system.theme_version": "主题版本", "code generate tool": "代码生成器", "tool.code generate tool": "代码生成器", "tool.table": "表格", "tool.connection": "连接", "tool.output path is empty": "输出路径为空", "tool.package": "包名", "tool.output": "输出路径", "tool.field": "字段", "tool.title": "标题", "tool.field name": "字段名", "tool.db type": "数据类型", "tool.form type": "表单类型", "tool.generate table model": "生成CRUD模型", "tool.primarykey": "主键", "tool.field filterable": "可筛选", "tool.field sortable": "可排序", "tool.yes": "是", "tool.no": "否", "tool.hide": "隐藏", "tool.show": "显示", "tool.generate success": "生成成功", "tool.display": "显示", "tool.use absolute path": "使用绝对路径", "tool.basic info": "基本信息", "tool.table info": "表格信息", "tool.form info": "表单信息", "tool.field editable": "允许编辑", "tool.field can add": "允许新增", "tool.info field editable": "可编辑", "tool.field default": "默认值", "tool.filter area": "筛选框", "tool.new button": "新建按钮", "tool.export button": "导出按钮", "tool.edit button": "编辑按钮", "tool.delete button": "删除按钮", "tool.extra import package": "导入包", "tool.detail button": "详情按钮", "tool.filter button": "筛选按钮", "tool.row selector": "列选择按钮", "tool.pagination": "分页", "tool.query info": "查询信息", "tool.filter form layout": "筛选表单布局", "tool.generate": "生成", "tool.generated tables": "生成过的表格", "tool.description": "描述", "tool.label": "标签", "tool.image": "图片", "tool.bool": "布尔", "tool.link": "链接", "tool.fileSize": "文件大小", "tool.date": "日期", "tool.icon": "Icon", "tool.dot": "标点", "tool.progressBar": "进度条", "tool.loading": "Loading", "tool.downLoadable": "可下载", "tool.copyable": "可复制", "tool.carousel": "图片轮播", "tool.qrcode": "二维码", "tool.field hide": "隐藏", "tool.field display": "显示", "tool.table permission": "生成表格权限", "tool.extra code": "额外代码", "tool.detail display": "显示", "tool.detail info": "详情页信息", "tool.follow list page": "跟随列表页", "tool.inherit from list page": "继承列表页", "tool.independent from list page": "独立", "tool.continue edit checkbox": "继续编辑按钮", "tool.continue new checkbox": "继续新增按钮", "tool.reset button": "重设按钮", "tool.back button": "返回按钮", "tool.field display normal": "显示", "tool.field diplay hide": "隐藏", "tool.field diplay edit hide": "编辑隐藏", "tool.field diplay create hide": "新建隐藏", "tool.generate table model success": "生成成功", "tool.generate table model fail": "生成失败", "generator.query": "查询", "generator.show edit form page": "编辑页显示", "generator.show create form page": "新建记录页显示", "generator.edit": "编辑", "generator.create": "新建", "generator.delete": "删除", "generator.export": "导出", "plugin.plugin": "插件", "plugin.plugin detail": "插件详情", "plugin.introduction": "介绍", "plugin.website": "网站", "plugin.version": "版本", "plugin.created at": "创建日期", "plugin.updated at": "更新日期", "plugin.provided by %s": "由 %s 提供", "plugin.upgrade": "升级", "plugin.install": "安装", "plugin.info": "详细信息", "plugin.download": "下载", "plugin.buy": "购买", "plugin.downloading": "下载中", "plugin.login": "登录", "plugin.login to goadmin member system": "登录到GoAdmin会员系统", "plugin.account": "账户名", "plugin.password": "密码", "plugin.learn more": "了解更多", "plugin.no account? click %s here %s to register.": "没有账号?点击%s这里%s注册。", "plugin.download fail, wrong name": "下载失败,错误的参数", "plugin.change to debug mode first": "先切换到debug模式", "plugin.download fail, plugin not exist": "下载失败,插件不存在", "plugin.download fail": "下载失败", "plugin.golang develop environment does not exist": "golang开发环境不存在", "plugin.download success, restart to install": "下载成功,重启程序进行安装", "plugin.restart to install": "重启程序进行安装", "plugin.can not connect to the goadmin remote server": "连接到GoAdmin远程服务器失败,请检查您的网络连接。", "admin.basic admin": "基础Admin", "admin.a built-in plugins of goadmin which help you to build a crud manager platform quickly.": "一个内置GoAdmin插件,帮助您快速搭建curd简易管理后台。", "admin.official": "GoAdmin官方", } ================================================ FILE: modules/language/en.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package language import "strings" var en = LangSet{ "managers": "Managers", "name": "Name", "nickname": "Nickname", "role": "Role", "createdat": "createdAt", "updatedat": "updatedAt", "path": "path", "new": "New", "filter": "Filter", "action": "Action", "toggle dropdown": "Toggle Dropdown", "delete": "Delete", "refresh": "Refresh", "expand": "Expand", "collapse": "Collapse", "back": "Back", "reset": "Reset", "save": "Save", "edit": "Edit", "operation": "Operation", "method": "Method", "input": "input", "online": "Online", "setting": "Setting", "sign out": "Sign out", "all": "All", "confirm password": "Confirm Password", "search": "Search", "remove": "Remove", "goadmin is now running. \nrunning in \"debug\" mode. switch to \"release\" mode in production.\n\n": "GoAdmin is now running. \nRunning in \"debug\" mode. Switch to \"release\" mode in production.\n\n", "wrong goadmin version, theme %s required goadmin version are %s": "wrong GoAdmin version, theme %s required GoAdmin version are %s", "wrong theme version, goadmin %s required version of theme %s is %s": "wrong Theme version, GoAdmin %s required version of theme %s is %s", "adapter is nil, import the default adapter or use addadapter method add the adapter": "adapter is nil, import the default adapter or use AddAdapter method add the adapter", "are you sure to delete": "Are you sure to delete", "yes": "yes", "got it": "got it", "cancel": "cancel", "refresh succeeded": "Refresh succeeded", "reload succeeded": "Reload succeeded", "all method if empty": "All method if empty", "password does not match": "Password does not match", "should be unique": "Should be unique", "slug exists": "Slug exists", "no corresponding options?": "No corresponding options?", "create here.": "Create here.", "use for login": "Use for login", "use to display": "Use to display", "a path a line, without global prefix": "A path a line", "slug or http_path or name should not be empty": "slug or http_path or name should not be empty", "no roles": "no roles", "fixed the sidebar": "Fixed the sidebar", "enter fullscreen": "Enter fullscreen", "exit fullscreen": "Exit fullscreen", "permission manage": "Permission Manage", "menus manage": "Menus Manage", "roles manage": "Roles manage", "operation log": "Operation log", "continue editing": "Continue editing", "continue creating": "Continue creating", "browse": "Browse", "avatar": "Avatar", "password": "Password", "username": "Username", "slug": "Slug", "permission": "Permission", "userid": "UserID", "content": "Content", "parent": "Parent", "icon": "Icon", "uri": "Uri", "detail": "Detail", "admin": "Admin", "users": "Users", "roles": "Roles", "menu": "Menu", "dashboard": "Dashboard", "home": "Home", "initialize configuration": "Initialize configuration", "initialize navigation buttons": "Initialize navigation buttons", "initialize plugins": "Initialize plugins", "initialize database connections": "Initialize database connections", "initialize success": "Initialize success🍺🍺", "not found": "Not found", "internal error": "Internal error", "unauthorized": "Unauthorized", "plugin setting": "Plugin Setting", "plugins": "Plugins", "plugin store": "Plugin Store", "get more plugins": "Get more plugins", "uninstalled": "Uninstalled", "second": "second", "seconds": "seconds", "minute": "minute", "minutes": "minutes", "hour": "hour", "hours": "hours", "day": "day", "days": "days", "week": "week", "weeks": "weeks", "month": "month", "months": "months", "year": "year", "years": "years", "config.domain": "Website Domain", "config.language": "Website Language", "config.url prefix": "URL Prefix", "config.theme": "Theme", "config.title": "Title", "config.index url": "Home URL", "config.login url": "Login URL", "config.env": "Env", "config.color scheme": "Color Scheme", "config.cdn url": "CDN Asset URL", "config.login title": "Login Title", "config.auth user table": "Auth User Table", "config.extra": "Extra Configuration", "config.store": "File Store Setting", "config.databases": "Database Setting", "config.general": "General", "config.log": "Log", "config.site setting": "Site Settings", "config.custom": "Customize", "config.debug": "Debug Mode", "config.site off": "Site Offline", "config.true": "On", "config.false": "Off", "config.logo": "Logo", "config.mini logo": "Mini Logo", "config.bootstrap file path": "Bootstrap File Path", "config.go mod file path": "go.mod File Path", "config.session life time": "Session Life Time", "config.custom head html": "Head HTML", "config.custom foot html": "Foot HTML", "config.custom 404 html": "404 Page", "config.custom 403 html": "403 Page", "config.custom 500 html": "500 Page", "config.hide config center entrance": "Hide Config Button", "config.hide app info entrance": "Hide App Info Button", "config.hide tool entrance": "Hide Tool Button", "config.footer info": "Footer Info", "config.login logo": "Login Logo", "config.no limit login ip": "No Limit Login Multi IPs", "config.operation log off": "Operation Log Off", "config.allow delete operation log": "Allow Delete Operation Log", "config.animation type": "Animation Type", "config.animation duration": "Animation Duration(s)", "config.animation delay": "Animation Delay(s)", "config.file upload engine": "File Upload Engine", "config.logger rotate": "Log Rotate Settings", "config.logger rotate max size": "Max Size(m)", "config.logger rotate max backups": "Max Buckups", "config.logger rotate max age": "Max Age(day)", "config.logger rotate compress": "Compress", "config.info log path": "Info Log File Path", "config.error log path": "Error Log File Path", "config.access log path": "Access Log File Path", "config.info log off": "Info Log Off", "config.error log off": "Error Log Off", "config.access log off": "Access Log Off", "config.access assets log off": "Access Assets Log Off", "config.sql log on": "Open SQL Log", "config.log level": "Level", "config.logger rotate encoder": "Log Encoder Settings", "config.logger rotate encoder time key": "Time Key", "config.logger rotate encoder level key": "Level Key", "config.logger rotate encoder name key": "Name Key", "config.logger rotate encoder caller key": "Caller Key", "config.logger rotate encoder message key": "Message Key", "config.logger rotate encoder stacktrace key": "Stacktrace Key", "config.logger rotate encoder level": "Level Encoder", "config.logger rotate encoder time": "Time Encoder", "config.logger rotate encoder duration": "Duration Encoder", "config.logger rotate encoder caller": "Caller Encoder", "config.logger rotate encoder encoding": "Output Format", "config.capital": "Capital", "config.capitalcolor": "Capital with color", "config.lowercase": "Lowercase", "config.lowercasecolor": "Lowercase with color", "config.seconds": "Seconds", "config.nanosecond": "Nanosecond", "config.microsecond": "Microsecond", "config.millisecond": "Millisecond", "config.full path": "Full path", "config.short path": "Short path", "config.do not modify when you have not set up all assets": "Do not modify when you have not set up all assets", "config.it will work when theme is adminlte": "It will work when theme is adminlte", "config.language." + CN: "Chinese", "config.language." + EN: "English", "config.language." + JP: "Japanese", "config.language." + strings.ToLower(TC): "Traditional Chinese", "config.language." + PTBR: "Brazilian Portuguese", "config.language." + RU: "Русский", "config.modify site config": "Site Configuration Modification", "config.modify site config success": "modified success", "config.modify site config fail": "modified failed", "system.system info": "System And Application Info", "system.application": "Application Info", "system.application run": "Applications Running Info", "system.system": "System Info", "system.process_id": "Process ID", "system.golang_version": "Golang Version", "system.server_uptime": "Server Uptime", "system.current_goroutine": "Current Goroutines", "system.current_memory_usage": "Current Memory Usage", "system.total_memory_allocated": "Total Memory Allocated", "system.memory_obtained": "Memory Obtained", "system.pointer_lookup_times": "Pointer Lookup Times", "system.memory_allocate_times": "Memory Allocate Times", "system.memory_free_times": "Memory Free Times", "system.current_heap_usage": "Current Heap Usage", "system.heap_memory_obtained": "Heap Memory Obtained", "system.heap_memory_idle": "Heap Memory Idle", "system.heap_memory_in_use": "Heap Memory In Use", "system.heap_memory_released": "Heap Memory Released", "system.heap_objects": "Heap Objects", "system.bootstrap_stack_usage": "Bootstrap Stack Usage", "system.stack_memory_obtained": "Stack Memory Obtained", "system.mspan_structures_usage": "MSpan Structures Usage", "system.mspan_structures_obtained": "MSpan Structures Obtained", "system.mcache_structures_usage": "MCache Structures Usage", "system.mcache_structures_obtained": "MCache Structures Obtained", "system.profiling_bucket_hash_table_obtained": "Profiling Bucket Hash Table Obtained", "system.gc_metadata_obtained": "GC Metadata Obtained", "system.other_system_allocation_obtained": "Other System Allocation Obtained", "system.next_gc_recycle": "Next GC Recycle", "system.last_gc_time": "Since Last GC Time", "system.total_gc_time": "Total GC Pause", "system.total_gc_pause": "Total GC Pause", "system.last_gc_pause": "Last GC Pause", "system.gc_times": "GC Times", "system.cpu_logical_core": "CPU Logical Core", "system.cpu_core": "CPU Physical Core", "system.os_platform": "OS Platform", "system.os_family": "OS Family", "system.os_version": "OS Version", "system.load1": "Load1", "system.load5": "Load5", "system.load15": "Load15", "system.mem_total": "Total Memory", "system.mem_available": "Available Memory", "system.mem_used": "Used Memory", "system.app_name": "App Name", "system.go_admin_version": "App Version", "system.theme_name": "Theme", "system.theme_version": "Theme Version", "tool.tool": "Tool", "tool.table": "Table", "tool.connection": "Connection", "tool.package": "Package", "tool.output": "Output Path", "tool.output path is empty": "Output path is empty", "tool.field": "Field", "tool.title": "Title", "tool.field name": "Name", "tool.db type": "Database Type", "tool.form type": "Form Type", "tool.generate table model": "Generate Table Model", "tool.primarykey": "Primary Key", "tool.field filterable": "Filterable", "tool.field sortable": "Sortable", "tool.yes": "Yes", "tool.no": "No", "tool.hide": "Hide", "tool.show": "Show", "tool.generate success": "Generate Success", "tool.hide filter area": "Hide Filter Area", "tool.use absolute path": "Use absolute path", "tool.display": "Display", "tool.basic info": "Basic", "tool.table info": "Table", "tool.form info": "Form", "tool.field editable": "Editable", "tool.info field editable": "Editable", "tool.extra import package": "Import Package", "tool.field can add": "Can Add", "tool.field default": "Default", "tool.filter area": "Filter Area", "tool.new button": "New Button", "tool.export button": "Export Button", "tool.edit button": "Edit Button", "tool.delete button": "Delete Button", "tool.detail button": "Detail Button", "tool.filter button": "Filter Button", "tool.row selector": "Row Selector", "tool.pagination": "Pagination", "tool.query info": "Query Info", "tool.filter form layout": "Filter Form Layout", "tool.continue edit checkbox": "Continue Edit Checkbox", "tool.continue new checkbox": "Continue New Checkbox", "tool.reset button": "Reset Button", "tool.back button": "Back Button", "tool.generate": "Generate", "tool.generated tables": "Generated Tables", "tool.description": "Description", "tool.label": "Label", "tool.image": "Image", "tool.bool": "Bool", "tool.link": "Link", "tool.fileSize": "File Size", "tool.date": "Date", "tool.icon": "Icon", "tool.dot": "Dot", "tool.progressBar": "ProgressBar", "tool.loading": "Loading", "tool.downLoadable": "DownLoadable", "tool.copyable": "Copyable", "tool.carousel": "Carousel", "tool.qrcode": "Qrcode", "tool.field hide": "Hide", "tool.field display": "Display", "tool.table permission": "Generate Permissions", "tool.extra code": "Extra Code", "tool.field display normal": "Normal", "tool.field diplay hide": "Hide", "tool.field diplay edit hide": "Edit Hide", "tool.field diplay create hide": "Create Hide", "tool.generate table model success": "generate success", "tool.generate table model fail": "generate fail", "tool.detail display": "Display", "tool.detail info": "Detail Info", "tool.follow list page": "Follow List Page", "tool.inherit from list page": "Inherit From List Page", "tool.independent from list page": "Independent From List Page", "generator.query": "Query", "generator.show edit form page": "Show Edit Form Page", "generator.show create form page": "Show Create Form Page", "generator.edit": "Edit", "generator.create": "Create", "generator.delete": "Delete", "generator.export": "Export", "plugin.plugin": "Plugin", "plugin.plugin detail": "Plugin Detail", "plugin.introduction": "Introduction", "plugin.website": "Website", "plugin.version": "Version", "plugin.created at": "Created At", "plugin.updated at": "Updated At", "plugin.provided by %s": "Provided by %s", "plugin.upgrade": "Upgrade", "plugin.install": "Install", "plugin.download": "Download", "plugin.buy": "Buy", "plugin.downloading": "Downloading", "plugin.info": "Detail", "plugin.login": "Login", "plugin.login to goadmin member system": "Login to GoAdmin member system", "plugin.account": "Account", "plugin.password": "Password", "plugin.learn more": "Learn more", "plugin.no account? click %s here %s to register.": "No account?Click %shere%s to register。", "plugin.download fail, wrong name": "Download fail, wrong name", "plugin.change to debug mode first": "Change to debug mode first", "plugin.download fail, plugin not exist": "Download fail, plugin not exist", "plugin.download fail": "Download fail", "plugin.golang develop environment does not exist": "Golang develop environment does not exist", "plugin.download success, restart to install": "Download success, restart to install", "plugin.restart to install": "Restart to install", "plugin.can not connect to the goadmin remote server": "Failed to connect the GoAdmin remote server, check your network connection.", "admin.basic admin": "Basic Admin", "admin.a built-in plugins of goadmin which help you to build a crud manager platform quickly.": "A built-in plugins of GoAdmin which help you to build a crud manager platform quickly.", "admin.official": "Official", "current page": "Current Page", "login": "Login", "username and password can not be empty": "Username and password can not be empty", "showing %s to %s of %s entries": "showing %s to %s of %s entries", "code generate tool": "Code Generator", "close": "close", "fail": "fail", "wrong captcha": "incorrect verification code", "config.must bigger than 900 seconds": "Must be greater than 900 seconds", "permission denied": "permission denied", "config.local": "local env", "view": "view", "site setting": "Site Setting", "del": "delete", "error": "error", "operation not allow": "operation not allowed", "config.prod": "production env", "edit fail": "edit failed", "login info": "Login Info", "config.hide plugin entrance": "Hide plugin page entry", "submit": "Submit", "managers manage": "Managers Manage", "menus": "Menu", "delete succeed": "delete succeed", "query time": "query time", "login overdue, please login again": "Login information expired. Please log in again", "create fail": "create failed", "tool.code generate tool": "Code Generator", "user": "user", "modify success": "modify success", "menu name": "menu name", "login fail": "login failed", "export": "export", "no permission": "no permission", "confirm": "confirm", "delete fail": "deletion failed", "success": "success", "system.site info": "Site Info", "site info": "Site Info", "more": "More", "config.test": "test env", } ================================================ FILE: modules/language/jp.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package language import "strings" var jp = LangSet{ "managers": "管理者", "name": "ユーザー名", "nickname": "ニックネーム", "role": "ロール", "createdat": "作成日時", "updatedat": "更新日時", "path": "パス", "submit": "提出", "filter": "フィルター", "new": "新規", "export": "出力", "action": "操作", "toggle dropdown": "プルダウン", "delete": "削除", "refresh": "更新", "back": "戻る", "reset": "リセット", "save": "保存", "edit": "編集", "expand": "展開", "collapse": "折り畳み", "online": "オンライン", "setting": "設定", "sign out": "ログアウト", "home": "ホーム", "all": "全て", "more": "更に", "remove": "削除する", "permission manage": "権限管理", "menus manage": "メニュー管理", "roles manage": "ロール管理", "operation log": "操作履歴", "method": "メソッド", "input": "入力", "operation": "操作", "menu name": "表示名", "reload succeeded": "再読み込み完了", "search": "検索", "permission denied": "権限がありません", "error": "エラー", "current page": "現在のページ", "query time": "クエリ時間", "are you sure to delete": "本当に削除しますか", "yes": "はい", "got it": "はい", "cancel": "キャンセル", "refresh succeeded": "更新に成功しました", "edit fail": "編集に失敗しました", "create fail": "作成に失敗しました", "confirm password": "パスワード(確認)", "all method if empty": "空の場合は全メソッド", "detail": "詳細", "avatar": "アバター", "password": "パスワード", "username": "ユーザー名", "slug": "スラッグ", "permission": "権限", "userid": "ユーザーID", "content": "内容", "parent": "親メニュー", "icon": "アイコン", "uri": "URL", "login": "ログイン", "login fail": "ログイン失敗", "admin": "運営管理", "users": "ユーザー", "roles": "ロール", "menu": "メニュー", "dashboard": "ダッシュボード", "goadmin is now running. \nrunning in \"debug\" mode. switch to \"release\" mode in production.\n\n": "GoAdminが現在稼働中です。\n\"デバッグ\"モードで実行中です。本番環境では\"リリース\"モードに切り替えてください。\n\n", "wrong goadmin version, theme %s required goadmin version are %s": "GoAdminバージョンが間違っています、テーマ%sの必要なGoAdminバージョンは%sです。", "wrong theme version, goadmin %s required version of theme %s is %s": "テーマのバージョンが間違っています、GoAdmin%sの必要なテーマ%sのバージョンは%sです。", "adapter is nil, import the default adapter or use addadapter method add the adapter": "アダプターがnilです。デフォルトのアダプターをインポートするか、AddAdapterメソッドを使用してアダプターを追加してください。", "username and password can not be empty": "アカウントまたパスワードが正しく入力されていることを確認してください", "operation not allow": "この操作を実行するアクセス許可が必要です", "password does not match": "パスワードが正しくありません", "should be unique": "重複しないことを確認してください", "slug exists": "スラッグが既に存在していないことを確認してください", "no corresponding options?": "対応できるオプションがありません", "create here.": "ここに新規作成", "use for login": "ログインに使う", "use to display": "表示に使う", "a path a line, without global prefix": "パスを1行ずつ入力してください", "slug or http_path or name should not be empty": "スラッグ、http_pathまたユーザー名が正しく入力されていることを確認してください", "no roles": "ロールなし", "initialize configuration": "設定の初期化", "initialize navigation buttons": "ナビゲーションボタンの初期化", "initialize plugins": "プラグインの初期化", "initialize database connections": "データベース接続の初期化", "initialize success": "初期化成功🍺🍺 ", "not found": "見つかりません", "internal error": "内部エラー", "unauthorized": "権限がありません", "plugins": "プラグイン", "plugin store": "プラグインストア", "get more plugins": "もっとプラグインを取得する", "uninstalled": "アンインストールされました", "plugin setting": "プラグイン設定", "second": "秒", "seconds": "秒", "minute": "分", "minutes": "分", "hour": "時間", "hours": "時間", "day": "日", "days": "日", "week": "週間", "weeks": "週間", "month": "月", "months": "月", "year": "年", "years": "年", "config.domain": "ウェブサイトのドメイン", "config.language": "ウェブサイトの言語", "config.url prefix": "URLプレフィックス", "config.theme": "テーマ", "config.title": "タイトル", "config.index url": "ホームURL", "config.login url": "ログインURL", "config.env": "環境", "config.color scheme": "カラースキーム", "config.cdn url": "CDNアセットURL", "config.login title": "ログインタイトル", "config.auth user table": "認証ユーザーテーブル", "config.extra": "追加の設定", "config.store": "ファイルストアの設定", "config.databases": "データベースの設定", "config.general": "一般", "config.log": "ログ", "config.site setting": "サイト設定", "config.custom": "カスタマイズ", "config.debug": "デバッグモード", "config.site off": "サイトオフライン", "config.true": "オン", "config.false": "オフ", "config.logo": "ロゴ", "config.mini logo": "ミニロゴ", "config.bootstrap file path": "Bootstrapファイルのパス", "config.go mod file path": "go.modファイルのパス", "config.session life time": "セッションの有効期間", "config.custom head html": "ヘッドHTML", "config.custom foot html": "フッターHTML", "config.custom 404 html": "404ページ", "config.custom 403 html": "403ページ", "config.custom 500 html": "500ページ", "config.hide config center entrance": "設定ボタンを非表示にする", "config.hide app info entrance": "アプリ情報ボタンを非表示にする", "config.hide tool entrance": "ツールボタンを非表示にする", "config.hide plugin entrance": "プラグインリストボタンを非表示にする", "config.footer info": "フッター情報", "config.login logo": "ログインロゴ", "config.no limit login ip": "制限なしの複数IPでのログイン", "config.operation log off": "操作ログオフ", "config.allow delete operation log": "操作ログの削除を許可する", "config.animation type": "アニメーションタイプ", "config.animation duration": "アニメーションの期間(秒)", "config.animation delay": "アニメーションの遅延(秒)", "config.file upload engine": "ファイルアップロードエンジン", "config.logger rotate": "ログローテーション設定", "config.logger rotate max size": "最大サイズ(MB)", "config.logger rotate max backups": "最大バックアップ数", "config.logger rotate max age": "最大保存期間(日)", "config.logger rotate compress": "圧縮", "config.info log path": "情報ログファイルのパス", "config.error log path": "エラーログファイルのパス", "config.access log path": "アクセスログファイルのパス", "config.info log off": "情報ログオフ", "config.error log off": "エラーログオフ", "config.access log off": "アクセスログオフ", "config.access assets log off": "アクセスアセットログオフ", "config.sql log on": "SQLログを開く", "config.log level": "レベル", "config.logger rotate encoder": "ログエンコーダー設定", "config.logger rotate encoder time key": "時間キー", "config.logger rotate encoder level key": "レベルキー", "config.logger rotate encoder name key": "名前キー", "config.logger rotate encoder caller key": "呼び出し元キー", "config.logger rotate encoder message key": "メッセージキー", "config.logger rotate encoder stacktrace key": "スタックトレースキー", "config.logger rotate encoder level": "レベルエンコーダー", "config.logger rotate encoder time": "時間エンコーダー", "config.logger rotate encoder duration": "持続時間エンコーダー", "config.logger rotate encoder caller": "呼び出し元エンコーダー", "config.logger rotate encoder encoding": "出力形式", "config.capital": "大文字", "config.capitalcolor": "色付き大文字", "config.lowercase": "小文字", "config.lowercasecolor": "色付き小文字", "config.seconds": "秒", "config.nanosecond": "ナノ秒", "config.microsecond": "マイクロ秒", "config.millisecond": "ミリ秒", "config.full path": "完全なパス", "config.short path": "短縮パス", "config.do not modify when you have not set up all assets": "すべてのアセットが設定されていない場合は変更しないでください", "config.it will work when theme is adminlte": "テーマがadminlteの場合に機能します", "config.language." + CN: "中国語", "config.language." + EN: "英語", "config.language." + JP: "日本語", "config.language." + PTBR: "ブラジルポルトガル語", "config.language." + strings.ToLower(TC): "繁体字中国語", "config.language." + RU: "ロシア語", "config.modify site config": "サイト設定の変更", "config.modify site config success": "変更成功", "config.modify site config fail": "変更失敗", "system.system info": "システムおよびアプリケーション情報", "system.application": "アプリケーション情報", "system.application run": "実行中アプリケーション情報", "system.system": "システム情報", "system.process_id": "プロセスID", "system.golang_version": "Golangバージョン", "system.server_uptime": "サーバーの稼働時間", "system.current_goroutine": "現在のゴールーチン数", "system.current_memory_usage": "現在のメモリ使用量", "system.total_memory_allocated": "割り当てられた総メモリ量", "system.memory_obtained": "取得されたメモリ", "system.pointer_lookup_times": "ポインター検索回数", "system.memory_allocate_times": "メモリ割り当て回数", "system.memory_free_times": "メモリ解放回数", "system.current_heap_usage": "現在のヒープ使用量", "system.heap_memory_obtained": "取得されたヒープメモリ", "system.heap_memory_idle": "アイドル状態のヒープメモリ", "system.heap_memory_in_use": "使用中のヒープメモリ", "system.heap_memory_released": "解放されたヒープメモリ", "system.heap_objects": "ヒープオブジェクト数", "system.bootstrap_stack_usage": "ブートストラップスタック使用量", "system.stack_memory_obtained": "取得されたスタックメモリ", "system.mspan_structures_usage": "MSpan構造の使用量", "system.mspan_structures_obtained": "取得されたMSpan構造", "system.mcache_structures_usage": "MCache構造の使用量", "system.mcache_structures_obtained": "取得されたMCache構造", "system.profiling_bucket_hash_table_obtained": "プロファイリングバケットハッシュテーブルの取得", "system.gc_metadata_obtained": "GCメタデータの取得", "system.other_system_allocation_obtained": "その他のシステム割り当ての取得", "system.next_gc_recycle": "次のGC再利用", "system.last_gc_time": "最後のGCからの時間経過", "system.total_gc_time": "総GC時間", "system.total_gc_pause": "総GC停止時間", "system.last_gc_pause": "最後のGC停止時間", "system.gc_times": "GC回数", "system.cpu_logical_core": "CPU論理コア", "system.cpu_core": "CPU物理コア", "system.os_platform": "OSプラットフォーム", "system.os_family": "OSファミリー", "system.os_version": "OSバージョン", "system.load1": "Load1", "system.load5": "Load5", "system.load15": "Load15", "system.mem_total": "総メモリ量", "system.mem_available": "利用可能なメモリ", "system.mem_used": "使用中のメモリ", "system.app_name": "アプリ名", "system.go_admin_version": "アプリバージョン", "system.theme_name": "テーマ", "system.theme_version": "テーマバージョン", "tool.tool": "ツール", "tool.table": "テーブル", "tool.connection": "接続", "tool.package": "パッケージ", "tool.output": "出力パス", "tool.output path is empty": "出力パスが空です", "tool.field": "データベースフィールド", "tool.title": "タイトル", "tool.field name": "名前", "tool.db type": "データベースタイプ", "tool.form type": "フォームタイプ", "tool.generate table model": "テーブルモデルを生成する", "tool.primarykey": "主キー", "tool.field filterable": "フィルター可能", "tool.field sortable": "ソート可能", "tool.yes": "はい", "tool.no": "いいえ", "tool.hide": "非表示", "tool.show": "表示", "tool.generate success": "生成成功", "tool.hide filter area": "フィルターエリアを非表示にする", "tool.use absolute path": "絶対パスを使用する", "tool.display": "表示", "tool.basic info": "基本", "tool.table info": "テーブル", "tool.form info": "フォーム", "tool.field editable": "編集可能", "tool.info field editable": "編集非表示", "tool.field can add": "追加可能", "tool.field default": "デフォルト", "tool.filter area": "フィルターエリア", "tool.new button": "新規ボタン", "tool.extra import package": "パッケージのインポート", "tool.export button": "エクスポートボタン", "tool.edit button": "編集ボタン", "tool.delete button": "削除ボタン", "tool.detail button": "詳細ボタン", "tool.filter button": "フィルターボタン", "tool.row selector": "行選択器", "tool.pagination": "ページネーション", "tool.query info": "クエリ情報", "tool.filter form layout": "フィルターフォームレイアウト", "tool.continue edit checkbox": "編集の続行チェックボックス", "tool.continue new checkbox": "新規作成の続行チェックボックス", "tool.reset button": "リセットボタン", "tool.back button": "戻るボタン", "tool.generate": "生成する", "tool.generated tables": "生成されたテーブル", "tool.description": "説明", "tool.label": "ラベル", "tool.image": "画像", "tool.bool": "ブール", "tool.link": "リンク", "tool.fileSize": "ファイルサイズ", "tool.date": "日付", "tool.icon": "アイコン", "tool.dot": "ドット", "tool.progressBar": "プログレスバー", "tool.loading": "ロード中", "tool.downLoadable": "ダウンロード可能", "tool.copyable": "コピー可能", "tool.carousel": "カルーセル", "tool.qrcode": "QRコード", "tool.field hide": "非表示", "tool.field display": "表示", "tool.table permission": "権限を生成する", "tool.extra code": "追加コード", "tool.field display normal": "通常", "tool.field diplay hide": "非表示", "tool.field diplay edit hide": "編集非表示", "tool.field diplay create hide": "作成非表示", "tool.detail display": "表示", "tool.detail info": "詳細情報", "tool.follow list page": "リストページに従う", "tool.inherit from list page": "リストページから継承", "tool.independent from list page": "リストページから独立", "tool.generate table model success": "生成成功", "tool.generate table model fail": "生成失敗", "generator.query": "クエリ", "generator.show edit form page": "編集フォームページを表示", "generator.show create form page": "作成フォームページを表示", "generator.edit": "編集", "generator.create": "作成", "generator.delete": "削除", "generator.export": "エクスポート", "plugin.plugin": "プラグイン", "plugin.plugin detail": "プラグイン詳細", "plugin.introduction": "導入", "plugin.website": "ウェブサイト", "plugin.version": "バージョン", "plugin.created at": "作成日時", "plugin.updated at": "更新日時", "plugin.provided by %s": "%sに提供されます", "plugin.upgrade": "アップグレード", "plugin.install": "インストール", "plugin.info": "詳細", "plugin.download": "ダウンロード", "plugin.buy": "購入", "plugin.downloading": "ダウンロード中", "plugin.login": "ログイン", "plugin.login to goadmin member system": "GoAdminメンバーシステムにログインする", "plugin.account": "アカウント", "plugin.password": "パスワード", "plugin.learn more": "もっと学ぶ", "plugin.no account? click %s here %s to register.": "アカウントがありませんか?登録するには%sここ%sをクリックしてください。", "plugin.download fail, wrong name": "ダウンロードに失敗しました、間違った名前です", "plugin.change to debug mode first": "まずデバッグモードに変更してください", "plugin.download fail, plugin not exist": "ダウンロードに失敗しました、プラグインが存在しません", "plugin.download fail": "ダウンロードに失敗しました", "plugin.golang develop environment does not exist": "Golangの開発環境が存在しません", "plugin.download success, restart to install": "ダウンロードが成功しました、インストールのために再起動します", "plugin.restart to install": "インストールのために再起動します", "plugin.can not connect to the goadmin remote server": "GoAdminリモートサーバーに接続できませんでした、ネットワーク接続を確認してください。", "admin.basic admin": "基本管理者", "admin.a built-in plugins of goadmin which help you to build a crud manager platform quickly.": "GoAdminの組み込みプラグインで、CRUDマネージャープラットフォームを素早く構築できます。", "admin.official": "公式", "browse": "開く", "system.site info": "実行情報", "delete succeed": "削除成功", "continue creating": "追加続行", "wrong captcha": "エラーの認証コード", "code generate tool": "コードジェネレーター", "fixed the sidebar": "固定サイドバー", "config.must bigger than 900 seconds": "900秒以上である必要があります", "enter fullscreen": "フルスクリーンに入る", "fail": "失敗", "modify success": "修正成功", "menus": "メニュー", "config.test": "テスト環境", "del": "削除", "close": "閉じる", "view": "表示", "tool.code generate tool": "コードジェネレーター", "login info": "ログイン情報", "login overdue, please login again": "ログイン情報が期限切れです。再ログインしてください。", "site setting": "ウェブサイト設定", "managers manage": "管理者管理", "continue editing": "編集を続ける", "site info": "実行情報", "success": "成功", "delete fail": "削除失敗", "exit fullscreen": "フルスクリーンを終了する", "confirm": "確認", "user": "ユーザー", "showing %s to %s of %s entries": "第%sから第%sのレコードを表示、合計%sレコード", "config.local": "ローカル環境", "config.prod": "プロダクション環境", "no permission": "権限がありません", } ================================================ FILE: modules/language/language.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package language import ( "html/template" "strings" "github.com/GoAdminGroup/go-admin/modules/config" "golang.org/x/text/language" ) var ( EN = language.English.String() CN = language.Chinese.String() JP = language.Japanese.String() TC = language.TraditionalChinese.String() PTBR = language.BrazilianPortuguese.String() RU = language.Russian.String() ) func FixedLanguageKey(key string) string { if key == "en" { return EN } if key == "cn" { return CN } if key == "jp" { return JP } if key == "tc" { return TC } if key == "pt-br" { return PTBR } if key == "ru" { return RU } return key } var Langs = [...]string{EN, CN, JP, TC, RU} // Get return the value of default scope. func Get(value string) string { return GetWithScope(value) } // GetWithScope return the value of given scopes. func GetWithScope(value string, scopes ...string) string { if config.GetLanguage() == "" { return value } return GetWithScopeAndLanguageSet(value, config.GetLanguage(), scopes...) } // GetWithLang return the value of given language set. func GetWithLang(value, lang string) string { if lang == "" { lang = config.GetLanguage() } return GetWithScopeAndLanguageSet(value, lang) } // GetWithScopeAndLanguageSet return the value of given scopes and language set. func GetWithScopeAndLanguageSet(value, lang string, scopes ...string) string { if locale, ok := Lang[lang][JoinScopes(scopes)+strings.ToLower(value)]; ok { return locale } return value } // GetFromHtml return the value of given scopes and template.HTML value. func GetFromHtml(value template.HTML, scopes ...string) template.HTML { if config.GetLanguage() == "" { return value } if locale, ok := Lang[config.GetLanguage()][JoinScopes(scopes)+strings.ToLower(string(value))]; ok { return template.HTML(locale) } return value } // WithScopes join scopes prefix and the value. func WithScopes(value string, scopes ...string) string { return JoinScopes(scopes) + strings.ToLower(value) } type LangSet map[string]string func (l LangSet) Add(key, value string) { l[key] = value } func (l LangSet) Combine(set LangSet) LangSet { for k, s := range set { l[k] = s } return l } // LangMap is the map of language packages. type LangMap map[string]LangSet // Lang is the global LangMap. var Lang = LangMap{ language.Chinese.String(): cn, language.English.String(): en, language.Japanese.String(): jp, language.TraditionalChinese.String(): tc, language.BrazilianPortuguese.String(): ptbr, language.Russian.String(): ru, "cn": cn, "en": en, "jp": jp, "tc": tc, "pt-br": ptbr, "ru": ru, } // Get get the value from LangMap. func (lang LangMap) Get(value string) string { return lang.GetWithScope(value) } // GetWithScope get the value from LangMap with given scopes. func (lang LangMap) GetWithScope(value string, scopes ...string) string { if config.GetLanguage() == "" { return value } if locale, ok := lang[config.GetLanguage()][JoinScopes(scopes)+strings.ToLower(value)]; ok { return locale } return value } // Add add a language package to the Lang. func Add(key string, lang map[string]string) { Lang[key] = lang } // AppendTo add more language translations to the given language set. func AppendTo(lang string, set map[string]string) { for key, value := range set { Lang[lang][key] = value } } func JoinScopes(scopes []string) string { j := "" for _, scope := range scopes { if scope != "" { j += scope + "." } } return j } ================================================ FILE: modules/language/language_test.go ================================================ package language import ( "fmt" "html/template" "testing" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/stretchr/testify/assert" ) func TestKK(t *testing.T) { for key := range cn { if _, ok := ptbr[key]; !ok { fmt.Println(key, "===", cn[key]) } } } func TestAdd(t *testing.T) { Add("cn", map[string]string{}) } func TestGetWithScope(t *testing.T) { config.Initialize(&config.Config{ Language: CN, }) cn["foo"] = "bar" assert.Equal(t, GetWithScope("foo"), "bar") cn["user.table.foo2"] = "bar" assert.Equal(t, GetWithScope("foo2"), "foo2") assert.Equal(t, GetWithScope("foo2", "user"), "foo2") assert.Equal(t, GetWithScope("foo2", "user", "table"), "bar") } func TestGet(t *testing.T) { config.Initialize(&config.Config{ Language: CN, }) cn["foo"] = "bar" assert.Equal(t, Get("foo"), "bar") } func TestWithScopes(t *testing.T) { assert.Equal(t, WithScopes("foo", "user", "table"), "user.table.foo") } func TestGetFromHtml(t *testing.T) { config.Initialize(&config.Config{ Language: CN, }) cn["user.table.foo"] = "bar" assert.Equal(t, GetFromHtml("foo", "user", "table"), template.HTML("bar")) } ================================================ FILE: modules/language/pt-BR.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package language import "strings" var ptbr = LangSet{ "managers": "Gerentes", "name": "Nome", "nickname": "Apelido", "role": "Role", "createdat": "criadoEm", "updatedat": "atualizadoEm", "path": "caminho", "new": "Novo", "filter": "Filtro", "action": "Ação", "toggle dropdown": "Toggle Dropdown", "delete": "Excluir", "refresh": "Atualizar", "expand": "Expandir", "collapse": "Recolher", "back": "Voltar", "reset": "Redefinir", "save": "Salvar", "edit": "Editar", "operation": "Operação", "method": "Método", "input": "entrada", "online": "Online", "setting": "Configuração", "sign out": "Sair", "all": "Tudo", "confirm password": "Confirmar a Senha", "search": "Procurar", "remove": "Remover", "query time": "tempo de consulta", "goadmin is now running. \nrunning in \"debug\" mode. switch to \"release\" mode in production.\n\n": "GoAdmin agora está em execução. \nExecutando no modo \"debug \". Mude para o modo de \"release\" em produção. \n\n", "wrong goadmin version, theme %s required goadmin version are %s": "Versão incorreta do GoAdmin, o tema %s requer a versão do GoAdmin %s", "wrong theme version, goadmin %s required version of theme %s is %s": "Versão incorreta do tema, o GoAdmin %s requer a versão do tema %s como %s", "adapter is nil, import the default adapter or use addadapter method add the adapter": "O adaptador está nulo, importe o adaptador padrão ou use o método AddAdapter para adicionar o adaptador", "are you sure to delete": "Você tem certeza que quer deletar", "yes": "sim", "got it": "entendi", "cancel": "cancelar", "refresh succeeded": "Atualizado com sucesso", "reload succeeded": "Recarregado com sucesso", "all method if empty": "Todo método é vazio", "password does not match": "Senha não confere", "should be unique": "Deve ser único", "slug exists": "Slug existe", "no corresponding options?": "Sem opções correspondentes ?", "create here.": "Crie aqui.", "use for login": "Use para login", "use to display": "Use para exibir", "a path a line, without global prefix": "Um caminho uma linha", "slug or http_path or name should not be empty": "slug ou http_path ou nome não deve estar vazio", "no roles": "sem roles", "fixed the sidebar": "Barra lateral fixada", "enter fullscreen": "Entrar em tela cheia", "exit fullscreen": "Sair da tela inteira", "permission manage": "Gerenciamento de permissão", "menus manage": "Gerenciar menu", "roles manage": "Gerenciar roles", "operation log": "Log de operação", "continue editing": "Continue editando", "continue creating": "Continue criando", "browse": "Navegar", "avatar": "Avatar", "password": "Senha", "username": "Nome do usuário", "slug": "Slug", "permission": "Permissão", "userid": "UserID", "content": "Conteúdo", "parent": "Pai", "icon": "Ícone", "uri": "Uri", "detail": "Detalhe", "admin": "Administração", "users": "Usuários", "roles": "Funções", "menu": "Menu", "dashboard": "Painel de Controle", "home": "Página Inicial", "initialize configuration": "Inicializando configuração", "initialize navigation buttons": "Inicializando botões de navegação", "initialize plugins": "Inicializando plugins", "initialize database connections": "Inicializando conexões de banco de dados", "initialize success": "Inicialização feita com sucesso🍺🍺", "not found": "Não encontrado", "internal error": "Erro interno", "unauthorized": "Não autorizado", "plugin setting": "Configuração de Plugin", "plugins": "Plugins", "plugin store": "Loja de Plugins", "get more plugins": "Mais plugins", "uninstalled": "Desinstalado", "second": "segundo", "seconds": "segundos", "minute": "minuto", "minutes": "minutos", "hour": "hora", "hours": "horass", "day": "dia", "days": "dias", "week": "semana", "weeks": "semanas", "month": "mês", "months": "meses", "year": "ano", "years": "anos", "config.domain": "Domínio do site", "config.language": "Idioma do site", "config.url prefix": "URL Prefix", "config.theme": "Tema", "config.title": "Título", "config.index url": "Home URL", "config.login url": "Login URL", "config.env": "Env", "config.color scheme": "Color Scheme", "config.cdn url": "CDN Asset URL", "config.login title": "Título de Login", "config.auth user table": "Auth User Table", "config.extra": "Extra Configuration", "config.store": "File Store Setting", "config.databases": "Database Setting", "config.general": "Geral", "config.log": "Registro", "config.site setting": "Configurações do Site", "config.custom": "Personalizar", "config.debug": "Modo de Depuração", "config.site off": "Site Offline", "config.true": "Ligado", "config.false": "Desligado", "config.logo": "Logotipo", "config.mini logo": "Mini Logotipo", "config.bootstrap file path": "Caminho do Arquivo Bootstrap", "config.go mod file path": "Caminho do Arquivo go.mod", "config.session life time": "Tempo de Vida da Sessão", "config.custom head html": "HTML do Cabeçalho", "config.custom foot html": "HTML do Rodapé", "config.custom 404 html": "Página 404", "config.custom 403 html": "Página 403", "config.custom 500 html": "Página 500", "config.hide config center entrance": "Ocultar Botão de Configuração", "config.hide app info entrance": "Ocultar Botão de Informações do Aplicativo", "config.hide tool entrance": "Ocultar Botão de Ferramenta", "config.footer info": "Informações do Rodapé", "config.login logo": "Logotipo de Login", "config.no limit login ip": "Login sem Limite de IPs Múltiplos", "config.operation log off": "Desligar Log de Operações", "config.allow delete operation log": "Permitir Excluir Log de Operações", "config.animation type": "Tipo de Animação", "config.animation duration": "Duração da Animação (s)", "config.animation delay": "Atraso da Animação (s)", "config.file upload engine": "Motor de Envio de Arquivos", "config.logger rotate": "Configurações de Rotação de Log", "config.logger rotate max size": "Tamanho Máximo (m)", "config.logger rotate max backups": "Backup Máximo", "config.logger rotate max age": "Idade Máxima (dias)", "config.logger rotate compress": "Comprimir", "config.info log path": "Caminho do Arquivo de Log de Informações", "config.error log path": "Caminho do Arquivo de Log de Erro", "config.access log path": "Caminho do Arquivo de Log de Acesso", "config.info log off": "Desligar Log de Informações", "config.error log off": "Desligar Log de Erro", "config.access log off": "Desligar Log de Acesso", "config.access assets log off": "Desligar Log de Ativos de Acesso", "config.sql log on": "Abrir log SQL", "config.log level": "Nível", "config.logger rotate encoder": "Configurações do codificador de registro", "config.logger rotate encoder time key": "Chave de tempo", "config.logger rotate encoder level key": "Chave de Nível", "config.logger rotate encoder name key": "Chave do Nome", "config.logger rotate encoder caller key": "Tecla do chamador", "config.logger rotate encoder message key": "Chave de mensagem", "config.logger rotate encoder stacktrace key": "Chave Stacktrace", "config.logger rotate encoder level": "Codificador de Nível", "config.logger rotate encoder time": "Codificador de tempo", "config.logger rotate encoder duration": "Codificador de duração", "config.logger rotate encoder caller": "Codificador de Chamadas", "config.logger rotate encoder encoding": "Formato de saída", "config.capital": "Maiúsculo", "config.capitalcolor": "Maiúsculo com cor", "config.lowercase": "Minúsculas", "config.lowercasecolor": "Minúsculas com cor", "config.seconds": "Segundos", "config.nanosecond": "Nanossegundo", "config.microsecond": "Microssegundo", "config.millisecond": "Milissegundo", "config.full path": "Caminho completo", "config.short path": "Caminho curto", "config.do not modify when you have not set up all assets": "Não modifique quando você não configurou todos os assets", "config.it will work when theme is adminlte": "Funcionará quando o tema for adminlte", "config.language." + CN: "Chinês", "config.language." + EN: "Inglês", "config.language." + JP: "Japonês", "config.language." + strings.ToLower(TC): "Chinês Tradicional", "config.language." + PTBR: "Português Brasileiro", "config.language." + RU: "Русский", "config.modify site config": "Modificação da configuração do site", "config.modify site config success": "modificado com successo", "config.modify site config fail": "modificação falhou", "system.system info": "Informações do sistema e do aplicativo", "system.application": "Informações do aplicativo", "system.application run": "Informações de execução de aplicativos", "system.system": "Informação do sistema", "system.process_id": "ID do Processo", "system.golang_version": "Versão do Golang", "system.server_uptime": "Tempo de atividade do servidor", "system.current_goroutine": "Goroutines Atuais", "system.current_memory_usage": "Uso de Memória Atual", "system.total_memory_allocated": "Memória Total Alocada", "system.memory_obtained": "Memória Obtida", "system.pointer_lookup_times": "Tempos de Pesquisa de Ponteiro", "system.memory_allocate_times": "Tempos de Alocação de Memória", "system.memory_free_times": "Tempos de Liberação de Memória", "system.current_heap_usage": "Uso de Heap Atual", "system.heap_memory_obtained": "Memória de Heap Obtida", "system.heap_memory_idle": "Memória de Heap Inativa", "system.heap_memory_in_use": "Memória de Heap em Uso", "system.heap_memory_released": "Memória de Heap Liberada", "system.heap_objects": "Objetos de Heap", "system.bootstrap_stack_usage": "Uso de Pilha de Inicialização", "system.stack_memory_obtained": "Memória de Pilha Obtida", "system.mspan_structures_usage": "Uso de Estruturas MSpan", "system.mspan_structures_obtained": "Estruturas MSpan Obtidas", "system.mcache_structures_usage": "Uso de Estruturas MCache", "system.mcache_structures_obtained": "Estruturas MCache Obtidas", "system.profiling_bucket_hash_table_obtained": "Tabela de Hash de Baldes de Perfil Objetida", "system.gc_metadata_obtained": "Metadados de GC Obtidos", "system.other_system_allocation_obtained": "Outras Alocações de Sistema Obtidas", "system.next_gc_recycle": "Próxima Reciclagem de GC", "system.last_gc_time": "Desde a Última Hora de GC", "system.total_gc_time": "Pausa Total de GC", "system.total_gc_pause": "Pausa Total de GC", "system.last_gc_pause": "Última Pausa de GC", "system.gc_times": "Tempos de GC", "system.cpu_logical_core": "CPU Core Lógico", "system.cpu_core": "CPU Core Físico", "system.os_platform": "OS Plataforma", "system.os_family": "OS Familia", "system.os_version": "OS Versão", "system.load1": "Load1", "system.load5": "Load5", "system.load15": "Load15", "system.mem_total": "Memória Total", "system.mem_available": "Memória disponível", "system.mem_used": "Memória usada", "system.app_name": "Nome da aplicação", "system.go_admin_version": "Versão da aplicação", "system.theme_name": "Tema", "system.theme_version": "Versão do Tema", "tool.tool": "Ferramenta", "tool.table": "Tabela", "tool.connection": "Conexão", "tool.package": "Pacote", "tool.output": "Caminho de saída", "tool.output path is empty": "O caminho de saída está vazio", "tool.field": "Campo", "tool.title": "Título", "tool.field name": "Nome", "tool.db type": "Tipo de banco de dados", "tool.form type": "Tipo de Formulário", "tool.generate table model": "Modelo de tabela gerado", "tool.primarykey": "Chave primária", "tool.field filterable": "Filtrável", "tool.field sortable": "Classificável", "tool.yes": "Sim", "tool.no": "Não", "tool.hide": "Esconder", "tool.show": "Mostrar", "tool.generate success": "Gerado com sucesso", "tool.hide filter area": "Esconder a Área do Filtro", "tool.use absolute path": "Use o caminho absoluto", "tool.display": "Exibição", "tool.basic info": "Básico", "tool.table info": "Tabela", "tool.form info": "Formulário", "tool.field editable": "Editável", "tool.info field editable": "Editável", "tool.extra import package": "Pacote de Importação", "tool.field can add": "Pode adicionar", "tool.field default": "Default", "tool.filter area": "Area de filtro", "tool.new button": "Botão Novo", "tool.export button": "Botão exportar", "tool.edit button": "Botão editar", "tool.delete button": "Botão excluir", "tool.detail button": "Botão Detalhe", "tool.filter button": "Botão Filtro", "tool.row selector": "Seletor de linha", "tool.pagination": "Paginação", "tool.query info": "Informações de consulta", "tool.filter form layout": "Layout do formulário de filtro", "tool.continue edit checkbox": "Continue Edição Checkbox", "tool.continue new checkbox": "Continuar Novo Checkbox", "tool.reset button": "Botão Redefinir", "tool.back button": "Botão Voltar", "tool.generate": "Gerado", "tool.generated tables": "Tabelas geradas", "tool.description": "Descrição", "tool.label": "Etiqueta", "tool.image": "Imagem", "tool.bool": "Bool", "tool.link": "Link", "tool.fileSize": "Tamanho do Arquivo", "tool.date": "Data", "tool.icon": "Ícone", "tool.dot": "Ponto", "tool.progressBar": "Barra de progresso", "tool.loading": "Carregando", "tool.downLoadable": "DownLoadable", "tool.copyable": "Copiável", "tool.carousel": "Carrossel", "tool.qrcode": "Qrcode", "tool.field hide": "Esconder", "tool.field display": "Exibição", "tool.table permission": "Gerar permissões", "tool.extra code": "Código Extra", "tool.field display normal": "Normal", "tool.field diplay hide": "Esconder", "tool.field diplay edit hide": "Editar Esconder", "tool.field diplay create hide": "Criar Esconder", "tool.generate table model success": "sucesso ao gerar", "tool.generate table model fail": "falha ao gerar", "tool.detail display": "Exibição", "tool.detail info": "Informação detalhada", "tool.follow list page": "Seguir a página da lista", "tool.inherit from list page": "Herdar da página da lista", "tool.independent from list page": "Independente da página da lista", "generator.query": "Query", "generator.show edit form page": "Mostrar formulário de edição", "generator.show create form page": "Mostrar formulário de criação", "generator.edit": "Editar", "generator.create": "Criar", "generator.delete": "Excluir", "generator.export": "Exportar", "plugin.plugin": "Plugin", "plugin.plugin detail": "Detalhe do plugin", "plugin.introduction": "Introdução", "plugin.website": "Website", "plugin.version": "Versão", "plugin.created at": "Criado Em", "plugin.updated at": "Atualizado Em", "plugin.provided by %s": "Fornecido por %s", "plugin.upgrade": "Upgrade", "plugin.install": "Instalar", "plugin.download": "Download", "plugin.buy": "Comprar", "plugin.downloading": "Baixando", "plugin.info": "Detalhe", "plugin.login": "Login", "plugin.login to goadmin member system": "Faça login no sistema de membros GoAdmin", "plugin.account": "Conta", "plugin.password": "Senha", "plugin.learn more": "Saber mais", "plugin.no account? click %s here %s to register.": "Sem conta? Clique %saqui%s para se registrar.", "plugin.download fail, wrong name": "Falha no download, nome errado", "plugin.change to debug mode first": "Mude para o modo debug primeiro", "plugin.download fail, plugin not exist": "O download falhou, o plugin não existe", "plugin.download fail": "Falha no download", "plugin.golang develop environment does not exist": "O ambiente de desenvolvimento de Golang não existe", "plugin.download success, restart to install": "Download bem-sucedido, reinicie para instalar", "plugin.restart to install": "Reinicie para instalar", "plugin.can not connect to the goadmin remote server": "Falha ao conectar o servidor remoto GoAdmin, verifique sua conexão de rede.", "admin.basic admin": "Admin básico", "admin.a built-in plugins of goadmin which help you to build a crud manager platform quickly.": "Plug-ins integrados ao GoAdmin que ajudam você a construir uma plataforma de gerenciamento crud rapidamente.", "admin.official": "Oficial", "create fail": "Falha ao adicionar", "modify success": "Modificado com sucesso", "system.site info": "Informações de execução", "username and password can not be empty": "Nome de usuário e senha não podem estar vazios", "login": "Entrar", "confirm": "Confirmar", "export": "Exportar", "delete fail": "Falha ao excluir", "user": "Usuário", "error": "Erro", "current page": "Página atual", "config.must bigger than 900 seconds": "Deve ser superior a 900 segundos", "no permission": "Sem permissão", "wrong captcha": "Código de verificação incorreto", "tool.code generate tool": "Gerador de código", "site info": "Informações de execução", "login overdue, please login again": "As informações de login expiraram, faça o login novamente", "menu name": "Nome do menu", "success": "Sucesso", "delete succeed": "Excluído com sucesso", "edit fail": "Falha ao editar", "config.local": "Ambiente local", "menus": "Menu", "del": "Excluir", "managers manage": "Gerenciamento de administradores", "login fail": "Falha ao fazer login", "operation not allow": "Operação não permitida", "config.hide plugin entrance": "Ocultar entrada da lista de plugins", "showing %s to %s of %s entries": "Mostrando %s a %s registros, totalizando %s registros", "login info": "Informações de login", "view": "Visualizar", "code generate tool": "Gerador de código", "config.test": "Ambiente de teste", "submit": "Enviar", "close": "Fechar", "fail": "Falha", "more": "Mais", "config.prod": "Ambiente de produção", "site setting": "Configurações do site", "permission denied": "Sem permissão", } ================================================ FILE: modules/language/ru.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package language import "strings" var ru = LangSet{ "managers": "Менеджеры", "name": "Имя", "nickname": "Никнейм", "role": "Роль", "createdat": "Дата создания", "updatedat": "Дата обновления", "path": "Путь", "new": "Новый", "filter": "Фильтр", "action": "Действие", "toggle dropdown": "Раскрыть меню", "delete": "Удалить", "refresh": "Обновить", "expand": "Развернуть", "collapse": "Свернуть", "back": "Назад", "reset": "Сбросить", "save": "Сохранить", "edit": "Редактировать", "operation": "Операция", "method": "Метод", "input": "Входные данные", "online": "Онлайн", "setting": "Настройки", "sign out": "Выйти", "all": "Все", "confirm password": "Подтвердите пароль", "search": "Поиск", "remove": "Удалить", "goadmin is now running. \nrunning in \"debug\" mode. switch to \"release\" mode in production.\n\n": "GoAdmin запущен. \nРаботает в режиме \"отладки\". В продакшене переключитесь на режим \"релиза\".\n\n", "wrong goadmin version, theme %s required goadmin version are %s": "Неверная версия GoAdmin, для темы %s требуется версия GoAdmin %s", "wrong theme version, goadmin %s required version of theme %s is %s": "Неверная версия темы, для GoAdmin %s требуется версия темы %s %s", "adapter is nil, import the default adapter or use addadapter method add the adapter": "адаптер не установлен, импортируйте стандартный адаптер или используйте метод AddAdapter для добавления адаптера", "are you sure to delete": "Вы уверены, что хотите удалить", "yes": "да", "got it": "понятно", "cancel": "отмена", "refresh succeeded": "Обновление успешно", "reload succeeded": "Перезагрузка успешна", "all method if empty": "Все методы, если пусто", "password does not match": "Пароль не совпадает", "should be unique": "Должен быть уникальным", "slug exists": "Slug уже существует", "no corresponding options?": "Нет соответствующих опций?", "create here.": "Создать здесь.", "use for login": "Использовать для входа", "use to display": "Использовать для отображения", "a path a line, without global prefix": "Путь одной строкой, без глобального префикса", "slug or http_path or name should not be empty": "Slug, http_path или имя не должны быть пустыми", "no roles": "нет ролей", "fixed the sidebar": "Фиксированная боковая панель", "enter fullscreen": "Перейти в полноэкранный режим", "exit fullscreen": "Выйти из полноэкранного режима", "permission manage": "Управление правами", "menus manage": "Управление меню", "roles manage": "Управление ролями", "operation log": "Журнал операций", "continue editing": "Продолжить редактирование", "continue creating": "Продолжить создание", "browse": "Обзор", "avatar": "Аватар", "password": "Пароль", "username": "Имя пользователя", "slug": "Slug", "permission": "Разрешение", "userid": "Идентификатор пользователя", "content": "Содержание", "parent": "Родительский элемент", "icon": "Иконка", "uri": "Uri", "detail": "Подробности", "admin": "Администратор", "users": "Пользователи", "roles": "Роли", "menu": "Меню", "dashboard": "Панель управления", "home": "Домой", "initialize configuration": "Инициализация конфигурации", "initialize navigation buttons": "Инициализация кнопок навигации", "initialize plugins": "Инициализация плагинов", "initialize database connections": "Инициализация подключений к базе данных", "initialize success": "Инициализация прошла успешно🍺🍺", "not found": "Не найдено", "internal error": "Внутренняя ошибка", "unauthorized": "Неавторизованный", "plugin setting": "Настройки плагина", "plugins": "Плагины", "plugin store": "Магазин плагинов", "get more plugins": "Получить больше плагинов", "uninstalled": "Удален", "second": "секунда", "seconds": "секунды", "minute": "минута", "minutes": "минуты", "hour": "час", "hours": "часы", "day": "день", "days": "дни", "week": "неделя", "weeks": "недели", "month": "месяц", "months": "месяцы", "year": "год", "years": "года", "config.domain": "Домен", "config.language": "Язык", "config.url prefix": "URL-префикс", "config.theme": "Тема", "config.title": "Заголовок", "config.index url": "URL главной страницы", "config.login url": "URL страницы входа", "config.env": "Среда", "config.color scheme": "Цветовая схема", "config.cdn url": "URL к CDN-хранилищу ресурсов", "config.login title": "Заголовок страницы входа", "config.auth user table": "Таблица пользователей", "config.extra": "Дополнительная конфигурация", "config.store": "Настройки файлового хранилища", "config.databases": "Настройки базы данных", "config.general": "Общие настройки", "config.log": "Логи", "config.site setting": "Настройки сайта", "config.custom": "Персонализация", "config.debug": "Режим отладки", "config.site off": "Сайт оффлайн", "config.true": "Включено", "config.false": "Выключено", "config.logo": "Логотип", "config.mini logo": "Мини-логотип", "config.bootstrap file path": "Путь к файлу Bootstrap", "config.go mod file path": "Путь к файлу go.mod", "config.session life time": "Время жизни сессии", "config.custom head html": "HTML заголовка", "config.custom foot html": "HTML подвала", "config.custom 404 html": "404 страница", "config.custom 403 html": "403 страница", "config.custom 500 html": "500 страница", "config.hide config center entrance": "Скрыть кнопку конфигурации", "config.hide app info entrance": "Скрыть кнопку информации о приложении", "config.hide tool entrance": "Скрыть кнопку инструментов", "config.footer info": "Информация в подвале", "config.login logo": "Логотип при входе в систему", "config.no limit login ip": "Разрешить вход с любых IP-адресов", "config.operation log off": "Отключить журнал операций", "config.allow delete operation log": "Разрешить удаление журнала операций", "config.animation type": "Тип анимации", "config.animation duration": "Длительность анимации (сек)", "config.animation delay": "Задержка анимации (сек)", "config.file upload engine": "Движок загрузки файлов", "config.logger rotate": "Настройки поворота логов", "config.logger rotate max size": "Макс. размер (мб)", "config.logger rotate max backups": "Макс. количество резервных копий", "config.logger rotate max age": "Макс. возраст (дней)", "config.logger rotate compress": "Сжатие", "config.info log path": "Путь к файлу журнала информации", "config.error log path": "Путь к файлу журнала ошибок", "config.access log path": "Путь к файлу журнала доступа", "config.info log off": "Выключить журнал информации", "config.error log off": "Выключить журнал ошибок", "config.access log off": "Выключить журнал доступа", "config.access assets log off": "Выключить журнал доступа к ресурсам", "config.sql log on": "Включить журнал SQL", "config.log level": "Уровень журнала", "config.logger rotate encoder": "Настройки кодирования журнала", "config.logger rotate encoder time key": "Ключ времени", "config.logger rotate encoder level key": "Ключ уровня", "config.logger rotate encoder name key": "Ключ имени", "config.logger rotate encoder caller key": "Ключ вызывающей функции", "config.logger rotate encoder message key": "Ключ сообщения", "config.logger rotate encoder stacktrace key": "Ключ стека вызовов", "config.logger rotate encoder level": "Кодировщик уровня", "config.logger rotate encoder time": "Кодировщик времени", "config.logger rotate encoder duration": "Кодировщик продолжительности", "config.logger rotate encoder caller": "Кодировщик вызывающей функции", "config.logger rotate encoder encoding": "Формат вывода", "config.capital": "Заглавные буквы", "config.capitalcolor": "Заглавные буквы с цветом", "config.lowercase": "Строчные буквы", "config.lowercasecolor": "Строчные буквы с цветом", "config.seconds": "Секунды", "config.nanosecond": "Наносекунды", "config.microsecond": "Микросекунды", "config.millisecond": "Миллисекунды", "config.full path": "Полный путь", "config.short path": "Короткий путь", // "config.do not modify when you have not set up all assets": "Не изменяйте, если все ресурсы не настроены", "config.it will work when theme is adminlte": "Работает только с темой AdminLTE", "config.language." + CN: "Китайский", "config.language." + EN: "Английский", "config.language." + JP: "Японский", "config.language." + strings.ToLower(TC): "Традиционный китайский", "config.language." + PTBR: "Бразильский португальский", "config.language." + RU: "Русский", "config.modify site config": "Изменение конфигурации сайта", "config.modify site config success": "Успешно изменено", "config.modify site config fail": "Не удалось изменить", "system.system info": "Информация о системе и приложении", "system.application": "Информация о приложении", "system.application run": "Информация о запущенных приложениях", "system.system": "Информация о системе", "system.process_id": "ID процесса", "system.golang_version": "Версия Golang", "system.server_uptime": "Время работы сервера", "system.current_goroutine": "Текущие горутины", "system.current_memory_usage": "Использование памяти", "system.total_memory_allocated": "Общее количество выделенной памяти", "system.memory_obtained": "Полученная память", "system.pointer_lookup_times": "Время поиска указателя", "system.memory_allocate_times": "Время выделения памяти", "system.memory_free_times": "Время освобождения памяти", "system.current_heap_usage": "Использование кучи", "system.heap_memory_obtained": "Полученная куча памяти", "system.heap_memory_idle": "Неиспользуемая куча памяти", "system.heap_memory_in_use": "Используемая куча памяти", "system.heap_memory_released": "Освобожденная куча памяти", "system.heap_objects": "Объекты кучи", "system.bootstrap_stack_usage": "Использование стека Bootstrap", "system.stack_memory_obtained": "Полученная память стека", "system.mspan_structures_usage": "Использование структур MSpan", "system.mspan_structures_obtained": "Полученные структуры MSpan", "system.mcache_structures_usage": "Использование структур MCache", "system.mcache_structures_obtained": "Полученные структуры MCache", "system.profiling_bucket_hash_table_obtained": "Полученная таблица хешей ведра профилирования", "system.gc_metadata_obtained": "Полученная метадата GC", "system.other_system_allocation_obtained": "Другие системные выделения", "system.next_gc_recycle": "Следующая переработка GC", "system.last_gc_time": "Время с момента последней переработки GC", "system.total_gc_time": "Общая приостановка GC", "system.total_gc_pause": "Общая приостановка GC", "system.last_gc_pause": "Последняя приостановка GC", "system.gc_times": "Число циклов GC", "system.cpu_logical_core": "Логические ядра CPU", "system.cpu_core": "Физические ядра CPU", "system.os_platform": "Платформа ОС", "system.os_family": "Семейство ОС", "system.os_version": "Версия ОС", "system.load1": "Загрузка 1", "system.load5": "Загрузка 5", "system.load15": "Загрузка 15", "system.mem_total": "Общий объем памяти", "system.mem_available": "Доступный объем памяти", "system.mem_used": "Использованный объем памяти", "system.app_name": "Название приложения", "system.go_admin_version": "Версия GoAdmin", "system.theme_name": "Тема", "system.theme_version": "Версия темы", "tool.tool": "Инструмент", "tool.table": "Таблица", "tool.connection": "Подключение", "tool.package": "Пакет", "tool.output": "Путь вывода", "tool.output path is empty": "Путь вывода пуст", "tool.field": "Поле", "tool.title": "Название", "tool.field name": "Имя поля", "tool.db type": "Тип базы данных", "tool.form type": "Тип формы", "tool.generate table model": "Создать модель таблицы", "tool.primarykey": "Первичный ключ", "tool.field filterable": "Фильтруемое", "tool.field sortable": "Сортируемое", "tool.yes": "Да", "tool.no": "Нет", "tool.hide": "Скрыть", "tool.show": "Показать", "tool.generate success": "Успешно создано", "tool.hide filter area": "Скрыть область фильтров", "tool.use absolute path": "Использовать абсолютный путь", "tool.display": "Отображение", "tool.basic info": "Основная информация", "tool.table info": "Информация о таблице", "tool.form info": "Информация о форме", "tool.field editable": "Редактируемое", "tool.info field editable": "Редактируемое", "tool.extra import package": "Дополнительный пакет импорта", "tool.field can add": "Можно добавлять", "tool.field default": "Значение по умолчанию", "tool.filter area": "Область фильтрации", "tool.new button": "Кнопка Новый", "tool.export button": "Кнопка Экспорт", "tool.edit button": "Кнопка Редактировать", "tool.delete button": "Кнопка Удалить", "tool.detail button": "Кнопка Подробно", "tool.filter button": "Кнопка Фильтр", "tool.row selector": "Селектор строки", "tool.pagination": "Пагинация", "tool.query info": "Информация о запросе", "tool.filter form layout": "Макет формы фильтрации", // "tool.continue edit checkbox": "Флажок продолжить редактирование", "tool.continue new checkbox": "Флажок продолжить создание", "tool.reset button": "Кнопка сброса", "tool.back button": "Кнопка назад", "tool.generate": "Сгенерировать", "tool.generated tables": "Сгенерированные таблицы", "tool.description": "Описание", "tool.label": "Метка", "tool.image": "Изображение", "tool.bool": "Логическое значение", "tool.link": "Ссылка", "tool.fileSize": "Размер файла", "tool.date": "Дата", "tool.icon": "Иконка", "tool.dot": "Точка", "tool.progressBar": "Индикатор выполнения", "tool.loading": "Загрузка", "tool.downLoadable": "Можно скачать", "tool.copyable": "Можно копировать", "tool.carousel": "Карусель", "tool.qrcode": "QR-код", "tool.field hide": "Скрыть поле", "tool.field display": "Отобразить поле", "tool.table permission": "Сгенерировать права доступа", "tool.extra code": "Дополнительный код", // "tool.field display normal": "Обычный", "tool.field diplay hide": "Скрыт", "tool.field diplay edit hide": "Скрыть при редактировании", "tool.field diplay create hide": "Скрыть при создании", "tool.generate table model success": "Успешно сгенерирована модель таблицы", "tool.generate table model fail": "Не удалось сгенерировать модель таблицы", "tool.detail display": "Отображение деталей", "tool.detail info": "Информация о деталях", "tool.follow list page": "Следовать за страницей списка", "tool.inherit from list page": "Наследовать от страницы списка", "tool.independent from list page": "Независимо от страницы списка", "generator.query": "Запрос", "generator.show edit form page": "Показать страницу формы редактирования", "generator.show create form page": "Показать страницу формы создания", "generator.edit": "Редактировать", "generator.create": "Создать", "generator.delete": "Удалить", "generator.export": "Экспортировать", "plugin.plugin": "Плагин", "plugin.plugin detail": "Детали плагина", "plugin.introduction": "Введение", "plugin.website": "Веб-сайт", "plugin.version": "Версия", "plugin.created at": "Дата создания", "plugin.updated at": "Дата обновления", "plugin.provided by %s": "Предоставлено %s", "plugin.upgrade": "Обновить", "plugin.install": "Установить", "plugin.download": "Скачать", "plugin.buy": "Купить", "plugin.downloading": "Загрузка", "plugin.info": "Информация", "plugin.login": "Вход", "plugin.login to goadmin member system": "Войти в систему участников GoAdmin", "plugin.account": "Аккаунт", "plugin.password": "Пароль", "plugin.learn more": "Узнать больше", "plugin.no account? click %s here %s to register.": "Нет аккаунта? Нажмите %sздесь%s, чтобы зарегистрироваться.", "plugin.download fail, wrong name": "Сбой загрузки, неправильное имя", "plugin.change to debug mode first": "Сначала переключитесь в режим отладки", "plugin.download fail, plugin not exist": "Сбой загрузки, плагин не существует", "plugin.download fail": "Сбой загрузки", "plugin.golang develop environment does not exist": "Среда разработки Golang не существует", "plugin.download success, restart to install": "Успешная загрузка, перезапустите для установки", "plugin.restart to install": "Перезапустите для установки", "plugin.can not connect to the goadmin remote server": "Не удалось подключиться к удаленному серверу GoAdmin, проверьте соединение с сетью.", "admin.basic admin": "Базовый администратор", "admin.a built-in plugins of goadmin which help you to build a crud manager platform quickly.": "Встроенные плагины GoAdmin, которые помогают вам быстро создавать платформу для управления crud.", "admin.official": "Официальный", } ================================================ FILE: modules/language/tc.go ================================================ package language import "strings" var tc = LangSet{ "managers": "管理員管理", "name": "用戶名", "nickname": "暱稱", "role": "角色", "createdat": "創建時間", "updatedat": "更新時間", "path": "路徑", "submit": "提交", "filter": "篩選", "new": "新建", "action": "操作", "toggle dropdown": "下拉", "delete": "刪除", "refresh": "刷新", "back": "返回", "reset": "重置", "save": "保存", "edit": "編輯", "expand": "展開", "collapse": "折疊", "online": "在線", "setting": "設置", "sign out": "登出", "remove": "移除", "permission manage": "權限管理", "menus manage": "菜單管理", "roles manage": "角色管理", "operation log": "操作日誌", "method": "方法", "input": "輸入", "operation": "操作", "menu name": "菜單名", "query time": "查询时间", "are you sure to delete": "你確定要刪除嗎", "delete succeed": "刪除成功", "yes": "確定", "got it": "知道了", "cancel": "取消", "refresh succeeded": "刷新成功", "avatar": "頭像", "password": "密碼", "slug": "標誌", "permission": "權限", "userid": "用戶ID", "content": "內容", "parent": "父級", "icon": "圖標", "uri": "路徑", "export": "導出", "home": "首頁", "all": "全部", "more": "更多", "browse": "打開", "admin": "管理", "users": "用戶", "roles": "角色", "menu": "菜單", "dashboard": "儀表盤", "permission denied": "沒有權限", "error": "錯誤", "success": "成功", "fail": "失敗", "current page": "當前頁", "confirm": "確認", "edit fail": "編輯失敗", "create fail": "新增失敗", "delete fail": "刪除失敗", "confirm password": "確認密碼", "all method if empty": "為空默認為所有方法", "detail": "詳情", "username": "用戶名", "close": "關閉", "login": "登錄", "login fail": "登錄失敗", "user": "用戶", "continue editing": "繼續編輯", "continue creating": "繼續新增", "goadmin is now running. \nrunning in \"debug\" mode. switch to \"release\" mode in production.\n\n": "GoAdmin 啟動成功。\n目前處於 \"debug\" 模式。請在生產環境中切換為 \"release\" 模式。\n\n", "wrong goadmin version, theme %s required goadmin version are %s": "錯誤的 GoAdmin 版本,當前主題 %s 需要 GoAdmin 版本為 %s", "wrong theme version, goadmin %s required version of theme %s is %s": "錯誤的主題版本, GoAdmin %s 需要主題 %s 的版本為 %s", "adapter is nil, import the default adapter or use addadapter method add the adapter": "適配器為空,請先 import 對應的適配器或使用 AddAdapter 方法引入", "username and password can not be empty": "用戶名密碼不能為空", "operation not allow": "不允許的操作", "password does not match": "密碼不壹致", "should be unique": "需要保證唯壹", "slug exists": "標誌已經存在了", "no corresponding options?": "沒找到對應選項?", "create here.": "在這裏新建壹個。", "use for login": "用於登錄", "use to display": "用來展示", "a path a line, without global prefix": "壹行壹個路徑,換行輸入新路徑,路徑不包含全局路由前綴", "slug or http_path or name should not be empty": "標誌或路徑或權限名不能為空", "no roles": "無角色", "no permission": "沒有權限", "fixed the sidebar": "固定側邊欄", "enter fullscreen": "進入全屏", "exit fullscreen": "退出全屏", "wrong captcha": "錯誤的驗證碼", "modify success": "修改成功", "not found": "找不到記錄", "internal error": "系統內部錯誤", "unauthorized": "未認證", "login overdue, please login again": "登錄信息過期,請重新登錄", "login info": "登錄信息", "initialize configuration": "初始化配置", "initialize navigation buttons": "初始化導航欄按鈕", "initialize plugins": "初始化插件", "initialize database connections": "初始化數據庫連接", "initialize success": "初始化成功🍺🍺", "plugins": "插件", "plugin store": "插件商店", "get more plugins": "獲取更多插件", "uninstalled": "未安裝", "plugin setting": "插件設置", "second": "秒", "seconds": "秒", "minute": "分", "minutes": "分", "hour": "小時", "hours": "小時", "day": "天", "days": "天", "week": "周", "weeks": "周", "month": "月", "months": "月", "year": "年", "years": "年", "config.domain": "網站域名", "config.language": "網站語言", "config.url prefix": "URL前綴", "config.theme": "主題", "config.title": "標題", "config.index url": "首頁URL", "config.login url": "登錄URL", "config.env": "開發環境", "config.color scheme": "顏色主題", "config.cdn url": "cdn資源URL", "config.login title": "登錄標題", "config.auth user table": "登錄用戶表", "config.extra": "額外配置", "config.store": "文件存儲設置", "config.databases": "數據庫設置", "config.general": "通用", "config.log": "日誌", "config.site setting": "網站設置", "config.custom": "定制", "config.debug": "Debug模式", "config.site off": "關閉網站", "config.true": "是", "config.false": "否", "config.test": "測試環境", "config.prod": "生產環境", "config.local": "本地環境", "config.logo": "Logo", "config.mini logo": "Mini Logo", "config.bootstrap file path": "引导文件路徑", "config.go mod file path": "go.mod文件路徑", "config.session life time": "Session時長", "config.custom head html": "自定義Head HTML", "config.custom foot html": "自定義Foot HTML", "config.custom 404 html": "自定義404頁面", "config.custom 403 html": "自定義403頁面", "config.custom 500 html": "自定義500頁面", "config.hide config center entrance": "隱藏配置中心入口", "config.hide app info entrance": "隱藏應用信息入口", "config.hide tool entrance": "隱藏工具入口", "config.hide plugin entrance": "隱藏插件列表入口", "config.footer info": "自定義底部信息", "config.login logo": "登錄Logo", "config.no limit login ip": "取消限制多IP登錄", "config.operation log off": "關閉操作日誌", "config.allow delete operation log": "允許刪除操作日誌", "config.animation type": "動畫類型", "config.animation duration": "動畫間隔(秒)", "config.animation delay": "動畫延遲(秒)", "config.file upload engine": "文件上傳引擎", "config.logger rotate": "日誌切割設置", "config.logger rotate max size": "存儲最大文件大小(m)", "config.logger rotate max backups": "存儲最多文件數", "config.logger rotate max age": "最長存儲時間(天)", "config.logger rotate compress": "壓縮", "config.info log path": "信息日誌存儲路徑", "config.error log path": "錯誤日誌存儲路徑", "config.access log path": "訪問日誌存儲路徑", "config.info log off": "關閉信息日誌", "config.error log off": "關閉錯誤日誌", "config.access log off": "關閉訪問日誌", "config.access assets log off": "關閉靜態資源訪問日誌", "config.sql log on": "打開SQL日誌", "config.log level": "日誌級別", "config.logger rotate encoder": "日誌encoder設置", "config.logger rotate encoder time key": "Time Key", "config.logger rotate encoder level key": "Level Key", "config.logger rotate encoder name key": "Name Key", "config.logger rotate encoder caller key": "Caller Key", "config.logger rotate encoder message key": "Message Key", "config.logger rotate encoder stacktrace key": "Stacktrace Key", "config.logger rotate encoder level": "Level字段編碼", "config.logger rotate encoder time": "Time字段編碼", "config.logger rotate encoder duration": "Duration字段編碼", "config.logger rotate encoder caller": "Caller字段編碼", "config.logger rotate encoder encoding": "輸出格式", "config.capital": "大寫", "config.capitalcolor": "大寫帶顏色", "config.lowercase": "小寫", "config.lowercasecolor": "小寫帶顏色", "config.seconds": "秒", "config.nanosecond": "納秒", "config.microsecond": "微秒", "config.millisecond": "毫秒", "config.full path": "完整路徑", "config.short path": "簡短路徑", "config.do not modify when you have not set up all assets": "不要修改,當妳還沒有設置好所有資源文件的時候", "config.it will work when theme is adminlte": "當主題為adminlte時生效", "config.must bigger than 900 seconds": "必須大於900秒", "config.language." + CN: "中文", "config.language." + EN: "英文", "config.language." + JP: "日文", "config.language." + strings.ToLower(TC): "繁體中文", "config.language." + PTBR: "Brazilian Portuguese", "config.language." + RU: "Русский", "config.modify site config": "修改網站配置", "config.modify site config success": "修改網站配置成功", "config.modify site config fail": "修改網站配置失敗", "system.system info": "應用系統信息", "system.application": "應用信息", "system.application run": "應用運行信息", "system.system": "系統信息", "system.process_id": "進程ID", "system.golang_version": "Golang版本", "system.server_uptime": "服務運行時間", "system.current_goroutine": "當前 Goroutines 數量", "system.current_memory_usage": "當前內存使用量", "system.total_memory_allocated": "所有被分配的內存", "system.memory_obtained": "內存占用量", "system.pointer_lookup_times": "指針查找次數", "system.memory_allocate_times": "內存分配次數", "system.memory_free_times": "內存釋放次數", "system.current_heap_usage": "當前 Heap 內存使用量", "system.heap_memory_obtained": "Heap 內存占用量", "system.heap_memory_idle": "Heap 內存空閑量", "system.heap_memory_in_use": "正在使用的 Heap 內存", "system.heap_memory_released": "被釋放的 Heap 內存", "system.heap_objects": "Heap 對象數量", "system.bootstrap_stack_usage": "啟動 Stack 使用量", "system.stack_memory_obtained": "被分配的 Stack 內存", "system.mspan_structures_usage": "MSpan 結構內存使用量", "system.mspan_structures_obtained": "被分配的 MSpan 結構內存", "system.mcache_structures_usage": "MCache 結構內存使用量", "system.mcache_structures_obtained": "被分配的 MCache 結構內存", "system.profiling_bucket_hash_table_obtained": "被分配的剖析哈希表內存", "system.gc_metadata_obtained": "被分配的 GC 元數據內存", "system.other_system_allocation_obtained": "其它被分配的系統內存", "system.next_gc_recycle": "下次 GC 內存回收量", "system.last_gc_time": "距離上次 GC 時間", "system.total_gc_time": "GC 執行時間總量", "system.total_gc_pause": "GC 暫停時間總量", "system.last_gc_pause": "上次 GC 暫停時間", "system.gc_times": "GC 執行次數", "system.cpu_logical_core": "cpu邏輯核數", "system.cpu_core": "cpu物理核數", "system.os_platform": "系統平臺", "system.os_family": "系統家族", "system.os_version": "系統版本", "system.load1": "1分鐘內負載", "system.load5": "5分鐘內負載", "system.load15": "15分鐘內負載", "system.mem_total": "總內存", "system.mem_available": "可用內存", "system.mem_used": "使用內存", "system.app_name": "應用名", "system.go_admin_version": "應用版本", "system.theme_name": "主題", "system.theme_version": "主題版本", "tool.tool": "工具", "tool.table": "表格", "tool.connection": "連接", "tool.package": "包名", "tool.output": "輸出路徑", "tool.output path is empty": "輸出路徑為空", "tool.field": "字段名", "tool.title": "標題", "tool.field name": "字段名", "tool.db type": "數據類型", "tool.form type": "表單類型", "tool.generate table model": "生成CRUD模型", "tool.primarykey": "主鍵", "tool.field filterable": "可篩選", "tool.field sortable": "可排序", "tool.yes": "是", "tool.no": "否", "tool.generate success": "生成成功", "tool.hide filter area": "隱藏篩選框", "tool.use absolute path": "使用絕對路徑", "tool.hide": "隱藏", "tool.show": "顯示", "tool.display": "顯示", "tool.basic info": "基本信息", "tool.table info": "表格信息", "tool.form info": "表單信息", "tool.field editable": "允許編輯", "tool.field can add": "允許新增", "tool.info field editable": "可編輯", "tool.extra import package": "導入包", "tool.field default": "默認值", "tool.filter area": "篩選框", "tool.new button": "新建按鈕", "tool.export button": "導出按鈕", "tool.edit button": "編輯按鈕", "tool.delete button": "刪除按鈕", "tool.detail button": "詳情按鈕", "tool.filter button": "篩選按鈕", "tool.row selector": "列選擇按鈕", "tool.pagination": "分頁", "tool.query info": "查詢信息", "tool.filter form layout": "篩選表單布局", "tool.continue edit checkbox": "繼續編輯按鈕", "tool.continue new checkbox": "繼續新增按鈕", "tool.reset button": "重設按鈕", "tool.back button": "返回按鈕", "tool.generate": "生成", "tool.generated tables": "生成過的表格", "tool.description": "描述", "tool.label": "標簽", "tool.image": "圖片", "tool.bool": "布爾", "tool.link": "鏈接", "tool.fileSize": "文件大小", "tool.date": "日期", "tool.icon": "Icon", "tool.dot": "標點", "tool.progressBar": "進度條", "tool.loading": "Loading", "tool.downLoadable": "可下載", "tool.copyable": "可復制", "tool.carousel": "圖片輪播", "tool.qrcode": "二維碼", "tool.field hide": "隱藏", "tool.field display": "顯示", "tool.table permission": "生成表格權限", "tool.extra code": "額外代碼", "tool.field display normal": "顯示", "tool.field diplay hide": "隱藏", "tool.field diplay edit hide": "編輯隱藏", "tool.field diplay create hide": "新建隱藏", "tool.detail display": "顯示", "tool.detail info": "詳情頁信息", "tool.follow list page": "跟隨列表頁", "tool.inherit from list page": "繼承列表頁", "tool.independent from list page": "獨立", "tool.generate table model success": "生成成功", "tool.generate table model fail": "生成失敗", "generator.query": "查詢", "generator.show edit form page": "編輯頁顯示", "generator.show create form page": "新建記錄頁顯示", "generator.edit": "編輯", "generator.create": "新建", "generator.delete": "刪除", "generator.export": "導出", "plugin.plugin": "插件", "plugin.plugin detail": "插件詳情", "plugin.introduction": "介紹", "plugin.website": "網站", "plugin.version": "版本", "plugin.created at": "創建日期", "plugin.updated at": "更新日期", "plugin.provided by %s": "由 %s 提供", "plugin.upgrade": "升級", "plugin.install": "安裝", "plugin.info": "詳細信息", "plugin.download": "下载", "plugin.buy": "購買", "plugin.downloading": "下载中", "plugin.login": "登錄", "plugin.login to goadmin member system": "登錄到GoAdmin會員系統", "plugin.account": "賬戶名", "plugin.password": "密碼", "plugin.learn more": "了解更多", "plugin.no account? click %s here %s to register.": "沒有賬號?點擊%s這裏%s註冊。", "plugin.download fail, wrong name": "下載失敗,錯誤的參數", "plugin.change to debug mode first": "先切換到debug模式", "plugin.download fail, plugin not exist": "下載失敗,插件不存在", "plugin.download fail": "下載失敗", "plugin.golang develop environment does not exist": "golang開發環境不存在", "plugin.download success, restart to install": "下載成功,重啟程序進行安裝", "plugin.restart to install": "重啟程序進行安裝", "plugin.can not connect to the goadmin remote server": "不能連接到GoAdmin遠程服務器,請檢查您的網絡連接。", "admin.basic admin": "基礎Admin", "admin.a built-in plugins of goadmin which help you to build a crud manager platform quickly.": "壹個內置GoAdmin插件,幫助您快速搭建curd簡易管理後臺。", "admin.official": "GoAdmin官方", "search": "搜索", "reload succeeded": "載入成功", "showing %s to %s of %s entries": "顯示第 %s 到第 %s 條記錄,總共 %s 條記錄", "site info": "運行信息", "menus": "菜單", "tool.code generate tool": "代碼生成器", "del": "刪除", "site setting": "網站設置", "code generate tool": "代碼生成器", "managers manage": "管理員管理", "system.site info": "運行信息", "view": "查看", } ================================================ FILE: modules/logger/logger.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package logger import ( "fmt" "os" "path/filepath" "strconv" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/trace" "github.com/GoAdminGroup/go-admin/modules/utils" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) var ( defaultEncoderCfg = EncoderCfg{ TimeKey: "ts", LevelKey: "level", NameKey: "logger", CallerKey: "caller", MessageKey: "msg", StacktraceKey: "stacktrace", Level: "capitalColor", Time: "ISO8601", Duration: "seconds", Caller: "short", Encoding: "console", } defaultRotateCfg = RotateCfg{ MaxSize: 10, MaxBackups: 5, MaxAge: 30, Compress: false, } logger = &Logger{ rotate: defaultRotateCfg, encoder: defaultEncoderCfg, Level: zapcore.InfoLevel, } infoLevelEnabler = zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl == zapcore.InfoLevel }) errorLevelEnabler = zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl >= zapcore.ErrorLevel }) accessLevelEnabler = zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl == zapcore.WarnLevel }) ) func init() { logger.Init() } type Logger struct { logger *zap.Logger sugaredLogger *zap.SugaredLogger infoLogOff bool errorLogOff bool accessLogOff bool accessAssetsLogOff bool debug bool sqlLogOpen bool infoLogPath string errorLogPath string accessLogPath string rotate RotateCfg encoder EncoderCfg Level zapcore.Level } type EncoderCfg struct { TimeKey string LevelKey string NameKey string CallerKey string MessageKey string StacktraceKey string Level string Time string Duration string Caller string Encoding string } type RotateCfg struct { MaxSize int MaxBackups int MaxAge int Compress bool } func (l *Logger) Init() { zapLogger := zap.New(zapcore.NewTee( zapcore.NewCore(l.getEncoder(l.encoder.LevelKey), l.getLogWriter(l.infoLogPath), infoLevelEnabler), zapcore.NewCore(l.getEncoder(l.encoder.LevelKey), l.getLogWriter(l.errorLogPath), errorLevelEnabler), zapcore.NewCore(l.getEncoder(""), l.getLogWriter(l.accessLogPath), accessLevelEnabler), ), zap.AddCaller(), zap.AddCallerSkip(1), zap.AddStacktrace(errorLevelEnabler)) l.sugaredLogger = zapLogger.Sugar() l.logger = zapLogger } func (l *Logger) getEncoder(levelKey string) zapcore.Encoder { var ( timeEncoder = new(zapcore.TimeEncoder) durationEncoder = new(zapcore.DurationEncoder) callerEncoder = new(zapcore.CallerEncoder) nameEncoder = new(zapcore.NameEncoder) levelEncoder = new(zapcore.LevelEncoder) ) _ = timeEncoder.UnmarshalText([]byte(l.encoder.Time)) _ = durationEncoder.UnmarshalText([]byte(l.encoder.Duration)) _ = callerEncoder.UnmarshalText([]byte(l.encoder.Caller)) _ = nameEncoder.UnmarshalText([]byte("full")) _ = levelEncoder.UnmarshalText([]byte(l.encoder.Level)) encoderConfig := zapcore.EncoderConfig{ TimeKey: l.encoder.TimeKey, LevelKey: levelKey, NameKey: l.encoder.NameKey, CallerKey: l.encoder.CallerKey, MessageKey: l.encoder.MessageKey, StacktraceKey: l.encoder.StacktraceKey, LineEnding: zapcore.DefaultLineEnding, EncodeLevel: *levelEncoder, EncodeTime: *timeEncoder, EncodeDuration: *durationEncoder, EncodeCaller: *callerEncoder, EncodeName: *nameEncoder, } return filterZapEncoder(l.encoder.Encoding, encoderConfig) } func (l *Logger) getLogWriter(path string) zapcore.WriteSyncer { if path != "" { lumberJackLogger := &lumberjack.Logger{ Filename: path, MaxSize: l.rotate.MaxSize, MaxBackups: l.rotate.MaxBackups, MaxAge: l.rotate.MaxAge, Compress: l.rotate.Compress, } if l.debug { return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(lumberJackLogger)) } return zapcore.AddSync(lumberJackLogger) } return zapcore.AddSync(os.Stdout) } func (l *Logger) SetRotate(cfg RotateCfg) { if cfg.MaxSize != 0 && cfg.MaxAge != 0 && cfg.MaxBackups != 0 { l.rotate = cfg } } func (l *Logger) SetEncoder(cfg EncoderCfg) { cfg.TimeKey = utils.SetDefault(cfg.TimeKey, "", defaultEncoderCfg.TimeKey) cfg.LevelKey = utils.SetDefault(cfg.LevelKey, "", defaultEncoderCfg.LevelKey) cfg.NameKey = utils.SetDefault(cfg.NameKey, "", defaultEncoderCfg.NameKey) cfg.CallerKey = utils.SetDefault(cfg.CallerKey, "", defaultEncoderCfg.CallerKey) cfg.MessageKey = utils.SetDefault(cfg.MessageKey, "", defaultEncoderCfg.MessageKey) cfg.StacktraceKey = utils.SetDefault(cfg.StacktraceKey, "", defaultEncoderCfg.StacktraceKey) cfg.Level = utils.SetDefault(cfg.Level, "", defaultEncoderCfg.Level) cfg.Time = utils.SetDefault(cfg.Time, "", defaultEncoderCfg.Time) cfg.Duration = utils.SetDefault(cfg.Duration, "", defaultEncoderCfg.Duration) cfg.Caller = utils.SetDefault(cfg.Caller, "", defaultEncoderCfg.Caller) cfg.Encoding = utils.SetDefault(cfg.Encoding, "", defaultEncoderCfg.Encoding) l.encoder = cfg } type Config struct { InfoLogOff bool ErrorLogOff bool AccessLogOff bool SqlLogOpen bool InfoLogPath string ErrorLogPath string AccessLogPath string AccessAssetsLogOff bool Rotate RotateCfg Encode EncoderCfg Level int8 Debug bool } func InitWithConfig(cfg Config) { logger.infoLogPath = cfg.InfoLogPath logger.infoLogOff = cfg.InfoLogOff logger.errorLogPath = cfg.ErrorLogPath logger.errorLogOff = cfg.ErrorLogOff logger.accessLogPath = cfg.AccessLogPath logger.accessLogOff = cfg.AccessLogOff logger.sqlLogOpen = cfg.SqlLogOpen logger.accessAssetsLogOff = cfg.AccessAssetsLogOff logger.debug = cfg.Debug logger.SetRotate(cfg.Rotate) logger.SetEncoder(cfg.Encode) logger.Level = filterZapAtomicLevelByViper(cfg.Level) logger.Init() } func SetRotate(cfg RotateCfg) { logger.rotate = cfg logger.Init() } // OpenSQLLog set the sqlLogOpen true. func OpenSQLLog() { logger.sqlLogOpen = true } // Debug print the debug message. func Debug(info ...interface{}) { if !logger.infoLogOff { if logger.Level <= zapcore.DebugLevel { logger.sugaredLogger.Info(info...) } } } // Debugf print the debug message. func Debugf(template string, args ...interface{}) { if !logger.infoLogOff && logger.Level <= zapcore.DebugLevel { logger.sugaredLogger.Infof(template, args...) } } // Info print the info message. func Info(info ...interface{}) { if !logger.infoLogOff && logger.Level <= zapcore.InfoLevel { logger.sugaredLogger.Info(info...) } } // InfoCtx print the info message with ctx. func InfoCtx(ctx *context.Context, format string, args ...interface{}) { if !logger.infoLogOff && logger.Level <= zapcore.InfoLevel { logCtx(ctx, logger.logger.Info, format, args...) } } type logFunc func(msg string, fields ...zapcore.Field) func logCtx(ctx *context.Context, logFunc logFunc, format string, args ...interface{}) { logFunc(fmt.Sprintf(format, args...), zap.String("traceID", trace.GetTraceID(ctx))) } // Info print the info message. func Infof(template string, args ...interface{}) { if !logger.infoLogOff && logger.Level <= zapcore.InfoLevel { logger.sugaredLogger.Infof(template, args...) } } // Warn print the warning message. func Warn(info ...interface{}) { if !logger.infoLogOff && logger.Level <= zapcore.WarnLevel { logger.sugaredLogger.Warn(info...) } } // WarnCtx print the warning message with ctx. func WarnCtx(ctx *context.Context, format string, args ...interface{}) { if !logger.infoLogOff && logger.Level <= zapcore.WarnLevel { logCtx(ctx, logger.logger.Warn, format, args...) } } // Warnf print the warning message. func Warnf(template string, args ...interface{}) { if !logger.infoLogOff && logger.Level <= zapcore.WarnLevel { logger.sugaredLogger.Warnf(template, args...) } } // Error print the error message. func Error(err ...interface{}) { if !logger.errorLogOff && logger.Level <= zapcore.ErrorLevel { logger.sugaredLogger.Error(err...) } } // ErrorCtx print the error message with ctx. func ErrorCtx(ctx *context.Context, format string, args ...interface{}) { if !logger.errorLogOff && logger.Level <= zapcore.ErrorLevel { logCtx(ctx, logger.logger.Error, format, args...) } } // Errorf print the error message. func Errorf(template string, args ...interface{}) { if !logger.errorLogOff && logger.Level <= zapcore.ErrorLevel { logger.sugaredLogger.Errorf(template, args...) } } // Fatal print the fatal message. func Fatal(info ...interface{}) { if !logger.errorLogOff && logger.Level <= zapcore.ErrorLevel { logger.sugaredLogger.Fatal(info...) } } // FatalCtx print the fatal message with ctx. func FatalCtx(ctx *context.Context, format string, args ...interface{}) { if !logger.errorLogOff && logger.Level <= zapcore.FatalLevel { logCtx(ctx, logger.logger.Fatal, format, args...) } } // Fatalf print the fatal message. func Fatalf(template string, args ...interface{}) { if !logger.errorLogOff && logger.Level <= zapcore.ErrorLevel { logger.sugaredLogger.Fatalf(template, args...) } } // Fatal print the panic message. func Panic(info ...interface{}) { logger.sugaredLogger.Panic(info...) } // PanicCtx print the panic message with ctx. func PanicCtx(ctx *context.Context, format string, args ...interface{}) { logCtx(ctx, logger.logger.Panic, format, args...) } // Panicf print the panic message. func Panicf(template string, args ...interface{}) { logger.sugaredLogger.Panicf(template, args...) } // Access print the access message. func Access(ctx *context.Context) { if !logger.accessLogOff && logger.Level <= zapcore.InfoLevel { if logger.accessAssetsLogOff { if filepath.Ext(ctx.Path()) == "" { logger.logger.Info("[GoAdmin] access log", zap.String("traceID", trace.GetTraceID(ctx)), zap.String("statuscode", strconv.Itoa(ctx.Response.StatusCode)), zap.String("method", string(ctx.Method())), zap.String("path", ctx.Path())) } } else { logger.logger.Info("[GoAdmin] access log", zap.String("traceID", trace.GetTraceID(ctx)), zap.String("statuscode", strconv.Itoa(ctx.Response.StatusCode)), zap.String("method", string(ctx.Method())), zap.String("path", ctx.Path())) } } } // LogSQL print the sql info message. func LogSQL(statement string, args []interface{}) { if !logger.infoLogOff && logger.sqlLogOpen && statement != "" { if logger.Level <= zapcore.InfoLevel { logger.sugaredLogger.With("statement", statement, "args", args).Info("[GoAdmin]") } } } func filterZapEncoder(encoding string, encoderConfig zapcore.EncoderConfig) zapcore.Encoder { var encoder zapcore.Encoder switch encoding { default: encoder = zapcore.NewConsoleEncoder(encoderConfig) case "json": encoder = zapcore.NewJSONEncoder(encoderConfig) case "console": encoder = zapcore.NewConsoleEncoder(encoderConfig) } return encoder } func filterZapAtomicLevelByViper(level int8) zapcore.Level { var atomViper zapcore.Level switch level { default: atomViper = zap.InfoLevel case -1: atomViper = zap.DebugLevel case 0: atomViper = zap.InfoLevel case 1: atomViper = zap.WarnLevel case 2: atomViper = zap.ErrorLevel } return atomViper } ================================================ FILE: modules/logger/logger_test.go ================================================ package logger import "testing" func TestInfo(t *testing.T) { Info("test") } ================================================ FILE: modules/menu/menu.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package menu import ( "html/template" "regexp" "strconv" "strings" "github.com/GoAdminGroup/go-admin/modules/db/dialect" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/admin/models" ) // Item is an menu item. type Item struct { Name string `json:"name"` ID string `json:"id"` Url string `json:"url"` IsLinkUrl bool `json:"isLinkUrl"` Icon string `json:"icon"` Header string `json:"header"` Active string `json:"active"` ChildrenList []Item `json:"childrenList"` } // Menu contains list of menu items and other info. type Menu struct { List []Item `json:"list"` Options []map[string]string `json:"options"` MaxOrder int64 `json:"maxOrder"` PluginName string `json:"pluginName"` ForceUpdate bool `json:"forceUpdate"` } func (menu *Menu) GetUpdateJS(updateFlag bool) template.JS { if !updateFlag { return "" } forceUpdate := "false" if menu.ForceUpdate { forceUpdate = "true" } return template.JS(`$(function () { let curMenuPlug = $(".main-sidebar section.sidebar ul.sidebar-menu").attr("data-plug"); if (curMenuPlug !== '` + menu.PluginName + `' || ` + forceUpdate + `) { $(".main-sidebar section.sidebar").html($("#sidebar-menu-tmpl").html()) } });`) } // SetMaxOrder set the max order of menu. func (menu *Menu) SetMaxOrder(order int64) { menu.MaxOrder = order } // AddMaxOrder add the max order of menu. func (menu *Menu) AddMaxOrder() { menu.MaxOrder++ } // SetActiveClass set the active class of menu. func (menu *Menu) SetActiveClass(path string) *Menu { reg, _ := regexp.Compile(`\?(.*)`) path = reg.ReplaceAllString(path, "") for i := 0; i < len(menu.List); i++ { menu.List[i].Active = "" } for i := 0; i < len(menu.List); i++ { if menu.List[i].Url == path && len(menu.List[i].ChildrenList) == 0 { menu.List[i].Active = "active" return menu } for j := 0; j < len(menu.List[i].ChildrenList); j++ { if menu.List[i].ChildrenList[j].Url == path { menu.List[i].Active = "active" menu.List[i].ChildrenList[j].Active = "active" return menu } menu.List[i].Active = "" menu.List[i].ChildrenList[j].Active = "" } } return menu } // FormatPath get template.HTML for front-end. func (menu Menu) FormatPath() template.HTML { res := template.HTML(``) for i := 0; i < len(menu.List); i++ { if menu.List[i].Active != "" { if menu.List[i].Url != "#" && menu.List[i].Url != "" && len(menu.List[i].ChildrenList) > 0 { res += template.HTML(`
  • ` + menu.List[i].Name + `
  • `) } else { res += template.HTML(`
  • ` + menu.List[i].Name + `
  • `) if len(menu.List[i].ChildrenList) == 0 { return res } } for j := 0; j < len(menu.List[i].ChildrenList); j++ { if menu.List[i].ChildrenList[j].Active != "" { return res + template.HTML(`
  • `+menu.List[i].ChildrenList[j].Name+`
  • `) } } } } return res } // GetEditMenuList return menu items list. func (menu *Menu) GetEditMenuList() []Item { return menu.List } type NewMenuData struct { ParentId int64 `json:"parent_id"` Type int64 `json:"type"` Order int64 `json:"order"` Title string `json:"title"` Icon string `json:"icon"` PluginName string `json:"plugin_name"` Uri string `json:"uri"` Header string `json:"header"` Uuid string `json:"uuid"` } func NewMenu(conn db.Connection, data NewMenuData) (int64, error) { maxOrder := data.Order checkOrder, _ := db.WithDriver(conn).Table("goadmin_menu"). Where("plugin_name", "=", data.PluginName). OrderBy("order", "desc"). First() if checkOrder != nil { maxOrder = checkOrder["order"].(int64) } id, err := db.WithDriver(conn).Table("goadmin_menu"). Insert(dialect.H{ "parent_id": data.ParentId, "type": data.Type, "order": maxOrder, "title": data.Title, "uuid": data.Uuid, "icon": data.Icon, "plugin_name": data.PluginName, "uri": data.Uri, "header": data.Header, }) if !db.CheckError(err, db.INSERT) { return id, nil } return id, err } // GetGlobalMenu return Menu of given user model. func GetGlobalMenu(user models.UserModel, conn db.Connection, lang string, pluginNames ...string) *Menu { var ( menus []map[string]interface{} menuOption = make([]map[string]string, 0) plugName = "" ) if len(pluginNames) > 0 { plugName = pluginNames[0] } user.WithRoles().WithMenus() if user.IsSuperAdmin() { menus, _ = db.WithDriver(conn).Table("goadmin_menu"). Where("id", ">", 0). Where("plugin_name", "=", plugName). OrderBy("order", "asc"). All() } else { var ids []interface{} for i := 0; i < len(user.MenuIds); i++ { ids = append(ids, user.MenuIds[i]) } menus, _ = db.WithDriver(conn).Table("goadmin_menu"). WhereIn("id", ids). Where("plugin_name", "=", plugName). OrderBy("order", "asc"). All() } var title string for i := 0; i < len(menus); i++ { title = language.GetWithLang(menus[i]["title"].(string), lang) menuOption = append(menuOption, map[string]string{ "id": strconv.FormatInt(menus[i]["id"].(int64), 10), "title": title, }) } menuList := constructMenuTree(menus, 0, lang) maxOrder := int64(0) if len(menus) > 0 { maxOrder = menus[len(menus)-1]["parent_id"].(int64) } return &Menu{ List: menuList, Options: menuOption, MaxOrder: maxOrder, PluginName: plugName, } } func constructMenuTree(menus []map[string]interface{}, parentID int64, lang string) []Item { branch := make([]Item, 0) var title string for j := 0; j < len(menus); j++ { if parentID == menus[j]["parent_id"].(int64) { if menus[j]["type"].(int64) == 1 { title = language.Get(menus[j]["title"].(string)) } else { title = menus[j]["title"].(string) } header, _ := menus[j]["header"].(string) uri := menus[j]["uri"].(string) if lang != "" { if strings.Contains(uri, "?") { uri += "&__ga_lang=" + lang } else { uri += "?__ga_lang=" + lang } } child := Item{ Name: title, ID: strconv.FormatInt(menus[j]["id"].(int64), 10), Url: uri, Icon: menus[j]["icon"].(string), Header: header, Active: "", ChildrenList: constructMenuTree(menus, menus[j]["id"].(int64), lang), } branch = append(branch, child) } } return branch } ================================================ FILE: modules/menu/menu_test.go ================================================ package menu import ( "testing" "github.com/magiconair/properties/assert" ) func TestMenu_AddMaxOrder(t *testing.T) { menus := Menu{ MaxOrder: 0, } menus.AddMaxOrder() assert.Equal(t, menus.MaxOrder, int64(1)) } func TestMenu_SetMaxOrder(t *testing.T) { menus := Menu{ MaxOrder: 0, } menus.SetMaxOrder(2) assert.Equal(t, menus.MaxOrder, int64(2)) } func TestMenu_SetActiveClass(t *testing.T) { menus := Menu{ List: []Item{ { Name: "item1", ID: "1", Url: "/item1", Icon: "icon", }, { Name: "item2", ID: "2", Url: "/item2", Icon: "icon", }, { Name: "item3", ID: "3", Url: "/item3", Icon: "icon", }, { Name: "item4", ID: "4", Url: "/item4", Icon: "icon", ChildrenList: []Item{ { Name: "item5", ID: "5", Url: "/item5", Icon: "icon", }, { Name: "item6", ID: "6", Url: "/item6", Icon: "icon", }, }, }, }, Options: []map[string]string{}, MaxOrder: 0, } menus.SetActiveClass("/item3") assert.Equal(t, menus.List[0].Active, "") assert.Equal(t, menus.List[1].Active, "") assert.Equal(t, menus.List[2].Active, "active") assert.Equal(t, menus.List[3].Active, "") menus.SetActiveClass("/item5") assert.Equal(t, menus.List[0].Active, "") assert.Equal(t, menus.List[1].Active, "") assert.Equal(t, menus.List[2].Active, "") assert.Equal(t, menus.List[3].Active, "active") assert.Equal(t, menus.List[3].ChildrenList[0].Active, "active") assert.Equal(t, menus.List[3].ChildrenList[1].Active, "") } ================================================ FILE: modules/page/page.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package page import ( "bytes" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/menu" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" ) // SetPageContent set and return the panel of page content. func SetPageContent(ctx *context.Context, user models.UserModel, c func(ctx interface{}) (types.Panel, error), conn db.Connection) { panel, err := c(ctx) if err != nil { logger.ErrorCtx(ctx, "SetPageContent %+v", err) panel = template.WarningPanel(ctx, err.Error()) } tmpl, tmplName := template.Get(ctx, config.GetTheme()).GetTemplate(ctx.IsPjax()) ctx.AddHeader("Content-Type", "text/html; charset=utf-8") buf := new(bytes.Buffer) err = tmpl.ExecuteTemplate(buf, tmplName, types.NewPage(ctx, &types.NewPageParam{ User: user, Menu: menu.GetGlobalMenu(user, conn, ctx.Lang()).SetActiveClass(config.URLRemovePrefix(ctx.Path())), Panel: panel.GetContent(config.IsProductionEnvironment()), Assets: template.GetComponentAssetImportHTML(ctx), TmplHeadHTML: template.Default(ctx).GetHeadHTML(), TmplFootJS: template.Default(ctx).GetFootJS(), Iframe: ctx.IsIframe(), })) if err != nil { logger.ErrorCtx(ctx, "SetPageContent %+v", err) } ctx.WriteString(buf.String()) } ================================================ FILE: modules/remote_server/remote_server.go ================================================ package remote_server import ( "encoding/json" "io/ioutil" "net/http" "strings" "github.com/GoAdminGroup/go-admin/modules/system" "github.com/GoAdminGroup/go-admin/modules/logger" ) const ( // ServerHost = "http://localhost:8055" // ServerHostApi = "http://localhost:8055/api" ServerHost = "https://www.go-admin.cn" ServerHostApi = "https://www.go-admin.cn/api" ) type LoginRes struct { Code int `json:"code"` Data struct { Token string `json:"token"` Name string `json:"name"` Expire int64 `json:"expire"` } `json:"data"` Msg string `json:"msg"` } func Login(account, password string) LoginRes { var resData LoginRes req, err := http.NewRequest("POST", ServerHostApi+"/signin", strings.NewReader(`{"account":"`+account+ `","password":"`+password+`"}`)) if err != nil { logger.Error("login: ", err) resData.Code = 500 resData.Msg = "request error" return resData } req.Header.Add("Content-Type", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { logger.Error("login: ", err) resData.Code = 500 resData.Msg = "request error" return resData } defer func() { _ = res.Body.Close() }() body, err := ioutil.ReadAll(res.Body) if err != nil { logger.Error("login: ", err) resData.Code = 500 resData.Msg = "request error" return resData } err = json.Unmarshal(body, &resData) if err != nil { logger.Error("login: ", err) resData.Code = 500 resData.Msg = "request error" return resData } if resData.Code != 0 { logger.Error("login to remote GoAdmin server error: ", resData.Msg) return resData } return resData } type GetDownloadURLRes struct { Code int `json:"code"` Data struct { Url string `json:"url"` ExtraUrl string `json:"extra_url"` } `json:"data"` Msg string `json:"msg"` } func GetDownloadURL(uuid, token string) (string, string, error) { var resData GetDownloadURLRes req, err := http.NewRequest("GET", ServerHostApi+"/plugin/download", strings.NewReader(`{"uuid":"`+uuid+`", "version":"`+system.Version()+`"}`)) if err != nil { logger.Error("get plugin download url error: ", err) return "", "", err } req.Header.Add(TokenKey, token) req.Header.Add("Content-Type", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { return "", "", err } defer func() { _ = res.Body.Close() }() body, err := ioutil.ReadAll(res.Body) if err != nil { return "", "", err } err = json.Unmarshal(body, &resData) if err != nil { return "", "", err } if resData.Code != 0 { return "", "", err } return resData.Data.Url, resData.Data.ExtraUrl, nil } const TokenKey = "GOADMIN_OFFICIAL_SESS" type GetOnlineReq struct { Page string `json:"page"` Free string `json:"free"` PageSize string `json:"page_size"` Filter string `json:"filter"` Order string `json:"order"` Lang string `json:"lang"` CategoryId string `json:"category_id"` Version string `json:"version"` } func (req GetOnlineReq) Format() string { res := "" if req.Page != "" { res += "page=" + req.Page + "&" } if req.PageSize != "" { res += "page_size=" + req.PageSize + "&" } if req.Lang != "" { res += "lang=" + req.Lang + "&" } if req.Filter != "" { res += "filter=" + req.Filter + "&" } if req.Order != "" { res += "order=" + req.Order + "&" } if req.CategoryId != "" { res += "category_id=" + req.CategoryId + "&" } if req.Free != "" { res += "free=" + req.Free + "&" } if req.Version != "" { res += "version=" + req.Version + "&" } if res != "" { return res[:len(res)-1] } return res } func GetOnline(reqData GetOnlineReq, token string) ([]byte, error) { // TODO: add cache req, err := http.NewRequest("GET", ServerHostApi+"/plugin/list?"+reqData.Format(), nil) if err != nil { logger.Error("get online plugins: ", err) return nil, err } if token != "" { req.Header.Add(TokenKey, token) } res, err := http.DefaultClient.Do(req) if err != nil { logger.Error("get online plugins: ", err) return nil, err } defer func() { _ = res.Body.Close() }() body, err := ioutil.ReadAll(res.Body) if err != nil { logger.Error("get online plugins: ", err) return nil, err } return body, nil } ================================================ FILE: modules/service/service.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package service import ( "log" ) type Service interface { Name() string } type Generator func() (Service, error) func Register(k string, gen Generator) { if _, ok := services[k]; ok { log.Panicf("service %s has been registered", k) } services[k] = gen } func GetServices() List { var ( l = make(List) err error ) for k, gen := range services { if l[k], err = gen(); err != nil { log.Panicf("service %s initialize fail, error: %v", k, err) } } return l } var services = make(Generators) type Generators map[string]Generator type List map[string]Service func (g List) Get(k string) Service { if v, ok := g[k]; ok { return v } log.Panicf("service %s not found", k) return nil } func (g List) GetOrNot(k string) (Service, bool) { v, ok := g[k] return v, ok } func (g List) Add(k string, service Service) { if _, ok := g[k]; ok { log.Panicf("service %s exist", k) } g[k] = service } ================================================ FILE: modules/system/application.go ================================================ package system import ( "fmt" "runtime" "time" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/utils" ) var ( startTime = time.Now() ) type AppStatus struct { Uptime string NumGoroutine int // General statistics. MemAllocated string // bytes allocated and still in use MemTotal string // bytes allocated (even if freed) MemSys string // bytes obtained from system (sum of XxxSys below) Lookups uint64 // number of pointer lookups MemMallocs uint64 // number of mallocs MemFrees uint64 // number of frees // Main allocation heap statistics. HeapAlloc string // bytes allocated and still in use HeapSys string // bytes obtained from system HeapIdle string // bytes in idle spans HeapInuse string // bytes in non-idle span HeapReleased string // bytes released to the OS HeapObjects uint64 // total number of allocated objects // Low-level fixed-size structure allocator statistics. // Inuse is bytes used now. // Sys is bytes obtained from system. StackInuse string // bootstrap stacks StackSys string MSpanInuse string // mspan structures MSpanSys string MCacheInuse string // mcache structures MCacheSys string BuckHashSys string // profiling bucket hash table GCSys string // GC metadata OtherSys string // other system allocations // Garbage collector statistics. NextGC string // next run in HeapAlloc time (bytes) LastGC string // last run in absolute time (ns) PauseTotalNs string PauseNs string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256] NumGC uint32 } func GetAppStatus() AppStatus { var app AppStatus app.Uptime = utils.TimeSincePro(startTime, language.Lang[config.GetLanguage()]) m := new(runtime.MemStats) runtime.ReadMemStats(m) app.NumGoroutine = runtime.NumGoroutine() app.MemAllocated = utils.FileSize(m.Alloc) app.MemTotal = utils.FileSize(m.TotalAlloc) app.MemSys = utils.FileSize(m.Sys) app.Lookups = m.Lookups app.MemMallocs = m.Mallocs app.MemFrees = m.Frees app.HeapAlloc = utils.FileSize(m.HeapAlloc) app.HeapSys = utils.FileSize(m.HeapSys) app.HeapIdle = utils.FileSize(m.HeapIdle) app.HeapInuse = utils.FileSize(m.HeapInuse) app.HeapReleased = utils.FileSize(m.HeapReleased) app.HeapObjects = m.HeapObjects app.StackInuse = utils.FileSize(m.StackInuse) app.StackSys = utils.FileSize(m.StackSys) app.MSpanInuse = utils.FileSize(m.MSpanInuse) app.MSpanSys = utils.FileSize(m.MSpanSys) app.MCacheInuse = utils.FileSize(m.MCacheInuse) app.MCacheSys = utils.FileSize(m.MCacheSys) app.BuckHashSys = utils.FileSize(m.BuckHashSys) app.GCSys = utils.FileSize(m.GCSys) app.OtherSys = utils.FileSize(m.OtherSys) app.NextGC = utils.FileSize(m.NextGC) app.LastGC = fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000) app.PauseTotalNs = fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000) app.PauseNs = fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000) app.NumGC = m.NumGC return app } type SysStatus struct { CpuLogicalCore int CpuCore int OSPlatform string OSFamily string OSVersion string Load1 float64 Load5 float64 Load15 float64 MemTotal string MemAvailable string MemUsed string } ================================================ FILE: modules/system/version.go ================================================ package system const version = "v1.2.27" var requireThemeVersion = map[string][]string{ "adminlte": {">=v0.0.41"}, "sword": {">=v0.0.41"}, } // Version return the version of framework. func Version() string { return version } // RequireThemeVersion return the require official version func RequireThemeVersion() map[string][]string { return requireThemeVersion } ================================================ FILE: modules/trace/trace.go ================================================ package trace import ( "fmt" "net" "os" "sync" "sync/atomic" "time" "github.com/GoAdminGroup/go-admin/context" ) var ( machineIDOnce sync.Once machineID string counter uint32 ) func getMachineID() string { machineIDOnce.Do(func() { addrs, err := net.InterfaceAddrs() if err == nil { for _, addr := range addrs { if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { if ipNet.IP.To4() != nil { machineID = ipNet.IP.String() break } } } } if machineID == "" { machineID = "127.0.0.1" } }) return machineID } func GenerateTraceID() string { machineID := getMachineID() timestamp := time.Now().UnixNano() / int64(time.Millisecond) processID := os.Getpid() id := atomic.AddUint32(&counter, 1) id = id % 1000 traceID := fmt.Sprintf("%08x%05d%013d%04d", machineIDToHex(machineID), processID, timestamp, id) return traceID } func machineIDToHex(machineID string) uint32 { ip := net.ParseIP(machineID) ipUint32 := uint32(ip[12])<<24 | uint32(ip[13])<<16 | uint32(ip[14])<<8 | uint32(ip[15]) return ipUint32 } func GetTraceID(ctx *context.Context) string { traceID, ok := ctx.GetUserValue(TraceIDKey).(string) if !ok { return "" } return traceID } const ( TraceIDKey = "traceID" ) ================================================ FILE: modules/ui/ui.go ================================================ package ui import ( "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/service" "github.com/GoAdminGroup/go-admin/template/icon" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/action" ) type Service struct { NavButtons *types.Buttons } const ServiceKey = "ui" func (s *Service) Name() string { return "ui" } func GetService(srv service.List) *Service { if v, ok := srv.Get("ui").(*Service); ok { return v } panic("wrong service") } func NewService(btns *types.Buttons) *Service { return &Service{ NavButtons: btns, } } func (s *Service) UpdateButtons() { } func (s *Service) RemoveOrShowSiteNavButton(remove bool) { if remove { *s.NavButtons = (*s.NavButtons).RemoveSiteNavButton() } else { *s.NavButtons = (*s.NavButtons).AddNavButton(icon.Gear, types.NavBtnSiteName, action.JumpInNewTab(config.Url("/info/site/edit"), language.GetWithScope("site setting", "config"))) } } func (s *Service) RemoveOrShowInfoNavButton(remove bool) { if remove { *s.NavButtons = (*s.NavButtons).RemoveInfoNavButton() } else { *s.NavButtons = (*s.NavButtons).AddNavButton(icon.Info, types.NavBtnInfoName, action.JumpInNewTab(config.Url("/application/info"), language.GetWithScope("system info", "system"))) } } func (s *Service) RemoveOrShowToolNavButton(remove bool) { if remove { *s.NavButtons = (*s.NavButtons).RemoveToolNavButton() } else { *s.NavButtons = (*s.NavButtons).AddNavButton(icon.Wrench, types.NavBtnToolName, action.JumpInNewTab(config.Url("/info/generate/new"), language.GetWithScope("tool", "tool"))) } } func (s *Service) RemoveOrShowPlugNavButton(remove bool) { if remove { *s.NavButtons = (*s.NavButtons).RemovePlugNavButton() } else { *s.NavButtons = (*s.NavButtons).AddNavButton(icon.Plug, types.NavBtnToolName, action.JumpInNewTab(config.Url("/plugin"), language.GetWithScope("plugin", "plugin"))) } } ================================================ FILE: modules/utils/utils.go ================================================ package utils import ( "archive/zip" "bytes" "encoding/gob" "encoding/json" "fmt" "html/template" "io" "math" "net/http" "net/url" "os" "path/filepath" "reflect" "regexp" "strconv" "strings" textTmpl "text/template" "time" "github.com/NebulousLabs/fastrand" ) func Uuid(length int64) string { ele := []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "v", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "Driver", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"} ele, _ = Random(ele) uuid := "" var i int64 for i = 0; i < length; i++ { uuid += ele[fastrand.Intn(59)] } return uuid } func Random(strings []string) ([]string, error) { for i := len(strings) - 1; i > 0; i-- { num := fastrand.Intn(i + 1) strings[i], strings[num] = strings[num], strings[i] } str := make([]string, 0) for i := 0; i < len(strings); i++ { str = append(str, strings[i]) } return str, nil } func CompressedContent(h *template.HTML) { st := strings.Split(string(*h), "\n") var ss []string for i := 0; i < len(st); i++ { st[i] = strings.TrimSpace(st[i]) if st[i] != "" { ss = append(ss, st[i]) } } *h = template.HTML(strings.Join(ss, "\n")) } func ReplaceNth(s, old, new string, n int) string { i := 0 for m := 1; m <= n; m++ { x := strings.Index(s[i:], old) if x < 0 { break } i += x if m == n { return s[:i] + new + s[i+len(old):] } i += len(old) } return s } func InArray(arr []string, str string) bool { for _, v := range arr { if v == str { return true } } return false } func WrapURL(u string) string { uarr := strings.Split(u, "?") if len(uarr) < 2 { return url.QueryEscape(strings.ReplaceAll(u, "/", "_")) } v, err := url.ParseQuery(uarr[1]) if err != nil { return url.QueryEscape(strings.ReplaceAll(u, "/", "_")) } return url.QueryEscape(strings.ReplaceAll(uarr[0], "/", "_")) + "?" + strings.ReplaceAll(v.Encode(), "%7B%7B.Id%7D%7D", "{{.Id}}") } func JSON(a interface{}) string { if a == nil { return "" } b, _ := json.Marshal(a) return string(b) } func ParseBool(s string) bool { b1, _ := strconv.ParseBool(s) return b1 } func ReplaceAll(s string, oldnew ...string) string { repl := strings.NewReplacer(oldnew...) return repl.Replace(s) } func PackageName(v interface{}) string { if v == nil { return "" } val := reflect.ValueOf(v) if val.Kind() == reflect.Ptr { return val.Elem().Type().PkgPath() } return val.Type().PkgPath() } func ParseFloat32(f string) float32 { s, _ := strconv.ParseFloat(f, 32) return float32(s) } func SetDefault(value, condition, def string) string { if value == condition { return def } return value } func AorB(condition bool, a, b string) string { if condition { return a } return b } func IsJSON(str string) bool { var js json.RawMessage return json.Unmarshal([]byte(str), &js) == nil } func CopyMap(m map[string]string) map[string]string { var buf bytes.Buffer enc := gob.NewEncoder(&buf) dec := gob.NewDecoder(&buf) err := enc.Encode(m) if err != nil { panic(err) } var cm map[string]string err = dec.Decode(&cm) if err != nil { panic(err) } return cm } func ParseTime(stringTime string) time.Time { loc, _ := time.LoadLocation("Local") theTime, _ := time.ParseInLocation("2006-01-02 15:04:05", stringTime, loc) return theTime } func ParseHTML(name, tmpl string, param interface{}) template.HTML { t := template.New(name) t, err := t.Parse(tmpl) if err != nil { fmt.Println("utils parseHTML error", err) return "" } buf := new(bytes.Buffer) err = t.Execute(buf, param) if err != nil { fmt.Println("utils parseHTML error", err) return "" } return template.HTML(buf.String()) } func ParseText(name, tmpl string, param interface{}) string { t := textTmpl.New(name) t, err := t.Parse(tmpl) if err != nil { fmt.Println("utils parseHTML error", err) return "" } buf := new(bytes.Buffer) err = t.Execute(buf, param) if err != nil { fmt.Println("utils parseHTML error", err) return "" } return buf.String() } func CompareVersion(src, toCompare string) bool { if toCompare == "" { return false } exp, _ := regexp.Compile(`-(.*)`) src = exp.ReplaceAllString(src, "") toCompare = exp.ReplaceAllString(toCompare, "") srcs := strings.Split(src, "v") srcArr := strings.Split(srcs[1], ".") op := ">" srcs[0] = strings.TrimSpace(srcs[0]) if InArray([]string{">=", "<=", "=", ">", "<"}, srcs[0]) { op = srcs[0] } toCompare = strings.ReplaceAll(toCompare, "v", "") if op == "=" { return srcs[1] == toCompare } if srcs[1] == toCompare && (op == "<=" || op == ">=") { return true } toCompareArr := strings.Split(strings.ReplaceAll(toCompare, "v", ""), ".") for i := 0; i < len(srcArr); i++ { v, err := strconv.Atoi(srcArr[i]) if err != nil { return false } vv, err := strconv.Atoi(toCompareArr[i]) if err != nil { return false } switch op { case ">", ">=": if v < vv { return true } else if v > vv { return false } else { continue } case "<", "<=": if v > vv { return true } else if v < vv { return false } else { continue } } } return false } const ( Byte = 1 KByte = Byte * 1024 MByte = KByte * 1024 GByte = MByte * 1024 TByte = GByte * 1024 PByte = TByte * 1024 EByte = PByte * 1024 ) func logn(n, b float64) float64 { return math.Log(n) / math.Log(b) } func humanateBytes(s uint64, base float64, sizes []string) string { if s < 10 { return fmt.Sprintf("%d B", s) } e := math.Floor(logn(float64(s), base)) suffix := sizes[int(e)] val := float64(s) / math.Pow(base, math.Floor(e)) f := "%.0f" if val < 10 { f = "%.1f" } return fmt.Sprintf(f+" %s", val, suffix) } // FileSize calculates the file size and generate user-friendly string. func FileSize(s uint64) string { sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"} return humanateBytes(s, 1024, sizes) } func FileExist(path string) bool { _, err := os.Stat(path) if err != nil { return os.IsExist(err) } return true } // TimeSincePro calculates the time interval and generate full user-friendly string. func TimeSincePro(then time.Time, m map[string]string) string { now := time.Now() diff := now.Unix() - then.Unix() if then.After(now) { return "future" } var timeStr, diffStr string for { if diff == 0 { break } diff, diffStr = computeTimeDiff(diff, m) timeStr += ", " + diffStr } return strings.TrimPrefix(timeStr, ", ") } // Seconds-based time units const ( Minute = 60 Hour = 60 * Minute Day = 24 * Hour Week = 7 * Day Month = 30 * Day Year = 12 * Month ) func computeTimeDiff(diff int64, m map[string]string) (int64, string) { diffStr := "" switch { case diff <= 0: diff = 0 diffStr = "now" case diff < 2: diff = 0 diffStr = "1 " + m["second"] case diff < 1*Minute: diffStr = fmt.Sprintf("%d "+m["seconds"], diff) diff = 0 case diff < 2*Minute: diff -= 1 * Minute diffStr = "1 " + m["minute"] case diff < 1*Hour: diffStr = fmt.Sprintf("%d "+m["minutes"], diff/Minute) diff -= diff / Minute * Minute case diff < 2*Hour: diff -= 1 * Hour diffStr = "1 " + m["hour"] case diff < 1*Day: diffStr = fmt.Sprintf("%d "+m["hours"], diff/Hour) diff -= diff / Hour * Hour case diff < 2*Day: diff -= 1 * Day diffStr = "1 " + m["day"] case diff < 1*Week: diffStr = fmt.Sprintf("%d "+m["days"], diff/Day) diff -= diff / Day * Day case diff < 2*Week: diff -= 1 * Week diffStr = "1 " + m["week"] case diff < 1*Month: diffStr = fmt.Sprintf("%d "+m["weeks"], diff/Week) diff -= diff / Week * Week case diff < 2*Month: diff -= 1 * Month diffStr = "1 " + m["month"] case diff < 1*Year: diffStr = fmt.Sprintf("%d "+m["months"], diff/Month) diff -= diff / Month * Month case diff < 2*Year: diff -= 1 * Year diffStr = "1 " + m["year"] default: diffStr = fmt.Sprintf("%d "+m["years"], diff/Year) diff = 0 } return diff, diffStr } func DownloadTo(url, output string) error { req, err := http.NewRequest("GET", url, nil) if err != nil { return err } res, err := http.DefaultClient.Do(req) if err != nil { return err } defer func() { _ = res.Body.Close() }() file, err := os.Create(output) if err != nil { return err } _, err = io.Copy(file, res.Body) if err != nil { return err } return nil } func UnzipDir(src, dest string) error { r, err := zip.OpenReader(src) if err != nil { return err } defer func() { if err := r.Close(); err != nil { panic(err) } }() err = os.MkdirAll(dest, 0750) if err != nil { return err } // Closure to address file descriptors issue with all the deferred .Close() methods extractAndWriteFile := func(f *zip.File) error { rc, err := f.Open() if err != nil { return err } defer func() { if err := rc.Close(); err != nil { panic(err) } }() path := filepath.Join(dest, f.Name) if f.FileInfo().IsDir() { err = os.MkdirAll(path, f.Mode()) if err != nil { return err } } else { err = os.MkdirAll(filepath.Dir(path), f.Mode()) if err != nil { return err } f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) if err != nil { return err } defer func() { if err := f.Close(); err != nil { panic(err) } }() _, err = io.Copy(f, rc) if err != nil { return err } } return nil } for _, f := range r.File { err := extractAndWriteFile(f) if err != nil { return err } } return nil } ================================================ FILE: modules/utils/utils_test.go ================================================ package utils import ( "html/template" "testing" "github.com/stretchr/testify/assert" ) func TestCompressedContent(t *testing.T) { htmlContent1 := template.HTML(`

    Test

    CompressedContent

    `) htmlContent2 := htmlContent1 CompressedContent(&htmlContent2) t.Log(len(htmlContent1) > len(htmlContent2)) } func TestCompareVersion(t *testing.T) { assert.Equal(t, true, CompareVersion("v1.2.4", "v1.2.5")) assert.Equal(t, false, CompareVersion("v1.2.4", "v1.2.4")) assert.Equal(t, false, CompareVersion("v1.2.4", "v1.2.3")) assert.Equal(t, false, CompareVersion("v1.2.4", "v1.1.3")) assert.Equal(t, true, CompareVersion("v1.2.4", "v1.3.3")) assert.Equal(t, false, CompareVersion("v1.2.4", "v0.3.3")) assert.Equal(t, true, CompareVersion("v1.2.4", "v1.2.5")) assert.Equal(t, false, CompareVersion(">v1.2.4", "v1.2.4")) assert.Equal(t, true, CompareVersion(">=v1.2.4", "v1.2.4")) assert.Equal(t, true, CompareVersion(">=v1.2.4", "v1.2.5")) assert.Equal(t, false, CompareVersion(">=v1.2.4", "v1.2.3")) assert.Equal(t, false, CompareVersion("=v1.2.4", "v1.2.3")) assert.Equal(t, true, CompareVersion("=v1.2.4", "v1.2.4")) assert.Equal(t, true, CompareVersion("= v1.2.4", "v1.2.4")) } ================================================ FILE: plugins/admin/admin.go ================================================ package admin import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/service" "github.com/GoAdminGroup/go-admin/modules/system" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/controller" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/action" _ "github.com/GoAdminGroup/go-admin/template/types/display" ) // Admin is a GoAdmin plugin. type Admin struct { *plugins.Base config *config.Config tableList table.GeneratorList guardian *guard.Guard handler *controller.Handler } // InitPlugin implements Plugin.InitPlugin. // TODO: find a better way to manage the dependencies func (admin *Admin) InitPlugin(services service.List) { // DO NOT DELETE admin.InitBase(services, "") c := config.GetService(services.Get("config")) st := table.NewSystemTable(admin.Conn, c) genList := table.GeneratorList{ "manager": st.GetManagerTable, "permission": st.GetPermissionTable, "roles": st.GetRolesTable, "op": st.GetOpTable, "menu": st.GetMenuTable, "normal_manager": st.GetNormalManagerTable, } if c.IsAllowConfigModification() { genList.Add("site", st.GetSiteTable) } if c.IsNotProductionEnvironment() { genList.Add("generate", st.GetGenerateForm) } admin.tableList.Combine(genList) admin.guardian = guard.New(admin.Services, admin.Conn, admin.tableList, admin.UI.NavButtons) handlerCfg := controller.Config{ Config: c, Services: services, Generators: admin.tableList, Connection: admin.Conn, } admin.config = c admin.handler.UpdateCfg(handlerCfg) admin.initRouter() admin.handler.SetRoutes(admin.App.Routers) admin.handler.AddNavButton(admin.UI.NavButtons) table.SetServices(services) action.InitOperationHandlerSetter(admin.GetAddOperationFn()) } func (admin *Admin) GetIndexURL() string { return config.GetIndexURL() } func (admin *Admin) GetInfo() plugins.Info { return plugins.Info{ Title: "Basic Admin", Website: "https://www.go-admin.cn", Description: "A built-in plugins of GoAdmin which help you to build a crud manager platform quickly.", Author: "official", Version: system.Version(), CreateDate: utils.ParseTime("2018-07-08 00:00:00"), UpdateDate: utils.ParseTime("2020-06-28 00:00:00"), } } func (admin *Admin) IsInstalled() bool { return true } // NewAdmin return the global Admin plugin. func NewAdmin(tableCfg ...table.GeneratorList) *Admin { return &Admin{ tableList: make(table.GeneratorList).CombineAll(tableCfg), Base: &plugins.Base{PlugName: "admin"}, handler: controller.New(), } } func (admin *Admin) GetAddOperationFn() context.NodeProcessor { return admin.handler.AddOperation } // SetCaptcha set captcha driver. func (admin *Admin) SetCaptcha(captcha map[string]string) *Admin { admin.handler.SetCaptcha(captcha) return admin } // AddGenerator add table model generator. func (admin *Admin) AddGenerator(key string, g table.Generator) *Admin { admin.tableList.Add(key, g) return admin } // AddGenerators add table model generators. func (admin *Admin) AddGenerators(gen ...table.GeneratorList) *Admin { admin.tableList.CombineAll(gen) return admin } // AddGlobalDisplayProcessFn call types.AddGlobalDisplayProcessFn func (admin *Admin) AddGlobalDisplayProcessFn(f types.FieldFilterFn) *Admin { types.AddGlobalDisplayProcessFn(f) return admin } // AddDisplayFilterLimit call types.AddDisplayFilterLimit func (admin *Admin) AddDisplayFilterLimit(limit int) *Admin { types.AddLimit(limit) return admin } // AddDisplayFilterTrimSpace call types.AddDisplayFilterTrimSpace func (admin *Admin) AddDisplayFilterTrimSpace() *Admin { types.AddTrimSpace() return admin } // AddDisplayFilterSubstr call types.AddDisplayFilterSubstr func (admin *Admin) AddDisplayFilterSubstr(start int, end int) *Admin { types.AddSubstr(start, end) return admin } // AddDisplayFilterToTitle call types.AddDisplayFilterToTitle func (admin *Admin) AddDisplayFilterToTitle() *Admin { types.AddToTitle() return admin } // AddDisplayFilterToUpper call types.AddDisplayFilterToUpper func (admin *Admin) AddDisplayFilterToUpper() *Admin { types.AddToUpper() return admin } // AddDisplayFilterToLower call types.AddDisplayFilterToLower func (admin *Admin) AddDisplayFilterToLower() *Admin { types.AddToUpper() return admin } // AddDisplayFilterXssFilter call types.AddDisplayFilterXssFilter func (admin *Admin) AddDisplayFilterXssFilter() *Admin { types.AddXssFilter() return admin } // AddDisplayFilterXssJsFilter call types.AddDisplayFilterXssJsFilter func (admin *Admin) AddDisplayFilterXssJsFilter() *Admin { types.AddXssJsFilter() return admin } ================================================ FILE: plugins/admin/controller/Update.go ================================================ package controller import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" ) // Update update the table row of given id. func (h *Handler) Update(ctx *context.Context) { param := guard.GetUpdateParam(ctx) err := param.Panel.UpdateData(ctx, param.Value) if err != nil { response.Error(ctx, err.Error()) return } response.Ok(ctx) } ================================================ FILE: plugins/admin/controller/api_create.go ================================================ package controller import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/file" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" ) func (h *Handler) ApiCreate(ctx *context.Context) { param := guard.GetNewFormParam(ctx) if len(param.MultiForm.File) > 0 { err := file.GetFileEngine(h.config.FileUploadEngine.Name).Upload(param.MultiForm) if err != nil { response.Error(ctx, err.Error()) return } } err := param.Panel.InsertData(ctx, param.Value()) if err != nil { response.Error(ctx, err.Error()) return } response.Ok(ctx) } func (h *Handler) ApiCreateForm(ctx *context.Context) { var ( params = guard.GetShowNewFormParam(ctx) prefix, paramStr = params.Prefix, params.Param.GetRouteParamStr() panel = h.table(prefix, ctx) formInfo = panel.GetNewFormInfo() infoUrl = h.routePathWithPrefix("api_info", prefix) + paramStr newUrl = h.routePathWithPrefix("api_new", prefix) referer = ctx.Referer() f = panel.GetActualNewForm() ) if referer != "" && !isInfoUrl(referer) && !isNewUrl(referer, ctx.Query(constant.PrefixKey)) { infoUrl = referer } response.OkWithData(ctx, map[string]interface{}{ "panel": formInfo, "urls": map[string]string{ "info": infoUrl, "new": newUrl, }, "pk": panel.GetPrimaryKey().Name, "header": f.HeaderHtml, "footer": f.FooterHtml, "prefix": h.config.PrefixFixSlash(), "token": h.authSrv().AddToken(), "operation_footer": formFooter(ctx, "new", f.IsHideContinueEditCheckBox, f.IsHideContinueNewCheckBox, f.IsHideResetButton, f.FormNewBtnWord), }) } ================================================ FILE: plugins/admin/controller/api_detail.go ================================================ package controller import ( "fmt" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/form" ) func (h *Handler) ApiDetail(ctx *context.Context) { prefix := ctx.Query(constant.PrefixKey) id := ctx.Query(constant.DetailPKKey) panel := h.table(prefix, ctx) user := auth.Auth(ctx) newPanel := panel.Copy() formModel := newPanel.GetForm() var fieldList types.FieldList if len(panel.GetDetail().FieldList) == 0 { fieldList = panel.GetInfo().FieldList } else { fieldList = panel.GetDetail().FieldList } formModel.FieldList = make([]types.FormField, len(fieldList)) for i, field := range fieldList { formModel.FieldList[i] = types.FormField{ Field: field.Field, FieldClass: field.Field, TypeName: field.TypeName, Head: field.Head, Hide: field.Hide, Joins: field.Joins, FormType: form.Default, FieldDisplay: field.FieldDisplay, } } param := parameter.GetParam(ctx.Request.URL, panel.GetInfo().DefaultPageSize, panel.GetInfo().SortField, panel.GetInfo().GetSort()) paramStr := param.DeleteDetailPk().GetRouteParamStr() editUrl := modules.AorEmpty(!panel.GetInfo().IsHideEditButton, h.routePathWithPrefix("show_edit", prefix)+paramStr+ "&"+constant.EditPKKey+"="+ctx.Query(constant.DetailPKKey)) deleteUrl := modules.AorEmpty(!panel.GetInfo().IsHideDeleteButton, h.routePathWithPrefix("delete", prefix)+paramStr) infoUrl := h.routePathWithPrefix("info", prefix) + paramStr editUrl = user.GetCheckPermissionByUrlMethod(editUrl, h.route("show_edit").Method()) deleteUrl = user.GetCheckPermissionByUrlMethod(deleteUrl, h.route("delete").Method()) deleteJs := "" if deleteUrl != "" { deleteJs = fmt.Sprintf(``, language.Get("are you sure to delete"), language.Get("yes"), language.Get("cancel"), deleteUrl, infoUrl, id) } desc := panel.GetDetail().Description if desc == "" { desc = panel.GetInfo().Description + language.Get("Detail") } formInfo, err := newPanel.GetDataWithId(param.WithPKs(id)) if err != nil { response.Error(ctx, err.Error()) return } response.OkWithData(ctx, map[string]interface{}{ "panel": formInfo, "previous": infoUrl, "footer": deleteJs, "prefix": h.config.PrefixFixSlash(), }) } ================================================ FILE: plugins/admin/controller/api_list.go ================================================ package controller import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" ) func (h *Handler) ApiList(ctx *context.Context) { prefix := ctx.Query(constant.PrefixKey) panel := h.table(prefix, ctx) params := parameter.GetParam(ctx.Request.URL, panel.GetInfo().DefaultPageSize, panel.GetInfo().SortField, panel.GetInfo().GetSort()) panel, panelInfo, urls, err := h.showTableData(ctx, prefix, params, panel, "api_") if err != nil { response.Error(ctx, err.Error()) return } response.OkWithData(ctx, map[string]interface{}{ "panel": panelInfo, "footer": panelInfo.Paginator.GetContent() + panel.GetInfo().FooterHtml, "header": aDataTable(ctx).GetDataTableHeader() + panel.GetInfo().HeaderHtml, "prefix": h.config.PrefixFixSlash(), "urls": map[string]string{ "edit": urls[0], "new": urls[1], "delete": urls[2], "export": urls[3], "detail": urls[4], "info": urls[5], "update": urls[6], }, }) } ================================================ FILE: plugins/admin/controller/api_update.go ================================================ package controller import ( "net/url" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/file" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/template/types/form" ) func (h *Handler) ApiUpdate(ctx *context.Context) { param := guard.GetEditFormParam(ctx) if len(param.MultiForm.File) > 0 { err := file.GetFileEngine(h.config.FileUploadEngine.Name).Upload(param.MultiForm) if err != nil { response.Error(ctx, err.Error()) return } } for i := 0; i < len(param.Panel.GetForm().FieldList); i++ { if param.Panel.GetForm().FieldList[i].FormType == form.File && len(param.MultiForm.File[param.Panel.GetForm().FieldList[i].Field]) == 0 && param.MultiForm.Value[param.Panel.GetForm().FieldList[i].Field+"__delete_flag"][0] != "1" { delete(param.MultiForm.Value, param.Panel.GetForm().FieldList[i].Field) } } err := param.Panel.UpdateData(ctx, param.Value()) if err != nil { response.Error(ctx, err.Error()) return } response.Ok(ctx) } func (h *Handler) ApiUpdateForm(ctx *context.Context) { params := guard.GetShowFormParam(ctx) prefix, param := params.Prefix, params.Param panel := h.table(prefix, ctx) user := auth.Auth(ctx) paramStr := param.GetRouteParamStr() newUrl := modules.AorEmpty(panel.GetCanAdd(), h.routePathWithPrefix("api_show_new", prefix)+paramStr) footerKind := "edit" if newUrl == "" || !user.CheckPermissionByUrlMethod(newUrl, h.route("api_show_new").Method(), url.Values{}) { footerKind = "edit_only" } formInfo, err := panel.GetDataWithId(param) if err != nil { response.Error(ctx, err.Error()) return } infoUrl := h.routePathWithPrefix("api_info", prefix) + param.DeleteField(constant.EditPKKey).GetRouteParamStr() editUrl := h.routePathWithPrefix("api_edit", prefix) f := panel.GetForm() response.OkWithData(ctx, map[string]interface{}{ "panel": formInfo, "urls": map[string]string{ "info": infoUrl, "edit": editUrl, }, "pk": panel.GetPrimaryKey().Name, "header": f.HeaderHtml, "footer": f.FooterHtml, "prefix": h.config.PrefixFixSlash(), "token": h.authSrv().AddToken(), "operation_footer": formFooter(ctx, footerKind, f.IsHideContinueEditCheckBox, f.IsHideContinueNewCheckBox, f.IsHideResetButton, f.FormEditBtnWord), }) } ================================================ FILE: plugins/admin/controller/auth.go ================================================ package controller import ( "bytes" template2 "html/template" "net/http" "net/url" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/system" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/captcha" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" ) // Auth check the input password and username for authentication. func (h *Handler) Auth(ctx *context.Context) { var ( user models.UserModel ok bool errMsg = "fail" s, exist = h.services.GetOrNot(auth.ServiceKey) ) if capDriver, ok := h.captchaConfig["driver"]; ok { capt, ok := captcha.Get(capDriver) if ok { if !capt.Validate(ctx.FormValue("token")) { response.BadRequest(ctx, "wrong captcha") return } } } if !exist { password := ctx.FormValue("password") username := ctx.FormValue("username") if password == "" || username == "" { response.BadRequest(ctx, "wrong password or username") return } user, ok = auth.Check(password, username, h.conn) } else { user, ok, errMsg = auth.GetService(s).P(ctx) } if !ok { response.BadRequest(ctx, errMsg) return } err := auth.SetCookie(ctx, user, h.conn) if err != nil { response.Error(ctx, err.Error()) return } if ref := ctx.Referer(); ref != "" { if u, err := url.Parse(ref); err == nil { v := u.Query() if r := v.Get("ref"); r != "" { rr, _ := url.QueryUnescape(r) response.OkWithData(ctx, map[string]interface{}{ "url": rr, }) return } } } response.OkWithData(ctx, map[string]interface{}{ "url": h.config.GetIndexURL(), }) } // Logout delete the cookie. func (h *Handler) Logout(ctx *context.Context) { err := auth.DelCookie(ctx, db.GetConnection(h.services)) if err != nil { logger.ErrorCtx(ctx, "logout error %+v", err) } ctx.AddHeader("Location", h.config.Url(config.GetLoginUrl())) ctx.SetStatusCode(302) } // ShowLogin show the login page. func (h *Handler) ShowLogin(ctx *context.Context) { tmpl, name := template.GetComp("login").GetTemplate() buf := new(bytes.Buffer) if err := tmpl.ExecuteTemplate(buf, name, struct { UrlPrefix string Title string Logo template2.HTML CdnUrl string System types.SystemInfo }{ UrlPrefix: h.config.AssertPrefix(), Title: h.config.LoginTitle, Logo: h.config.LoginLogo, System: types.SystemInfo{ Version: system.Version(), }, CdnUrl: h.config.AssetUrl, }); err == nil { ctx.HTML(http.StatusOK, buf.String()) } else { logger.ErrorCtx(ctx, "ShowLogin error %+v", err) ctx.HTML(http.StatusOK, "parse template error (;′⌒`)") } } ================================================ FILE: plugins/admin/controller/common.go ================================================ package controller import ( "bytes" template2 "html/template" "net/http" "regexp" "strings" "sync" "github.com/GoAdminGroup/go-admin/template/types/action" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" c "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/menu" "github.com/GoAdminGroup/go-admin/modules/service" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/icon" "github.com/GoAdminGroup/go-admin/template/types" ) type Handler struct { config *c.Config captchaConfig map[string]string services service.List conn db.Connection routes context.RouterMap generators table.GeneratorList operations []context.Node navButtons *types.Buttons operationLock sync.Mutex assetsTheme map[string]string } func New(cfg ...Config) *Handler { if len(cfg) == 0 { return &Handler{ operations: make([]context.Node, 0), navButtons: new(types.Buttons), } } return &Handler{ config: cfg[0].Config, services: cfg[0].Services, conn: cfg[0].Connection, generators: cfg[0].Generators, operations: make([]context.Node, 0), navButtons: new(types.Buttons), assetsTheme: make(map[string]string), } } type Config struct { Config *c.Config Services service.List Connection db.Connection Generators table.GeneratorList } func (h *Handler) UpdateCfg(cfg Config) { h.config = cfg.Config h.services = cfg.Services h.conn = cfg.Connection h.generators = cfg.Generators h.assetsTheme = make(map[string]string) } func (h *Handler) SetCaptcha(captcha map[string]string) { h.captchaConfig = captcha } func (h *Handler) AssetsTheme(asset, theme string) { h.assetsTheme[asset] = theme } func (h *Handler) SetRoutes(r context.RouterMap) { h.routes = r } func (h *Handler) table(prefix string, ctx *context.Context) table.Table { t := h.generators[prefix](ctx) authHandler := auth.Middleware(db.GetConnection(h.services)) for _, cb := range t.GetInfo().Callbacks { if cb.Value[constant.ContextNodeNeedAuth] == 1 { h.AddOperation(context.Node{ Path: cb.Path, Method: cb.Method, Handlers: append([]context.Handler{authHandler}, cb.Handlers...), }) } else { h.AddOperation(context.Node{Path: cb.Path, Method: cb.Method, Handlers: cb.Handlers}) } } for _, cb := range t.GetForm().Callbacks { if cb.Value[constant.ContextNodeNeedAuth] == 1 { h.AddOperation(context.Node{ Path: cb.Path, Method: cb.Method, Handlers: append([]context.Handler{authHandler}, cb.Handlers...), }) } else { h.AddOperation(context.Node{Path: cb.Path, Method: cb.Method, Handlers: cb.Handlers}) } } return t } func (h *Handler) route(name string) context.Router { return h.routes.Get(name) } func (h *Handler) routePath(name string, value ...string) string { return h.routes.Get(name).GetURL(value...) } func (h *Handler) routePathWithPrefix(name string, prefix string) string { return h.routePath(name, "prefix", prefix) } func (h *Handler) AddOperation(nodes ...context.Node) { h.operationLock.Lock() defer h.operationLock.Unlock() // TODO: 避免重复增加,第一次加入后,后面大部分会存在重复情况,以下循环可以优化 addNodes := make([]context.Node, 0) for _, node := range nodes { if h.searchOperation(node.Path, node.Method) { continue } addNodes = append(addNodes, node) } h.operations = append(h.operations, addNodes...) } func (h *Handler) AddNavButton(btns *types.Buttons) { h.navButtons = btns for _, btn := range *btns { h.AddOperation(btn.GetAction().GetCallbacks()) } } func (h *Handler) searchOperation(path, method string) bool { for _, node := range h.operations { if node.Path == path && node.Method == method { return true } } return false } func (h *Handler) OperationHandler(path string, ctx *context.Context) bool { for _, node := range h.operations { if node.Path == path { for _, handler := range node.Handlers { handler(ctx) } return true } } return false } func (h *Handler) HTML(ctx *context.Context, user models.UserModel, panel types.Panel, options ...template.ExecuteOptions) { buf := h.Execute(ctx, user, panel, "", options...) ctx.HTML(http.StatusOK, buf.String()) } func (h *Handler) HTMLPlug(ctx *context.Context, user models.UserModel, panel types.Panel, plugName string, options ...template.ExecuteOptions) { var btns types.Buttons if plugName == "" { btns = (*h.navButtons).CheckPermission(user) } else { btns = (*h.navButtons).Copy(). RemoveToolNavButton(). RemoveSiteNavButton(). RemoveInfoNavButton(). Add(types.GetDropDownButton("", icon.Gear, []*types.NavDropDownItemButton{ types.GetDropDownItemButton(language.GetFromHtml("plugin setting"), action.Jump(h.config.Url("/info/plugin_"+plugName+"/edit"))), types.GetDropDownItemButton(language.GetFromHtml("menus manage"), action.Jump(h.config.Url("/menu?__plugin_name="+plugName))), })). CheckPermission(user) } buf := h.ExecuteWithBtns(ctx, user, panel, plugName, btns, options...) ctx.HTML(http.StatusOK, buf.String()) } func (h *Handler) ExecuteWithBtns(ctx *context.Context, user models.UserModel, panel types.Panel, plugName string, btns types.Buttons, options ...template.ExecuteOptions) *bytes.Buffer { tmpl, tmplName := aTemplate(ctx).GetTemplate(isPjax(ctx)) option := template.GetExecuteOptions(options) return template.Execute(ctx, &template.ExecuteParam{ User: user, TmplName: tmplName, Tmpl: tmpl, Panel: panel, Config: h.config, Menu: menu.GetGlobalMenu(user, h.conn, ctx.Lang(), plugName).SetActiveClass(h.config.URLRemovePrefix(ctx.Path())), Animation: option.Animation, Buttons: btns, Iframe: ctx.IsIframe(), IsPjax: isPjax(ctx), NoCompress: option.NoCompress, }) } func (h *Handler) Execute(ctx *context.Context, user models.UserModel, panel types.Panel, plugName string, options ...template.ExecuteOptions) *bytes.Buffer { tmpl, tmplName := aTemplate(ctx).GetTemplate(isPjax(ctx)) option := template.GetExecuteOptions(options) return template.Execute(ctx, &template.ExecuteParam{ User: user, TmplName: tmplName, Tmpl: tmpl, Panel: panel, Config: h.config, Menu: menu.GetGlobalMenu(user, h.conn, ctx.Lang(), plugName).SetActiveClass(h.config.URLRemovePrefix(ctx.Path())), Animation: option.Animation, Buttons: (*h.navButtons).CheckPermission(user), Iframe: ctx.IsIframe(), IsPjax: isPjax(ctx), NoCompress: option.NoCompress, }) } func isInfoUrl(s string) bool { reg, _ := regexp.Compile("(.*?)info/(.*?)$") sub := reg.FindStringSubmatch(s) return len(sub) > 2 && !strings.Contains(sub[2], "/") } func isNewUrl(s string, p string) bool { reg, _ := regexp.Compile("(.*?)info/" + p + "/new") return reg.MatchString(s) } func isEditUrl(s string, p string) bool { reg, _ := regexp.Compile("(.*?)info/" + p + "/edit") return reg.MatchString(s) } func (h *Handler) authSrv() *auth.TokenService { return auth.GetTokenService(h.services.Get(auth.TokenServiceKey)) } func aAlert(ctx *context.Context) types.AlertAttribute { return aTemplate(ctx).Alert() } func aForm(ctx *context.Context) types.FormAttribute { return aTemplate(ctx).Form() } func aRow(ctx *context.Context) types.RowAttribute { return aTemplate(ctx).Row() } func aCol(ctx *context.Context) types.ColAttribute { return aTemplate(ctx).Col() } func aImage(ctx *context.Context) types.ImgAttribute { return aTemplate(ctx).Image() } func aButton(ctx *context.Context) types.ButtonAttribute { return aTemplate(ctx).Button() } func aTree(ctx *context.Context) types.TreeAttribute { return aTemplate(ctx).Tree() } func aTable(ctx *context.Context) types.TableAttribute { return aTemplate(ctx).Table() } func aDataTable(ctx *context.Context) types.DataTableAttribute { return aTemplate(ctx).DataTable() } func aBox(ctx *context.Context) types.BoxAttribute { return aTemplate(ctx).Box() } func aTab(ctx *context.Context) types.TabsAttribute { return aTemplate(ctx).Tabs() } func aTemplate(ctx *context.Context) template.Template { return template.Get(ctx, c.GetTheme()) } func aTemplateByTheme(ctx *context.Context, theme string) template.Template { return template.Get(ctx, theme) } func isPjax(ctx *context.Context) bool { return ctx.IsPjax() } func formFooter(ctx *context.Context, page string, isHideEdit, isHideNew, isHideReset bool, btnWord template2.HTML) template2.HTML { col1 := aCol(ctx).SetSize(types.SizeMD(2)).GetContent() var ( checkBoxs template2.HTML checkBoxJS template2.HTML editCheckBox = template.HTML(` `) newCheckBox = template.HTML(` `) editWithNewCheckBoxJs = template.HTML(`$('.continue_edit').iCheck({checkboxClass: 'icheckbox_minimal-blue'}).on('ifChanged', function (event) { if (this.checked) { $('.continue_new').iCheck('uncheck'); $('input[name="` + form.PreviousKey + `"]').val(location.href) } else { $('input[name="` + form.PreviousKey + `"]').val(previous_url_goadmin) } }); `) newWithEditCheckBoxJs = template.HTML(`$('.continue_new').iCheck({checkboxClass: 'icheckbox_minimal-blue'}).on('ifChanged', function (event) { if (this.checked) { $('.continue_edit').iCheck('uncheck'); $('input[name="` + form.PreviousKey + `"]').val(location.href.replace('/edit', '/new')) } else { $('input[name="` + form.PreviousKey + `"]').val(previous_url_goadmin) } });`) ) if page == "edit" { if isHideNew { newCheckBox = "" newWithEditCheckBoxJs = "" } if isHideEdit { editCheckBox = "" editWithNewCheckBoxJs = "" } checkBoxs = editCheckBox + newCheckBox checkBoxJS = ` ` } else if page == "edit_only" && !isHideEdit { checkBoxs = editCheckBox checkBoxJS = template.HTML(` `) } else if page == "new" && !isHideNew { checkBoxs = newCheckBox checkBoxJS = template.HTML(` `) } btn1 := aButton(ctx). SetType("submit"). AddClass("submit"). SetContent(btnWord). SetThemePrimary(). SetOrientationRight(). GetContent() btn2 := template.HTML("") if !isHideReset { btn2 = aButton(ctx). SetType("reset"). AddClass("reset"). SetContent(language.GetFromHtml("Reset")). SetThemeWarning(). SetOrientationLeft(). GetContent() } col2 := aCol(ctx).SetSize(types.SizeMD(8)). SetContent(btn1 + checkBoxs + btn2 + checkBoxJS).GetContent() return col1 + col2 } func filterFormFooter(ctx *context.Context, infoUrl string) template2.HTML { col1 := aCol(ctx).SetSize(types.SizeMD(2)).GetContent() btn1 := aButton(ctx).SetType("submit"). AddClass("submit"). SetContent(icon.Icon(icon.Search, 2) + language.GetFromHtml("search")). SetThemePrimary(). SetSmallSize(). SetOrientationLeft(). SetLoadingText(icon.Icon(icon.Spinner, 1) + language.GetFromHtml("search")). GetContent() btn2 := aButton(ctx).SetType("reset"). AddClass("reset"). SetContent(icon.Icon(icon.Undo, 2) + language.GetFromHtml("reset")). SetThemeDefault(). SetOrientationLeft(). SetSmallSize(). SetHref(infoUrl). SetMarginLeft(12). GetContent() col2 := aCol(ctx).SetSize(types.SizeMD(8)). SetContent(btn1 + btn2).GetContent() return col1 + col2 } func formContent(ctx *context.Context, form types.FormAttribute, isTab, iframe, isHideBack bool, header template2.HTML) template2.HTML { if isTab { return form.GetContent() } if iframe { header = "" } else if header == template2.HTML("") { header = form.GetDefaultBoxHeader(isHideBack) } return aBox(ctx). SetHeader(header). WithHeadBorder(). SetStyle(" "). SetIframeStyle(iframe). SetBody(form.GetContent()). GetContent() } func detailContent(ctx *context.Context, form types.FormAttribute, editUrl, deleteUrl string, iframe bool) template2.HTML { return aBox(ctx). SetHeader(form.GetDetailBoxHeader(editUrl, deleteUrl)). WithHeadBorder(). SetBody(form.GetContent()). SetIframeStyle(iframe). GetContent() } func menuFormContent(ctx *context.Context, form types.FormAttribute) template2.HTML { return aBox(ctx). SetHeader(form.GetBoxHeaderNoButton()). SetStyle(" "). WithHeadBorder(). SetBody(form.GetContent()). GetContent() } ================================================ FILE: plugins/admin/controller/common_test.go ================================================ package controller import ( "testing" "github.com/magiconair/properties/assert" ) func TestIsInfoUrl(t *testing.T) { u := "https://localhost:8098/admin/info/user?id=sdfs" assert.Equal(t, true, isInfoUrl(u)) } func TestIsNewUrl(t *testing.T) { u := "https://localhost:8098/admin/info/user/new?id=sdfs" assert.Equal(t, true, isNewUrl(u, "user")) } ================================================ FILE: plugins/admin/controller/delete.go ================================================ package controller import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" ) // Delete delete the row from database. func (h *Handler) Delete(ctx *context.Context) { param := guard.GetDeleteParam(ctx) //token := ctx.FormValue("_t") // //if !auth.TokenHelper.CheckToken(token) { // ctx.SetStatusCode(http.StatusBadRequest) // ctx.WriteString(`{"code":400, "msg":"delete fail"}`) // return //} if err := h.table(param.Prefix, ctx).DeleteData(param.Id); err != nil { logger.ErrorCtx(ctx, "Delete error %+v", err) response.Error(ctx, "delete fail") return } response.OkWithData(ctx, map[string]interface{}{ "token": h.authSrv().AddToken(), }) } ================================================ FILE: plugins/admin/controller/detail.go ================================================ package controller import ( "fmt" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" form2 "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/form" ) func (h *Handler) ShowDetail(ctx *context.Context) { var ( prefix = ctx.Query(constant.PrefixKey) id = ctx.Query(constant.DetailPKKey) panel = h.table(prefix, ctx) user = auth.Auth(ctx) newPanel = panel.Copy() detail = panel.GetDetail() info = panel.GetInfo() formModel = newPanel.GetForm() fieldList = make(types.FieldList, 0) ) if len(detail.FieldList) == 0 { fieldList = info.FieldList } else { fieldList = detail.FieldList } formModel.FieldList = make([]types.FormField, len(fieldList)) for i, field := range fieldList { formModel.FieldList[i] = types.FormField{ Field: field.Field, FieldClass: field.Field, TypeName: field.TypeName, Head: field.Head, Hide: field.Hide, Joins: field.Joins, FormType: form.Default, FieldDisplay: field.FieldDisplay, } } if detail.Table != "" { formModel.Table = detail.Table } else { formModel.Table = info.Table } param := parameter.GetParam(ctx.Request.URL, info.DefaultPageSize, info.SortField, info.GetSort()) paramStr := param.DeleteDetailPk().GetRouteParamStr() editUrl := modules.AorEmpty(!info.IsHideEditButton, h.routePathWithPrefix("show_edit", prefix)+paramStr+ "&"+constant.EditPKKey+"="+ctx.Query(constant.DetailPKKey)) deleteUrl := modules.AorEmpty(!info.IsHideDeleteButton, h.routePathWithPrefix("delete", prefix)+paramStr) infoUrl := h.routePathWithPrefix("info", prefix) + paramStr editUrl = user.GetCheckPermissionByUrlMethod(editUrl, h.route("show_edit").Method()) deleteUrl = user.GetCheckPermissionByUrlMethod(deleteUrl, h.route("delete").Method()) deleteJs := "" if deleteUrl != "" { deleteJs = fmt.Sprintf(``, language.Get("are you sure to delete"), language.Get("yes"), language.Get("cancel"), deleteUrl, infoUrl, id) } title := "" desc := "" isNotIframe := ctx.Query(constant.IframeKey) != "true" if isNotIframe { title = detail.Title if title == "" { title = info.Title + language.Get("Detail") } desc = detail.Description if desc == "" { desc = info.Description + language.Get("Detail") } } formInfo, err := newPanel.GetDataWithId(param.WithPKs(id)) if err != nil { h.HTML(ctx, user, template.WarningPanelWithDescAndTitle(ctx, err.Error(), desc, title), template.ExecuteOptions{Animation: param.Animation}) return } h.HTML(ctx, user, types.Panel{ Content: detailContent(ctx, aForm(ctx). SetTitle(template.HTML(title)). SetContent(formInfo.FieldList). SetHeader(detail.HeaderHtml). SetFooter(template.HTML(deleteJs)+detail.FooterHtml). SetHiddenFields(map[string]string{ form2.PreviousKey: infoUrl, }). SetPrefix(h.config.PrefixFixSlash()), editUrl, deleteUrl, !isNotIframe), Description: template.HTML(desc), Title: template.HTML(title), }, template.ExecuteOptions{Animation: param.Animation}) } ================================================ FILE: plugins/admin/controller/edit.go ================================================ package controller import ( "fmt" template2 "html/template" "net/http" "net/url" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/file" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" form2 "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/form" ) // ShowForm show form page. func (h *Handler) ShowForm(ctx *context.Context) { param := guard.GetShowFormParam(ctx) h.showForm(ctx, "", param.Prefix, param.Param, false) } func (h *Handler) showForm(ctx *context.Context, alert template2.HTML, prefix string, param parameter.Parameters, isEdit bool, animation ...bool) { panel := h.table(prefix, ctx) if panel.GetForm().HasError() { if panel.GetForm().PageErrorHTML != template2.HTML("") { h.HTML(ctx, auth.Auth(ctx), types.Panel{Content: panel.GetForm().PageErrorHTML}, template.ExecuteOptions{Animation: param.Animation}) return } h.HTML(ctx, auth.Auth(ctx), template.WarningPanel(ctx, panel.GetForm().PageError.Error(), template.GetPageTypeFromPageError(panel.GetForm().PageError)), template.ExecuteOptions{Animation: param.Animation}) return } var ( user = auth.Auth(ctx) paramStr = param.GetRouteParamStr() newUrl = modules.AorEmpty(panel.GetCanAdd(), h.routePathWithPrefix("show_new", prefix)+paramStr) footerKind = "edit" ) if newUrl == "" || !user.CheckPermissionByUrlMethod(newUrl, h.route("show_new").Method(), url.Values{}) { footerKind = "edit_only" } formInfo, err := panel.GetDataWithId(param) if err != nil { logger.ErrorCtx(ctx, "receive data error: %+v", err) h.HTML(ctx, user, template. WarningPanelWithDescAndTitle(ctx, err.Error(), panel.GetForm().Description, panel.GetForm().Title), template.ExecuteOptions{Animation: alert == "" || ((len(animation) > 0) && animation[0])}) if isEdit { ctx.AddHeader(constant.PjaxUrlHeader, h.routePathWithPrefix("show_edit", prefix)+ param.DeletePK().GetRouteParamStr()) } return } showEditUrl := h.routePathWithPrefix("show_edit", prefix) + param.DeletePK().GetRouteParamStr() infoUrl := h.routePathWithPrefix("info", prefix) + param.DeleteField(constant.EditPKKey).GetRouteParamStr() editUrl := h.routePathWithPrefix("edit", prefix) referer := ctx.Referer() if referer != "" && !isInfoUrl(referer) && !isEditUrl(referer, ctx.Query(constant.PrefixKey)) { infoUrl = referer } f := panel.GetForm() isNotIframe := ctx.Query(constant.IframeKey) != "true" hiddenFields := map[string]string{ form2.TokenKey: h.authSrv().AddToken(), form2.PreviousKey: infoUrl, } if ctx.Query(constant.IframeKey) != "" { hiddenFields[constant.IframeKey] = ctx.Query(constant.IframeKey) } if ctx.Query(constant.IframeIDKey) != "" { hiddenFields[constant.IframeIDKey] = ctx.Query(constant.IframeIDKey) } content := formContent(ctx, aForm(ctx). SetContent(formInfo.FieldList). SetFieldsHTML(f.HTMLContent). SetTabContents(formInfo.GroupFieldList). SetTabHeaders(formInfo.GroupFieldHeaders). SetPrefix(h.config.PrefixFixSlash()). SetInputWidth(f.InputWidth). SetHeadWidth(f.HeadWidth). SetPrimaryKey(panel.GetPrimaryKey().Name). SetUrl(editUrl). SetTitle(f.FormEditTitle). SetAjax(f.AjaxSuccessJS, f.AjaxErrorJS). SetLayout(f.Layout). SetHiddenFields(hiddenFields). SetOperationFooter(formFooter(ctx, footerKind, f.IsHideContinueEditCheckBox, f.IsHideContinueNewCheckBox, f.IsHideResetButton, f.FormEditBtnWord)). SetHeader(f.HeaderHtml). SetFooter(f.FooterHtml), len(formInfo.GroupFieldHeaders) > 0, !isNotIframe, f.IsHideBackButton, f.Header) if f.Wrapper != nil { content = f.Wrapper(content) } h.HTML(ctx, user, types.Panel{ Content: alert + content, Description: template2.HTML(formInfo.Description), Title: modules.AorBHTML(isNotIframe, template2.HTML(formInfo.Title), ""), MiniSidebar: f.HideSideBar, }, template.ExecuteOptions{Animation: alert == "" || ((len(animation) > 0) && animation[0]), NoCompress: f.NoCompress}) if isEdit { ctx.AddHeader(constant.PjaxUrlHeader, showEditUrl) } } func (h *Handler) EditForm(ctx *context.Context) { param := guard.GetEditFormParam(ctx) if len(param.MultiForm.File) > 0 { err := file.GetFileEngine(h.config.FileUploadEngine.Name).Upload(param.MultiForm) if err != nil { logger.ErrorCtx(ctx, "get file engine error: %+v", err) if ctx.WantJSON() { response.Error(ctx, err.Error()) } else { h.showForm(ctx, aAlert(ctx).Warning(err.Error()), param.Prefix, param.Param, true) } return } } formPanel := param.Panel.GetForm() for i := 0; i < len(formPanel.FieldList); i++ { if formPanel.FieldList[i].FormType == form.File && len(param.MultiForm.File[formPanel.FieldList[i].Field]) == 0 && len(param.MultiForm.Value[formPanel.FieldList[i].Field+"__delete_flag"]) > 0 && param.MultiForm.Value[formPanel.FieldList[i].Field+"__delete_flag"][0] != "1" { param.MultiForm.Value[formPanel.FieldList[i].Field] = []string{""} } if formPanel.FieldList[i].FormType == form.File && len(param.MultiForm.Value[formPanel.FieldList[i].Field+"__change_flag"]) > 0 && param.MultiForm.Value[formPanel.FieldList[i].Field+"__change_flag"][0] != "1" { delete(param.MultiForm.Value, formPanel.FieldList[i].Field) } } err := param.Panel.UpdateData(ctx, param.Value()) if err != nil { logger.ErrorCtx(ctx, "update data error: %+v", err) if ctx.WantJSON() { response.Error(ctx, err.Error(), map[string]interface{}{ "token": h.authSrv().AddToken(), }) } else { h.showForm(ctx, aAlert(ctx).Warning(err.Error()), param.Prefix, param.Param, true) } return } if formPanel.Responder != nil { formPanel.Responder(ctx) return } if ctx.WantJSON() && !param.IsIframe { response.OkWithData(ctx, map[string]interface{}{ "url": param.PreviousPath, "token": h.authSrv().AddToken(), }) return } if !param.FromList { if isNewUrl(param.PreviousPath, param.Prefix) { h.showNewForm(ctx, param.Alert, param.Prefix, param.Param.DeleteEditPk().GetRouteParamStr(), true) return } if isEditUrl(param.PreviousPath, param.Prefix) { h.showForm(ctx, param.Alert, param.Prefix, param.Param, true, false) return } ctx.HTML(http.StatusOK, fmt.Sprintf(``, param.PreviousPath)) ctx.AddHeader(constant.PjaxUrlHeader, param.PreviousPath) return } if param.IsIframe { ctx.HTML(http.StatusOK, fmt.Sprintf(``, language.Get("success"), param.IframeID)) return } buf := h.showTable(ctx, param.Prefix, param.Param.DeletePK().DeleteEditPk(), nil) ctx.HTML(http.StatusOK, buf.String()) ctx.AddHeader(constant.PjaxUrlHeader, param.PreviousPath) } ================================================ FILE: plugins/admin/controller/handler.go ================================================ package controller import ( template2 "html/template" "regexp" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" "golang.org/x/text/cases" "golang.org/x/text/language" ) // GlobalDeferHandler is a global error handler of admin plugin. func (h *Handler) GlobalDeferHandler(ctx *context.Context) { logger.Access(ctx) if !h.config.OperationLogOff { h.RecordOperationLog(ctx) } if err := recover(); err != nil { logger.ErrorCtx(ctx, "GlobalDeferHandler error %+v", err) var ( errMsg string ok bool e error ) if errMsg, ok = err.(string); !ok { if e, ok = err.(error); ok { errMsg = e.Error() } } if errMsg == "" { errMsg = "system error" } if ctx.WantJSON() { response.Error(ctx, errMsg) return } if ok, _ = regexp.MatchString("/edit(.*)", ctx.Path()); ok { h.setFormWithReturnErrMessage(ctx, errMsg, "edit") return } if ok, _ = regexp.MatchString("/new(.*)", ctx.Path()); ok { h.setFormWithReturnErrMessage(ctx, errMsg, "new") return } h.HTML(ctx, auth.Auth(ctx), template.WarningPanelWithDescAndTitle(ctx, errMsg, errors.Msg, errors.Msg)) } } func (h *Handler) setFormWithReturnErrMessage(ctx *context.Context, errMsg string, kind string) { var ( formInfo table.FormInfo prefix = ctx.Query(constant.PrefixKey) panel = h.table(prefix, ctx) btnWord template2.HTML f *types.FormPanel ) if kind == "edit" { f = panel.GetForm() id := ctx.Query("id") if id == "" { id = ctx.Request.MultipartForm.Value[panel.GetPrimaryKey().Name][0] } formInfo, _ = panel.GetDataWithId(parameter.GetParam(ctx.Request.URL, panel.GetInfo().DefaultPageSize, panel.GetInfo().SortField, panel.GetInfo().GetSort()).WithPKs(id)) btnWord = f.FormEditBtnWord } else { f = panel.GetActualNewForm() formInfo = panel.GetNewFormInfo() formInfo.Title = f.Title formInfo.Description = f.Description btnWord = f.FormNewBtnWord } queryParam := parameter.GetParam(ctx.Request.URL, panel.GetInfo().DefaultPageSize, panel.GetInfo().SortField, panel.GetInfo().GetSort()).GetRouteParamStr() h.HTML(ctx, auth.Auth(ctx), types.Panel{ Content: aAlert(ctx).Warning(errMsg) + formContent(ctx, aForm(ctx). SetContent(formInfo.FieldList). SetTabContents(formInfo.GroupFieldList). SetTabHeaders(formInfo.GroupFieldHeaders). SetTitle(template2.HTML(cases.Title(language.Und).String(kind))). SetPrimaryKey(panel.GetPrimaryKey().Name). SetPrefix(h.config.PrefixFixSlash()). SetHiddenFields(map[string]string{ form.TokenKey: h.authSrv().AddToken(), form.PreviousKey: h.config.Url("/info/" + prefix + queryParam), }). SetUrl(h.config.Url("/"+kind+"/"+prefix)). SetOperationFooter(formFooter(ctx, kind, f.IsHideContinueEditCheckBox, f.IsHideContinueNewCheckBox, f.IsHideResetButton, btnWord)). SetHeader(f.HeaderHtml). SetFooter(f.FooterHtml), len(formInfo.GroupFieldHeaders) > 0, ctx.IsIframe(), f.IsHideBackButton, f.Header), Description: template2.HTML(formInfo.Description), Title: template2.HTML(formInfo.Title), }) ctx.AddHeader(constant.PjaxUrlHeader, h.config.Url("/info/"+prefix+"/"+kind+queryParam)) } ================================================ FILE: plugins/admin/controller/install.go ================================================ package controller import ( "bytes" "database/sql" "net/http" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" ) // ShowInstall show install page. func (h *Handler) ShowInstall(ctx *context.Context) { buffer := new(bytes.Buffer) //template.GetInstallPage(buffer) //rs, _ := mysql.Query("show tables;") //fmt.Println(rs[0]["Tables_in_godmin"]) //rs2, _ := mysql.Query("show columns from users") //fmt.Println(rs2[0]["Field"]) ctx.HTML(http.StatusOK, buffer.String()) } // CheckDatabase check the database connection. func (h *Handler) CheckDatabase(ctx *context.Context) { ip := ctx.FormValue("h") port := ctx.FormValue("po") username := ctx.FormValue("u") password := ctx.FormValue("pa") databaseName := ctx.FormValue("db") SqlDB, err := sql.Open("mysql", username+":"+password+"@tcp("+ip+":"+port+")/"+databaseName+"?charset=utf8mb4") if SqlDB != nil { if SqlDB.Ping() != nil { response.Error(ctx, "请检查参数是否设置正确") return } } defer func() { _ = SqlDB.Close() }() if err != nil { response.Error(ctx, "请检查参数是否设置正确") return } //db.InitDB(username, password, port, ip, databaseName, 100, 100) tables := make([]map[string]interface{}, 0) list := "[" for i := 0; i < len(tables); i++ { if i != len(tables)-1 { list += `"` + tables[i]["Tables_in_godmin"].(string) + `",` } else { list += `"` + tables[i]["Tables_in_godmin"].(string) + `"` } } list += "]" response.OkWithData(ctx, map[string]interface{}{ "list": list, }) } ================================================ FILE: plugins/admin/controller/menu.go ================================================ package controller import ( "encoding/json" template2 "html/template" "net/url" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/menu" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" form2 "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" ) // ShowMenu show menu info page. func (h *Handler) ShowMenu(ctx *context.Context) { h.getMenuInfoPanel(ctx, "", "") } // ShowNewMenu show new menu page. func (h *Handler) ShowNewMenu(ctx *context.Context) { h.showNewMenu(ctx, nil) } func getPlugNameFromReferer(ctx *context.Context) string { plugName := "" if ref := ctx.Referer(); ref != "" { if u, err := url.Parse(ref); err == nil && u != nil { plugName = u.Query().Get("__plugin_name") } } return plugName } func getMenuPlugNameParams(plugName string) string { params := "" if plugName != "" { params = "?__plugin_name=" + plugName } return params } func (h *Handler) showNewMenu(ctx *context.Context, err error) { var ( alert template2.HTML panel = h.table("menu", ctx) formInfo = panel.GetNewFormInfo() user = auth.Auth(ctx) plugName = getPlugNameFromReferer(ctx) ) if err != nil { alert = aAlert(ctx).Warning(err.Error()) } h.HTMLPlug(ctx, user, types.Panel{ Content: alert + formContent(ctx, aForm(ctx). SetContent(formInfo.FieldList). SetTabContents(formInfo.GroupFieldList). SetTabHeaders(formInfo.GroupFieldHeaders). SetPrefix(h.config.PrefixFixSlash()). SetPrimaryKey(panel.GetPrimaryKey().Name). SetUrl(h.routePath("menu_edit")). SetHiddenFields(map[string]string{ form2.TokenKey: h.authSrv().AddToken(), form2.PreviousKey: h.routePath("menu") + getMenuPlugNameParams(plugName), }). SetOperationFooter(formFooter(ctx, "new", false, false, false, panel.GetForm().FormNewBtnWord)), false, ctx.IsIframe(), false, ""), Description: template2.HTML(panel.GetForm().Description), Title: template2.HTML(panel.GetForm().Title), }, plugName) } // ShowEditMenu show edit menu page. func (h *Handler) ShowEditMenu(ctx *context.Context) { plugName := getPlugNameFromReferer(ctx) if ctx.Query("id") == "" { h.getMenuInfoPanel(ctx, "", template.Get(ctx, h.config.Theme).Alert().Warning(errors.WrongID)) ctx.AddHeader("Content-Type", "text/html; charset=utf-8") ctx.AddHeader(constant.PjaxUrlHeader, h.routePath("menu")+getMenuPlugNameParams(plugName)) return } model := h.table("menu", ctx) formInfo, err := model.GetDataWithId(parameter.BaseParam().WithPKs(ctx.Query("id"))) user := auth.Auth(ctx) if err != nil { h.HTMLPlug(ctx, user, template.WarningPanelWithDescAndTitle(ctx, err.Error(), model.GetForm().Description, model.GetForm().Title), plugName) return } h.showEditMenu(ctx, plugName, formInfo, nil) } func (h *Handler) showEditMenu(ctx *context.Context, plugName string, formInfo table.FormInfo, err error) { var alert template2.HTML if err != nil { alert = aAlert(ctx).Warning(err.Error()) } params := getMenuPlugNameParams(plugName) panel := h.table("menu", ctx) h.HTMLPlug(ctx, auth.Auth(ctx), types.Panel{ Content: alert + formContent(ctx, aForm(ctx). SetContent(formInfo.FieldList). SetTabContents(formInfo.GroupFieldList). SetTabHeaders(formInfo.GroupFieldHeaders). SetPrefix(h.config.PrefixFixSlash()). SetPrimaryKey(panel.GetPrimaryKey().Name). SetUrl(h.routePath("menu_edit")). SetOperationFooter(formFooter(ctx, "edit", false, false, false, panel.GetForm().FormEditBtnWord)). SetHiddenFields(map[string]string{ form2.TokenKey: h.authSrv().AddToken(), form2.PreviousKey: h.routePath("menu") + params, }), false, ctx.IsIframe(), false, ""), Description: template2.HTML(formInfo.Description), Title: template2.HTML(formInfo.Title), }, plugName) } // DeleteMenu delete the menu of given id. func (h *Handler) DeleteMenu(ctx *context.Context) { models.MenuWithId(guard.GetMenuDeleteParam(ctx).Id).SetConn(h.conn).Delete() response.OkWithMsg(ctx, language.Get("delete succeed")) } // EditMenu edit the menu of given id. func (h *Handler) EditMenu(ctx *context.Context) { param := guard.GetMenuEditParam(ctx) params := getMenuPlugNameParams(param.PluginName) if param.HasAlert() { h.getMenuInfoPanel(ctx, param.PluginName, param.Alert) ctx.AddHeader("Content-Type", "text/html; charset=utf-8") ctx.AddHeader(constant.PjaxUrlHeader, h.routePath("menu")+params) return } menuModel := models.MenuWithId(param.Id).SetConn(h.conn) // TODO: use transaction deleteRolesErr := menuModel.DeleteRoles() if db.CheckError(deleteRolesErr, db.DELETE) { formInfo, _ := h.table("menu", ctx).GetDataWithId(parameter.BaseParam().WithPKs(param.Id)) h.showEditMenu(ctx, param.PluginName, formInfo, deleteRolesErr) ctx.AddHeader(constant.PjaxUrlHeader, h.routePath("menu")+params) return } for _, roleId := range param.Roles { _, addRoleErr := menuModel.AddRole(roleId) if db.CheckError(addRoleErr, db.INSERT) { formInfo, _ := h.table("menu", ctx).GetDataWithId(parameter.BaseParam().WithPKs(param.Id)) h.showEditMenu(ctx, param.PluginName, formInfo, addRoleErr) ctx.AddHeader(constant.PjaxUrlHeader, h.routePath("menu")+params) return } } _, updateErr := menuModel.Update(param.Title, param.Icon, param.Uri, param.Header, param.PluginName, param.ParentId) if db.CheckError(updateErr, db.UPDATE) { formInfo, _ := h.table("menu", ctx).GetDataWithId(parameter.BaseParam().WithPKs(param.Id)) h.showEditMenu(ctx, param.PluginName, formInfo, updateErr) ctx.AddHeader(constant.PjaxUrlHeader, h.routePath("menu")+params) return } h.getMenuInfoPanel(ctx, param.PluginName, "") ctx.AddHeader("Content-Type", "text/html; charset=utf-8") ctx.AddHeader(constant.PjaxUrlHeader, h.routePath("menu")+params) } // NewMenu create a new menu item. func (h *Handler) NewMenu(ctx *context.Context) { param := guard.GetMenuNewParam(ctx) params := getMenuPlugNameParams(param.PluginName) if param.HasAlert() { h.getMenuInfoPanel(ctx, param.PluginName, param.Alert) ctx.AddHeader("Content-Type", "text/html; charset=utf-8") ctx.AddHeader(constant.PjaxUrlHeader, h.routePath("menu")+params) return } user := auth.Auth(ctx) // TODO: use transaction menuModel, createErr := models.Menu().SetConn(h.conn). New(param.Title, param.Icon, param.Uri, param.Header, param.PluginName, param.ParentId, (menu.GetGlobalMenu(user, h.conn, ctx.Lang(), param.PluginName)).MaxOrder+1) if db.CheckError(createErr, db.INSERT) { h.showNewMenu(ctx, createErr) return } for _, roleId := range param.Roles { _, addRoleErr := menuModel.AddRole(roleId) if db.CheckError(addRoleErr, db.INSERT) { h.showNewMenu(ctx, addRoleErr) return } } menu.GetGlobalMenu(user, h.conn, ctx.Lang(), param.PluginName).AddMaxOrder() h.getMenuInfoPanel(ctx, param.PluginName, "") ctx.AddHeader("Content-Type", "text/html; charset=utf-8") ctx.AddHeader(constant.PjaxUrlHeader, h.routePath("menu")+params) } // MenuOrder change the order of menu items. func (h *Handler) MenuOrder(ctx *context.Context) { var data []map[string]interface{} _ = json.Unmarshal([]byte(ctx.FormValue("_order")), &data) models.Menu().SetConn(h.conn).ResetOrder([]byte(ctx.FormValue("_order"))) response.Ok(ctx) } func (h *Handler) getMenuInfoPanel(ctx *context.Context, plugName string, alert template2.HTML) { user := auth.Auth(ctx) if plugName == "" { plugName = ctx.Query("__plugin_name") } tree := aTree(ctx). SetTree((menu.GetGlobalMenu(user, h.conn, ctx.Lang(), plugName)).List). SetEditUrl(h.routePath("menu_edit_show")). SetUrlPrefix(h.config.Prefix()). SetDeleteUrl(h.routePath("menu_delete")). SetOrderUrl(h.routePath("menu_order")). GetContent() var ( header = aTree(ctx).GetTreeHeader() box = aBox(ctx).SetHeader(header).SetBody(tree).GetContent() col1 = aCol(ctx).SetSize(types.SizeMD(6)).SetContent(box).GetContent() panel = h.table("menu", ctx) formInfo = panel.GetNewFormInfo() ) newForm := menuFormContent(ctx, aForm(ctx). SetPrefix(h.config.PrefixFixSlash()). SetUrl(h.routePath("menu_new")). SetPrimaryKey(panel.GetPrimaryKey().Name). SetHiddenFields(map[string]string{ form2.TokenKey: h.authSrv().AddToken(), form2.PreviousKey: h.routePath("menu") + getMenuPlugNameParams(plugName), }). SetOperationFooter(formFooter(ctx, "menu", false, false, false, panel.GetForm().FormNewBtnWord)). SetTitle("New"). SetContent(formInfo.FieldList). SetTabContents(formInfo.GroupFieldList). SetTabHeaders(formInfo.GroupFieldHeaders)) col2 := aCol(ctx).SetSize(types.SizeMD(6)).SetContent(newForm).GetContent() row := aRow(ctx).SetContent(col1 + col2).GetContent() h.HTMLPlug(ctx, user, types.Panel{ Content: alert + row, Description: "Menus Manage", Title: "Menus", }, plugName) } ================================================ FILE: plugins/admin/controller/new.go ================================================ package controller import ( "fmt" template2 "html/template" "net/http" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/file" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" form2 "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" "github.com/GoAdminGroup/go-admin/template/types" ) // ShowNewForm show a new form page. func (h *Handler) ShowNewForm(ctx *context.Context) { param := guard.GetShowNewFormParam(ctx) h.showNewForm(ctx, "", param.Prefix, param.Param.GetRouteParamStr(), false) } func (h *Handler) showNewForm(ctx *context.Context, alert template2.HTML, prefix, paramStr string, isNew bool) { var ( user = auth.Auth(ctx) panel = h.table(prefix, ctx) formInfo = panel.GetNewFormInfo() infoUrl = h.routePathWithPrefix("info", prefix) + paramStr newUrl = h.routePathWithPrefix("new", prefix) showNewUrl = h.routePathWithPrefix("show_new", prefix) + paramStr referer = ctx.Referer() f = panel.GetActualNewForm() isNotIframe = ctx.Query(constant.IframeKey) != "true" ) if referer != "" && !isInfoUrl(referer) && !isNewUrl(referer, ctx.Query(constant.PrefixKey)) { infoUrl = referer } hiddenFields := map[string]string{ form2.TokenKey: h.authSrv().AddToken(), form2.PreviousKey: infoUrl, } if ctx.Query(constant.IframeKey) != "" { hiddenFields[constant.IframeKey] = ctx.Query(constant.IframeKey) } if ctx.Query(constant.IframeIDKey) != "" { hiddenFields[constant.IframeIDKey] = ctx.Query(constant.IframeIDKey) } content := formContent(ctx, aForm(ctx). SetPrefix(h.config.PrefixFixSlash()). SetFieldsHTML(f.HTMLContent). SetContent(formInfo.FieldList). SetTabContents(formInfo.GroupFieldList). SetTabHeaders(formInfo.GroupFieldHeaders). SetUrl(newUrl). SetAjax(f.AjaxSuccessJS, f.AjaxErrorJS). SetInputWidth(f.InputWidth). SetHeadWidth(f.HeadWidth). SetLayout(f.Layout). SetPrimaryKey(panel.GetPrimaryKey().Name). SetHiddenFields(hiddenFields). SetTitle(f.FormNewTitle). SetOperationFooter(formFooter(ctx, "new", f.IsHideContinueEditCheckBox, f.IsHideContinueNewCheckBox, f.IsHideResetButton, f.FormNewBtnWord)). SetHeader(f.HeaderHtml). SetFooter(f.FooterHtml), len(formInfo.GroupFieldHeaders) > 0, !isNotIframe, f.IsHideBackButton, f.Header) if f.Wrapper != nil { content = f.Wrapper(content) } h.HTML(ctx, user, types.Panel{ Content: alert + content, Description: template2.HTML(f.Description), Title: modules.AorBHTML(isNotIframe, template2.HTML(f.Title), ""), MiniSidebar: f.HideSideBar, }, template.ExecuteOptions{Animation: alert == ""}) if isNew { ctx.AddHeader(constant.PjaxUrlHeader, showNewUrl) } } // NewForm insert a table row into database. func (h *Handler) NewForm(ctx *context.Context) { param := guard.GetNewFormParam(ctx) // process uploading files, only support local storage if len(param.MultiForm.File) > 0 { err := file.GetFileEngine(h.config.FileUploadEngine.Name).Upload(param.MultiForm) if err != nil { logger.ErrorCtx(ctx, "get file engine error: %+v", err) if ctx.WantJSON() { response.Error(ctx, err.Error()) } else { h.showNewForm(ctx, aAlert(ctx).Warning(err.Error()), param.Prefix, param.Param.GetRouteParamStr(), true) } return } } err := param.Panel.InsertData(ctx, param.Value()) if err != nil { logger.ErrorCtx(ctx, "insert data error: %+v", err) if ctx.WantJSON() { response.Error(ctx, err.Error(), map[string]interface{}{ "token": h.authSrv().AddToken(), }) } else { h.showNewForm(ctx, aAlert(ctx).Warning(err.Error()), param.Prefix, param.Param.GetRouteParamStr(), true) } return } f := param.Panel.GetActualNewForm() if f.Responder != nil { f.Responder(ctx) return } if ctx.WantJSON() && !param.IsIframe { response.OkWithData(ctx, map[string]interface{}{ "url": param.PreviousPath, "token": h.authSrv().AddToken(), }) return } if !param.FromList { if isNewUrl(param.PreviousPath, param.Prefix) { h.showNewForm(ctx, param.Alert, param.Prefix, param.Param.GetRouteParamStr(), true) return } ctx.HTML(http.StatusOK, fmt.Sprintf(``, param.PreviousPath)) ctx.AddHeader(constant.PjaxUrlHeader, param.PreviousPath) return } if param.IsIframe { ctx.HTML(http.StatusOK, fmt.Sprintf(``, language.Get("success"), param.IframeID)) return } buf := h.showTable(ctx, param.Prefix, param.Param, nil) ctx.HTML(http.StatusOK, buf.String()) ctx.AddHeader(constant.PjaxUrlHeader, h.routePathWithPrefix("info", param.Prefix)+param.Param.GetRouteParamStr()) } ================================================ FILE: plugins/admin/controller/operation.go ================================================ package controller import ( "encoding/json" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" ) func (h *Handler) Operation(ctx *context.Context) { id := ctx.Query("__goadmin_op_id") if !h.OperationHandler(config.Url("/operation/"+id), ctx) { errMsg := "not found" if ctx.Headers(constant.PjaxHeader) == "" && ctx.Method() != "GET" { response.BadRequest(ctx, errMsg) } else { response.Alert(ctx, errMsg, errMsg, errMsg, h.conn, h.navButtons) } return } } // RecordOperationLog record all operation logs, store into database. func (h *Handler) RecordOperationLog(ctx *context.Context) { if user, ok := ctx.UserValue["user"].(models.UserModel); ok { var input []byte form := ctx.Request.MultipartForm if form != nil { input, _ = json.Marshal((*form).Value) } models.OperationLog().SetConn(h.conn).New(user.Id, ctx.Path(), ctx.Method(), ctx.LocalIP(), string(input)) } } ================================================ FILE: plugins/admin/controller/plugins.go ================================================ package controller import ( "bytes" "fmt" "html/template" "net/http" "os" "path/filepath" "strings" "time" "github.com/GoAdminGroup/go-admin/modules/system" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/remote_server" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" template2 "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/form" "github.com/GoAdminGroup/html" "github.com/gin-gonic/gin" ) func (h *Handler) Plugins(ctx *context.Context) { list := plugins.Get() size := types.Size(6, 3, 2) rows := template.HTML("") if h.config.IsNotProductionEnvironment() { getMoreCover := config.Url("/assets/dist/img/plugin_more.png") list = list.Add(plugins.NewBasePluginWithInfoAndIndexURL(plugins.Info{ Title: "get more plugins", Name: "", MiniCover: getMoreCover, Cover: getMoreCover, }, config.Url("/plugins/store"), true)) } for i := 0; i < len(list); i += 6 { box1 := aBox(ctx). SetBody(h.pluginBox(ctx, GetPluginBoxParamFromPlug(list[i]))). GetContent() content := aCol(ctx).SetSize(size).SetContent(box1).GetContent() offset := len(list) - i if offset > 6 { offset = 6 } for j := i + 1; j < offset; j++ { box2 := aBox(ctx). SetBody(h.pluginBox(ctx, GetPluginBoxParamFromPlug(list[j]))). GetContent() content += aCol(ctx).SetSize(size).SetContent(box2).GetContent() } rows += aRow(ctx).SetContent(content).GetContent() } h.HTML(ctx, auth.Auth(ctx), types.Panel{ Content: rows, CSS: pluginsPageCSS, Description: language.GetFromHtml("plugins"), Title: language.GetFromHtml("plugins"), }) } func (h *Handler) PluginStore(ctx *context.Context) { var ( size = types.Size(12, 6, 4) list, page = plugins.GetAll( remote_server.GetOnlineReq{ Page: ctx.Query("page"), Free: ctx.Query("free"), PageSize: ctx.Query("page_size"), Filter: ctx.Query("filter"), Order: ctx.Query("order"), Lang: h.config.Language, Version: system.Version(), CategoryId: ctx.Query("category_id"), }, ctx.Cookie(remote_server.TokenKey)) rows = template.HTML(page.HTML) ) if ctx.Query("page") == "" && len(list) == 0 { h.HTML(ctx, auth.Auth(ctx), types.Panel{ Content: pluginStore404(), CSS: template.CSS(`.plugin-store-404-content { margin: auto; width: 80%; text-align: center; color: #9e9e9e; font-size: 17px; height: 250px; line-height: 250px; }`), Description: language.GetFromHtml("plugin store"), Title: language.GetFromHtml("plugin store"), }) return } for i := 0; i < len(list); i += 3 { box1 := aBox(ctx). SetBody(h.pluginStoreBox(ctx, GetPluginBoxParamFromPlug(list[i]))). GetContent() col1 := aCol(ctx).SetSize(size).SetContent(box1).GetContent() box2, col2, box3, col3 := template.HTML(""), template.HTML(""), template.HTML(""), template.HTML("") if i+1 < len(list) { box2 = aBox(ctx). SetBody(h.pluginStoreBox(ctx, GetPluginBoxParamFromPlug(list[i+1]))). GetContent() col2 = aCol(ctx).SetSize(size).SetContent(box2).GetContent() if i+2 < len(list) { box3 = aBox(ctx). SetBody(h.pluginStoreBox(ctx, GetPluginBoxParamFromPlug(list[i+2]))). GetContent() col3 = aCol(ctx).SetSize(size).SetContent(box3).GetContent() } } rows += aRow(ctx).SetContent(col1 + col2 + col3).GetContent() } detailPopupModal := template2.Default(ctx).Popup().SetID("detail-popup-modal"). SetTitle(plugWordHTML("plugin detail")). SetBody(pluginsPageDetailPopupBody()). SetWidth("730px"). SetHeight("400px"). SetFooter("1"). GetContent() buyPopupModal := template2.Default(ctx).Popup().SetID("buy-popup-modal"). SetTitle(plugWordHTML("plugin detail")). SetWidth("730px"). SetHeight("400px"). SetFooter("1"). GetContent() loginPopupModal := template2.Default(ctx).Popup().SetID("login-popup-modal"). SetTitle(plugWordHTML("login to goadmin member system")). SetBody(aForm(ctx).SetContent(types.FormFields{ {Field: "name", Head: plugWord("account"), FormType: form.Text, Editable: true}, {Field: "password", Head: plugWord("password"), FormType: form.Password, Editable: true, HelpMsg: template.HTML(fmt.Sprintf(plugWord("no account? click %s here %s to register."), "", ""))}, }).GetContent()). SetWidth("540px"). SetHeight("250px"). SetFooterHTML(template.HTML(``)). GetContent() h.HTML(ctx, auth.Auth(ctx), types.Panel{ Content: rows + detailPopupModal + buyPopupModal + loginPopupModal, CSS: pluginsStorePageCSS + template.CSS(page.CSS), JS: template.JS(page.JS) + GetPluginsPageJS(PluginsPageJSData{Prefix: h.config.Prefix()}), Description: language.GetFromHtml("plugin store"), Title: language.GetFromHtml("plugin store"), }) } func (h *Handler) PluginDetail(ctx *context.Context) { name := ctx.Query("name") plug, exist := plugins.FindByNameAll(name) if !exist { ctx.JSON(http.StatusOK, gin.H{ "code": 400, "msg": "bad request", }) return } info := plug.GetInfo() if info.MiniCover == "" { info.MiniCover = config.Url("/assets/dist/img/plugin_default.png") } ctx.JSON(http.StatusOK, gin.H{ "code": 0, "msg": "ok", "data": gin.H{ "mini_cover": info.MiniCover, "title": language.GetWithScope(info.Title, name), "author": fmt.Sprintf(plugWord("provided by %s"), language.GetWithScope(info.Author, name)), "introduction": language.GetWithScope(info.Description, name), "website": language.GetWithScope(info.Website, name), "version": language.GetWithScope(info.Version, name), "created_at": language.GetWithScope(info.CreateDate.Format("2006-01-02"), name), "updated_at": language.GetWithScope(info.UpdateDate.Format("2006-01-02"), name), "downloaded": info.Downloaded, "download_reboot": plugins.Exist(plug), "skip": info.SkipInstallation, "uuid": info.Uuid, "upgrade": info.CanUpdate, "install": plug.IsInstalled(), "free": info.IsFree(), }, }) } type PluginBoxParam struct { Info plugins.Info Install bool Upgrade bool Skip bool DownloadReboot bool Name string IndexURL string } func GetPluginBoxParamFromPlug(plug plugins.Plugin) PluginBoxParam { return PluginBoxParam{ Info: plug.GetInfo(), Install: plug.IsInstalled(), Upgrade: plug.GetInfo().CanUpdate, Skip: plug.GetInfo().SkipInstallation, DownloadReboot: plugins.Exist(plug), Name: plug.Name(), IndexURL: plug.GetIndexURL(), } } func (h *Handler) pluginStoreBox(ctx *context.Context, param PluginBoxParam) template.HTML { cover := template2.HTML(param.Info.MiniCover) if cover == template2.HTML("") { cover = template2.HTML(config.Url("/assets/dist/img/plugin_default.png")) } col1 := html.DivEl().SetClass("plugin-store-item-img"). SetContent(aImage(ctx). SetSrc(cover). SetHeight("110px"). SetWidth("110px"). GetContent()). Get() footer := html.ButtonEl().SetClass(pluginBtnClass("plugin-info")...). SetAttr("onclick", `pluginDetail('`+param.Name+`','`+param.Info.Uuid+`')`). SetContent(plugWordHTML("info")). Get() if param.Install { if param.Upgrade { footer += html.ButtonEl().SetClass(pluginBtnClass("installation")...). SetAttr("onclick", `pluginDownload('`+param.Name+`', this)`). SetContent(plugWordHTML("upgrade")). Get() } } else { if param.Info.Downloaded { if param.DownloadReboot { if !param.Skip && !param.Install { footer += html.AEl().SetAttr("href", h.config.Url(`/info/plugin_`+param.Name+`/new`)). SetContent( html.ButtonEl().SetClass(pluginBtnClass("installation")...). SetAttr("onclick", `pluginInstall('`+param.Name+`')`). SetContent(plugWordHTML("install")). Get(), ).Get() } } else { footer += html.ButtonEl().SetClass(pluginBtnClass("installation")...). SetAttr("onclick", `pluginRebootInstall()`). SetContent(plugWordHTML("install")). Get() } } else { if param.Info.IsFree() || param.Info.HasBought { footer += html.ButtonEl().SetClass(pluginBtnClass("installation")...). SetAttr("onclick", `pluginDownload('`+param.Name+`', this)`). SetContent(plugWordHTML("download")). Get() } else { footer += html.ButtonEl().SetClass(pluginBtnClass("installation")...). SetAttr("onclick", `pluginBuy('`+param.Name+`', '`+param.Info.Uuid+`')`). SetContent(plugWordHTML("buy")). Get() } } } col2 := html.DivEl().SetClass("plugin-item-content").SetContent( html.DivEl().SetClass("plugin-item-content-title"). SetContent(language.GetFromHtml(template.HTML(param.Info.Title), param.Name)). Get() + html.DivEl().SetClass("plugin-item-content-description"). SetContent(language.GetFromHtml(template.HTML(param.Info.Description), param.Name)). Get() + footer, ).Get() return html.Div(col1+col2, html.M{"clear": "both"}) } func (h *Handler) pluginBox(ctx *context.Context, param PluginBoxParam) template.HTML { cover := template2.HTML(param.Info.MiniCover) if cover == template2.HTML("") { cover = "/admin/assets/dist/img/plugin_default.png" } jump := param.IndexURL label := template.HTML("") if !param.Install { jump = h.config.Url("/info/plugin_" + param.Name + "/new") label = html.SpanEl().SetClass("plugin-item-label").SetContent(language.GetFromHtml("uninstalled")).Get() } col1 := html.AEl().SetContent(html.DivEl().SetClass("plugin-item-img"). SetContent(aImage(ctx). SetSrc(cover). GetContent()+ html.PEl().SetContent(language.GetFromHtml(template.HTML(param.Info.Title), param.Name)). SetClass("plugin-item-title").Get()). Get()+label).SetAttr("href", jump).Get() return col1 } func (h *Handler) PluginDownload(ctx *context.Context) { if !h.config.Debug { ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 400, "msg": plugWord("change to debug mode first"), }) return } name := ctx.FormValue("name") if name == "" { ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 400, "msg": plugWord("download fail, wrong name"), }) return } plug, exist := plugins.FindByNameAll(name) if !exist { ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 400, "msg": plugWord("download fail, plugin not exist"), }) return } if !plug.GetInfo().IsFree() && !plug.GetInfo().HasBought { ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 400, "msg": plugWord("download fail, plugin has not been bought"), }) return } downloadURL := plug.GetInfo().Url extraDownloadURL := plug.GetInfo().ExtraDownloadUrl if !plug.GetInfo().IsFree() { var err error downloadURL, extraDownloadURL, err = remote_server.GetDownloadURL(plug.GetInfo().Uuid, ctx.Cookie(remote_server.TokenKey)) if err != nil { logger.ErrorCtx(ctx, "download plugins error: %+v", err) ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 500, "msg": plugWord("download fail"), }) return } } tempFile := "./temp-" + utils.Uuid(10) + ".zip" err := utils.DownloadTo(downloadURL, tempFile) if err != nil { logger.ErrorCtx(ctx, "download plugins error %+v", map[string]interface{}{ "error": err, "downloadURL": downloadURL, }) ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 500, "msg": plugWord("download fail"), }) return } gopath := os.Getenv("GOPATH") if gopath == "" { ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 500, "msg": plugWord("golang develop environment does not exist"), }) return } gomodule := os.Getenv("GO111MODULE") base := filepath.Dir(plug.GetInfo().ModulePath) installPath := "" if gomodule == "off" { installPath = filepath.ToSlash(gopath + "/src/" + base) } else { installPath = filepath.ToSlash(gopath + "/pkg/mod/" + base) } err = utils.UnzipDir(tempFile, installPath) if err != nil { logger.ErrorCtx(ctx, "download plugins, unzip error %+v", map[string]interface{}{ "error": err, "installPath": installPath, }) ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 500, "msg": plugWord("download fail"), }) return } _ = os.Remove(tempFile) if len(downloadURL) > 18 && downloadURL[:18] == "https://github.com" { name := filepath.Base(plug.GetInfo().ModulePath) version := strings.ReplaceAll(plug.GetInfo().Version, "v", "") rawPath := installPath + "/" + name nowPath := rawPath + "-" + version if gomodule == "off" { err = os.Rename(nowPath, rawPath) } else { err = os.Rename(nowPath, rawPath+"@"+plug.GetInfo().Version) } if err != nil { logger.ErrorCtx(ctx, "download plugins, rename error %+v", map[string]interface{}{ "error": err, "nowPath": nowPath, "rawPath": rawPath, }) ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 500, "msg": plugWord("download fail"), }) return } } else if gomodule != "off" { rawPath := installPath + "/" + name err = os.Rename(rawPath, rawPath+"@"+plug.GetInfo().Version) if err != nil { logger.ErrorCtx(ctx, "download plugins, rename error %+v", map[string]interface{}{ "error": err, "rawPath": rawPath, }) ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 500, "msg": plugWord("download fail"), }) return } } if h.config.BootstrapFilePath != "" && utils.FileExist(h.config.BootstrapFilePath) { content, err := os.ReadFile(h.config.BootstrapFilePath) if err != nil { logger.ErrorCtx(ctx, "read bootstrap file error: %+v", err) } else { err = os.WriteFile(h.config.BootstrapFilePath, []byte(string(content)+` import _ "`+plug.GetInfo().ModulePath+`"`), 0644) if err != nil { logger.ErrorCtx(ctx, "write bootstrap file error: %+v", err) } } } if h.config.GoModFilePath != "" && utils.FileExist(h.config.GoModFilePath) && plug.GetInfo().CanUpdate && plug.GetInfo().OldVersion != "" { content, _ := os.ReadFile(h.config.BootstrapFilePath) src := plug.GetInfo().ModulePath + " " + plug.GetInfo().OldVersion dist := plug.GetInfo().ModulePath + " " + plug.GetInfo().Version content = bytes.ReplaceAll(content, []byte(src), []byte(dist)) _ = os.WriteFile(h.config.BootstrapFilePath, content, 0644) } // TODO: 实现运行环境与编译环境隔离 if plug.GetInfo().ExtraDownloadUrl != "" { err = utils.DownloadTo(extraDownloadURL, "./"+plug.Name()+"_extra_"+ fmt.Sprintf("%d", time.Now().Unix())+".zip") if err != nil { logger.ErrorCtx(ctx, "failed to download "+plug.Name()+" extra data: %+v", err) } } plug.(*plugins.BasePlugin).Info.Downloaded = true plug.(*plugins.BasePlugin).Info.CanUpdate = false ctx.JSON(http.StatusOK, map[string]interface{}{ "code": 0, "msg": plugWord("download success, restart to install"), }) } func (h *Handler) ServerLogin(ctx *context.Context) { param := guard.GetServerLoginParam(ctx) res := remote_server.Login(param.Account, param.Password) if res.Code == 0 && res.Data.Token != "" { ctx.SetCookie(&http.Cookie{ Name: remote_server.TokenKey, Value: res.Data.Token, Expires: time.Now().Add(time.Second * time.Duration(res.Data.Expire/1000)), HttpOnly: true, Path: "/", }) } ctx.JSON(http.StatusOK, gin.H{ "code": res.Code, "data": res.Data, "msg": res.Msg, }) } func pluginBtnClass(class ...string) []string { return append([]string{"btn", "btn-primary"}, class...) } func plugWord(word string) string { return language.GetWithScope(word, "plugin") } func plugWordHTML(word template.HTML) template.HTML { return language.GetFromHtml(word, "plugin") } ================================================ FILE: plugins/admin/controller/plugins_tmpl.go ================================================ package controller import ( "bytes" "html/template" "github.com/GoAdminGroup/go-admin/modules/remote_server" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/logger" ) func GetPluginsPageJS(data PluginsPageJSData) template.JS { t := template.New("plugins_page_js").Funcs(map[string]interface{}{ "lang": language.Get, "plugWord": plugWord, }) t, err := t.Parse(pluginsPageJS) if err != nil { logger.Error(err) return "" } buf := new(bytes.Buffer) err = t.Execute(buf, data) if err != nil { logger.Error(err) return "" } return template.JS(buf.String()) } type PluginsPageJSData struct { Prefix string } var pluginsPageJS = ` function pluginInstall(name){ location.href="{{.Prefix}}/info/plugin_"+name+"/new" } var downloadLock = false; const apiTokenKey = "GOADMIN_SERVER_API_TOKEN"; const apiTokenExpireKey = "GOADMIN_SERVER_API_TOKEN_EXPIRE"; const serverHost = "` + remote_server.ServerHost + `" function login() { $.ajax({ type: 'POST', url: '{{.Prefix}}/server/login', dataType: "json", contentType: "application/json", data: JSON.stringify({ "account": $("#login-popup-modal form input.name").val(), "password": $("#login-popup-modal form input.password").val() }), success: function (data) { if (data.code == 0) { localStorage.setItem(apiTokenKey, data.data.token); localStorage.setItem(apiTokenExpireKey, (new Date()).getTime() + data.data.expire); $('#login-popup-modal').modal('hide'); if (typeof loginSuccessCallback != "undefined") { loginSuccessCallback(data); } $.pjax.reload('#pjax-container'); } else { swal({ type: "error", title: data.msg, showCancelButton: false, html: true, confirmButtonColor: "#3c8dbc", confirmButtonText: '{{lang "got it"}}', }) } }, error: function (data) { swal({ type: "error", title: data.responseJSON.msg ? data.responseJSON.msg : "error", showCancelButton: false, html: true, confirmButtonColor: "#3c8dbc", confirmButtonText: '{{lang "got it"}}', }) } }); } function pluginBuy(name, uuid) { window.open(serverHost + "/plugins/detail/" + uuid); } function pluginDetail(name, uuid) { $.ajax({ dataType: 'json', type: 'POST', url: '{{.Prefix}}/plugin/detail?name=' + name, async: 'true', success: function (data) { if (data.code == 0) { let head_ele = "#detail-popup-modal .plugin-detail .plugin-detail-head " $(head_ele + ".plugin-detail-head-logo img").attr('src', data.data.mini_cover); $(head_ele + ".plugin-detail-head-title .plugin-detail-title").html(data.data.title); $(head_ele + ".plugin-detail-head-title .plugin-detail-provider").html(data.data.author); let item_ele = "#detail-popup-modal .plugin-detail .plugin-detail-info .plugin-detail-info-item"; $(item_ele).eq(0).find(".plugin-detail-info-item-content").html(data.data.introduction); $(item_ele).eq(1).find(".plugin-detail-info-item-content").html(data.data.website); $(item_ele).eq(2).find(".plugin-detail-info-item-content").html(data.data.version); $(item_ele).eq(3).find(".plugin-detail-info-item-content").html(data.data.created_at); $(item_ele).eq(4).find(".plugin-detail-info-item-content").html(data.data.updated_at); $(item_ele).eq(5).find("a").attr("href", "https://www.go-admin.cn/plugins/detail/" + data.data.uuid); let footer_ele = "#detail-popup-modal .modal-footer .btn.btn-primary"; if (data.data.install) { if (data.data.upgrade) { $(footer_ele).html('{{plugWord "upgrade"}}').attr("onclick", "pluginDownload('"+ name +"', this)"); $(footer_ele).show(); } else { $(footer_ele).hide(); } } else { if (data.data.downloaded) { if (data.data.download_reboot) { if (data.data.skip) { $(footer_ele).html('{{plugWord "install"}}') } else { $(footer_ele).html('{{plugWord "install"}}').attr("onclick", "pluginInstall('"+ name +"')") } } else { $(footer_ele).html('{{plugWord "install"}}').attr("onclick", 'pluginRebootInstall()') } } else { if (data.data.free) { $(footer_ele).html('{{plugWord "download"}}').attr("onclick", "pluginInstall('"+ name +"', this)") } else { $(footer_ele).html('{{plugWord "buy"}}').attr("onclick", "pluginBuy('"+ name +"', '"+ uuid +"')") } } $(footer_ele).show(); } $("#detail-popup-modal").modal('show'); } else { swal({ type: "error", title: data.msg, showCancelButton: false, html: true, confirmButtonColor: "#3c8dbc", confirmButtonText: '{{lang "got it"}}', }) } }, error: function (data) { swal({ type: "error", title: data.responseJSON.msg ? data.responseJSON.msg : "error", showCancelButton: false, html: true, confirmButtonColor: "#3c8dbc", confirmButtonText: '{{lang "got it"}}', }) } }); } function pluginDownload(name, ele) { if (downloadLock) { return } NProgress.start(); downloadLock = true; $(ele).html(' {{plugWord "downloading"}}') $.ajax({ dataType: 'json', type: 'POST', url: '{{.Prefix}}/plugin/download', async: 'true', data: { 'name': name }, success: function (data) { NProgress.done(); downloadLock = false; if (data.code == 0) { $(ele).attr('onclick', 'pluginRebootInstall()') $(ele).html('{{plugWord "install"}}') swal({ type: "success", title: data.msg, showCancelButton: false, confirmButtonColor: "#3c8dbc", confirmButtonText: '{{lang "got it"}}', }) } else { $(ele).html('{{plugWord "download"}}') swal({ type: "error", title: data.msg, showCancelButton: false, text: "点这里手动下载", html: true, confirmButtonColor: "#3c8dbc", confirmButtonText: '{{lang "got it"}}', }) } }, error: function (data) { downloadLock = false; $(ele).html('{{plugWord "download"}}') alert('download fail'); } }); } function pluginRebootInstall() { swal({ type: "success", title: "{{plugWord "restart to install"}}", showCancelButton: false, confirmButtonColor: "#3c8dbc", confirmButtonText: '{{lang "got it"}}', }) } ` var pluginsPageCSS = template.CSS(` .plugin-item-img { text-align: center; } .plugin-item-img img { width: 100%; height: auto; border: 1px solid #f5f4f4; } .plugin-item-title { margin-top: 10px; color: #717171; overflow: hidden; text-overflow: ellipsis; word-break: break-all; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; } @media screen and (min-width: 1200px) { .pjax-container-content .row .col-lg-2 { width: 14%; max-width: 200px; } } .plugin-item-label { color: white; background-color: red; padding: 4px; border-radius: 3px; font-size: 12px; position: absolute; top: 5px; right: 5px; } `) var pluginsStorePageCSS = template.CSS(` .plugin-item-content { margin-left: 15px; } .plugin-store-item-img img, .plugin-detail-head-logo img { border: 1px solid #f5f4f4; } .plugin-item-content-title { font-size: 15px; margin-bottom: 6px; font-weight: bold; padding-top: 2px; } .plugin-item-content { position: absolute; margin-left: 121px; padding-right: 10px; top: 7px; width: 100%; padding-right: 139px; } .plugin-item-content-description { overflow: hidden; text-overflow: ellipsis; word-break: break-all; display: -webkit-box; font-size: 15px; -webkit-line-clamp: 2; -webkit-box-orient: vertical; height: 42px; } .installation { float: right; margin-top: 10px; } .plugin-info { float: right; margin-top: 10px; margin-left: 10px; } .plugin-detail { padding: 10px; } .plugin-detail-head { clear: both; height: 112px; margin-bottom: 33px; } .plugin-detail-title { font-size: 30px; } .plugin-detail-provider { font-size: 15px; margin-top: 4px; } .plugin-detail-head-logo { width: 120px; float: left; } .plugin-detail-head-title { float: left; margin-left: 10px; } .plugin-detail-info-item { clear: both; height: 15px; margin-bottom: 17px; } .plugin-detail-info-item-head { width: 120px; float: left; font-weight: bold; } .plugin-detail-info-item-content { float: left; margin-left: 10px; } `) var pluginStore404 = func() template.HTML { return template.HTML(`

    ` + plugWord("can not connect to the goadmin remote server") + `

    `) } var pluginsPageDetailPopupBody = func() template.HTML { return template.HTML(`
    ` + plugWord("introduction") + `
    ` + plugWord("website") + `
    ` + plugWord("version") + `
    ` + plugWord("created at") + `
    ` + plugWord("updated at") + `
    `) } ================================================ FILE: plugins/admin/controller/show.go ================================================ package controller import ( "bytes" "crypto/md5" "fmt" template2 "html/template" "mime" "net/http" "path" "strconv" "strings" "time" "github.com/360EntSecGroup-Skylar/excelize" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/icon" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/action" form2 "github.com/GoAdminGroup/go-admin/template/types/form" "github.com/GoAdminGroup/html" ) // ShowInfo show info page. func (h *Handler) ShowInfo(ctx *context.Context) { prefix := ctx.Query(constant.PrefixKey) panel := h.table(prefix, ctx) if panel.GetOnlyUpdateForm() { ctx.Redirect(h.routePathWithPrefix("show_edit", prefix)) return } if panel.GetOnlyNewForm() { ctx.Redirect(h.routePathWithPrefix("show_new", prefix)) return } if panel.GetOnlyDetail() { ctx.Redirect(h.routePathWithPrefix("detail", prefix)) return } params := parameter.GetParam(ctx.Request.URL, panel.GetInfo().DefaultPageSize, panel.GetInfo().SortField, panel.GetInfo().GetSort()) buf := h.showTable(ctx, prefix, params, panel) ctx.HTML(http.StatusOK, buf.String()) } func (h *Handler) showTableData(ctx *context.Context, prefix string, params parameter.Parameters, panel table.Table, urlNamePrefix string) (table.Table, table.PanelInfo, []string, error) { if panel == nil { panel = h.table(prefix, ctx) } panelInfo, err := panel.GetData(ctx, params.WithIsAll(false)) if err != nil { return panel, panelInfo, nil, err } var ( paramStr = params.DeleteIsAll().GetRouteParamStr() editUrl = modules.AorEmpty(!panel.GetInfo().IsHideEditButton, h.routePathWithPrefix(urlNamePrefix+"show_edit", prefix)+paramStr) newUrl = modules.AorEmpty(!panel.GetInfo().IsHideNewButton, h.routePathWithPrefix(urlNamePrefix+"show_new", prefix)+paramStr) deleteUrl = modules.AorEmpty(!panel.GetInfo().IsHideDeleteButton, h.routePathWithPrefix(urlNamePrefix+"delete", prefix)+paramStr) exportUrl = modules.AorEmpty(!panel.GetInfo().IsHideExportButton, h.routePathWithPrefix(urlNamePrefix+"export", prefix)+paramStr) detailUrl = modules.AorEmpty(!panel.GetInfo().IsHideDetailButton, h.routePathWithPrefix(urlNamePrefix+"detail", prefix)+paramStr) infoUrl = h.routePathWithPrefix(urlNamePrefix+"info", prefix) updateUrl = h.routePathWithPrefix(urlNamePrefix+"update", prefix) + paramStr user = auth.Auth(ctx) ) editUrl = user.GetCheckPermissionByUrlMethod(editUrl, h.route(urlNamePrefix+"show_edit").Method()) newUrl = user.GetCheckPermissionByUrlMethod(newUrl, h.route(urlNamePrefix+"show_new").Method()) deleteUrl = user.GetCheckPermissionByUrlMethod(deleteUrl, h.route(urlNamePrefix+"delete").Method()) exportUrl = user.GetCheckPermissionByUrlMethod(exportUrl, h.route(urlNamePrefix+"export").Method()) detailUrl = user.GetCheckPermissionByUrlMethod(detailUrl, h.route(urlNamePrefix+"detail").Method()) return panel, panelInfo, []string{editUrl, newUrl, deleteUrl, exportUrl, detailUrl, infoUrl, updateUrl}, nil } func (h *Handler) showTable(ctx *context.Context, prefix string, params parameter.Parameters, panel table.Table) *bytes.Buffer { panel, panelInfo, urls, err := h.showTableData(ctx, prefix, params, panel, "") if err != nil { return h.Execute(ctx, auth.Auth(ctx), template.WarningPanelWithDescAndTitle(ctx, err.Error(), errors.Msg, errors.Msg), "", template.ExecuteOptions{Animation: params.Animation}) } if panel.GetInfo().HasError() { if panel.GetInfo().PageErrorHTML != template2.HTML("") { return h.Execute(ctx, auth.Auth(ctx), types.Panel{Content: panel.GetInfo().PageErrorHTML}, "", template.ExecuteOptions{Animation: params.Animation}) } return h.Execute(ctx, auth.Auth(ctx), template.WarningPanel(ctx, panel.GetInfo().PageError.Error(), template.GetPageTypeFromPageError(panel.GetInfo().PageError)), "", template.ExecuteOptions{Animation: params.Animation}) } editUrl, newUrl, deleteUrl, exportUrl, detailUrl, infoUrl, updateUrl := urls[0], urls[1], urls[2], urls[3], urls[4], urls[5], urls[6] var ( actionJs template2.JS body template2.HTML dataTable types.DataTableAttribute user = auth.Auth(ctx) info = panel.GetInfo() actionBtns = info.Action allActionBtns = info.ActionButtons.CheckPermissionWhenURLAndMethodNotEmpty(user) ) hasExtAction := actionBtns == template.HTML("") && len(allActionBtns) > 0 hasAction := hasExtAction || (editUrl != "" || newUrl != "" || deleteUrl != "") if hasExtAction { if info.ActionButtonFold { ext := template2.HTML("") if deleteUrl != "" { ext = html.LiEl().SetClass("divider").Get() allActionBtns = append([]types.Button{types.GetActionButton(language.GetFromHtml("delete"), types.NewDefaultAction(`data-id='{{.Id}}' data-param='{{(index .Value "__goadmin_delete_params").Content}}' style="cursor: pointer;"`, ext, "", ""), "grid-row-delete")}, allActionBtns...) } ext = template2.HTML("") if detailUrl != "" { if editUrl == "" && deleteUrl == "" { ext = html.LiEl().SetClass("divider").Get() } allActionBtns = append([]types.Button{types.GetActionButton(language.GetFromHtml("detail"), action.Jump(detailUrl+"&"+constant.DetailPKKey+`={{.Id}}{{(index .Value "__goadmin_detail_params").Content}}`, ext))}, allActionBtns...) } if editUrl != "" { if detailUrl == "" && deleteUrl == "" { ext = html.LiEl().SetClass("divider").Get() } allActionBtns = append([]types.Button{types.GetActionButton(language.GetFromHtml("edit"), action.Jump(editUrl+"&"+constant.EditPKKey+`={{.Id}}{{(index .Value "__goadmin_edit_params").Content}}`, ext))}, allActionBtns...) } var content template2.HTML content, actionJs = allActionBtns.Content(ctx) actionBtns = html.Div(html.Div( html.A(icon.Icon(icon.EllipsisV), html.M{"color": "#676565"}, html.M{"href": "#"}, ), html.M{"cursor": "pointer", "width": "100%"}, html.M{"class": "dropdown-toggle", "data-toggle": "dropdown"})+ html.Ul(content, html.M{"min-width": "20px !important", "left": "-112px", "overflow": "hidden"}, html.M{"class": "dropdown-menu", "role": "menu", "aria-labelledby": "dLabel"}), html.M{"text-align": "center"}, html.M{"class": "dropdown"}) } else { actionBtns, actionJs = allActionBtns.Content(ctx) } } else { info.ActionButtonFold = false } btns, btnsJs := info.Buttons.CheckPermissionWhenURLAndMethodNotEmpty(user).Content(ctx) if info.TabGroups.Valid() { dataTable = aDataTable(ctx). SetThead(panelInfo.Thead). SetDeleteUrl(deleteUrl). SetNewUrl(newUrl). SetExportUrl(exportUrl) var ( tabsHtml = make([]map[string]template2.HTML, len(info.TabHeaders)) infoListArr = panelInfo.InfoList.GroupBy(info.TabGroups) theadArr = panelInfo.Thead.GroupBy(info.TabGroups) ) for key, header := range info.TabHeaders { tabsHtml[key] = map[string]template2.HTML{ "title": template2.HTML(header), "content": aDataTable(ctx). SetInfoList(infoListArr[key]). SetInfoUrl(infoUrl). SetButtons(btns). SetSticky(hasAction). SetActionJs(btnsJs + actionJs). SetHasFilter(len(panelInfo.FilterFormData) > 0). SetAction(actionBtns). SetActionFold(info.ActionButtonFold). SetIsTab(key != 0). SetPrimaryKey(panel.GetPrimaryKey().Name). SetThead(theadArr[key]). SetHideRowSelector(info.IsHideRowSelector). SetLayout(info.TableLayout). SetExportUrl(exportUrl). SetNewUrl(newUrl). SetSortUrl(params.GetFixedParamStrWithoutSort()). SetEditUrl(editUrl). SetUpdateUrl(updateUrl). SetDetailUrl(detailUrl). SetDeleteUrl(deleteUrl). GetContent(), } } body = aTab(ctx).SetData(tabsHtml).GetContent() } else { dataTable = aDataTable(ctx). SetInfoList(panelInfo.InfoList). SetInfoUrl(infoUrl). SetButtons(btns). SetSticky(hasAction). SetLayout(info.TableLayout). SetActionJs(btnsJs + actionJs). SetAction(actionBtns). SetHasFilter(len(panelInfo.FilterFormData) > 0). SetPrimaryKey(panel.GetPrimaryKey().Name). SetThead(panelInfo.Thead). SetExportUrl(exportUrl). SetActionFold(info.ActionButtonFold). SetHideRowSelector(info.IsHideRowSelector). SetHideFilterArea(info.IsHideFilterArea). SetNewUrl(newUrl). SetEditUrl(editUrl). SetSortUrl(params.GetFixedParamStrWithoutSort()). SetUpdateUrl(updateUrl). SetDetailUrl(detailUrl). SetDeleteUrl(deleteUrl) body = dataTable.GetContent() } isNotIframe := ctx.Query(constant.IframeKey) != "true" paginator := panelInfo.Paginator if !isNotIframe { paginator = paginator.SetEntriesInfo("") } boxModel := aBox(ctx). SetBody(body). SetStyle(template2.HTMLAttr(`overflow-x: auto;overflow-y: hidden;`)). SetNoPadding(). SetHeader(dataTable.GetDataTableHeader() + info.HeaderHtml). WithHeadBorder(). SetIframeStyle(!isNotIframe). SetFooter(paginator.GetContent() + info.FooterHtml + ` `) content := template2.HTML("") if len(panelInfo.FilterFormData) > 0 && info.FilterFormLayout == form2.LayoutFilter { filterBoxModel := aBox(ctx).SetClass("filter-area"). SetAttr(`style="padding-top: 20px;margin-top: -10px;margin-bottom: 12px;padding-left: 20px;display: block;padding-bottom: 5px;"`). SetStyle(`padding: 0px;`). SetBody(aForm(ctx). SetContent(panelInfo.FilterFormData). SetHorizontal(true). SetPrefix(h.config.PrefixFixSlash()). SetInputWidth(info.FilterFormInputWidth). SetHeadWidth(info.FilterFormHeadWidth). SetMethod("get"). SetLayout(info.FilterFormLayout). SetUrl(infoUrl). // + params.GetFixedParamStrWithoutColumnsAndPage() SetHiddenFields(map[string]string{ form.NoAnimationKey: "true", }). GetContent()) content = filterBoxModel.GetContent() + boxModel.GetContent() } else { if len(panelInfo.FilterFormData) > 0 { boxModel = boxModel.SetSecondHeaderClass("filter-area"). SetSecondHeader(aForm(ctx). SetContent(panelInfo.FilterFormData). SetPrefix(h.config.PrefixFixSlash()). SetInputWidth(info.FilterFormInputWidth). SetHeadWidth(info.FilterFormHeadWidth). SetMethod("get"). SetLayout(info.FilterFormLayout). SetUrl(infoUrl). // + params.GetFixedParamStrWithoutColumnsAndPage() SetHiddenFields(map[string]string{ form.NoAnimationKey: "true", }). SetOperationFooter(filterFormFooter(ctx, infoUrl)). GetContent()) } content = boxModel.GetContent() } if info.Wrapper != nil { content = info.Wrapper(content) } interval := make([]int, 0) autoRefresh := info.AutoRefresh != uint(0) if autoRefresh { interval = append(interval, int(info.AutoRefresh)) } return h.Execute(ctx, user, types.Panel{ Content: content, Description: template2.HTML(panelInfo.Description), Title: modules.AorBHTML(isNotIframe, template2.HTML(panelInfo.Title), ""), MiniSidebar: info.HideSideBar, AutoRefresh: autoRefresh, RefreshInterval: interval, }, "", template.ExecuteOptions{Animation: params.Animation, NoCompress: info.NoCompress}) } // Assets return front-end assets according the request path. func (h *Handler) Assets(ctx *context.Context) { filepath := h.config.URLRemovePrefix(ctx.Path()) theme := h.assetsTheme[filepath] if theme == "" { theme = h.config.Theme } data, err := aTemplateByTheme(ctx, theme).GetAsset(filepath) if err != nil { data, err = template.GetAsset(filepath) if err != nil { logger.ErrorCtx(ctx, "asset err %+v", err) ctx.Write(http.StatusNotFound, map[string]string{}, "") return } } var contentType = mime.TypeByExtension(path.Ext(filepath)) if contentType == "" { contentType = "application/octet-stream" } etag := fmt.Sprintf("%x", md5.Sum(data)) if match := ctx.Headers("If-None-Match"); match != "" { if strings.Contains(match, etag) { ctx.SetStatusCode(http.StatusNotModified) return } } ctx.DataWithHeaders(http.StatusOK, map[string]string{ "Content-Type": contentType, "Cache-Control": "max-age=2592000", "Content-Length": strconv.Itoa(len(data)), "ETag": etag, }, data) } // Export export table rows as excel object. func (h *Handler) Export(ctx *context.Context) { param := guard.GetExportParam(ctx) tableName := "Sheet1" prefix := ctx.Query(constant.PrefixKey) panel := h.table(prefix, ctx) f := excelize.NewFile() index := f.NewSheet(tableName) f.SetActiveSheet(index) var ( infoData table.PanelInfo fileName string err error tableInfo = panel.GetInfo() params parameter.Parameters ) if fn := panel.GetInfo().ExportProcessFn; fn != nil { params = parameter.GetParam(ctx.Request.URL, tableInfo.DefaultPageSize, tableInfo.SortField, tableInfo.GetSort()) p, err := fn(params.WithIsAll(param.IsAll)) if err != nil { response.Error(ctx, "export error") return } infoData.Thead = p.Thead infoData.InfoList = p.InfoList } else { if len(param.Id) == 0 { params = parameter.GetParam(ctx.Request.URL, tableInfo.DefaultPageSize, tableInfo.SortField, tableInfo.GetSort()) infoData, err = panel.GetData(ctx, params.WithIsAll(param.IsAll)) fileName = fmt.Sprintf("%s-%d-page-%s-pageSize-%s.xlsx", tableInfo.Title, time.Now().Unix(), params.Page, params.PageSize) } else { infoData, err = panel.GetDataWithIds(ctx, parameter.GetParam(ctx.Request.URL, tableInfo.DefaultPageSize, tableInfo.SortField, tableInfo.GetSort()).WithPKs(param.Id...)) fileName = fmt.Sprintf("%s-%d-id-%s.xlsx", tableInfo.Title, time.Now().Unix(), strings.Join(param.Id, "_")) } if err != nil { response.Error(ctx, "export error") return } } // TODO: support any numbers of fields. orders := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"} if len(infoData.Thead) > 26 { j := -1 for i := 0; i < len(infoData.Thead)-26; i++ { if i%26 == 0 { j++ } letter := orders[j] + orders[i%26] orders = append(orders, letter) } } columnIndex := 0 for _, head := range infoData.Thead { if !head.Hide { f.SetCellValue(tableName, orders[columnIndex]+"1", head.Head) columnIndex++ } } count := 2 for _, info := range infoData.InfoList { columnIndex = 0 for _, head := range infoData.Thead { if !head.Hide { if tableInfo.IsExportValue() { f.SetCellValue(tableName, orders[columnIndex]+strconv.Itoa(count), info[head.Field].Value) } else { f.SetCellValue(tableName, orders[columnIndex]+strconv.Itoa(count), info[head.Field].Content) } columnIndex++ } } count++ } buf, err := f.WriteToBuffer() if err != nil || buf == nil { response.Error(ctx, "export error") return } ctx.AddHeader("content-disposition", `attachment; filename=`+fileName) ctx.Data(200, "application/vnd.ms-excel", buf.Bytes()) } ================================================ FILE: plugins/admin/controller/system.go ================================================ package controller import ( "fmt" "html/template" "os" "runtime" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/system" "github.com/GoAdminGroup/go-admin/template/types" ) func (h *Handler) SystemInfo(ctx *context.Context) { size := types.Size(6, 6, 6) box1 := aBox(ctx). WithHeadBorder(). SetHeader("" + lg("application") + ""). SetBody(stripedTable(ctx, []map[string]types.InfoItem{ { "key": types.InfoItem{Content: lg("app_name")}, "value": types.InfoItem{Content: "GoAdmin"}, }, { "key": types.InfoItem{Content: lg("go_admin_version")}, "value": types.InfoItem{Content: template.HTML(system.Version())}, }, { "key": types.InfoItem{Content: lg("theme_name")}, "value": types.InfoItem{Content: template.HTML(aTemplate(ctx).Name())}, }, { "key": types.InfoItem{Content: lg("theme_version")}, "value": types.InfoItem{Content: template.HTML(aTemplate(ctx).GetVersion())}, }, })). GetContent() app := system.GetAppStatus() box2 := aBox(ctx). WithHeadBorder(). SetHeader("" + lg("application run") + ""). SetBody(stripedTable(ctx, []map[string]types.InfoItem{ { "key": types.InfoItem{Content: lg("current_heap_usage")}, "value": types.InfoItem{Content: template.HTML(app.HeapAlloc)}, }, { "key": types.InfoItem{Content: lg("heap_memory_obtained")}, "value": types.InfoItem{Content: template.HTML(app.HeapSys)}, }, { "key": types.InfoItem{Content: lg("heap_memory_idle")}, "value": types.InfoItem{Content: template.HTML(app.HeapIdle)}, }, { "key": types.InfoItem{Content: lg("heap_memory_in_use")}, "value": types.InfoItem{Content: template.HTML(app.HeapInuse)}, }, { "key": types.InfoItem{Content: lg("heap_memory_released")}, "value": types.InfoItem{Content: template.HTML(app.HeapReleased)}, }, { "key": types.InfoItem{Content: lg("heap_objects")}, "value": types.InfoItem{Content: itos(app.HeapObjects)}, }, }) + `

    ` + stripedTable(ctx, []map[string]types.InfoItem{ { "key": types.InfoItem{Content: lg("next_gc_recycle")}, "value": types.InfoItem{Content: template.HTML(app.NextGC)}, }, { "key": types.InfoItem{Content: lg("last_gc_time")}, "value": types.InfoItem{Content: template.HTML(app.LastGC)}, }, { "key": types.InfoItem{Content: lg("total_gc_pause")}, "value": types.InfoItem{Content: template.HTML(app.PauseTotalNs)}, }, { "key": types.InfoItem{Content: lg("last_gc_pause")}, "value": types.InfoItem{Content: template.HTML(app.PauseNs)}, }, { "key": types.InfoItem{Content: lg("gc_times")}, "value": types.InfoItem{Content: itos(app.NumGC)}, }, })). GetContent() col1 := aCol(ctx).SetSize(size).SetContent(box1 + box2).GetContent() box4 := aBox(ctx). WithHeadBorder(). SetHeader("" + lg("application run") + ""). SetBody(stripedTable(ctx, []map[string]types.InfoItem{ { "key": types.InfoItem{Content: lg("golang_version")}, "value": types.InfoItem{Content: template.HTML(runtime.Version())}, }, { "key": types.InfoItem{Content: lg("process_id")}, "value": types.InfoItem{Content: itos(os.Getpid())}, }, { "key": types.InfoItem{Content: lg("server_uptime")}, "value": types.InfoItem{Content: template.HTML(app.Uptime)}, }, { "key": types.InfoItem{Content: lg("current_goroutine")}, "value": types.InfoItem{Content: itos(app.NumGoroutine)}, }, }) + `

    ` + stripedTable(ctx, []map[string]types.InfoItem{ { "key": types.InfoItem{Content: lg("current_memory_usage")}, "value": types.InfoItem{Content: template.HTML(app.MemAllocated)}, }, { "key": types.InfoItem{Content: lg("total_memory_allocated")}, "value": types.InfoItem{Content: template.HTML(app.MemTotal)}, }, { "key": types.InfoItem{Content: lg("memory_obtained")}, "value": types.InfoItem{Content: itos(app.MemSys)}, }, { "key": types.InfoItem{Content: lg("pointer_lookup_times")}, "value": types.InfoItem{Content: itos(app.Lookups)}, }, { "key": types.InfoItem{Content: lg("memory_allocate_times")}, "value": types.InfoItem{Content: itos(app.MemMallocs)}, }, { "key": types.InfoItem{Content: lg("memory_free_times")}, "value": types.InfoItem{Content: itos(app.MemFrees)}, }, }) + `

    ` + stripedTable(ctx, []map[string]types.InfoItem{ { "key": types.InfoItem{Content: lg("bootstrap_stack_usage")}, "value": types.InfoItem{Content: template.HTML(app.StackInuse)}, }, { "key": types.InfoItem{Content: lg("stack_memory_obtained")}, "value": types.InfoItem{Content: template.HTML(app.StackSys)}, }, { "key": types.InfoItem{Content: lg("mspan_structures_usage")}, "value": types.InfoItem{Content: template.HTML(app.MSpanInuse)}, }, { "key": types.InfoItem{Content: lg("mspan_structures_obtained")}, "value": types.InfoItem{Content: template.HTML(app.HeapSys)}, }, { "key": types.InfoItem{Content: lg("mcache_structures_usage")}, "value": types.InfoItem{Content: template.HTML(app.MCacheInuse)}, }, { "key": types.InfoItem{Content: lg("mcache_structures_obtained")}, "value": types.InfoItem{Content: template.HTML(app.MCacheSys)}, }, { "key": types.InfoItem{Content: lg("profiling_bucket_hash_table_obtained")}, "value": types.InfoItem{Content: template.HTML(app.BuckHashSys)}, }, { "key": types.InfoItem{Content: lg("gc_metadata_obtained")}, "value": types.InfoItem{Content: template.HTML(app.GCSys)}, }, { "key": types.InfoItem{Content: lg("other_system_allocation_obtained")}, "value": types.InfoItem{Content: template.HTML(app.OtherSys)}, }, })). GetContent() col2 := aCol(ctx).SetSize(size).SetContent(box4).GetContent() row := aRow(ctx).SetContent(col1 + col2).GetContent() h.HTML(ctx, auth.Auth(ctx), types.Panel{ Content: row, Description: language.GetFromHtml("site info", "system"), Title: language.GetFromHtml("site info", "system"), }) } func stripedTable(ctx *context.Context, list []map[string]types.InfoItem) template.HTML { return aTable(ctx). SetStyle("striped"). SetHideThead(). SetMinWidth("0.01%"). SetThead(types.Thead{ types.TheadItem{Head: "key", Width: "50%"}, types.TheadItem{Head: "value"}, }). SetInfoList(list).GetContent() } func lg(v template.HTML) template.HTML { return language.GetFromHtml(v, "system") } func itos(i interface{}) template.HTML { return template.HTML(fmt.Sprintf("%v", i)) } ================================================ FILE: plugins/admin/data/mysql/admin.sql ================================================ # ************************************************************ # Sequel Pro SQL dump # Version 4468 # # http://www.sequelpro.com/ # https://github.com/sequelpro/sequelpro # # Host: 127.0.0.1 (MySQL 5.7.19) # Database: godmin # Generation Time: 2019-09-12 04:16:47 +0000 # ************************************************************ /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; # Dump of table goadmin_menu # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_menu`; CREATE TABLE `goadmin_menu` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `parent_id` int(11) unsigned NOT NULL DEFAULT '0', `type` tinyint(4) unsigned NOT NULL DEFAULT '0', `order` int(11) unsigned NOT NULL DEFAULT '0', `title` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `icon` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `uri` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `header` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_menu` WRITE; /*!40000 ALTER TABLE `goadmin_menu` DISABLE KEYS */; INSERT INTO `goadmin_menu` (`id`, `parent_id`, `type`, `order`, `title`, `icon`, `uri`, `header`, `created_at`, `updated_at`) VALUES (1,0,1,2,'Admin','fa-tasks','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,1,1,2,'Users','fa-users','/info/manager',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (3,1,1,3,'Roles','fa-user','/info/roles',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (4,1,1,4,'Permission','fa-ban','/info/permission',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (5,1,1,5,'Menu','fa-bars','/menu',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (6,1,1,6,'Operation log','fa-history','/info/op',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (7,0,1,1,'Dashboard','fa-bar-chart','/',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_menu` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_operation_log # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_operation_log`; CREATE TABLE `goadmin_operation_log` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(11) unsigned NOT NULL, `path` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `method` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL, `ip` varchar(15) COLLATE utf8mb4_unicode_ci NOT NULL, `input` text COLLATE utf8mb4_unicode_ci NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `admin_operation_log_user_id_index` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; # Dump of table goadmin_permissions # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_permissions`; CREATE TABLE `goadmin_permissions` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `slug` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `http_method` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `http_path` text COLLATE utf8mb4_unicode_ci NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `admin_permissions_name_unique` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_permissions` WRITE; /*!40000 ALTER TABLE `goadmin_permissions` DISABLE KEYS */; INSERT INTO `goadmin_permissions` (`id`, `name`, `slug`, `http_method`, `http_path`, `created_at`, `updated_at`) VALUES (1,'All permission','*','','*','2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,'Dashboard','dashboard','GET,PUT,POST,DELETE','/','2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_permissions` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_role_menu # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_role_menu`; CREATE TABLE `goadmin_role_menu` ( `role_id` int(11) unsigned NOT NULL, `menu_id` int(11) unsigned NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, KEY `admin_role_menu_role_id_menu_id_index` (`role_id`,`menu_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_role_menu` WRITE; /*!40000 ALTER TABLE `goadmin_role_menu` DISABLE KEYS */; INSERT INTO `goadmin_role_menu` (`role_id`, `menu_id`, `created_at`, `updated_at`) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (1,7,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,7,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (1,8,'2019-09-11 10:20:55','2019-09-11 10:20:55'), (2,8,'2019-09-11 10:20:55','2019-09-11 10:20:55'); /*!40000 ALTER TABLE `goadmin_role_menu` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_role_permissions # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_role_permissions`; CREATE TABLE `goadmin_role_permissions` ( `role_id` int(11) unsigned NOT NULL, `permission_id` int(11) unsigned NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `admin_role_permissions` (`role_id`,`permission_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_role_permissions` WRITE; /*!40000 ALTER TABLE `goadmin_role_permissions` DISABLE KEYS */; INSERT INTO `goadmin_role_permissions` (`role_id`, `permission_id`, `created_at`, `updated_at`) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (1,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_role_permissions` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_role_users # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_role_users`; CREATE TABLE `goadmin_role_users` ( `role_id` int(11) unsigned NOT NULL, `user_id` int(11) unsigned NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `admin_user_roles` (`role_id`,`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_role_users` WRITE; /*!40000 ALTER TABLE `goadmin_role_users` DISABLE KEYS */; INSERT INTO `goadmin_role_users` (`role_id`, `user_id`, `created_at`, `updated_at`) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_role_users` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_roles # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_roles`; CREATE TABLE `goadmin_roles` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `slug` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `admin_roles_name_unique` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_roles` WRITE; /*!40000 ALTER TABLE `goadmin_roles` DISABLE KEYS */; INSERT INTO `goadmin_roles` (`id`, `name`, `slug`, `created_at`, `updated_at`) VALUES (1,'Administrator','administrator','2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,'Operator','operator','2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_roles` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_session # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_session`; CREATE TABLE `goadmin_session` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `sid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `values` varchar(3000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; # Dump of table goadmin_user_permissions # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_user_permissions`; CREATE TABLE `goadmin_user_permissions` ( `user_id` int(11) unsigned NOT NULL, `permission_id` int(11) unsigned NOT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `admin_user_permissions` (`user_id`,`permission_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_user_permissions` WRITE; /*!40000 ALTER TABLE `goadmin_user_permissions` DISABLE KEYS */; INSERT INTO `goadmin_user_permissions` (`user_id`, `permission_id`, `created_at`, `updated_at`) VALUES (1,1,'2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,2,'2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_user_permissions` ENABLE KEYS */; UNLOCK TABLES; # Dump of table goadmin_users # ------------------------------------------------------------ DROP TABLE IF EXISTS `goadmin_users`; CREATE TABLE `goadmin_users` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL, `password` varchar(80) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `avatar` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `admin_users_username_unique` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; LOCK TABLES `goadmin_users` WRITE; /*!40000 ALTER TABLE `goadmin_users` DISABLE KEYS */; INSERT INTO `goadmin_users` (`id`, `username`, `password`, `name`, `avatar`, `remember_token`, `created_at`, `updated_at`) VALUES (1,'admin','$2a$10$U3F/NSaf2kaVbyXTBp7ppOn0jZFyRqXRnYXB.AMioCjXl3Ciaj4oy','admin','','tlNcBVK9AvfYH7WEnwB1RKvocJu8FfRy4um3DJtwdHuJy0dwFsLOgAc0xUfh','2019-09-10 00:00:00','2019-09-10 00:00:00'), (2,'operator','$2a$10$rVqkOzHjN2MdlEprRflb1eGP0oZXuSrbJLOmJagFsCd81YZm0bsh.','Operator','',NULL,'2019-09-10 00:00:00','2019-09-10 00:00:00'); /*!40000 ALTER TABLE `goadmin_users` ENABLE KEYS */; UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; ================================================ FILE: plugins/admin/models/base.go ================================================ package models import ( "database/sql" "github.com/GoAdminGroup/go-admin/modules/db" ) // Base is base model structure. type Base struct { TableName string Conn db.Connection Tx *sql.Tx } func (b Base) SetConn(con db.Connection) Base { b.Conn = con return b } func (b Base) Table(table string) *db.SQL { return db.Table(table).WithDriver(b.Conn) } ================================================ FILE: plugins/admin/models/menu.go ================================================ package models import ( "encoding/json" "strconv" "time" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/db/dialect" ) // MenuModel is menu model structure. type MenuModel struct { Base Id int64 Title string ParentId int64 Icon string Uri string Header string CreatedAt string UpdatedAt string } // Menu return a default menu model. func Menu() MenuModel { return MenuModel{Base: Base{TableName: "goadmin_menu"}} } // MenuWithId return a default menu model of given id. func MenuWithId(id string) MenuModel { idInt, _ := strconv.Atoi(id) return MenuModel{Base: Base{TableName: "goadmin_menu"}, Id: int64(idInt)} } func (t MenuModel) SetConn(con db.Connection) MenuModel { t.Conn = con return t } // Find return a default menu model of given id. func (t MenuModel) Find(id interface{}) MenuModel { item, _ := t.Table(t.TableName).Find(id) return t.MapToModel(item) } // New create a new menu model. func (t MenuModel) New(title, icon, uri, header, pluginName string, parentId, order int64) (MenuModel, error) { id, err := t.Table(t.TableName).Insert(dialect.H{ "title": title, "parent_id": parentId, "icon": icon, "uri": uri, "order": order, "header": header, "plugin_name": pluginName, }) t.Id = id t.Title = title t.ParentId = parentId t.Icon = icon t.Uri = uri t.Header = header return t, err } // Delete delete the menu model. func (t MenuModel) Delete() { _ = t.Table(t.TableName).Where("id", "=", t.Id).Delete() _ = t.Table("goadmin_role_menu").Where("menu_id", "=", t.Id).Delete() items, _ := t.Table(t.TableName).Where("parent_id", "=", t.Id).All() if len(items) > 0 { ids := make([]interface{}, len(items)) for i := 0; i < len(ids); i++ { ids[i] = items[i]["id"] } _ = t.Table("goadmin_role_menu").WhereIn("menu_id", ids).Delete() } _ = t.Table(t.TableName).Where("parent_id", "=", t.Id).Delete() } // Update update the menu model. func (t MenuModel) Update(title, icon, uri, header, pluginName string, parentId int64) (int64, error) { return t.Table(t.TableName). Where("id", "=", t.Id). Update(dialect.H{ "title": title, "parent_id": parentId, "icon": icon, "plugin_name": pluginName, "uri": uri, "header": header, "updated_at": time.Now().Format("2006-01-02 15:04:05"), }) } type OrderItems []OrderItem type OrderItem struct { ID uint `json:"id"` Children OrderItems `json:"children"` } // ResetOrder update the order of menu models. func (t MenuModel) ResetOrder(data []byte) { var items OrderItems _ = json.Unmarshal(data, &items) count := 1 for _, v := range items { if len(v.Children) > 0 { _, _ = t.Table(t.TableName). Where("id", "=", v.ID). Update(dialect.H{ "order": count, "parent_id": 0, }) for _, v2 := range v.Children { if len(v2.Children) > 0 { _, _ = t.Table(t.TableName). Where("id", "=", v2.ID). Update(dialect.H{ "order": count, "parent_id": v.ID, }) for _, v3 := range v2.Children { _, _ = t.Table(t.TableName). Where("id", "=", v3.ID). Update(dialect.H{ "order": count, "parent_id": v2.ID, }) count++ } } else { _, _ = t.Table(t.TableName). Where("id", "=", v2.ID). Update(dialect.H{ "order": count, "parent_id": v.ID, }) count++ } } } else { _, _ = t.Table(t.TableName). Where("id", "=", v.ID). Update(dialect.H{ "order": count, "parent_id": 0, }) count++ } } } // CheckRole check the role if has permission to get the menu. func (t MenuModel) CheckRole(roleId string) bool { checkRole, _ := t.Table("goadmin_role_menu"). Where("role_id", "=", roleId). Where("menu_id", "=", t.Id). First() return checkRole != nil } // AddRole add a role to the menu. func (t MenuModel) AddRole(roleId string) (int64, error) { if roleId != "" { if !t.CheckRole(roleId) { return t.Table("goadmin_role_menu"). Insert(dialect.H{ "role_id": roleId, "menu_id": t.Id, }) } } return 0, nil } // DeleteRoles delete roles with menu. func (t MenuModel) DeleteRoles() error { return t.Table("goadmin_role_menu"). Where("menu_id", "=", t.Id). Delete() } // MapToModel get the menu model from given map. func (t MenuModel) MapToModel(m map[string]interface{}) MenuModel { t.Id = m["id"].(int64) t.Title, _ = m["title"].(string) t.ParentId = m["parent_id"].(int64) t.Icon, _ = m["icon"].(string) t.Uri, _ = m["uri"].(string) t.Header, _ = m["header"].(string) t.CreatedAt, _ = m["created_at"].(string) t.UpdatedAt, _ = m["updated_at"].(string) return t } ================================================ FILE: plugins/admin/models/operation_log.go ================================================ package models import ( "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/db/dialect" ) // OperationLogModel is operation log model structure. type OperationLogModel struct { Base Id int64 UserId int64 Path string Method string Ip string Input string CreatedAt string UpdatedAt string } // OperationLog return a default operation log model. func OperationLog() OperationLogModel { return OperationLogModel{Base: Base{TableName: "goadmin_operation_log"}} } // Find return a default operation log model of given id. func (t OperationLogModel) Find(id interface{}) OperationLogModel { item, _ := t.Table(t.TableName).Find(id) return t.MapToModel(item) } func (t OperationLogModel) SetConn(con db.Connection) OperationLogModel { t.Conn = con return t } // New create a new operation log model. func (t OperationLogModel) New(userId int64, path, method, ip, input string) OperationLogModel { id, _ := t.Table(t.TableName).Insert(dialect.H{ "user_id": userId, "path": path, "method": method, "ip": ip, "input": input, }) t.Id = id t.UserId = userId t.Path = path t.Method = method t.Ip = ip t.Input = input return t } // MapToModel get the operation log model from given map. func (t OperationLogModel) MapToModel(m map[string]interface{}) OperationLogModel { t.Id = m["id"].(int64) t.UserId = m["user_id"].(int64) t.Path, _ = m["path"].(string) t.Method, _ = m["method"].(string) t.Ip, _ = m["ip"].(string) t.Input, _ = m["input"].(string) t.CreatedAt, _ = m["created_at"].(string) t.UpdatedAt, _ = m["updated_at"].(string) return t } ================================================ FILE: plugins/admin/models/permission.go ================================================ package models import ( "strconv" "strings" "github.com/GoAdminGroup/go-admin/modules/db" ) // PermissionModel is permission model structure. type PermissionModel struct { Base Id int64 Name string Slug string HttpMethod []string HttpPath []string CreatedAt string UpdatedAt string } // Permission return a default permission model. func Permission() PermissionModel { return PermissionModel{Base: Base{TableName: "goadmin_permissions"}} } // PermissionWithId return a default permission model of given id. func PermissionWithId(id string) PermissionModel { idInt, _ := strconv.Atoi(id) return PermissionModel{Base: Base{TableName: "goadmin_permissions"}, Id: int64(idInt)} } func (t PermissionModel) SetConn(con db.Connection) PermissionModel { t.Conn = con return t } // IsEmpty check the user model is empty or not. func (t PermissionModel) IsEmpty() bool { return t.Id == int64(0) } // IsSlugExist check the row exist with given slug and id. func (t PermissionModel) IsSlugExist(slug string, id string) bool { if id == "" { check, _ := t.Table(t.TableName).Where("slug", "=", slug).First() return check != nil } check, _ := t.Table(t.TableName). Where("slug", "=", slug). Where("id", "!=", id). First() return check != nil } // Find return the permission model of given id. func (t PermissionModel) Find(id interface{}) PermissionModel { item, _ := t.Table(t.TableName).Find(id) return t.MapToModel(item) } // FindBySlug return the permission model of given slug. func (t PermissionModel) FindBySlug(slug string) PermissionModel { item, _ := t.Table(t.TableName).Where("slug", "=", slug).First() return t.MapToModel(item) } // FindBySlug return the permission model of given slug. func (t PermissionModel) FindByName(name string) PermissionModel { item, _ := t.Table(t.TableName).Where("name", "=", name).First() return t.MapToModel(item) } // MapToModel get the permission model from given map. func (t PermissionModel) MapToModel(m map[string]interface{}) PermissionModel { t.Id = m["id"].(int64) t.Name, _ = m["name"].(string) t.Slug, _ = m["slug"].(string) methods, _ := m["http_method"].(string) if methods != "" { t.HttpMethod = strings.Split(methods, ",") } else { t.HttpMethod = []string{""} } path, _ := m["http_path"].(string) t.HttpPath = strings.Split(path, "\n") t.CreatedAt, _ = m["created_at"].(string) t.UpdatedAt, _ = m["updated_at"].(string) return t } ================================================ FILE: plugins/admin/models/role.go ================================================ package models import ( "database/sql" "strconv" "time" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/db/dialect" ) // RoleModel is role model structure. type RoleModel struct { Base Id int64 Name string Slug string CreatedAt string UpdatedAt string } // Role return a default role model. func Role() RoleModel { return RoleModel{Base: Base{TableName: "goadmin_roles"}} } // RoleWithId return a default role model of given id. func RoleWithId(id string) RoleModel { idInt, _ := strconv.Atoi(id) return RoleModel{Base: Base{TableName: "goadmin_roles"}, Id: int64(idInt)} } func (t RoleModel) SetConn(con db.Connection) RoleModel { t.Conn = con return t } func (t RoleModel) WithTx(tx *sql.Tx) RoleModel { t.Tx = tx return t } // Find return a default role model of given id. func (t RoleModel) Find(id interface{}) RoleModel { item, _ := t.Table(t.TableName).Find(id) return t.MapToModel(item) } // IsSlugExist check the row exist with given slug and id. func (t RoleModel) IsSlugExist(slug string, id string) bool { if id == "" { check, _ := t.Table(t.TableName).Where("slug", "=", slug).First() return check != nil } check, _ := t.Table(t.TableName). Where("slug", "=", slug). Where("id", "!=", id). First() return check != nil } // New create a role model. func (t RoleModel) New(name, slug string) (RoleModel, error) { id, err := t.WithTx(t.Tx).Table(t.TableName).Insert(dialect.H{ "name": name, "slug": slug, }) t.Id = id t.Name = name t.Slug = slug return t, err } // Update update the role model. func (t RoleModel) Update(name, slug string) (int64, error) { return t.WithTx(t.Tx).Table(t.TableName). Where("id", "=", t.Id). Update(dialect.H{ "name": name, "slug": slug, "updated_at": time.Now().Format("2006-01-02 15:04:05"), }) } // CheckPermission check the permission of role. func (t RoleModel) CheckPermission(permissionId string) bool { checkPermission, _ := t.Table("goadmin_role_permissions"). Where("permission_id", "=", permissionId). Where("role_id", "=", t.Id). First() return checkPermission != nil } // DeletePermissions delete all the permissions of role. func (t RoleModel) DeletePermissions() error { return t.WithTx(t.Tx).Table("goadmin_role_permissions"). Where("role_id", "=", t.Id). Delete() } // AddPermission add the permissions to the role. func (t RoleModel) AddPermission(permissionId string) (int64, error) { if permissionId != "" { if !t.CheckPermission(permissionId) { return t.WithTx(t.Tx).Table("goadmin_role_permissions"). Insert(dialect.H{ "permission_id": permissionId, "role_id": t.Id, }) } } return 0, nil } // MapToModel get the role model from given map. func (t RoleModel) MapToModel(m map[string]interface{}) RoleModel { t.Id = m["id"].(int64) t.Name, _ = m["name"].(string) t.Slug, _ = m["slug"].(string) t.CreatedAt, _ = m["created_at"].(string) t.UpdatedAt, _ = m["updated_at"].(string) return t } ================================================ FILE: plugins/admin/models/site.go ================================================ package models import ( "database/sql" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/modules/collection" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/db/dialect" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" ) // SiteModel is role model structure. type SiteModel struct { Base Id int64 Key string Value string Desc string State int64 CreatedAt string UpdatedAt string } const ( SiteItemOpenState = 1 SiteItemOffState = 0 ) // Site return a default role model. func Site() SiteModel { return SiteModel{Base: Base{TableName: "goadmin_site"}} } func (t SiteModel) SetConn(con db.Connection) SiteModel { t.Conn = con return t } func (t SiteModel) WithTx(tx *sql.Tx) SiteModel { t.Tx = tx return t } func (t SiteModel) Init(cfg map[string]string) SiteModel { items, err := t.Table(t.TableName).All() if db.CheckError(err, db.QUERY) { panic(err) } itemsCol := collection.Collection(items) for key, value := range cfg { row := itemsCol.Where("key", "=", key) if row.Length() == 0 { _, err := t.Table(t.TableName).Insert(dialect.H{ "key": key, "value": value, "state": SiteItemOpenState, }) if db.CheckError(err, db.INSERT) { panic(err) } } //else { // if value != "" { // _, err := t.Table(t.TableName). // Where("key", "=", key).Update(dialect.H{ // "value": value, // }) // if db.CheckError(err, db.UPDATE) { // panic(err) // } // } //} } return t } func (t SiteModel) AllToMap() map[string]string { var m = make(map[string]string) items, err := t.Table(t.TableName).Where("state", "=", SiteItemOpenState).All() if db.CheckError(err, db.QUERY) { return m } for _, item := range items { m[item["key"].(string)] = item["value"].(string) } return m } func (t SiteModel) AllToMapInterface() map[string]interface{} { var m = make(map[string]interface{}) items, err := t.Table(t.TableName).Where("state", "=", SiteItemOpenState).All() if db.CheckError(err, db.QUERY) { return m } for _, item := range items { m[item["key"].(string)] = item["value"] } m["id"] = "1" return m } var allowEmptyKeys = []string{ "animation_type", "custom_head_html", "custom_foot_html", "custom_404_html", "custom_403_html", "custom_500_html", "footer_info", "bootstrap_file_path", "info_log_path", "error_log_path", "access_log_path", "asset_url", "extra", "domain", } func (t SiteModel) Update(v form.Values) error { for key, vv := range v { if len(vv) > 0 && (vv[0] != "" || utils.InArray(allowEmptyKeys, key)) { _, err := t.Table(t.TableName).Where("key", "=", key).Update(dialect.H{ "value": vv[0], }) if db.CheckError(err, db.UPDATE) { return err } } } return nil } ================================================ FILE: plugins/admin/models/user.go ================================================ package models import ( "database/sql" "net/url" "regexp" "strconv" "strings" "time" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/db/dialect" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" ) // UserModel is user model structure. type UserModel struct { Base `json:"-"` Id int64 `json:"id"` Name string `json:"name"` UserName string `json:"user_name"` Password string `json:"password"` Avatar string `json:"avatar"` RememberToken string `json:"remember_token"` Permissions []PermissionModel `json:"permissions"` MenuIds []int64 `json:"menu_ids"` Roles []RoleModel `json:"role"` Level string `json:"level"` LevelName string `json:"level_name"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` cacheReplacer *strings.Replacer } // User return a default user model. func User() UserModel { return UserModel{Base: Base{TableName: config.GetAuthUserTable()}} } // UserWithId return a default user model of given id. func UserWithId(id string) UserModel { idInt, _ := strconv.Atoi(id) return UserModel{Base: Base{TableName: config.GetAuthUserTable()}, Id: int64(idInt)} } func (t UserModel) SetConn(con db.Connection) UserModel { t.Conn = con return t } func (t UserModel) WithTx(tx *sql.Tx) UserModel { t.Tx = tx return t } // Find return a default user model of given id. func (t UserModel) Find(id interface{}) UserModel { item, _ := t.Table(t.TableName).Find(id) return t.MapToModel(item) } // FindByUserName return a default user model of given name. func (t UserModel) FindByUserName(username interface{}) UserModel { item, _ := t.Table(t.TableName).Where("username", "=", username).First() return t.MapToModel(item) } // IsEmpty check the user model is empty or not. func (t UserModel) IsEmpty() bool { return t.Id == int64(0) } // HasMenu check the user has visitable menu or not. func (t UserModel) HasMenu() bool { return len(t.MenuIds) != 0 || t.IsSuperAdmin() } // IsSuperAdmin check the user model is super admin or not. func (t UserModel) IsSuperAdmin() bool { for _, per := range t.Permissions { if len(per.HttpPath) > 0 && per.HttpPath[0] == "*" && per.HttpMethod[0] == "" { return true } } return false } func (t UserModel) GetCheckPermissionByUrlMethod(path, method string) string { if !t.CheckPermissionByUrlMethod(path, method, url.Values{}) { return "" } return path } func (t UserModel) IsVisitor() bool { return !t.CheckPermissionByUrlMethod(config.Url("/info/normal_manager"), "GET", url.Values{}) } func (t UserModel) HideUserCenterEntrance() bool { return t.IsVisitor() && config.GetHideVisitorUserCenterEntrance() } func (t UserModel) Template(str string) string { if t.cacheReplacer == nil { t.cacheReplacer = strings.NewReplacer("{{.AuthId}}", strconv.Itoa(int(t.Id)), "{{.AuthName}}", t.Name, "{{.AuthUserName}}", t.UserName) } return t.cacheReplacer.Replace(str) } func (t UserModel) CheckPermissionByUrlMethod(path, method string, formParams url.Values) bool { // path, _ = url.PathUnescape(path) if t.IsSuperAdmin() { return true } if path == "" { return false } logoutCheck, _ := regexp.Compile(config.Url("/logout") + "(.*?)") if logoutCheck.MatchString(path) { return true } if path != "/" && path[len(path)-1] == '/' { path = path[:len(path)-1] } path = utils.ReplaceAll(path, constant.EditPKKey, "id", constant.DetailPKKey, "id") path, params := getParam(path) for key, value := range formParams { if len(value) > 0 { params.Add(key, value[0]) } } for _, v := range t.Permissions { if v.HttpMethod[0] == "" || inMethodArr(v.HttpMethod, method) { if v.HttpPath[0] == "*" { return true } for i := 0; i < len(v.HttpPath); i++ { matchPath := config.Url(t.Template(strings.TrimSpace(v.HttpPath[i]))) matchPath, matchParam := getParam(matchPath) if matchPath == path { if t.checkParam(params, matchParam) { return true } } reg, err := regexp.Compile(matchPath) if err != nil { logger.Error("CheckPermissions error: ", err) continue } if reg.FindString(path) == path { if t.checkParam(params, matchParam) { return true } } } } } return false } func getParam(u string) (string, url.Values) { m := make(url.Values) urr := strings.Split(u, "?") if len(urr) > 1 { m, _ = url.ParseQuery(urr[1]) } return urr[0], m } func (t UserModel) checkParam(src, comp url.Values) bool { if len(comp) == 0 { return true } if len(src) == 0 { return false } for key, value := range comp { v, find := src[key] if !find { return false } if len(value) == 0 { continue } if len(v) == 0 { return false } for i := 0; i < len(v); i++ { if v[i] == t.Template(value[i]) { continue } else { return false } } } return true } func inMethodArr(arr []string, str string) bool { for i := 0; i < len(arr); i++ { if strings.EqualFold(arr[i], str) { return true } } return false } // UpdateAvatar update the avatar of user. func (t UserModel) ReleaseConn() UserModel { t.Conn = nil return t } // UpdateAvatar update the avatar of user. func (t UserModel) UpdateAvatar(avatar string) { t.Avatar = avatar } // WithRoles query the role info of the user. func (t UserModel) WithRoles() UserModel { roleModel, _ := t.Table("goadmin_role_users"). LeftJoin("goadmin_roles", "goadmin_roles.id", "=", "goadmin_role_users.role_id"). Where("user_id", "=", t.Id). Select("goadmin_roles.id", "goadmin_roles.name", "goadmin_roles.slug", "goadmin_roles.created_at", "goadmin_roles.updated_at"). All() for _, role := range roleModel { t.Roles = append(t.Roles, Role().MapToModel(role)) } if len(t.Roles) > 0 { t.Level = t.Roles[0].Slug t.LevelName = t.Roles[0].Name } return t } func (t UserModel) GetAllRoleId() []interface{} { var ids = make([]interface{}, len(t.Roles)) for key, role := range t.Roles { ids[key] = role.Id } return ids } // WithPermissions query the permission info of the user. func (t UserModel) WithPermissions() UserModel { var permissions = make([]map[string]interface{}, 0) roleIds := t.GetAllRoleId() if len(roleIds) > 0 { permissions, _ = t.Table("goadmin_role_permissions"). LeftJoin("goadmin_permissions", "goadmin_permissions.id", "=", "goadmin_role_permissions.permission_id"). WhereIn("role_id", roleIds). Select("goadmin_permissions.http_method", "goadmin_permissions.http_path", "goadmin_permissions.id", "goadmin_permissions.name", "goadmin_permissions.slug", "goadmin_permissions.created_at", "goadmin_permissions.updated_at"). All() } userPermissions, _ := t.Table("goadmin_user_permissions"). LeftJoin("goadmin_permissions", "goadmin_permissions.id", "=", "goadmin_user_permissions.permission_id"). Where("user_id", "=", t.Id). Select("goadmin_permissions.http_method", "goadmin_permissions.http_path", "goadmin_permissions.id", "goadmin_permissions.name", "goadmin_permissions.slug", "goadmin_permissions.created_at", "goadmin_permissions.updated_at"). All() permissions = append(permissions, userPermissions...) for i := 0; i < len(permissions); i++ { exist := false for j := 0; j < len(t.Permissions); j++ { if t.Permissions[j].Id == permissions[i]["id"] { exist = true break } } if exist { continue } t.Permissions = append(t.Permissions, Permission().MapToModel(permissions[i])) } return t } // WithMenus query the menu info of the user. func (t UserModel) WithMenus() UserModel { var menuIdsModel []map[string]interface{} if t.IsSuperAdmin() { menuIdsModel, _ = t.Table("goadmin_role_menu"). LeftJoin("goadmin_menu", "goadmin_menu.id", "=", "goadmin_role_menu.menu_id"). Select("menu_id", "parent_id"). All() } else { rolesId := t.GetAllRoleId() if len(rolesId) > 0 { menuIdsModel, _ = t.Table("goadmin_role_menu"). LeftJoin("goadmin_menu", "goadmin_menu.id", "=", "goadmin_role_menu.menu_id"). WhereIn("goadmin_role_menu.role_id", rolesId). Select("menu_id", "parent_id"). All() } } var menuIds []int64 for _, mid := range menuIdsModel { if parentId, ok := mid["parent_id"].(int64); ok && parentId != 0 { for _, mid2 := range menuIdsModel { if mid2["menu_id"].(int64) == mid["parent_id"].(int64) { menuIds = append(menuIds, mid["menu_id"].(int64)) break } } } else { menuIds = append(menuIds, mid["menu_id"].(int64)) } } t.MenuIds = menuIds return t } // New create a user model. func (t UserModel) New(username, password, name, avatar string) (UserModel, error) { id, err := t.WithTx(t.Tx).Table(t.TableName).Insert(dialect.H{ "username": username, "password": password, "name": name, "avatar": avatar, }) t.Id = id t.UserName = username t.Password = password t.Avatar = avatar t.Name = name return t, err } // Update update the user model. func (t UserModel) Update(username, password, name, avatar string, isUpdateAvatar bool) (int64, error) { fieldValues := dialect.H{ "username": username, "name": name, "updated_at": time.Now().Format("2006-01-02 15:04:05"), } if avatar == "" || isUpdateAvatar { fieldValues["avatar"] = avatar } if password != "" { fieldValues["password"] = password } return t.WithTx(t.Tx).Table(t.TableName). Where("id", "=", t.Id). Update(fieldValues) } // UpdatePwd update the password of the user model. func (t UserModel) UpdatePwd(password string) UserModel { _, _ = t.Table(t.TableName). Where("id", "=", t.Id). Update(dialect.H{ "password": password, }) t.Password = password return t } // CheckRole check the role of the user model. func (t UserModel) CheckRoleId(roleId string) bool { checkRole, _ := t.Table("goadmin_role_users"). Where("role_id", "=", roleId). Where("user_id", "=", t.Id). First() return checkRole != nil } // DeleteRoles delete all the roles of the user model. func (t UserModel) DeleteRoles() error { return t.Table("goadmin_role_users"). Where("user_id", "=", t.Id). Delete() } // AddRole add a role of the user model. func (t UserModel) AddRole(roleId string) (int64, error) { if roleId != "" { if !t.CheckRoleId(roleId) { return t.WithTx(t.Tx).Table("goadmin_role_users"). Insert(dialect.H{ "role_id": roleId, "user_id": t.Id, }) } } return 0, nil } // CheckRole check the role of the user. func (t UserModel) CheckRole(slug string) bool { for _, role := range t.Roles { if role.Slug == slug { return true } } return false } // CheckPermission check the permission of the user. func (t UserModel) CheckPermissionById(permissionId string) bool { checkPermission, _ := t.Table("goadmin_user_permissions"). Where("permission_id", "=", permissionId). Where("user_id", "=", t.Id). First() return checkPermission != nil } // CheckPermission check the permission of the user. func (t UserModel) CheckPermission(permission string) bool { for _, per := range t.Permissions { if per.Slug == permission { return true } } return false } // DeletePermissions delete all the permissions of the user model. func (t UserModel) DeletePermissions() error { return t.WithTx(t.Tx).Table("goadmin_user_permissions"). Where("user_id", "=", t.Id). Delete() } // AddPermission add a permission of the user model. func (t UserModel) AddPermission(permissionId string) (int64, error) { if permissionId != "" { if !t.CheckPermissionById(permissionId) { return t.WithTx(t.Tx).Table("goadmin_user_permissions"). Insert(dialect.H{ "permission_id": permissionId, "user_id": t.Id, }) } } return 0, nil } // MapToModel get the user model from given map. func (t UserModel) MapToModel(m map[string]interface{}) UserModel { t.Id, _ = m["id"].(int64) t.Name, _ = m["name"].(string) t.UserName, _ = m["username"].(string) t.Password, _ = m["password"].(string) t.Avatar, _ = m["avatar"].(string) t.RememberToken, _ = m["remember_token"].(string) t.CreatedAt, _ = m["created_at"].(string) t.UpdatedAt, _ = m["updated_at"].(string) return t } ================================================ FILE: plugins/admin/modules/captcha/captcha.go ================================================ package captcha type Captcha interface { Validate(token string) bool } var List = make(map[string]Captcha) func Add(key string, captcha Captcha) { if _, exist := List[key]; exist { panic("captcha exist") } List[key] = captcha } func Get(key string) (Captcha, bool) { captcha, ok := List[key] return captcha, ok } ================================================ FILE: plugins/admin/modules/constant/constant.go ================================================ package constant import ( "github.com/GoAdminGroup/go-admin/modules/constant" ) const ( // PjaxHeader is default pjax http header key. PjaxHeader = constant.PjaxHeader // PjaxUrlHeader is default pjax url http header key. PjaxUrlHeader = constant.PjaxUrlHeader EditPKKey = "__goadmin_edit_pk" DetailPKKey = "__goadmin_detail_pk" PrefixKey = "__prefix" IframeKey = "__goadmin_iframe" IframeIDKey = "__goadmin_iframe_id" ContextNodeNeedAuth = constant.ContextNodeNeedAuth ) ================================================ FILE: plugins/admin/modules/form/form.go ================================================ package form import ( "errors" ) const ( PostTypeKey = "__go_admin_post_type" PostResultKey = "__go_admin_post_result" PostIsSingleUpdateKey = "__go_admin_is_single_update" PreviousKey = "__go_admin_previous_" TokenKey = "__go_admin_t_" MethodKey = "__go_admin_method_" NoAnimationKey = "__go_admin_no_animation_" ) // Values maps a string key to a list of values. // It is typically used for query parameters and form values. // Unlike in the http.Header map, the keys in a Values map // are case-sensitive. type Values map[string][]string // Get gets the first value associated with the given key. // If there are no values associated with the key, Get returns // the empty string. To access multiple values, use the map // directly. func (f Values) Get(key string) string { if len(f[key]) > 0 { return f[key][0] } return "" } // Add adds the value to key. It appends to any existing // values associated with key. func (f Values) Add(key string, value string) { f[key] = []string{value} } // IsEmpty check the key is empty or not. func (f Values) IsEmpty(key ...string) bool { for _, k := range key { if f.Get(k) == "" { return true } } return false } // Has check the key exists or not. func (f Values) Has(key ...string) bool { for _, k := range key { if f.Get(k) != "" { return true } } return false } // Delete deletes the values associated with key. func (f Values) Delete(key string) { delete(f, key) } // ToMap turn the values to a map[string]string type. func (f Values) ToMap() map[string]string { var m = make(map[string]string) for key, v := range f { if len(v) > 0 { m[key] = v[0] } } return m } // IsUpdatePost check the param if is from an update post request type or not. func (f Values) IsUpdatePost() bool { return f.Get(PostTypeKey) == "0" } // IsInsertPost check the param if is from an insert post request type or not. func (f Values) IsInsertPost() bool { return f.Get(PostTypeKey) == "1" } // PostError get the post result. func (f Values) PostError() error { msg := f.Get(PostResultKey) if msg == "" { return nil } return errors.New(msg) } // IsSingleUpdatePost check the param if from an single update post request type or not. func (f Values) IsSingleUpdatePost() bool { return f.Get(PostIsSingleUpdateKey) == "1" } // RemoveRemark removes the PostType and IsSingleUpdate flag parameters. func (f Values) RemoveRemark() Values { f.Delete(PostTypeKey) f.Delete(PostIsSingleUpdateKey) return f } // RemoveSysRemark removes all framework post flag parameters. func (f Values) RemoveSysRemark() Values { f.Delete(PostTypeKey) f.Delete(PostIsSingleUpdateKey) f.Delete(PostResultKey) f.Delete(PreviousKey) f.Delete(TokenKey) f.Delete(MethodKey) f.Delete(NoAnimationKey) return f } ================================================ FILE: plugins/admin/modules/guard/delete.go ================================================ package guard import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" ) type DeleteParam struct { Panel table.Table Id string Prefix string } func (g *Guard) Delete(ctx *context.Context) { panel, prefix := g.table(ctx) if !panel.GetDeletable() { alert(ctx, panel, errors.OperationNotAllow, g.conn, g.navBtns) ctx.Abort() return } id := ctx.FormValue("id") if id == "" { alert(ctx, panel, errors.WrongID, g.conn, g.navBtns) ctx.Abort() return } ctx.SetUserValue(deleteParamKey, &DeleteParam{ Panel: panel, Id: id, Prefix: prefix, }) ctx.Next() } func GetDeleteParam(ctx *context.Context) *DeleteParam { return ctx.UserValue[deleteParamKey].(*DeleteParam) } ================================================ FILE: plugins/admin/modules/guard/edit.go ================================================ package guard import ( tmpl "html/template" "mime/multipart" "regexp" "strings" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template" ) type ShowFormParam struct { Panel table.Table Id string Prefix string Param parameter.Parameters } func (g *Guard) ShowForm(ctx *context.Context) { panel, prefix := g.table(ctx) if !panel.GetEditable() { alert(ctx, panel, errors.OperationNotAllow, g.conn, g.navBtns) ctx.Abort() return } if panel.GetOnlyInfo() { ctx.Redirect(config.Url("/info/" + prefix)) ctx.Abort() return } if panel.GetOnlyDetail() { ctx.Redirect(config.Url("/info/" + prefix + "/detail")) ctx.Abort() return } if panel.GetOnlyNewForm() { ctx.Redirect(config.Url("/info/" + prefix + "/new")) ctx.Abort() return } id := ctx.Query(constant.EditPKKey) if id == "" { id = "1" } ctx.SetUserValue(showFormParamKey, &ShowFormParam{ Panel: panel, Id: id, Prefix: prefix, Param: parameter.GetParam(ctx.Request.URL, panel.GetInfo().DefaultPageSize, panel.GetInfo().SortField, panel.GetInfo().GetSort()).WithPKs(id), }) ctx.Next() } func GetShowFormParam(ctx *context.Context) *ShowFormParam { return ctx.UserValue[showFormParamKey].(*ShowFormParam) } type EditFormParam struct { Panel table.Table Id string Prefix string Param parameter.Parameters Path string MultiForm *multipart.Form PreviousPath string Alert tmpl.HTML FromList bool IsIframe bool IframeID string } func (e EditFormParam) Value() form.Values { return e.MultiForm.Value } func (g *Guard) EditForm(ctx *context.Context) { panel, prefix := g.table(ctx) if !panel.GetEditable() { alert(ctx, panel, errors.OperationNotAllow, g.conn, g.navBtns) ctx.Abort() return } token := ctx.FormValue(form.TokenKey) if !auth.GetTokenService(g.services.Get(auth.TokenServiceKey)).CheckToken(token) { alert(ctx, panel, errors.EditFailWrongToken, g.conn, g.navBtns) ctx.Abort() return } var ( previous = ctx.FormValue(form.PreviousKey) fromList = isInfoUrl(previous) param = parameter.GetParamFromURL(previous, panel.GetInfo().DefaultPageSize, panel.GetInfo().GetSort(), panel.GetPrimaryKey().Name) ) if fromList { previous = config.Url("/info/" + prefix + param.GetRouteParamStr()) } var ( multiForm = ctx.Request.MultipartForm id = multiForm.Value[panel.GetPrimaryKey().Name][0] values = ctx.Request.MultipartForm.Value ) ctx.SetUserValue(editFormParamKey, &EditFormParam{ Panel: panel, Id: id, Prefix: prefix, Param: param.WithPKs(id), Path: strings.Split(previous, "?")[0], MultiForm: multiForm, IsIframe: form.Values(values).Get(constant.IframeKey) == "true", IframeID: form.Values(values).Get(constant.IframeIDKey), PreviousPath: previous, FromList: fromList, }) ctx.Next() } func isInfoUrl(s string) bool { reg, _ := regexp.Compile("(.*?)info/(.*?)$") sub := reg.FindStringSubmatch(s) return len(sub) > 2 && !strings.Contains(sub[2], "/") } func GetEditFormParam(ctx *context.Context) *EditFormParam { return ctx.UserValue[editFormParamKey].(*EditFormParam) } func alert(ctx *context.Context, panel table.Table, msg string, conn db.Connection, btns *types.Buttons) { if ctx.WantJSON() { response.BadRequest(ctx, msg) } else { response.Alert(ctx, panel.GetInfo().Description, panel.GetInfo().Title, msg, conn, btns) } } func alertWithTitleAndDesc(ctx *context.Context, title, desc, msg string, conn db.Connection, btns *types.Buttons) { response.Alert(ctx, desc, title, msg, conn, btns) } func getAlert(ctx *context.Context, msg string) tmpl.HTML { return template.Get(ctx, config.GetTheme()).Alert().Warning(msg) } ================================================ FILE: plugins/admin/modules/guard/export.go ================================================ package guard import ( "strings" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" ) type ExportParam struct { Panel table.Table Id []string Prefix string IsAll bool } func (g *Guard) Export(ctx *context.Context) { panel, prefix := g.table(ctx) if !panel.GetExportable() { alert(ctx, panel, errors.OperationNotAllow, g.conn, g.navBtns) ctx.Abort() return } idStr := make([]string, 0) ids := ctx.FormValue("id") if ids != "" { idStr = strings.Split(ctx.FormValue("id"), ",") } ctx.SetUserValue(exportParamKey, &ExportParam{ Panel: panel, Id: idStr, Prefix: prefix, IsAll: ctx.FormValue("is_all") == "true", }) ctx.Next() } func GetExportParam(ctx *context.Context) *ExportParam { return ctx.UserValue[exportParamKey].(*ExportParam) } ================================================ FILE: plugins/admin/modules/guard/guard.go ================================================ package guard import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/service" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" ) type Guard struct { services service.List conn db.Connection tableList table.GeneratorList navBtns *types.Buttons } func New(s service.List, c db.Connection, t table.GeneratorList, b *types.Buttons) *Guard { return &Guard{ services: s, conn: c, tableList: t, navBtns: b, } } func (g *Guard) table(ctx *context.Context) (table.Table, string) { prefix := ctx.Query(constant.PrefixKey) return g.tableList[prefix](ctx), prefix } func (g *Guard) CheckPrefix(ctx *context.Context) { prefix := ctx.Query(constant.PrefixKey) if _, ok := g.tableList[prefix]; !ok { if ctx.Headers(constant.PjaxHeader) == "" && ctx.Method() != "GET" { response.BadRequest(ctx, errors.Msg) } else { response.Alert(ctx, errors.Msg, errors.Msg, "table model not found", g.conn, g.navBtns, template.Missing404Page) } ctx.Abort() return } ctx.Next() } const ( editFormParamKey = "edit_form_param" deleteParamKey = "delete_param" exportParamKey = "export_param" serverLoginParamKey = "server_login_param" deleteMenuParamKey = "delete_menu_param" editMenuParamKey = "edit_menu_param" newMenuParamKey = "new_menu_param" newFormParamKey = "new_form_param" updateParamKey = "update_param" showFormParamKey = "show_form_param" showNewFormParam = "show_new_form_param" ) ================================================ FILE: plugins/admin/modules/guard/menu_delete.go ================================================ package guard import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/errors" ) type MenuDeleteParam struct { Id string } func (g *Guard) MenuDelete(ctx *context.Context) { id := ctx.Query("id") if id == "" { alertWithTitleAndDesc(ctx, "Menu", "menu", errors.WrongID, g.conn, g.navBtns) ctx.Abort() return } // TODO: check the user permission ctx.SetUserValue(deleteMenuParamKey, &MenuDeleteParam{ Id: id, }) ctx.Next() } func GetMenuDeleteParam(ctx *context.Context) *MenuDeleteParam { return ctx.UserValue[deleteMenuParamKey].(*MenuDeleteParam) } ================================================ FILE: plugins/admin/modules/guard/menu_edit.go ================================================ package guard import ( "html/template" "strconv" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" ) type MenuEditParam struct { Id string Title string Header string PluginName string ParentId int64 Icon string Uri string Roles []string Alert template.HTML } func (e MenuEditParam) HasAlert() bool { return e.Alert != template.HTML("") } func (g *Guard) MenuEdit(ctx *context.Context) { parentId := ctx.FormValue("parent_id") if parentId == "" { parentId = "0" } var ( parentIdInt, _ = strconv.Atoi(parentId) token = ctx.FormValue(form.TokenKey) alert template.HTML ) if !auth.GetTokenService(g.services.Get(auth.TokenServiceKey)).CheckToken(token) { alert = getAlert(ctx, errors.EditFailWrongToken) } if alert == "" { alert = checkEmpty(ctx, "id", "title", "icon") } ctx.SetUserValue(editMenuParamKey, &MenuEditParam{ Id: ctx.FormValue("id"), Title: ctx.FormValue("title"), Header: ctx.FormValue("header"), PluginName: ctx.FormValue("plugin_name"), ParentId: int64(parentIdInt), Icon: ctx.FormValue("icon"), Uri: ctx.FormValue("uri"), Roles: ctx.Request.Form["roles[]"], Alert: alert, }) ctx.Next() } func GetMenuEditParam(ctx *context.Context) *MenuEditParam { return ctx.UserValue[editMenuParamKey].(*MenuEditParam) } func checkEmpty(ctx *context.Context, key ...string) template.HTML { for _, k := range key { if ctx.FormValue(k) == "" { return getAlert(ctx, "wrong "+k) } } return template.HTML("") } ================================================ FILE: plugins/admin/modules/guard/menu_new.go ================================================ package guard import ( "html/template" "strconv" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" ) type MenuNewParam struct { Title string Header string ParentId int64 Icon string PluginName string Uri string Roles []string Alert template.HTML } func (e MenuNewParam) HasAlert() bool { return e.Alert != template.HTML("") } func (g *Guard) MenuNew(ctx *context.Context) { parentId := ctx.FormValue("parent_id") if parentId == "" { parentId = "0" } var ( alert template.HTML token = ctx.FormValue(form.TokenKey) ) if !auth.GetTokenService(g.services.Get(auth.TokenServiceKey)).CheckToken(token) { alert = getAlert(ctx, errors.EditFailWrongToken) } if alert == "" { alert = checkEmpty(ctx, "title", "icon") } parentIdInt, _ := strconv.Atoi(parentId) ctx.SetUserValue(newMenuParamKey, &MenuNewParam{ Title: ctx.FormValue("title"), Header: ctx.FormValue("header"), PluginName: ctx.FormValue("plugin_name"), ParentId: int64(parentIdInt), Icon: ctx.FormValue("icon"), Uri: ctx.FormValue("uri"), Roles: ctx.Request.Form["roles[]"], Alert: alert, }) ctx.Next() } func GetMenuNewParam(ctx *context.Context) *MenuNewParam { return ctx.UserValue[newMenuParamKey].(*MenuNewParam) } ================================================ FILE: plugins/admin/modules/guard/new.go ================================================ package guard import ( "html/template" "mime/multipart" "strings" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" ) type ShowNewFormParam struct { Panel table.Table Prefix string Param parameter.Parameters } func (g *Guard) ShowNewForm(ctx *context.Context) { panel, prefix := g.table(ctx) if !panel.GetCanAdd() { alert(ctx, panel, errors.OperationNotAllow, g.conn, g.navBtns) ctx.Abort() return } if panel.GetOnlyInfo() { ctx.Redirect(config.Url("/info/" + prefix)) ctx.Abort() return } if panel.GetOnlyDetail() { ctx.Redirect(config.Url("/info/" + prefix + "/detail")) ctx.Abort() return } if panel.GetOnlyUpdateForm() { ctx.Redirect(config.Url("/info/" + prefix + "/edit")) ctx.Abort() return } ctx.SetUserValue(showNewFormParam, &ShowNewFormParam{ Panel: panel, Prefix: prefix, Param: parameter.GetParam(ctx.Request.URL, panel.GetInfo().DefaultPageSize, panel.GetInfo().SortField, panel.GetInfo().GetSort()), }) ctx.Next() } func GetShowNewFormParam(ctx *context.Context) *ShowNewFormParam { return ctx.UserValue[showNewFormParam].(*ShowNewFormParam) } type NewFormParam struct { Panel table.Table Id string Prefix string Param parameter.Parameters Path string MultiForm *multipart.Form PreviousPath string FromList bool IsIframe bool IframeID string Alert template.HTML } func (e NewFormParam) Value() form.Values { return e.MultiForm.Value } func (g *Guard) NewForm(ctx *context.Context) { var ( previous = ctx.FormValue(form.PreviousKey) panel, prefix = g.table(ctx) conn = db.GetConnection(g.services) token = ctx.FormValue(form.TokenKey) ) if !auth.GetTokenService(g.services.Get(auth.TokenServiceKey)).CheckToken(token) { alert(ctx, panel, errors.CreateFailWrongToken, conn, g.navBtns) ctx.Abort() return } fromList := isInfoUrl(previous) param := parameter.GetParamFromURL(previous, panel.GetInfo().DefaultPageSize, panel.GetInfo().GetSort(), panel.GetPrimaryKey().Name) if fromList { previous = config.Url("/info/" + prefix + param.GetRouteParamStr()) } values := ctx.Request.MultipartForm.Value ctx.SetUserValue(newFormParamKey, &NewFormParam{ Panel: panel, Id: "", Prefix: prefix, Param: param, IsIframe: form.Values(values).Get(constant.IframeKey) == "true", IframeID: form.Values(values).Get(constant.IframeIDKey), Path: strings.Split(previous, "?")[0], MultiForm: ctx.Request.MultipartForm, PreviousPath: previous, FromList: fromList, }) ctx.Next() } func GetNewFormParam(ctx *context.Context) *NewFormParam { return ctx.UserValue[newFormParamKey].(*NewFormParam) } ================================================ FILE: plugins/admin/modules/guard/server_login.go ================================================ package guard import ( "encoding/json" "io/ioutil" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/logger" ) type ServerLoginParam struct { Account string Password string } func (g *Guard) ServerLogin(ctx *context.Context) { var p ServerLoginParam body, err := ioutil.ReadAll(ctx.Request.Body) if err != nil { logger.Error("get server login parameter error: ", err) } err = json.Unmarshal(body, &p) if err != nil { logger.Error("unmarshal server login parameter error: ", err) } ctx.SetUserValue(serverLoginParamKey, &p) ctx.Next() } func GetServerLoginParam(ctx *context.Context) *ServerLoginParam { return ctx.UserValue[serverLoginParamKey].(*ServerLoginParam) } ================================================ FILE: plugins/admin/modules/guard/update.go ================================================ package guard import ( "net/http" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" ) type UpdateParam struct { Panel table.Table Prefix string Value form.Values } func (g *Guard) Update(ctx *context.Context) { panel, prefix := g.table(ctx) pname := panel.GetPrimaryKey().Name id := ctx.FormValue("pk") if id == "" { ctx.JSON(http.StatusBadRequest, map[string]interface{}{ "msg": "wrong " + pname, }) ctx.Abort() return } var f = make(form.Values) f.Add(form.PostIsSingleUpdateKey, "1") f.Add(pname, id) f.Add(ctx.FormValue("name"), ctx.FormValue("value")) ctx.SetUserValue(updateParamKey, &UpdateParam{ Panel: panel, Prefix: prefix, Value: f, }) ctx.Next() } func GetUpdateParam(ctx *context.Context) *UpdateParam { return ctx.UserValue[updateParamKey].(*UpdateParam) } ================================================ FILE: plugins/admin/modules/helper.go ================================================ package modules import ( "html/template" "strconv" "github.com/google/uuid" ) func InArray(arr []string, str string) bool { for _, v := range arr { if v == str { return true } } return false } func Delimiter(del, del2, s string) string { return del + s + del2 } func FilterField(filed, delimiter, delimiter2 string) string { return delimiter + filed + delimiter2 } func InArrayWithoutEmpty(arr []string, str string) bool { if len(arr) == 0 { return true } for _, v := range arr { if v == str { return true } } return false } func RemoveBlankFromArray(s []string) []string { var r []string for _, str := range s { if str != "" { r = append(r, str) } } return r } func Uuid() string { return uuid.New().String() } func SetDefault(source, def string) string { if source == "" { return def } return source } func GetPage(page string) (pageInt int) { if page == "" { pageInt = 1 } else { pageInt, _ = strconv.Atoi(page) } return } func AorB(condition bool, a, b string) string { if condition { return a } return b } func AorEmpty(condition bool, a string) string { if condition { return a } return "" } func AorBHTML(condition bool, a, b template.HTML) template.HTML { if condition { return a } return b } ================================================ FILE: plugins/admin/modules/helper_test.go ================================================ package modules import ( "regexp" "testing" "github.com/magiconair/properties/assert" ) func TestInArray(t *testing.T) { assert.Equal(t, isFormURL("/admin/info/profile/new"), true) } func isFormURL(s string) bool { reg, _ := regexp.Compile("(.*?)info/(.*)/(new|edit)(.*?)") return reg.MatchString(s) } ================================================ FILE: plugins/admin/modules/paginator/paginator.go ================================================ package paginator import ( "fmt" "html/template" "math" "strconv" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" template2 "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/components" "github.com/GoAdminGroup/go-admin/template/types" ) type Config struct { Size int Param parameter.Parameters PageSizeList []string } func Get(ctx *context.Context, cfg Config) types.PaginatorAttribute { paginator := template2.Default(ctx).Paginator().(*components.PaginatorAttribute) totalPage := int(math.Ceil(float64(cfg.Size) / float64(cfg.Param.PageSizeInt))) if cfg.Param.PageInt == 1 { paginator.PreviousClass = "disabled" paginator.PreviousUrl = cfg.Param.URLPath } else { paginator.PreviousClass = "" paginator.PreviousUrl = cfg.Param.URLPath + cfg.Param.GetLastPageRouteParamStr(true) } if cfg.Param.PageInt == totalPage { paginator.NextClass = "disabled" paginator.NextUrl = cfg.Param.URLPath } else { paginator.NextClass = "" paginator.NextUrl = cfg.Param.URLPath + cfg.Param.GetNextPageRouteParamStr(true) } paginator.Url = cfg.Param.URLPath + cfg.Param.GetRouteParamStrWithoutPageSize("1") + "&" + form.NoAnimationKey + "=true" paginator.CurPageEndIndex = strconv.Itoa((cfg.Param.PageInt) * cfg.Param.PageSizeInt) paginator.CurPageStartIndex = strconv.Itoa((cfg.Param.PageInt-1)*cfg.Param.PageSizeInt + 1) paginator.Total = strconv.Itoa(cfg.Size) if len(cfg.PageSizeList) == 0 { cfg.PageSizeList = []string{"10", "20", "50", "100"} } paginator.Option = make(map[string]template.HTML, len(cfg.PageSizeList)) for i := 0; i < len(cfg.PageSizeList); i++ { paginator.Option[cfg.PageSizeList[i]] = template.HTML("") } paginator.Option[cfg.Param.PageSize] = template.HTML("selected") paginator.Pages = []map[string]string{} var pagesArr []map[string]string if totalPage < 10 { for i := 1; i < totalPage+1; i++ { if i == cfg.Param.PageInt { pagesArr = addPageLink(pagesArr, cfg.Param, cfg.Param.PageInt, "active") } else { pagesArr = addPageLink(pagesArr, cfg.Param, i, "") } } } else { if cfg.Param.PageInt < 6 { for i := 1; i < totalPage+1; i++ { if i == cfg.Param.PageInt { pagesArr = addPageLink(pagesArr, cfg.Param, cfg.Param.PageInt, "active") } else { pagesArr = addPageLink(pagesArr, cfg.Param, i, "") } if i == 6 { pagesArr = addPageLink(pagesArr, cfg.Param, i, "split") i = totalPage - 2 } } } else if cfg.Param.PageInt < totalPage-4 { for i := 1; i < totalPage+1; i++ { if i == cfg.Param.PageInt { pagesArr = addPageLink(pagesArr, cfg.Param, cfg.Param.PageInt, "active") } else { pagesArr = addPageLink(pagesArr, cfg.Param, i, "") } if i == 2 { pagesArr = addPageLink(pagesArr, cfg.Param, i, "split") i = cfg.Param.PageInt - 3 } if i == cfg.Param.PageInt+2 { pagesArr = addPageLink(pagesArr, cfg.Param, i, "split") i = totalPage - 1 } } } else { for i := 1; i < totalPage+1; i++ { if i == cfg.Param.PageInt { pagesArr = addPageLink(pagesArr, cfg.Param, cfg.Param.PageInt, "active") } else { pagesArr = addPageLink(pagesArr, cfg.Param, i, "") } if i == 2 { pagesArr = addPageLink(pagesArr, cfg.Param, i, "split") i = totalPage - 6 } } } } paginator.Pages = pagesArr endNum := paginator.CurPageEndIndex if cfg.Size < cfg.Param.PageSizeInt { endNum = paginator.Total } if cfg.Param.PageInt >= (cfg.Size+cfg.Param.PageSizeInt-1)/cfg.Param.PageSizeInt { endNum = paginator.Total } paginator.SetEntriesInfo(template.HTML(fmt.Sprintf(language.Get("showing %s to %s of %s entries"), paginator.CurPageStartIndex, endNum, paginator.Total))) return paginator.SetPageSizeList(cfg.PageSizeList) } func addPageLink(arr []map[string]string, params parameter.Parameters, page int, active string) []map[string]string { pageStr := strconv.Itoa(page) isSplit := "0" if active == "split" { isSplit = "1" active = "" pageStr = "" } return append(arr, map[string]string{ "page": pageStr, "active": active, "isSplit": isSplit, "url": params.URLNoAnimation(pageStr), }) } ================================================ FILE: plugins/admin/modules/paginator/paginator_test.go ================================================ package paginator import ( "testing" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" _ "github.com/GoAdminGroup/themes/sword" ) func TestGet(t *testing.T) { config.Initialize(&config.Config{Theme: "sword"}) param := parameter.BaseParam() param.Page = "7" Get(nil, Config{ Size: 105, Param: param, PageSizeList: []string{"10", "20", "50", "100"}, }) } ================================================ FILE: plugins/admin/modules/parameter/parameter.go ================================================ package parameter import ( "net/url" "strconv" "strings" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" ) type Parameters struct { Page string PageInt int PageSize string PageSizeInt int SortField string Columns []string SortType string Animation bool URLPath string Fields map[string][]string OrConditions map[string]string cacheFixedStr url.Values } const ( Page = "__page" PageSize = "__pageSize" Sort = "__sort" SortType = "__sort_type" Columns = "__columns" Prefix = "__prefix" Pjax = "_pjax" sortTypeDesc = "desc" sortTypeAsc = "asc" IsAll = "__is_all" PrimaryKey = "__pk" True = "true" False = "false" FilterRangeParamStartSuffix = "_start__goadmin" FilterRangeParamEndSuffix = "_end__goadmin" FilterParamJoinInfix = "_goadmin_join_" FilterParamOperatorSuffix = "__goadmin_operator__" FilterParamCountInfix = "__goadmin_index__" Separator = "__goadmin_separator__" ) var operators = map[string]string{ "like": "like", "gr": ">", "gq": ">=", "eq": "=", "ne": "!=", "le": "<", "lq": "<=", "free": "free", } var keys = []string{Page, PageSize, Sort, Columns, Prefix, Pjax, form.NoAnimationKey} func BaseParam() Parameters { return Parameters{Page: "1", PageSize: "10", PageInt: 1, PageSizeInt: 10, Fields: make(map[string][]string)} } func GetParam(u *url.URL, defaultPageSize int, p ...string) Parameters { values := u.Query() primaryKey := "id" defaultSortType := "desc" if len(p) > 0 { primaryKey = p[0] defaultSortType = p[1] } page := getDefault(values, Page, "1") pageSize := getDefault(values, PageSize, strconv.Itoa(defaultPageSize)) sortField := getDefault(values, Sort, primaryKey) sortType := getDefault(values, SortType, defaultSortType) columns := getDefault(values, Columns, "") animation := true if values.Get(form.NoAnimationKey) == "true" { animation = false } fields := make(map[string][]string) for key, value := range values { if !modules.InArray(keys, key) && len(value) > 0 && value[0] != "" { if key == SortType { if value[0] != sortTypeDesc && value[0] != sortTypeAsc { fields[key] = []string{sortTypeDesc} } } else { if strings.Contains(key, FilterParamOperatorSuffix) && values.Get(strings.ReplaceAll(key, FilterParamOperatorSuffix, "")) == "" { continue } fields[strings.ReplaceAll(key, "[]", "")] = value } } } columnsArr := make([]string, 0) if columns != "" { columns, _ = url.QueryUnescape(columns) columnsArr = strings.Split(columns, ",") } pageInt, _ := strconv.Atoi(page) pageSizeInt, _ := strconv.Atoi(pageSize) return Parameters{ Page: page, PageSize: pageSize, PageSizeInt: pageSizeInt, PageInt: pageInt, URLPath: u.Path, SortField: sortField, SortType: sortType, Fields: fields, OrConditions: map[string]string{}, Animation: animation, Columns: columnsArr, } } func GetParamFromURL(urlStr string, defaultPageSize int, defaultSortType, primaryKey string) Parameters { u, err := url.Parse(urlStr) if err != nil { return BaseParam() } return GetParam(u, defaultPageSize, primaryKey, defaultSortType) } func (param Parameters) WithPKs(id ...string) Parameters { param.Fields[PrimaryKey] = []string{strings.Join(id, ",")} return param } func (param Parameters) PKs() []string { pk := param.GetFieldValue(PrimaryKey) if pk == "" { return []string{} } return strings.Split(param.GetFieldValue(PrimaryKey), ",") } func (param Parameters) DeletePK() Parameters { delete(param.Fields, PrimaryKey) return param } func (param Parameters) PK() string { pks := param.PKs() if len(pks) > 0 { return pks[0] } return "" } func (param Parameters) IsAll() bool { return param.GetFieldValue(IsAll) == True } func (param *Parameters) WithURLPath(path string) Parameters { param.URLPath = path return *param } func (param *Parameters) isAllTrue() { param.Fields[IsAll] = []string{True} } func (param *Parameters) isAllFalse() { param.Fields[IsAll] = []string{False} } func (param Parameters) WithIsAll(isAll bool) Parameters { if isAll { param.isAllTrue() } else { param.isAllFalse() } return param } func (param Parameters) DeleteIsAll() Parameters { delete(param.Fields, IsAll) return param } func (param Parameters) GetFilterFieldValueStart(field string) string { return param.GetFieldValue(field + FilterRangeParamStartSuffix) } func (param Parameters) GetFilterFieldValueEnd(field string) string { return param.GetFieldValue(field + FilterRangeParamEndSuffix) } func (param Parameters) GetFieldValue(field string) string { value, ok := param.Fields[field] if ok && len(value) > 0 { return value[0] } return "" } func (param Parameters) AddField(field, value string) Parameters { param.Fields[field] = []string{value} return param } func (param Parameters) DeleteField(fields ...string) Parameters { for _, field := range fields { delete(param.Fields, field) } return param } func (param Parameters) DeleteEditPk() Parameters { delete(param.Fields, constant.EditPKKey) return param } func (param Parameters) DeleteDetailPk() Parameters { delete(param.Fields, constant.DetailPKKey) return param } func (param Parameters) GetFieldValues(field string) []string { return param.Fields[field] } func (param Parameters) GetFieldValuesStr(field string) string { return strings.Join(param.Fields[field], Separator) } func (param Parameters) GetFieldOperator(field, suffix string) string { op := param.GetFieldValue(field + FilterParamOperatorSuffix + suffix) if op == "" { return "eq" } return op } func (param Parameters) Join() string { p := param.GetFixedParamStr() p.Add(Page, param.Page) return p.Encode() } func (param *Parameters) SetPage(page string) Parameters { param.Page = page param.PageInt, _ = strconv.Atoi(page) return *param } func (param *Parameters) SetPageSize(pageSize string) Parameters { param.PageSize = pageSize param.PageSizeInt, _ = strconv.Atoi(pageSize) return *param } func (param Parameters) GetRouteParamStr() string { p := param.GetFixedParamStr() p.Add(Page, param.Page) return "?" + p.Encode() } func (param Parameters) URL(page string) string { return param.URLPath + param.SetPage(page).GetRouteParamStr() } func (param Parameters) URLNoAnimation(page string) string { return param.URLPath + param.SetPage(page).GetRouteParamStr() + "&" + form.NoAnimationKey + "=true" } func (param Parameters) GetRouteParamStrWithoutPageSize(page string) string { p := make(url.Values) p.Add(Sort, param.SortField) p.Add(Page, page) p.Add(SortType, param.SortType) if len(param.Columns) > 0 { p.Add(Columns, strings.Join(param.Columns, ",")) } for key, value := range param.Fields { p[key] = value } return "?" + p.Encode() } func (param Parameters) GetFixedParamStrFromCache() url.Values { if param.cacheFixedStr != nil { return param.cacheFixedStr } p := param.GetFixedParamStr() param.cacheFixedStr = p return p } func (param Parameters) GetLastPageRouteParamStr(cache ...bool) string { var p url.Values if len(cache) > 0 && cache[0] { p = param.GetFixedParamStrFromCache() } else { p = param.GetFixedParamStr() } p.Add(Page, strconv.Itoa(param.PageInt-1)) return "?" + p.Encode() } func (param Parameters) GetNextPageRouteParamStr(cache ...bool) string { var p url.Values if len(cache) > 0 && cache[0] { p = param.GetFixedParamStrFromCache() } else { p = param.GetFixedParamStr() } p.Add(Page, strconv.Itoa(param.PageInt+1)) return "?" + p.Encode() } func (param Parameters) GetFixedParamStr() url.Values { p := make(url.Values) p.Add(Sort, param.SortField) p.Add(PageSize, param.PageSize) p.Add(SortType, param.SortType) if len(param.Columns) > 0 { p.Add(Columns, strings.Join(param.Columns, ",")) } for key, value := range param.Fields { p[key] = value } return p } func (param Parameters) GetFixedParamStrWithoutColumnsAndPage() string { p := make(url.Values) p.Add(Sort, param.SortField) p.Add(PageSize, param.PageSize) if len(param.Columns) > 0 { p.Add(Columns, strings.Join(param.Columns, ",")) } p.Add(SortType, param.SortType) return "?" + p.Encode() } func (param Parameters) GetFixedParamStrWithoutSort() string { p := make(url.Values) p.Add(PageSize, param.PageSize) for key, value := range param.Fields { p[key] = value } p.Add(form.NoAnimationKey, "true") if len(param.Columns) > 0 { p.Add(Columns, strings.Join(param.Columns, ",")) } return "&" + p.Encode() } func (param Parameters) Statement(wheres, table, delimiter, delimiter2 string, whereArgs []interface{}, columns, existKeys []string, filterProcess func(string, string, string) string) (string, []interface{}, []string) { var multiKey = make(map[string]uint8) for key, value := range param.Fields { keyIndexSuffix := "" keyArr := strings.Split(key, FilterParamCountInfix) if len(keyArr) > 1 { key = keyArr[0] keyIndexSuffix = FilterParamCountInfix + keyArr[1] } if keyIndexSuffix != "" { multiKey[key] = 0 } else if _, exist := multiKey[key]; !exist && modules.InArray(existKeys, key) { continue } var op string if strings.Contains(key, FilterRangeParamEndSuffix) { key = strings.ReplaceAll(key, FilterRangeParamEndSuffix, "") op = "<=" } else if strings.Contains(key, FilterRangeParamStartSuffix) { key = strings.ReplaceAll(key, FilterRangeParamStartSuffix, "") op = ">=" } else if len(value) > 1 { op = "in" } else if !strings.Contains(key, FilterParamOperatorSuffix) { op = operators[param.GetFieldOperator(key, keyIndexSuffix)] } else { continue } if strings.Contains(key, FilterParamJoinInfix) { keys := strings.Split(key, FilterParamJoinInfix) val := filterProcess(key, value[0], keyIndexSuffix) if op == "in" { qmark := "" for range value { qmark += "?," } wheres += keys[0] + "." + modules.FilterField(keys[1], delimiter, delimiter2) + " " + op + " (" + qmark[:len(qmark)-1] + ") and " } else { wheres += keys[0] + "." + modules.FilterField(keys[1], delimiter, delimiter2) + " " + op + " ? and " } if op == "like" && !strings.Contains(val, "%") { whereArgs = append(whereArgs, "%"+val+"%") } else { for _, v := range value { whereArgs = append(whereArgs, filterProcess(key, v, keyIndexSuffix)) } } } else { if modules.InArray(columns, key) { if op == "in" { qmark := "" for range value { qmark += "?," } wheres += modules.Delimiter(delimiter, delimiter2, table) + "." + modules.FilterField(key, delimiter, delimiter2) + " " + op + " (" + qmark[:len(qmark)-1] + ") and " } else { wheres += modules.Delimiter(delimiter, delimiter2, table) + "." + modules.FilterField(key, delimiter, delimiter2) + " " + op + " ? and " } if op == "like" && !strings.Contains(value[0], "%") { whereArgs = append(whereArgs, "%"+filterProcess(key, value[0], keyIndexSuffix)+"%") } else { for _, v := range value { whereArgs = append(whereArgs, filterProcess(key, v, keyIndexSuffix)) } } } else { continue } } existKeys = append(existKeys, key) } if len(wheres) > 3 { wheres = wheres[:len(wheres)-4] } for key, value := range param.OrConditions { columns = strings.Split(key, ",") op := "=" if strings.Contains(value, "%") { op = "like" } if len(wheres) > 0 { wheres += " and " } wheres += "(" for _, column := range columns { keys := strings.Split(column, FilterParamJoinInfix) if len(keys) > 1 { wheres += keys[0] + "." + modules.FilterField(keys[1], delimiter, delimiter2) + " " + op + " ? or " } else { wheres += modules.FilterField(column, delimiter, delimiter2) + " " + op + " ? or " } whereArgs = append(whereArgs, value) } wheres = strings.TrimSuffix(wheres, "or ") + ")" } return wheres, whereArgs, existKeys } func getDefault(values url.Values, key, def string) string { value := values.Get(key) if value == "" { return def } return value } ================================================ FILE: plugins/admin/modules/parameter/parameter_test.go ================================================ package parameter import ( "fmt" "testing" ) func TestGetParamFromUrl(t *testing.T) { fmt.Println(GetParamFromURL("/admin/info/user?__page=1&__pageSize=10&__sort=id&__sort_type=desc", 1, "asc", "id")) } func TestParameters_PKs(t *testing.T) { pks := BaseParam().PKs() fmt.Println("pks", pks, "len", len(pks)) } ================================================ FILE: plugins/admin/modules/response/response.go ================================================ package response import ( "net/http" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/menu" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" ) func Ok(ctx *context.Context) { ctx.JSON(http.StatusOK, map[string]interface{}{ "code": http.StatusOK, "msg": "ok", }) } func OkWithMsg(ctx *context.Context, msg string) { ctx.JSON(http.StatusOK, map[string]interface{}{ "code": http.StatusOK, "msg": msg, }) } func OkWithData(ctx *context.Context, data map[string]interface{}) { ctx.JSON(http.StatusOK, map[string]interface{}{ "code": http.StatusOK, "msg": "ok", "data": data, }) } func BadRequest(ctx *context.Context, msg string) { ctx.JSON(http.StatusBadRequest, map[string]interface{}{ "code": http.StatusBadRequest, "msg": language.Get(msg), }) } func Alert(ctx *context.Context, desc, title, msg string, conn db.Connection, btns *types.Buttons, pageType ...template.PageType) { user := auth.Auth(ctx) pt := template.Error500Page if len(pageType) > 0 { pt = pageType[0] } pageTitle, description, content := template.GetPageContentFromPageType(ctx, title, desc, msg, pt) tmpl, tmplName := template.Default(ctx).GetTemplate(ctx.IsPjax()) buf := template.Execute(ctx, &template.ExecuteParam{ User: user, TmplName: tmplName, Tmpl: tmpl, Panel: types.Panel{ Content: content, Description: description, Title: pageTitle, }, Config: config.Get(), Menu: menu.GetGlobalMenu(user, conn, ctx.Lang()).SetActiveClass(config.URLRemovePrefix(ctx.Path())), Animation: true, Buttons: *btns, IsPjax: ctx.IsPjax(), Iframe: ctx.IsIframe(), }) ctx.HTML(http.StatusOK, buf.String()) } func Error(ctx *context.Context, msg string, datas ...map[string]interface{}) { res := map[string]interface{}{ "code": http.StatusInternalServerError, "msg": language.Get(msg), } if len(datas) > 0 { res["data"] = datas[0] } ctx.JSON(http.StatusInternalServerError, res) } func Denied(ctx *context.Context, msg string) { ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ "code": http.StatusForbidden, "msg": language.Get(msg), }) } var OffLineHandler = func(ctx *context.Context) { if config.GetSiteOff() { if ctx.WantHTML() { ctx.HTML(http.StatusOK, `

    The website is offline

    `) } else { ctx.JSON(http.StatusForbidden, map[string]interface{}{ "code": http.StatusForbidden, "msg": language.Get(errors.SiteOff), }) } ctx.Abort() } } ================================================ FILE: plugins/admin/modules/table/config.go ================================================ package table import ( "github.com/GoAdminGroup/go-admin/modules/db" ) type Config struct { Driver string DriverMode string Connection string CanAdd bool Editable bool Deletable bool Exportable bool PrimaryKey PrimaryKey SourceURL string GetDataFun GetDataFun OnlyInfo bool OnlyNewForm bool OnlyUpdateForm bool OnlyDetail bool } func DefaultConfig() Config { return Config{ Driver: db.DriverMysql, CanAdd: true, Editable: true, Deletable: true, Exportable: true, Connection: DefaultConnectionName, PrimaryKey: PrimaryKey{ Type: db.Int, Name: DefaultPrimaryKeyName, }, } } func (config Config) SetPrimaryKey(name string, typ db.DatabaseType) Config { config.PrimaryKey.Name = name config.PrimaryKey.Type = typ return config } func (config Config) SetDriverMode(mode string) Config { config.DriverMode = mode return config } func (config Config) SetPrimaryKeyType(typ string) Config { config.PrimaryKey.Type = db.GetDTAndCheck(typ) return config } func (config Config) SetCanAdd(canAdd bool) Config { config.CanAdd = canAdd return config } func (config Config) SetSourceURL(url string) Config { config.SourceURL = url return config } func (config Config) SetGetDataFun(fun GetDataFun) Config { config.GetDataFun = fun return config } func (config Config) SetEditable(editable bool) Config { config.Editable = editable return config } func (config Config) SetDeletable(deletable bool) Config { config.Deletable = deletable return config } func (config Config) SetOnlyInfo() Config { config.OnlyInfo = true return config } func (config Config) SetOnlyUpdateForm() Config { config.OnlyUpdateForm = true return config } func (config Config) SetOnlyNewForm() Config { config.OnlyNewForm = true return config } func (config Config) SetOnlyDetail() Config { config.OnlyDetail = true return config } func (config Config) SetExportable(exportable bool) Config { config.Exportable = exportable return config } func (config Config) SetConnection(connection string) Config { config.Connection = connection return config } func DefaultConfigWithDriver(driver string) Config { return Config{ Driver: driver, Connection: DefaultConnectionName, CanAdd: true, Editable: true, Deletable: true, Exportable: true, PrimaryKey: PrimaryKey{ Type: db.Int, Name: DefaultPrimaryKeyName, }, } } func DefaultConfigWithDriverAndConnection(driver, conn string) Config { return Config{ Driver: driver, Connection: conn, CanAdd: true, Editable: true, Deletable: true, Exportable: true, PrimaryKey: PrimaryKey{ Type: db.Int, Name: DefaultPrimaryKeyName, }, } } ================================================ FILE: plugins/admin/modules/table/default.go ================================================ package table import ( "encoding/json" "errors" "fmt" "html/template" "io/ioutil" "net/http" "strconv" "strings" "time" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/db/dialect" errs "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/paginator" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/template/types" ) // DefaultTable is an implementation of table.Table type DefaultTable struct { *BaseTable connectionDriver string connectionDriverMode string connection string sourceURL string getDataFun GetDataFun dbObj db.Connection } type GetDataFun func(params parameter.Parameters) ([]map[string]interface{}, int) func NewDefaultTable(ctx *context.Context, cfgs ...Config) Table { var cfg Config if len(cfgs) > 0 && cfgs[0].PrimaryKey.Name != "" { cfg = cfgs[0] } else { cfg = DefaultConfig() } return &DefaultTable{ BaseTable: &BaseTable{ Info: types.NewInfoPanel(ctx, cfg.PrimaryKey.Name), Form: types.NewFormPanel(), NewForm: types.NewFormPanel(), Detail: types.NewInfoPanel(ctx, cfg.PrimaryKey.Name), CanAdd: cfg.CanAdd, Editable: cfg.Editable, Deletable: cfg.Deletable, Exportable: cfg.Exportable, PrimaryKey: cfg.PrimaryKey, OnlyNewForm: cfg.OnlyNewForm, OnlyUpdateForm: cfg.OnlyUpdateForm, OnlyDetail: cfg.OnlyDetail, OnlyInfo: cfg.OnlyInfo, }, connectionDriver: cfg.Driver, connectionDriverMode: cfg.DriverMode, connection: cfg.Connection, sourceURL: cfg.SourceURL, getDataFun: cfg.GetDataFun, } } // Copy copy a new table.Table from origin DefaultTable func (tb *DefaultTable) Copy() Table { return &DefaultTable{ BaseTable: &BaseTable{ Form: types.NewFormPanel().SetTable(tb.Form.Table). SetDescription(tb.Form.Description). SetTitle(tb.Form.Title), NewForm: types.NewFormPanel().SetTable(tb.Form.Table). SetDescription(tb.Form.Description). SetTitle(tb.Form.Title), Info: types.NewInfoPanel(tb.Info.Ctx, tb.PrimaryKey.Name).SetTable(tb.Info.Table). SetDescription(tb.Info.Description). SetTitle(tb.Info.Title). SetGetDataFn(tb.Info.GetDataFn), Detail: types.NewInfoPanel(tb.Info.Ctx, tb.PrimaryKey.Name).SetTable(tb.Detail.Table). SetDescription(tb.Detail.Description). SetTitle(tb.Detail.Title). SetGetDataFn(tb.Detail.GetDataFn), CanAdd: tb.CanAdd, Editable: tb.Editable, Deletable: tb.Deletable, Exportable: tb.Exportable, PrimaryKey: tb.PrimaryKey, }, connectionDriver: tb.connectionDriver, connectionDriverMode: tb.connectionDriverMode, connection: tb.connection, sourceURL: tb.sourceURL, getDataFun: tb.getDataFun, } } // GetData query the data set. func (tb *DefaultTable) GetData(ctx *context.Context, params parameter.Parameters) (PanelInfo, error) { var ( data []map[string]interface{} size int beginTime = time.Now() ) if tb.Info.UpdateParametersFns != nil { for _, fn := range tb.Info.UpdateParametersFns { fn(¶ms) } } if tb.Info.QueryFilterFn != nil { var ids []string var stopQuery bool if tb.getDataFun == nil && tb.Info.GetDataFn == nil { ids, stopQuery = tb.Info.QueryFilterFn(params, tb.db()) } else { ids, stopQuery = tb.Info.QueryFilterFn(params, nil) } if stopQuery { return tb.GetDataWithIds(ctx, params.WithPKs(ids...)) } } if tb.getDataFun != nil { data, size = tb.getDataFun(params) } else if tb.sourceURL != "" { data, size = tb.getDataFromURL(params) } else if tb.Info.GetDataFn != nil { data, size = tb.Info.GetDataFn(params) } else if params.IsAll() { return tb.getAllDataFromDatabase(params) } else { return tb.getDataFromDatabase(ctx, params) } infoList := make(types.InfoList, 0) for i := 0; i < len(data); i++ { infoList = append(infoList, tb.getTempModelData(data[i], params, []string{})) } thead, _, _, _, _, filterForm := tb.getTheadAndFilterForm(params, []string{}) endTime := time.Now() extraInfo := "" if !tb.Info.IsHideQueryInfo { extraInfo = fmt.Sprintf("" + language.Get("query time") + ": " + fmt.Sprintf("%.3fms", endTime.Sub(beginTime).Seconds()*1000)) } return PanelInfo{ Thead: thead, InfoList: infoList, Paginator: paginator.Get(ctx, paginator.Config{ Size: size, Param: params, PageSizeList: tb.Info.GetPageSizeList(), }).SetExtraInfo(template.HTML(extraInfo)), Title: tb.Info.Title, FilterFormData: filterForm, Description: tb.Info.Description, }, nil } type GetDataFromURLRes struct { Data []map[string]interface{} Size int } func (tb *DefaultTable) getDataFromURL(params parameter.Parameters) ([]map[string]interface{}, int) { u := "" if strings.Contains(tb.sourceURL, "?") { u = tb.sourceURL + "&" + params.Join() } else { u = tb.sourceURL + "?" + params.Join() } res, err := http.Get(u + "&pk=" + strings.Join(params.PKs(), ",")) if err != nil { return []map[string]interface{}{}, 0 } defer func() { _ = res.Body.Close() }() body, err := ioutil.ReadAll(res.Body) if err != nil { return []map[string]interface{}{}, 0 } var data GetDataFromURLRes err = json.Unmarshal(body, &data) if err != nil { return []map[string]interface{}{}, 0 } return data.Data, data.Size } // GetDataWithIds query the data set. func (tb *DefaultTable) GetDataWithIds(ctx *context.Context, params parameter.Parameters) (PanelInfo, error) { var ( data []map[string]interface{} size int beginTime = time.Now() ) if tb.getDataFun != nil { data, size = tb.getDataFun(params) } else if tb.sourceURL != "" { data, size = tb.getDataFromURL(params) } else if tb.Info.GetDataFn != nil { data, size = tb.Info.GetDataFn(params) } else { return tb.getDataFromDatabase(ctx, params) } infoList := make([]map[string]types.InfoItem, 0) for i := 0; i < len(data); i++ { infoList = append(infoList, tb.getTempModelData(data[i], params, []string{})) } thead, _, _, _, _, filterForm := tb.getTheadAndFilterForm(params, []string{}) endTime := time.Now() return PanelInfo{ Thead: thead, InfoList: infoList, Paginator: paginator.Get(ctx, paginator.Config{ Size: size, Param: params, PageSizeList: tb.Info.GetPageSizeList(), }). SetExtraInfo(template.HTML(fmt.Sprintf("" + language.Get("query time") + ": " + fmt.Sprintf("%.3fms", endTime.Sub(beginTime).Seconds()*1000)))), Title: tb.Info.Title, FilterFormData: filterForm, Description: tb.Info.Description, }, nil } func (tb *DefaultTable) getTempModelData(res map[string]interface{}, params parameter.Parameters, columns Columns) map[string]types.InfoItem { var tempModelData = map[string]types.InfoItem{ "__goadmin_edit_params": {}, "__goadmin_delete_params": {}, "__goadmin_detail_params": {}, } headField := "" editParams := "" deleteParams := "" detailParams := "" primaryKeyValue := db.GetValueFromDatabaseType(tb.PrimaryKey.Type, res[tb.PrimaryKey.Name], len(columns) == 0) for _, field := range tb.Info.FieldList { headField = field.Field if field.Joins.Valid() { headField = field.Joins.Last().GetTableName() + parameter.FilterParamJoinInfix + field.Field } if field.Hide { continue } if !modules.InArrayWithoutEmpty(params.Columns, headField) { continue } typeName := field.TypeName if field.Joins.Valid() { typeName = db.Varchar } combineValue := db.GetValueFromDatabaseType(typeName, res[headField], len(columns) == 0).String() // TODO: ToDisplay some same logic execute repeatedly, it can be improved. var value interface{} if len(columns) == 0 || modules.InArray(columns, headField) || field.Joins.Valid() { value = field.ToDisplay(types.FieldModel{ ID: primaryKeyValue.String(), Value: combineValue, Row: res, }) } else { value = field.ToDisplay(types.FieldModel{ ID: primaryKeyValue.String(), Value: "", Row: res, }) } var valueStr string var ok bool if valueStr, ok = value.(string); ok { tempModelData[headField] = types.InfoItem{ Content: template.HTML(valueStr), Value: combineValue, } } else { valueStr = string(value.(template.HTML)) tempModelData[headField] = types.InfoItem{ Content: value.(template.HTML), Value: combineValue, } } if field.IsEditParam { editParams += "__goadmin_edit_" + field.Field + "=" + valueStr + "&" } if field.IsDeleteParam { deleteParams += "__goadmin_delete_" + field.Field + "=" + valueStr + "&" } if field.IsDetailParam { detailParams += "__goadmin_detail_" + field.Field + "=" + valueStr + "&" } } if editParams != "" { tempModelData["__goadmin_edit_params"] = types.InfoItem{Content: template.HTML("&" + editParams[:len(editParams)-1])} } if deleteParams != "" { tempModelData["__goadmin_delete_params"] = types.InfoItem{Content: template.HTML("&" + deleteParams[:len(deleteParams)-1])} } if detailParams != "" { tempModelData["__goadmin_detail_params"] = types.InfoItem{Content: template.HTML("&" + detailParams[:len(detailParams)-1])} } primaryKeyField := tb.Info.FieldList.GetFieldByFieldName(tb.PrimaryKey.Name) value := primaryKeyField.ToDisplay(types.FieldModel{ ID: primaryKeyValue.String(), Value: primaryKeyValue.String(), Row: res, }) if valueStr, ok := value.(string); ok { tempModelData[tb.PrimaryKey.Name] = types.InfoItem{ Content: template.HTML(valueStr), Value: primaryKeyValue.String(), } } else { tempModelData[tb.PrimaryKey.Name] = types.InfoItem{ Content: value.(template.HTML), Value: primaryKeyValue.String(), } } return tempModelData } func (tb *DefaultTable) getAllDataFromDatabase(params parameter.Parameters) (PanelInfo, error) { var ( connection = tb.db() queryStatement = "select %s from %s %s %s %s order by " + modules.Delimiter(connection.GetDelimiter(), connection.GetDelimiter2(), "%s") + " %s" ) columns, _ := tb.getColumns(tb.Info.Table) thead, fields, joins := tb.Info.FieldList.GetThead(types.TableInfo{ Table: tb.Info.Table, Delimiter: connection.GetDelimiter(), Delimiter2: connection.GetDelimiter2(), Driver: tb.connectionDriver, PrimaryKey: tb.PrimaryKey.Name, }, params, columns) fields += tb.Info.Table + "." + modules.FilterField(tb.PrimaryKey.Name, connection.GetDelimiter(), connection.GetDelimiter2()) groupBy := "" if joins != "" { groupBy = " GROUP BY " + tb.Info.Table + "." + modules.Delimiter(connection.GetDelimiter(), connection.GetDelimiter2(), tb.PrimaryKey.Name) } var ( wheres = "" whereArgs = make([]interface{}, 0) existKeys = make([]string, 0) ) wheres, whereArgs, existKeys = params.Statement(wheres, tb.Info.Table, connection.GetDelimiter(), connection.GetDelimiter2(), whereArgs, columns, existKeys, tb.Info.FieldList.GetFieldFilterProcessValue) wheres, whereArgs = tb.Info.Wheres.Statement(wheres, connection.GetDelimiter(), connection.GetDelimiter2(), whereArgs, existKeys, columns) wheres, whereArgs = tb.Info.WhereRaws.Statement(wheres, whereArgs) if wheres != "" { wheres = " where " + wheres } if !modules.InArray(columns, params.SortField) { params.SortField = tb.PrimaryKey.Name } queryCmd := fmt.Sprintf(queryStatement, fields, tb.Info.Table, joins, wheres, groupBy, params.SortField, params.SortType) logger.LogSQL(queryCmd, []interface{}{}) res, err := connection.QueryWithConnection(tb.connection, queryCmd, whereArgs...) if err != nil { return PanelInfo{}, err } infoList := make([]map[string]types.InfoItem, 0) for i := 0; i < len(res); i++ { infoList = append(infoList, tb.getTempModelData(res[i], params, columns)) } return PanelInfo{ InfoList: infoList, Thead: thead, Title: tb.Info.Title, Description: tb.Info.Description, }, nil } // TODO: refactor func (tb *DefaultTable) getDataFromDatabase(ctx *context.Context, params parameter.Parameters) (PanelInfo, error) { var ( connection = tb.db() delimiter = connection.GetDelimiter() delimiter2 = connection.GetDelimiter2() placeholder = modules.Delimiter(delimiter, delimiter2, "%s") queryStatement string countStatement string ids = params.PKs() table = modules.Delimiter(delimiter, delimiter2, tb.Info.Table) pk = table + "." + modules.Delimiter(delimiter, delimiter2, tb.PrimaryKey.Name) ) beginTime := time.Now() if len(ids) > 0 { countExtra := "" if connection.Name() == db.DriverMssql { countExtra = "as [size]" } // %s means: fields, table, join table, pk values, group by, order by field, order by type queryStatement = "select %s from " + placeholder + " %s where " + pk + " in (%s) %s ORDER BY %s." + placeholder + " %s" // %s means: table, join table, pk values countStatement = "select count(*) " + countExtra + " from " + placeholder + " %s where " + pk + " in (%s)" } else { if connection.Name() == db.DriverMssql { // %s means: order by field, order by type, fields, table, join table, wheres, group by queryStatement = "SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY %s." + placeholder + " %s) as ROWNUMBER_, %s from " + placeholder + "%s %s %s ) as TMP_ WHERE TMP_.ROWNUMBER_ > ? AND TMP_.ROWNUMBER_ <= ?" // %s means: table, join table, wheres countStatement = "select count(*) as [size] from (select 1 as [size] from " + placeholder + " %s %s %s) src" } else { // %s means: fields, table, join table, wheres, group by, order by field, order by type queryStatement = "select %s from " + placeholder + "%s %s %s order by " + placeholder + "." + placeholder + " %s LIMIT ? OFFSET ?" // %s means: table, join table, wheres countStatement = "select count(*) from (select " + pk + " from " + placeholder + " %s %s %s) src" } } columns, _ := tb.getColumns(tb.Info.Table) thead, fields, joinFields, joins, joinTables, filterForm := tb.getTheadAndFilterForm(params, columns) fields += pk allFields := fields groupFields := fields if joinFields != "" { allFields += "," + joinFields[:len(joinFields)-1] if connection.Name() == db.DriverMssql { for _, field := range tb.Info.FieldList { if field.TypeName == db.Text || field.TypeName == db.Longtext { f := modules.Delimiter(connection.GetDelimiter(), connection.GetDelimiter2(), field.Field) headField := table + "." + f allFields = strings.ReplaceAll(allFields, headField, "CAST("+headField+" AS NVARCHAR(MAX)) as "+f) groupFields = strings.ReplaceAll(groupFields, headField, "CAST("+headField+" AS NVARCHAR(MAX))") } } } } if !modules.InArray(columns, params.SortField) { params.SortField = tb.PrimaryKey.Name } var ( wheres = "" whereArgs = make([]interface{}, 0) args = make([]interface{}, 0) existKeys = make([]string, 0) ) if len(ids) > 0 { for _, value := range ids { if value != "" { wheres += "?," args = append(args, value) } } wheres = wheres[:len(wheres)-1] } else { // parameter wheres, whereArgs, existKeys = params.Statement(wheres, tb.Info.Table, connection.GetDelimiter(), connection.GetDelimiter2(), whereArgs, columns, existKeys, tb.Info.FieldList.GetFieldFilterProcessValue) // pre query wheres, whereArgs = tb.Info.Wheres.Statement(wheres, connection.GetDelimiter(), connection.GetDelimiter2(), whereArgs, existKeys, columns) wheres, whereArgs = tb.Info.WhereRaws.Statement(wheres, whereArgs) if wheres != "" { wheres = " where " + wheres } if connection.Name() == db.DriverMssql { args = append(whereArgs, (params.PageInt-1)*params.PageSizeInt, params.PageInt*params.PageSizeInt) } else { args = append(whereArgs, params.PageSizeInt, (params.PageInt-1)*params.PageSizeInt) } } groupBy := "" if len(joinTables) > 0 { if connection.Name() == db.DriverMssql || connection.Name() == db.DriverPostgresql { groupBy = " GROUP BY " + groupFields } else { groupBy = " GROUP BY " + pk } } queryCmd := "" if connection.Name() == db.DriverMssql && len(ids) == 0 { queryCmd = fmt.Sprintf(queryStatement, tb.Info.Table, params.SortField, params.SortType, allFields, tb.Info.Table, joins, wheres, groupBy) } else { queryCmd = fmt.Sprintf(queryStatement, allFields, tb.Info.Table, joins, wheres, groupBy, tb.Info.Table, params.SortField, params.SortType) } logger.LogSQL(queryCmd, args) res, err := connection.QueryWithConnection(tb.connection, queryCmd, args...) if err != nil { return PanelInfo{}, err } infoList := make([]map[string]types.InfoItem, 0) for i := 0; i < len(res); i++ { infoList = append(infoList, tb.getTempModelData(res[i], params, columns)) } // TODO: use the dialect var size int if len(ids) == 0 { countCmd := fmt.Sprintf(countStatement, tb.Info.Table, joins, wheres, groupBy) total, err := connection.QueryWithConnection(tb.connection, countCmd, whereArgs...) if err != nil { return PanelInfo{}, err } logger.LogSQL(countCmd, nil) if tb.connectionDriver == "postgresql" { if tb.connectionDriverMode == "h2" { size = int(total[0]["count(*)"].(int64)) } else if config.GetDatabases().GetDefault().DriverMode == "h2" { size = int(total[0]["count(*)"].(int64)) } else { size = int(total[0]["count"].(int64)) } } else if tb.connectionDriver == db.DriverMssql { size = int(total[0]["size"].(int64)) } else { size = int(total[0]["count(*)"].(int64)) } } endTime := time.Now() return PanelInfo{ Thead: thead, InfoList: infoList, Paginator: tb.GetPaginator(ctx, size, params, template.HTML(fmt.Sprintf(""+language.Get("query time")+": "+ fmt.Sprintf("%.3fms", endTime.Sub(beginTime).Seconds()*1000)))), Title: tb.Info.Title, FilterFormData: filterForm, Description: tb.Info.Description, }, nil } func getDataRes(list []map[string]interface{}, _ int) map[string]interface{} { if len(list) > 0 { return list[0] } return nil } // GetDataWithId query the single row of data. func (tb *DefaultTable) GetDataWithId(param parameter.Parameters) (FormInfo, error) { var ( res map[string]interface{} columns Columns id = param.PK() ) if tb.getDataFun != nil { res = getDataRes(tb.getDataFun(param)) } else if tb.sourceURL != "" { res = getDataRes(tb.getDataFromURL(param)) } else if tb.Detail.GetDataFn != nil { res = getDataRes(tb.Detail.GetDataFn(param)) } else if tb.Info.GetDataFn != nil { res = getDataRes(tb.Info.GetDataFn(param)) } else { columns, _ = tb.getColumns(tb.Form.Table) var ( fields, joinFields, joins, groupBy = "", "", "", "" err error joinTables = make([]string, 0) args = []interface{}{id} connection = tb.db() delimiter = connection.GetDelimiter() delimiter2 = connection.GetDelimiter2() tableName = modules.Delimiter(delimiter, delimiter2, tb.GetForm().Table) pk = tableName + "." + modules.Delimiter(delimiter, delimiter2, tb.PrimaryKey.Name) queryStatement = "select %s from %s %s where " + pk + " = ? %s " ) for i := 0; i < len(tb.Form.FieldList); i++ { if tb.Form.FieldList[i].Field != pk && modules.InArray(columns, tb.Form.FieldList[i].Field) && !tb.Form.FieldList[i].Joins.Valid() { fields += tableName + "." + modules.FilterField(tb.Form.FieldList[i].Field, delimiter, delimiter2) + "," } if tb.Form.FieldList[i].Joins.Valid() { headField := tb.Form.FieldList[i].Joins.Last().GetTableName() + parameter.FilterParamJoinInfix + tb.Form.FieldList[i].Field joinFields += db.GetAggregationExpression(connection.Name(), tb.Form.FieldList[i].Joins.Last().GetTableName(delimiter, delimiter2)+"."+ modules.FilterField(tb.Form.FieldList[i].Field, delimiter, delimiter2), headField, types.JoinFieldValueDelimiter) + "," for _, join := range tb.Form.FieldList[i].Joins { if !modules.InArray(joinTables, join.GetTableName(delimiter, delimiter2)) { joinTables = append(joinTables, join.GetTableName(delimiter, delimiter2)) if join.BaseTable == "" { join.BaseTable = tableName } joins += " left join " + modules.FilterField(join.Table, delimiter, delimiter2) + " " + join.TableAlias + " on " + join.GetTableName(delimiter, delimiter2) + "." + modules.FilterField(join.JoinField, delimiter, delimiter2) + " = " + join.BaseTable + "." + modules.FilterField(join.Field, delimiter, delimiter2) } } } } fields += pk groupFields := fields if joinFields != "" { fields += "," + joinFields[:len(joinFields)-1] if connection.Name() == db.DriverMssql { for i := 0; i < len(tb.Form.FieldList); i++ { if tb.Form.FieldList[i].TypeName == db.Text || tb.Form.FieldList[i].TypeName == db.Longtext { f := modules.Delimiter(connection.GetDelimiter(), connection.GetDelimiter2(), tb.Form.FieldList[i].Field) headField := tb.Info.Table + "." + f fields = strings.ReplaceAll(fields, headField, "CAST("+headField+" AS NVARCHAR(MAX)) as "+f) groupFields = strings.ReplaceAll(groupFields, headField, "CAST("+headField+" AS NVARCHAR(MAX))") } } } } if len(joinTables) > 0 { if connection.Name() == db.DriverMssql || connection.Name() == db.DriverPostgresql { groupBy = " GROUP BY " + groupFields } else { groupBy = " GROUP BY " + pk } } queryCmd := fmt.Sprintf(queryStatement, fields, tableName, joins, groupBy) logger.LogSQL(queryCmd, args) result, err := connection.QueryWithConnection(tb.connection, queryCmd, args...) if err != nil { return FormInfo{Title: tb.Form.Title, Description: tb.Form.Description}, err } if len(result) == 0 { return FormInfo{Title: tb.Form.Title, Description: tb.Form.Description}, errors.New(errs.WrongID) } res = result[0] } var ( groupFormList = make([]types.FormFields, 0) groupHeaders = make([]string, 0) ) if len(tb.Form.TabGroups) > 0 { groupFormList, groupHeaders = tb.Form.GroupFieldWithValue(tb.PrimaryKey.Name, id, columns, res, tb.sqlObjOrNil) return FormInfo{ FieldList: tb.Form.FieldList, GroupFieldList: groupFormList, GroupFieldHeaders: groupHeaders, Title: tb.Form.Title, Description: tb.Form.Description, }, nil } var fieldList = tb.Form.FieldsWithValue(tb.PrimaryKey.Name, id, columns, res, tb.sqlObjOrNil) return FormInfo{ FieldList: fieldList, GroupFieldList: groupFormList, GroupFieldHeaders: groupHeaders, Title: tb.Form.Title, Description: tb.Form.Description, }, nil } // UpdateData update data. func (tb *DefaultTable) UpdateData(ctx *context.Context, dataList form.Values) error { dataList.Add(form.PostTypeKey, "0") var ( errMsg = "" err error ) if tb.Form.PostHook != nil { defer func() { dataList.Add(form.PostTypeKey, "0") dataList.Add(form.PostResultKey, errMsg) go func() { defer func() { if err := recover(); err != nil { logger.ErrorCtx(ctx, "UpdateData error %+v", err) } }() err := tb.Form.PostHook(dataList) if err != nil { logger.ErrorCtx(ctx, "UpdateData PostHook error %+v", err) } }() }() } if tb.Form.Validator != nil { if err := tb.Form.Validator(dataList); err != nil { errMsg = "post error: " + err.Error() return err } } if tb.Form.PreProcessFn != nil { dataList = tb.Form.PreProcessFn(dataList) } if tb.Form.UpdateFn != nil { dataList.Delete(form.PostTypeKey) err = tb.Form.UpdateFn(tb.PreProcessValue(dataList, types.PostTypeUpdate)) if err != nil { errMsg = "post error: " + err.Error() } return err } if len(dataList) == 0 { return nil } _, err = tb.sql().Table(tb.Form.Table). Where(tb.PrimaryKey.Name, "=", dataList.Get(tb.PrimaryKey.Name)). Update(tb.getInjectValueFromFormValue(dataList, types.PostTypeUpdate)) // NOTE: some errors should be ignored. if db.CheckError(err, db.UPDATE) { if err != nil { errMsg = "post error: " + err.Error() } return err } return nil } // InsertData insert data. func (tb *DefaultTable) InsertData(ctx *context.Context, dataList form.Values) error { dataList.Add(form.PostTypeKey, "1") var ( id = int64(0) err error errMsg = "" f = tb.GetActualNewForm() ) if f.PostHook != nil { defer func() { dataList.Add(form.PostTypeKey, "1") dataList.Add(tb.GetPrimaryKey().Name, strconv.Itoa(int(id))) dataList.Add(form.PostResultKey, errMsg) go func() { defer func() { if err := recover(); err != nil { logger.ErrorCtx(ctx, "InsertData error %+v", err) } }() err := f.PostHook(dataList) if err != nil { logger.ErrorCtx(ctx, "InsertData PostHook error %+v", err) } }() }() } if f.Validator != nil { if err := f.Validator(dataList); err != nil { errMsg = "post error: " + err.Error() return err } } if f.PreProcessFn != nil { dataList = f.PreProcessFn(dataList) } if f.InsertFn != nil { dataList.Delete(form.PostTypeKey) err = f.InsertFn(tb.PreProcessValue(dataList, types.PostTypeCreate)) if err != nil { errMsg = "post error: " + err.Error() } return err } if len(dataList) == 0 { return nil } id, err = tb.sql().Table(f.Table).Insert(tb.getInjectValueFromFormValue(dataList, types.PostTypeCreate)) // NOTE: some errors should be ignored. if db.CheckError(err, db.INSERT) { errMsg = "post error: " + err.Error() return err } return nil } func (tb *DefaultTable) getInjectValueFromFormValue(dataList form.Values, typ types.PostType) dialect.H { var ( value = make(dialect.H) exceptString = make([]string, 0) columns, auto = tb.getColumns(tb.Form.Table) fun types.PostFieldFilterFn ) // If a key is a auto increment primary key, it can`t be insert or update. if auto { exceptString = []string{tb.PrimaryKey.Name, form.PreviousKey, form.MethodKey, form.TokenKey, constant.IframeKey, constant.IframeIDKey} } else { exceptString = []string{form.PreviousKey, form.MethodKey, form.TokenKey, constant.IframeKey, constant.IframeIDKey} } if !dataList.IsSingleUpdatePost() { for i := 0; i < len(tb.Form.FieldList); i++ { if tb.Form.FieldList[i].FormType.IsMultiSelect() { if _, ok := dataList[tb.Form.FieldList[i].Field+"[]"]; !ok { dataList[tb.Form.FieldList[i].Field+"[]"] = []string{""} } } } } dataList = dataList.RemoveRemark() for k, v := range dataList { k = strings.ReplaceAll(k, "[]", "") if !modules.InArray(exceptString, k) { if modules.InArray(columns, k) { field := tb.Form.FieldList.FindByFieldName(k) delimiter := "," if field != nil { fun = field.PostFilterFn delimiter = modules.SetDefault(field.DefaultOptionDelimiter, ",") } vv := modules.RemoveBlankFromArray(v) if fun != nil { value[k] = fun(types.PostFieldModel{ ID: dataList.Get(tb.PrimaryKey.Name), Value: vv, Row: dataList.ToMap(), PostType: typ, }) } else { if len(vv) > 1 { value[k] = strings.Join(vv, delimiter) } else if len(vv) > 0 { value[k] = vv[0] } else { value[k] = "" } } } else { field := tb.Form.FieldList.FindByFieldName(k) if field != nil && field.PostFilterFn != nil { field.PostFilterFn(types.PostFieldModel{ ID: dataList.Get(tb.PrimaryKey.Name), Value: modules.RemoveBlankFromArray(v), Row: dataList.ToMap(), PostType: typ, }) } } } } return value } func (tb *DefaultTable) PreProcessValue(dataList form.Values, typ types.PostType) form.Values { exceptString := []string{form.PreviousKey, form.MethodKey, form.TokenKey, constant.IframeKey, constant.IframeIDKey} dataList = dataList.RemoveRemark() var fun types.PostFieldFilterFn for k, v := range dataList { k = strings.ReplaceAll(k, "[]", "") if !modules.InArray(exceptString, k) { field := tb.Form.FieldList.FindByFieldName(k) if field != nil { fun = field.PostFilterFn } vv := modules.RemoveBlankFromArray(v) if fun != nil { dataList.Add(k, fmt.Sprintf("%s", fun(types.PostFieldModel{ ID: dataList.Get(tb.PrimaryKey.Name), Value: vv, Row: dataList.ToMap(), PostType: typ, }))) } } } return dataList } // DeleteData delete data. func (tb *DefaultTable) DeleteData(id string) error { var ( idArr = strings.Split(id, ",") err error ) if tb.Info.DeleteHook != nil { defer func() { go func() { defer func() { if recoverErr := recover(); recoverErr != nil { logger.Error(recoverErr) } }() if hookErr := tb.Info.DeleteHook(idArr); hookErr != nil { logger.Error(hookErr) } }() }() } if tb.Info.DeleteHookWithRes != nil { defer func() { go func() { defer func() { if recoverErr := recover(); recoverErr != nil { logger.Error(recoverErr) } }() if hookErr := tb.Info.DeleteHookWithRes(idArr, err); hookErr != nil { logger.Error(hookErr) } }() }() } if tb.Info.PreDeleteFn != nil { if err = tb.Info.PreDeleteFn(idArr); err != nil { return err } } if tb.Info.DeleteFn != nil { err = tb.Info.DeleteFn(idArr) return err } if len(idArr) == 0 || tb.Info.Table == "" { err = errors.New("delete error: wrong parameter") return err } err = tb.delete(tb.Info.Table, tb.PrimaryKey.Name, idArr) return err } func (tb *DefaultTable) GetNewFormInfo() FormInfo { f := tb.GetActualNewForm() if len(f.TabGroups) == 0 { return FormInfo{FieldList: f.FieldsWithDefaultValue(tb.sqlObjOrNil)} } newForm, headers := f.GroupField(tb.sqlObjOrNil) return FormInfo{GroupFieldList: newForm, GroupFieldHeaders: headers} } // *************************************** // helper function for database operation // *************************************** func (tb *DefaultTable) delete(table, key string, values []string) error { var vals = make([]interface{}, len(values)) for i, v := range values { vals[i] = v } return tb.sql().Table(table). WhereIn(key, vals). Delete() } func (tb *DefaultTable) getTheadAndFilterForm(params parameter.Parameters, columns Columns) (types.Thead, string, string, string, []string, []types.FormField) { return tb.Info.FieldList.GetTheadAndFilterForm(types.TableInfo{ Table: tb.Info.Table, Delimiter: tb.delimiter(), Delimiter2: tb.delimiter2(), Driver: tb.connectionDriver, PrimaryKey: tb.PrimaryKey.Name, }, params, columns, tb.sqlObjOrNil) } // db is a helper function return raw db connection. func (tb *DefaultTable) db() db.Connection { if tb.dbObj == nil { tb.dbObj = db.GetConnectionFromService(services.Get(tb.connectionDriver)) } return tb.dbObj } func (tb *DefaultTable) delimiter() string { if tb.getDataFromDB() { return tb.db().GetDelimiter() } return "" } func (tb *DefaultTable) delimiter2() string { if tb.getDataFromDB() { return tb.db().GetDelimiter2() } return "" } func (tb *DefaultTable) getDataFromDB() bool { return tb.sourceURL == "" && tb.getDataFun == nil && tb.Info.GetDataFn == nil && tb.Detail.GetDataFn == nil } // sql is a helper function return db sql. func (tb *DefaultTable) sql() *db.SQL { return db.WithDriverAndConnection(tb.connection, tb.db()) } // sqlObjOrNil is a helper function return db sql obj or nil. func (tb *DefaultTable) sqlObjOrNil() *db.SQL { if tb.connectionDriver != "" && tb.getDataFromDB() { return db.WithDriverAndConnection(tb.connection, tb.db()) } return nil } type Columns []string func (tb *DefaultTable) getColumns(table string) (Columns, bool) { columnsModel, _ := tb.sql().Table(table).ShowColumns() columns := make(Columns, len(columnsModel)) switch tb.connectionDriver { case db.DriverPostgresql: auto := false for key, model := range columnsModel { columns[key] = model["column_name"].(string) if columns[key] == tb.PrimaryKey.Name { if v, ok := model["column_default"].(string); ok { if strings.Contains(v, "nextval") { auto = true } } } } return columns, auto case db.DriverMysql: auto := false for key, model := range columnsModel { columns[key] = model["Field"].(string) if columns[key] == tb.PrimaryKey.Name { if v, ok := model["Extra"].(string); ok { if v == "auto_increment" { auto = true } } } } return columns, auto case db.DriverSqlite: for key, model := range columnsModel { columns[key] = string(model["name"].(string)) } num, _ := tb.sql().Table("sqlite_sequence"). Where("name", "=", tb.GetForm().Table).Count() return columns, num > 0 case db.DriverMssql: for key, model := range columnsModel { columns[key] = string(model["column_name"].(string)) } return columns, true default: panic("wrong driver") } } ================================================ FILE: plugins/admin/modules/table/default_test.go ================================================ package table ================================================ FILE: plugins/admin/modules/table/generators.go ================================================ package table import ( "database/sql" "errors" "fmt" tmpl "html/template" "net/url" "regexp" "strconv" "strings" "time" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/collection" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/db/dialect" errs "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/ui" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins/admin/models" form2 "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/tools" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/action" "github.com/GoAdminGroup/go-admin/template/types/form" selection "github.com/GoAdminGroup/go-admin/template/types/form/select" "github.com/GoAdminGroup/html" "golang.org/x/crypto/bcrypt" "golang.org/x/text/cases" textLang "golang.org/x/text/language" ) type SystemTable struct { conn db.Connection c *config.Config } func NewSystemTable(conn db.Connection, c *config.Config) *SystemTable { return &SystemTable{conn: conn, c: c} } var filterType = types.FilterType{NoIcon: true, HeadWidth: 4, InputWidth: 8} func (s *SystemTable) GetManagerTable(ctx *context.Context) (managerTable Table) { managerTable = NewDefaultTable(ctx, DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver)) info := managerTable.GetInfo().AddXssJsFilter().SetFilterFormLayout(form.LayoutFilter) info.AddField("ID", "id", db.Int).FieldSortable() filterType := types.FilterType{NoIcon: true, HeadWidth: 4, InputWidth: 8} info.AddField(lg("Name"), "username", db.Varchar).FieldFilterable(filterType) info.AddField(lg("Nickname"), "name", db.Varchar).FieldFilterable(filterType) info.AddField(lg("role"), "name", db.Varchar). FieldJoin(types.Join{ Table: "goadmin_role_users", JoinField: "user_id", Field: "id", }). FieldJoin(types.Join{ Table: "goadmin_roles", JoinField: "id", Field: "role_id", BaseTable: "goadmin_role_users", }). FieldDisplay(func(model types.FieldModel) interface{} { labels := template.HTML("") labelTpl := label(ctx).SetType("success") labelValues := strings.Split(model.Value, types.JoinFieldValueDelimiter) for key, label := range labelValues { if key == len(labelValues)-1 { labels += labelTpl.SetContent(template.HTML(label)).GetContent() } else { labels += labelTpl.SetContent(template.HTML(label)).GetContent() + "

    " } } if labels == template.HTML("") { return lg("no roles") } return labels }).FieldFilterable(filterType) info.AddField(lg("createdAt"), "created_at", db.Timestamp) info.AddField(lg("updatedAt"), "updated_at", db.Timestamp) info.SetTable("goadmin_users"). SetTitle(lg("Managers")). SetDescription(lg("Managers manage")). SetDeleteFn(func(idArr []string) error { var ids = interfaces(idArr) _, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) { deleteUserRoleErr := s.connection().WithTx(tx). Table("goadmin_role_users"). WhereIn("user_id", ids). Delete() if db.CheckError(deleteUserRoleErr, db.DELETE) { return deleteUserRoleErr, nil } deleteUserPermissionErr := s.connection().WithTx(tx). Table("goadmin_user_permissions"). WhereIn("user_id", ids). Delete() if db.CheckError(deleteUserPermissionErr, db.DELETE) { return deleteUserPermissionErr, nil } deleteUserErr := s.connection().WithTx(tx). Table("goadmin_users"). WhereIn("id", ids). Delete() if db.CheckError(deleteUserErr, db.DELETE) { return deleteUserErr, nil } return nil, nil }) return txErr }) formList := managerTable.GetForm().AddXssJsFilter() formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() formList.AddField(lg("Name"), "username", db.Varchar, form.Text). FieldHelpMsg(template.HTML(lg("use for login"))).FieldMust() formList.AddField(lg("Nickname"), "name", db.Varchar, form.Text). FieldHelpMsg(template.HTML(lg("use to display"))).FieldMust() formList.AddField(lg("Avatar"), "avatar", db.Varchar, form.File) formList.AddField(lg("role"), "role_id", db.Varchar, form.Select). FieldOptionsFromTable("goadmin_roles", "slug", "id"). FieldDisplay(func(model types.FieldModel) interface{} { var roles []string if model.ID == "" { return roles } roleModel, _ := s.table("goadmin_role_users").Select("role_id"). Where("user_id", "=", model.ID).All() for _, v := range roleModel { roles = append(roles, strconv.FormatInt(v["role_id"].(int64), 10)) } return roles }).FieldHelpMsg(template.HTML(lg("no corresponding options?")) + link("/admin/info/roles/new", "Create here.")) formList.AddField(lg("permission"), "permission_id", db.Varchar, form.Select). FieldOptionsFromTable("goadmin_permissions", "slug", "id"). FieldDisplay(func(model types.FieldModel) interface{} { var permissions []string if model.ID == "" { return permissions } permissionModel, _ := s.table("goadmin_user_permissions"). Select("permission_id").Where("user_id", "=", model.ID).All() for _, v := range permissionModel { permissions = append(permissions, strconv.FormatInt(v["permission_id"].(int64), 10)) } return permissions }).FieldHelpMsg(template.HTML(lg("no corresponding options?")) + link("/admin/info/permission/new", "Create here.")) formList.AddField(lg("password"), "password", db.Varchar, form.Password). FieldDisplay(func(value types.FieldModel) interface{} { return "" }) formList.AddField(lg("confirm password"), "password_again", db.Varchar, form.Password). FieldDisplay(func(value types.FieldModel) interface{} { return "" }) formList.SetTable("goadmin_users").SetTitle(lg("Managers")).SetDescription(lg("Managers manage")) formList.SetUpdateFn(func(values form2.Values) error { if values.IsEmpty("name", "username") { return errors.New("username and password can not be empty") } user := models.UserWithId(values.Get("id")).SetConn(s.conn) password := values.Get("password") if password != "" { if password != values.Get("password_again") { return errors.New("password does not match") } password = encodePassword([]byte(values.Get("password"))) } _, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) { avatar := values.Get("avatar") if values.Get("avatar__delete_flag") == "1" { avatar = "" } _, updateUserErr := user.WithTx(tx).Update(values.Get("username"), password, values.Get("name"), avatar, values.Get("avatar__change_flag") == "1") if db.CheckError(updateUserErr, db.UPDATE) { return updateUserErr, nil } delRoleErr := user.WithTx(tx).DeleteRoles() if db.CheckError(delRoleErr, db.DELETE) { return delRoleErr, nil } for i := 0; i < len(values["role_id[]"]); i++ { _, addRoleErr := user.WithTx(tx).AddRole(values["role_id[]"][i]) if db.CheckError(addRoleErr, db.INSERT) { return addRoleErr, nil } } delPermissionErr := user.WithTx(tx).DeletePermissions() if db.CheckError(delPermissionErr, db.DELETE) { return delPermissionErr, nil } for i := 0; i < len(values["permission_id[]"]); i++ { _, addPermissionErr := user.WithTx(tx).AddPermission(values["permission_id[]"][i]) if db.CheckError(addPermissionErr, db.INSERT) { return addPermissionErr, nil } } return nil, nil }) return txErr }) formList.SetInsertFn(func(values form2.Values) error { if values.IsEmpty("name", "username", "password") { return errors.New("username and password can not be empty") } password := values.Get("password") if password != values.Get("password_again") { return errors.New("password does not match") } _, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) { user, createUserErr := models.User().WithTx(tx).SetConn(s.conn).New(values.Get("username"), encodePassword([]byte(values.Get("password"))), values.Get("name"), values.Get("avatar")) if db.CheckError(createUserErr, db.INSERT) { return createUserErr, nil } for i := 0; i < len(values["role_id[]"]); i++ { _, addRoleErr := user.WithTx(tx).AddRole(values["role_id[]"][i]) if db.CheckError(addRoleErr, db.INSERT) { return addRoleErr, nil } } for i := 0; i < len(values["permission_id[]"]); i++ { _, addPermissionErr := user.WithTx(tx).AddPermission(values["permission_id[]"][i]) if db.CheckError(addPermissionErr, db.INSERT) { return addPermissionErr, nil } } return nil, nil }) return txErr }) detail := managerTable.GetDetail() detail.AddField("ID", "id", db.Int) detail.AddField(lg("Name"), "username", db.Varchar) detail.AddField(lg("Avatar"), "avatar", db.Varchar). FieldDisplay(func(model types.FieldModel) interface{} { if model.Value == "" || config.GetStore().Prefix == "" { model.Value = config.Url("/assets/dist/img/avatar04.png") } else { model.Value = config.GetStore().URL(model.Value) } return template.Default(ctx).Image(). SetSrc(template.HTML(model.Value)). SetHeight("120").SetWidth("120").WithModal().GetContent() }) detail.AddField(lg("Nickname"), "name", db.Varchar) detail.AddField(lg("role"), "roles", db.Varchar). FieldDisplay(func(model types.FieldModel) interface{} { labelModels, _ := s.table("goadmin_role_users"). Select("goadmin_roles.name"). LeftJoin("goadmin_roles", "goadmin_roles.id", "=", "goadmin_role_users.role_id"). Where("user_id", "=", model.ID). All() labels := template.HTML("") labelTpl := label(ctx).SetType("success") for key, label := range labelModels { if key == len(labelModels)-1 { labels += labelTpl.SetContent(template.HTML(label["name"].(string))).GetContent() } else { labels += labelTpl.SetContent(template.HTML(label["name"].(string))).GetContent() + "

    " } } if labels == template.HTML("") { return lg("no roles") } return labels }) detail.AddField(lg("permission"), "roles", db.Varchar). FieldDisplay(func(model types.FieldModel) interface{} { permissionModel, _ := s.table("goadmin_user_permissions"). Select("goadmin_permissions.name"). LeftJoin("goadmin_permissions", "goadmin_permissions.id", "=", "goadmin_user_permissions.permission_id"). Where("user_id", "=", model.ID). All() permissions := template.HTML("") permissionTpl := label(ctx).SetType("success") for key, label := range permissionModel { if key == len(permissionModel)-1 { permissions += permissionTpl.SetContent(template.HTML(label["name"].(string))).GetContent() } else { permissions += permissionTpl.SetContent(template.HTML(label["name"].(string))).GetContent() + "

    " } } return permissions }) detail.AddField(lg("createdAt"), "created_at", db.Timestamp) detail.AddField(lg("updatedAt"), "updated_at", db.Timestamp) return } func (s *SystemTable) GetNormalManagerTable(ctx *context.Context) (managerTable Table) { managerTable = NewDefaultTable(ctx, DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver)) info := managerTable.GetInfo().AddXssJsFilter().SetFilterFormLayout(form.LayoutFilter) info.AddField("ID", "id", db.Int).FieldSortable() info.AddField(lg("Name"), "username", db.Varchar).FieldFilterable(filterType) info.AddField(lg("Nickname"), "name", db.Varchar).FieldFilterable(filterType) info.AddField(lg("role"), "name", db.Varchar). FieldJoin(types.Join{ Table: "goadmin_role_users", JoinField: "user_id", Field: "id", }). FieldJoin(types.Join{ Table: "goadmin_roles", JoinField: "id", Field: "role_id", BaseTable: "goadmin_role_users", }). FieldDisplay(func(model types.FieldModel) interface{} { labels := template.HTML("") labelTpl := label(ctx).SetType("success") labelValues := strings.Split(model.Value, types.JoinFieldValueDelimiter) for key, label := range labelValues { if key == len(labelValues)-1 { labels += labelTpl.SetContent(template.HTML(label)).GetContent() } else { labels += labelTpl.SetContent(template.HTML(label)).GetContent() + "

    " } } if labels == template.HTML("") { return lg("no roles") } return labels }) info.AddField(lg("createdAt"), "created_at", db.Timestamp) info.AddField(lg("updatedAt"), "updated_at", db.Timestamp) info.SetTable("goadmin_users"). SetTitle(lg("Managers")). SetDescription(lg("Managers manage")). SetDeleteFn(func(idArr []string) error { var ids = interfaces(idArr) _, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) { deleteUserRoleErr := s.connection().WithTx(tx). Table("goadmin_role_users"). WhereIn("user_id", ids). Delete() if db.CheckError(deleteUserRoleErr, db.DELETE) { return deleteUserRoleErr, nil } deleteUserPermissionErr := s.connection().WithTx(tx). Table("goadmin_user_permissions"). WhereIn("user_id", ids). Delete() if db.CheckError(deleteUserPermissionErr, db.DELETE) { return deleteUserPermissionErr, nil } deleteUserErr := s.connection().WithTx(tx). Table("goadmin_users"). WhereIn("id", ids). Delete() if db.CheckError(deleteUserErr, db.DELETE) { return deleteUserErr, nil } return nil, nil }) return txErr }) formList := managerTable.GetForm().AddXssJsFilter() formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() formList.AddField(lg("Name"), "username", db.Varchar, form.Text).FieldHelpMsg(template.HTML(lg("use for login"))).FieldMust() formList.AddField(lg("Nickname"), "name", db.Varchar, form.Text).FieldHelpMsg(template.HTML(lg("use to display"))).FieldMust() formList.AddField(lg("Avatar"), "avatar", db.Varchar, form.File) formList.AddField(lg("password"), "password", db.Varchar, form.Password). FieldDisplay(func(value types.FieldModel) interface{} { return "" }) formList.AddField(lg("confirm password"), "password_again", db.Varchar, form.Password). FieldDisplay(func(value types.FieldModel) interface{} { return "" }) formList.SetTable("goadmin_users").SetTitle(lg("Managers")).SetDescription(lg("Managers")) formList.SetUpdateFn(func(values form2.Values) error { if values.IsEmpty("name", "username") { return errors.New("username and password can not be empty") } user := models.UserWithId(values.Get("id")).SetConn(s.conn) if values.Has("permission", "role") { return errors.New(errs.NoPermission) } password := values.Get("password") if password != "" { if password != values.Get("password_again") { return errors.New("password does not match") } password = encodePassword([]byte(values.Get("password"))) } avatar := values.Get("avatar") if values.Get("avatar__delete_flag") == "1" { avatar = "" } _, updateUserErr := user.Update(values.Get("username"), password, values.Get("name"), avatar, values.Get("avatar__change_flag") == "1") if db.CheckError(updateUserErr, db.UPDATE) { return updateUserErr } return nil }) formList.SetInsertFn(func(values form2.Values) error { if values.IsEmpty("name", "username", "password") { return errors.New("username and password can not be empty") } password := values.Get("password") if password != values.Get("password_again") { return errors.New("password does not match") } if values.Has("permission", "role") { return errors.New(errs.NoPermission) } _, createUserErr := models.User().SetConn(s.conn).New(values.Get("username"), encodePassword([]byte(values.Get("password"))), values.Get("name"), values.Get("avatar")) if db.CheckError(createUserErr, db.INSERT) { return createUserErr } return nil }) return } func (s *SystemTable) GetPermissionTable(ctx *context.Context) (permissionTable Table) { permissionTable = NewDefaultTable(ctx, DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver)) info := permissionTable.GetInfo().AddXssJsFilter().SetFilterFormLayout(form.LayoutFilter) info.AddField("ID", "id", db.Int).FieldSortable() info.AddField(lg("permission"), "name", db.Varchar).FieldFilterable(filterType) info.AddField(lg("slug"), "slug", db.Varchar).FieldFilterable(filterType) info.AddField(lg("method"), "http_method", db.Varchar).FieldDisplay(func(value types.FieldModel) interface{} { if value.Value == "" { return "All methods" } return value.Value }) info.AddField(lg("path"), "http_path", db.Varchar). FieldDisplay(func(model types.FieldModel) interface{} { pathArr := strings.Split(model.Value, "\n") res := "" for i := 0; i < len(pathArr); i++ { if i == len(pathArr)-1 { res += string(label(ctx).SetContent(template.HTML(pathArr[i])).GetContent()) } else { res += string(label(ctx).SetContent(template.HTML(pathArr[i])).GetContent()) + "

    " } } return res }) info.AddField(lg("createdAt"), "created_at", db.Timestamp) info.AddField(lg("updatedAt"), "updated_at", db.Timestamp) info.SetTable("goadmin_permissions"). SetTitle(lg("Permission")). SetDescription(lg("Permission Manage")). SetDeleteFn(func(idArr []string) error { var ids = interfaces(idArr) _, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) { deleteRolePermissionErr := s.connection().WithTx(tx). Table("goadmin_role_permissions"). WhereIn("permission_id", ids). Delete() if db.CheckError(deleteRolePermissionErr, db.DELETE) { return deleteRolePermissionErr, nil } deleteUserPermissionErr := s.connection().WithTx(tx). Table("goadmin_user_permissions"). WhereIn("permission_id", ids). Delete() if db.CheckError(deleteUserPermissionErr, db.DELETE) { return deleteUserPermissionErr, nil } deletePermissionsErr := s.connection().WithTx(tx). Table("goadmin_permissions"). WhereIn("id", ids). Delete() if deletePermissionsErr != nil { return deletePermissionsErr, nil } return nil, nil }) return txErr }) formList := permissionTable.GetForm().AddXssJsFilter() formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() formList.AddField(lg("permission"), "name", db.Varchar, form.Text).FieldMust() formList.AddField(lg("slug"), "slug", db.Varchar, form.Text).FieldHelpMsg(template.HTML(lg("should be unique"))).FieldMust() formList.AddField(lg("method"), "http_method", db.Varchar, form.Select). FieldOptions(types.FieldOptions{ {Value: "GET", Text: "GET"}, {Value: "PUT", Text: "PUT"}, {Value: "POST", Text: "POST"}, {Value: "DELETE", Text: "DELETE"}, {Value: "PATCH", Text: "PATCH"}, {Value: "OPTIONS", Text: "OPTIONS"}, {Value: "HEAD", Text: "HEAD"}, }). FieldDisplay(func(model types.FieldModel) interface{} { return strings.Split(model.Value, ",") }). FieldPostFilterFn(func(model types.PostFieldModel) interface{} { return strings.Join(model.Value, ",") }). FieldHelpMsg(template.HTML(lg("all method if empty"))) formList.AddField(lg("path"), "http_path", db.Varchar, form.TextArea). FieldPostFilterFn(func(model types.PostFieldModel) interface{} { return strings.TrimSpace(model.Value.Value()) }). FieldHelpMsg(template.HTML(lg("a path a line, without global prefix"))) formList.AddField(lg("updatedAt"), "updated_at", db.Timestamp, form.Default).FieldDisableWhenCreate() formList.AddField(lg("createdAt"), "created_at", db.Timestamp, form.Default).FieldDisableWhenCreate() formList.SetTable("goadmin_permissions"). SetTitle(lg("Permission Manage")). SetDescription(lg("Permission Manage")). SetPostValidator(func(values form2.Values) error { if values.IsEmpty("slug", "http_path", "name") { return errors.New("slug or http_path or name should not be empty") } if models.Permission().SetConn(s.conn).IsSlugExist(values.Get("slug"), values.Get("id")) { return errors.New("slug exists") } return nil }).SetPostHook(func(values form2.Values) error { if values.IsInsertPost() { return nil } _, err := s.connection().Table("goadmin_permissions"). Where("id", "=", values.Get("id")). Update(dialect.H{ "updated_at": time.Now().Format("2006-01-02 15:04:05"), }) if db.CheckError(err, db.UPDATE) { return err } return nil }) return } func (s *SystemTable) GetRolesTable(ctx *context.Context) (roleTable Table) { roleTable = NewDefaultTable(ctx, DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver)) info := roleTable.GetInfo().AddXssJsFilter().SetFilterFormLayout(form.LayoutFilter) info.AddField("ID", "id", db.Int).FieldSortable() info.AddField(lg("role"), "name", db.Varchar).FieldFilterable(filterType) info.AddField(lg("slug"), "slug", db.Varchar).FieldFilterable(filterType) info.AddField(lg("createdAt"), "created_at", db.Timestamp) info.AddField(lg("updatedAt"), "updated_at", db.Timestamp) info.SetTable("goadmin_roles"). SetTitle(lg("Roles")). SetDescription(lg("Roles Manage")). SetDeleteFn(func(idArr []string) error { var ids = interfaces(idArr) _, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) { deleteRoleUserErr := s.connection().WithTx(tx). Table("goadmin_role_users"). WhereIn("role_id", ids). Delete() if db.CheckError(deleteRoleUserErr, db.DELETE) { return deleteRoleUserErr, nil } deleteRoleMenuErr := s.connection().WithTx(tx). Table("goadmin_role_menu"). WhereIn("role_id", ids). Delete() if db.CheckError(deleteRoleMenuErr, db.DELETE) { return deleteRoleMenuErr, nil } deleteRolePermissionErr := s.connection().WithTx(tx). Table("goadmin_role_permissions"). WhereIn("role_id", ids). Delete() if db.CheckError(deleteRolePermissionErr, db.DELETE) { return deleteRolePermissionErr, nil } deleteRolesErr := s.connection().WithTx(tx). Table("goadmin_roles"). WhereIn("id", ids). Delete() if db.CheckError(deleteRolesErr, db.DELETE) { return deleteRolesErr, nil } return nil, nil }) return txErr }) formList := roleTable.GetForm().AddXssJsFilter() formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() formList.AddField(lg("role"), "name", db.Varchar, form.Text).FieldMust() formList.AddField(lg("slug"), "slug", db.Varchar, form.Text).FieldHelpMsg(template.HTML(lg("should be unique"))).FieldMust() formList.AddField(lg("permission"), "permission_id", db.Varchar, form.SelectBox). FieldOptionsFromTable("goadmin_permissions", "name", "id"). FieldDisplay(func(model types.FieldModel) interface{} { var permissions = make([]string, 0) if model.ID == "" { return permissions } perModel, _ := s.table("goadmin_role_permissions"). Select("permission_id"). Where("role_id", "=", model.ID). All() for _, v := range perModel { permissions = append(permissions, strconv.FormatInt(v["permission_id"].(int64), 10)) } return permissions }).FieldHelpMsg(template.HTML(lg("no corresponding options?")) + link("/admin/info/permission/new", "Create here.")) formList.AddField(lg("updatedAt"), "updated_at", db.Timestamp, form.Default).FieldDisableWhenCreate() formList.AddField(lg("createdAt"), "created_at", db.Timestamp, form.Default).FieldDisableWhenCreate() formList.SetTable("goadmin_roles"). SetTitle(lg("Roles")). SetDescription(lg("Roles Manage")) formList.SetUpdateFn(func(values form2.Values) error { if models.Role().SetConn(s.conn).IsSlugExist(values.Get("slug"), values.Get("id")) { return errors.New("slug exists") } role := models.RoleWithId(values.Get("id")).SetConn(s.conn) _, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) { _, updateRoleErr := role.WithTx(tx).Update(values.Get("name"), values.Get("slug")) if db.CheckError(updateRoleErr, db.UPDATE) { return updateRoleErr, nil } delPermissionErr := role.WithTx(tx).DeletePermissions() if db.CheckError(delPermissionErr, db.DELETE) { return delPermissionErr, nil } for i := 0; i < len(values["permission_id[]"]); i++ { _, addPermissionErr := role.WithTx(tx).AddPermission(values["permission_id[]"][i]) if db.CheckError(addPermissionErr, db.INSERT) { return addPermissionErr, nil } } return nil, nil }) return txErr }) formList.SetInsertFn(func(values form2.Values) error { if models.Role().SetConn(s.conn).IsSlugExist(values.Get("slug"), "") { return errors.New("slug exists") } _, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) { role, createRoleErr := models.Role().WithTx(tx).SetConn(s.conn).New(values.Get("name"), values.Get("slug")) if db.CheckError(createRoleErr, db.INSERT) { return createRoleErr, nil } for i := 0; i < len(values["permission_id[]"]); i++ { _, addPermissionErr := role.WithTx(tx).AddPermission(values["permission_id[]"][i]) if db.CheckError(addPermissionErr, db.INSERT) { return addPermissionErr, nil } } return nil, nil }) return txErr }) return } func (s *SystemTable) GetOpTable(ctx *context.Context) (opTable Table) { opTable = NewDefaultTable(ctx, Config{ Driver: config.GetDatabases().GetDefault().Driver, CanAdd: false, Editable: false, Deletable: config.GetAllowDelOperationLog(), Exportable: true, Connection: "default", PrimaryKey: PrimaryKey{ Type: db.Int, Name: DefaultPrimaryKeyName, }, }) info := opTable.GetInfo().AddXssJsFilter(). HideDetailButton().HideEditButton().HideNewButton().SetFilterFormLayout(form.LayoutFilter) if !config.GetAllowDelOperationLog() { info = info.HideDeleteButton() } info.AddField("ID", "id", db.Int).FieldSortable() info.AddField("userID", "user_id", db.Int).FieldHide() info.AddField(lg("user"), "name", db.Varchar).FieldJoin(types.Join{ Table: config.GetAuthUserTable(), JoinField: "id", Field: "user_id", }).FieldDisplay(func(value types.FieldModel) interface{} { return template.Default(ctx). Link(). SetURL(config.Url("/info/manager/detail?__goadmin_detail_pk=") + strconv.Itoa(int(value.Row["user_id"].(int64)))). SetContent(template.HTML(value.Value)). OpenInNewTab(). SetTabTitle("Manager Detail"). GetContent() }) info.AddField(lg("path"), "path", db.Varchar).FieldFilterable(filterType) info.AddField(lg("method"), "method", db.Varchar) info.AddField(lg("ip"), "ip", db.Varchar).FieldFilterable(filterType) info.AddField(lg("content"), "input", db.Text).FieldWidth(230) info.AddField(lg("createdAt"), "created_at", db.Timestamp) users, _ := s.table(config.GetAuthUserTable()).Select("id", "name").All() options := make(types.FieldOptions, len(users)) for k, user := range users { options[k].Value = fmt.Sprintf("%v", user["id"]) options[k].Text = fmt.Sprintf("%v", user["name"]) } info.AddSelectBox(ctx, language.Get("user"), options, action.FieldFilter("user_id")) info.AddSelectBox(ctx, language.Get("method"), types.FieldOptions{ {Value: "GET", Text: "GET"}, {Value: "POST", Text: "POST"}, {Value: "OPTIONS", Text: "OPTIONS"}, {Value: "PUT", Text: "PUT"}, {Value: "HEAD", Text: "HEAD"}, {Value: "DELETE", Text: "DELETE"}, }, action.FieldFilter("method")) info.SetTable("goadmin_operation_log"). SetTitle(lg("operation log")). SetDescription(lg("operation log")) formList := opTable.GetForm().AddXssJsFilter() formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() formList.AddField(lg("userID"), "user_id", db.Int, form.Text) formList.AddField(lg("path"), "path", db.Varchar, form.Text) formList.AddField(lg("method"), "method", db.Varchar, form.Text) formList.AddField(lg("ip"), "ip", db.Varchar, form.Text) formList.AddField(lg("content"), "input", db.Varchar, form.Text) formList.AddField(lg("updatedAt"), "updated_at", db.Timestamp, form.Default).FieldDisableWhenCreate() formList.AddField(lg("createdAt"), "created_at", db.Timestamp, form.Default).FieldDisableWhenCreate() formList.SetTable("goadmin_operation_log"). SetTitle(lg("operation log")). SetDescription(lg("operation log")) return } func (s *SystemTable) GetMenuTable(ctx *context.Context) (menuTable Table) { menuTable = NewDefaultTable(ctx, DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver)) name := ctx.Query("__plugin_name") info := menuTable.GetInfo().AddXssJsFilter().HideFilterArea().Where("plugin_name", "=", name) info.AddField("ID", "id", db.Int).FieldSortable() info.AddField(lg("parent"), "parent_id", db.Int) info.AddField(lg("menu name"), "title", db.Varchar) info.AddField(lg("icon"), "icon", db.Varchar) info.AddField(lg("uri"), "uri", db.Varchar) info.AddField(lg("role"), "roles", db.Varchar) info.AddField(lg("header"), "header", db.Varchar) info.AddField(lg("createdAt"), "created_at", db.Timestamp) info.AddField(lg("updatedAt"), "updated_at", db.Timestamp) info.SetTable("goadmin_menu"). SetTitle(lg("Menus Manage")). SetDescription(lg("Menus Manage")). SetDeleteFn(func(idArr []string) error { var ids = interfaces(idArr) _, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) { deleteRoleMenuErr := s.connection().WithTx(tx). Table("goadmin_role_menu"). WhereIn("menu_id", ids). Delete() if db.CheckError(deleteRoleMenuErr, db.DELETE) { return deleteRoleMenuErr, nil } deleteMenusErr := s.connection().WithTx(tx). Table("goadmin_menu"). WhereIn("id", ids). Delete() if db.CheckError(deleteMenusErr, db.DELETE) { return deleteMenusErr, nil } return nil, map[string]interface{}{} }) return txErr }) var parentIDOptions = types.FieldOptions{ { Text: "ROOT", Value: "0", }, } allMenus, _ := s.connection().Table("goadmin_menu"). Where("parent_id", "=", 0). Where("plugin_name", "=", name). Select("id", "title"). OrderBy("order", "asc"). All() allMenuIDs := make([]interface{}, len(allMenus)) if len(allMenuIDs) > 0 { for i := 0; i < len(allMenus); i++ { allMenuIDs[i] = allMenus[i]["id"] } secondLevelMenus, _ := s.connection().Table("goadmin_menu"). WhereIn("parent_id", allMenuIDs). Where("plugin_name", "=", name). Select("id", "title", "parent_id"). All() secondLevelMenusCol := collection.Collection(secondLevelMenus) for i := 0; i < len(allMenus); i++ { parentIDOptions = append(parentIDOptions, types.FieldOption{ TextHTML: "  ┝ " + language.GetFromHtml(template.HTML(allMenus[i]["title"].(string))), Value: strconv.Itoa(int(allMenus[i]["id"].(int64))), }) col := secondLevelMenusCol.Where("parent_id", "=", allMenus[i]["id"].(int64)) for i := 0; i < len(col); i++ { parentIDOptions = append(parentIDOptions, types.FieldOption{ TextHTML: "         ┝ " + language.GetFromHtml(template.HTML(col[i]["title"].(string))), Value: strconv.Itoa(int(col[i]["id"].(int64))), }) } } } formList := menuTable.GetForm().AddXssJsFilter() formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() formList.AddField(lg("parent"), "parent_id", db.Int, form.SelectSingle). FieldOptions(parentIDOptions). FieldDisplay(func(model types.FieldModel) interface{} { var menuItem []string if model.ID == "" { return menuItem } menuModel, _ := s.table("goadmin_menu").Select("parent_id").Find(model.ID) menuItem = append(menuItem, strconv.FormatInt(menuModel["parent_id"].(int64), 10)) return menuItem }) formList.AddField(lg("menu name"), "title", db.Varchar, form.Text).FieldMust() formList.AddField(lg("header"), "header", db.Varchar, form.Text) formList.AddField(lg("icon"), "icon", db.Varchar, form.IconPicker) formList.AddField(lg("uri"), "uri", db.Varchar, form.Text) formList.AddField("PluginName", "plugin_name", db.Varchar, form.Text).FieldDefault(name).FieldHide() formList.AddField(lg("role"), "roles", db.Int, form.Select). FieldOptionsFromTable("goadmin_roles", "slug", "id"). FieldDisplay(func(model types.FieldModel) interface{} { var roles []string if model.ID == "" { return roles } roleModel, _ := s.table("goadmin_role_menu"). Select("role_id"). Where("menu_id", "=", model.ID). All() for _, v := range roleModel { roles = append(roles, strconv.FormatInt(v["role_id"].(int64), 10)) } return roles }) formList.AddField(lg("updatedAt"), "updated_at", db.Timestamp, form.Default).FieldDisableWhenCreate() formList.AddField(lg("createdAt"), "created_at", db.Timestamp, form.Default).FieldDisableWhenCreate() formList.SetTable("goadmin_menu"). SetTitle(lg("Menus Manage")). SetDescription(lg("Menus Manage")) return } func (s *SystemTable) GetSiteTable(ctx *context.Context) (siteTable Table) { siteTable = NewDefaultTable(ctx, DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver). SetOnlyUpdateForm(). SetGetDataFun(func(params parameter.Parameters) (i []map[string]interface{}, i2 int) { return []map[string]interface{}{models.Site().SetConn(s.conn).AllToMapInterface()}, 1 })) trueStr := lgWithConfigScore("true") falseStr := lgWithConfigScore("false") formList := siteTable.GetForm().AddXssJsFilter() formList.AddField("ID", "id", db.Varchar, form.Default).FieldDefault("1").FieldHide() formList.AddField(lgWithConfigScore("site off"), "site_off", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("debug"), "debug", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("env"), "env", db.Varchar, form.Default). FieldDisplay(func(value types.FieldModel) interface{} { return s.c.Env }) langOps := make(types.FieldOptions, len(language.Langs)) for k, t := range language.Langs { langOps[k] = types.FieldOption{Text: lgWithConfigScore(t, "language"), Value: t} } formList.AddField(lgWithConfigScore("language"), "language", db.Varchar, form.SelectSingle). FieldDisplay(func(value types.FieldModel) interface{} { return language.FixedLanguageKey(value.Value) }). FieldOptions(langOps) themes := template.Themes() themesOps := make(types.FieldOptions, len(themes)) for k, t := range themes { themesOps[k] = types.FieldOption{Text: t, Value: t} } formList.AddField(lgWithConfigScore("theme"), "theme", db.Varchar, form.SelectSingle). FieldOptions(themesOps). FieldOnChooseShow("adminlte", "color_scheme") formList.AddField(lgWithConfigScore("title"), "title", db.Varchar, form.Text).FieldMust() formList.AddField(lgWithConfigScore("color scheme"), "color_scheme", db.Varchar, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: "skin-black", Value: "skin-black"}, {Text: "skin-black-light", Value: "skin-black-light"}, {Text: "skin-blue", Value: "skin-blue"}, {Text: "skin-blue-light", Value: "skin-blue-light"}, {Text: "skin-green", Value: "skin-green"}, {Text: "skin-green-light", Value: "skin-green-light"}, {Text: "skin-purple", Value: "skin-purple"}, {Text: "skin-purple-light", Value: "skin-purple-light"}, {Text: "skin-red", Value: "skin-red"}, {Text: "skin-red-light", Value: "skin-red-light"}, {Text: "skin-yellow", Value: "skin-yellow"}, {Text: "skin-yellow-light", Value: "skin-yellow-light"}, }).FieldHelpMsg(template.HTML(lgWithConfigScore("It will work when theme is adminlte"))) formList.AddField(lgWithConfigScore("login title"), "login_title", db.Varchar, form.Text).FieldMust() formList.AddField(lgWithConfigScore("extra"), "extra", db.Varchar, form.TextArea) formList.AddField(lgWithConfigScore("logo"), "logo", db.Varchar, form.Code).FieldMust() formList.AddField(lgWithConfigScore("mini logo"), "mini_logo", db.Varchar, form.Code).FieldMust() if s.c.IsNotProductionEnvironment() { formList.AddField(lgWithConfigScore("bootstrap file path"), "bootstrap_file_path", db.Varchar, form.Text) formList.AddField(lgWithConfigScore("go mod file path"), "go_mod_file_path", db.Varchar, form.Text) } formList.AddField(lgWithConfigScore("session life time"), "session_life_time", db.Varchar, form.Number). FieldMust(). FieldHelpMsg(template.HTML(lgWithConfigScore("must bigger than 900 seconds"))) formList.AddField(lgWithConfigScore("custom head html"), "custom_head_html", db.Varchar, form.Code) formList.AddField(lgWithConfigScore("custom foot Html"), "custom_foot_html", db.Varchar, form.Code) formList.AddField(lgWithConfigScore("custom 404 html"), "custom_404_html", db.Varchar, form.Code) formList.AddField(lgWithConfigScore("custom 403 html"), "custom_403_html", db.Varchar, form.Code) formList.AddField(lgWithConfigScore("custom 500 Html"), "custom_500_html", db.Varchar, form.Code) formList.AddField(lgWithConfigScore("footer info"), "footer_info", db.Varchar, form.Code) formList.AddField(lgWithConfigScore("login logo"), "login_logo", db.Varchar, form.Code) formList.AddField(lgWithConfigScore("no limit login ip"), "no_limit_login_ip", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("operation log off"), "operation_log_off", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("allow delete operation log"), "allow_del_operation_log", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("hide config center entrance"), "hide_config_center_entrance", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("hide app info entrance"), "hide_app_info_entrance", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("hide tool entrance"), "hide_tool_entrance", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("hide plugin entrance"), "hide_plugin_entrance", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("animation type"), "animation_type", db.Varchar, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: "", Value: ""}, {Text: "bounce", Value: "bounce"}, {Text: "flash", Value: "flash"}, {Text: "pulse", Value: "pulse"}, {Text: "rubberBand", Value: "rubberBand"}, {Text: "shake", Value: "shake"}, {Text: "swing", Value: "swing"}, {Text: "tada", Value: "tada"}, {Text: "wobble", Value: "wobble"}, {Text: "jello", Value: "jello"}, {Text: "heartBeat", Value: "heartBeat"}, {Text: "bounceIn", Value: "bounceIn"}, {Text: "bounceInDown", Value: "bounceInDown"}, {Text: "bounceInLeft", Value: "bounceInLeft"}, {Text: "bounceInRight", Value: "bounceInRight"}, {Text: "bounceInUp", Value: "bounceInUp"}, {Text: "fadeIn", Value: "fadeIn"}, {Text: "fadeInDown", Value: "fadeInDown"}, {Text: "fadeInDownBig", Value: "fadeInDownBig"}, {Text: "fadeInLeft", Value: "fadeInLeft"}, {Text: "fadeInLeftBig", Value: "fadeInLeftBig"}, {Text: "fadeInRight", Value: "fadeInRight"}, {Text: "fadeInRightBig", Value: "fadeInRightBig"}, {Text: "fadeInUp", Value: "fadeInUp"}, {Text: "fadeInUpBig", Value: "fadeInUpBig"}, {Text: "flip", Value: "flip"}, {Text: "flipInX", Value: "flipInX"}, {Text: "flipInY", Value: "flipInY"}, {Text: "lightSpeedIn", Value: "lightSpeedIn"}, {Text: "rotateIn", Value: "rotateIn"}, {Text: "rotateInDownLeft", Value: "rotateInDownLeft"}, {Text: "rotateInDownRight", Value: "rotateInDownRight"}, {Text: "rotateInUpLeft", Value: "rotateInUpLeft"}, {Text: "rotateInUpRight", Value: "rotateInUpRight"}, {Text: "slideInUp", Value: "slideInUp"}, {Text: "slideInDown", Value: "slideInDown"}, {Text: "slideInLeft", Value: "slideInLeft"}, {Text: "slideInRight", Value: "slideInRight"}, {Text: "slideOutRight", Value: "slideOutRight"}, {Text: "zoomIn", Value: "zoomIn"}, {Text: "zoomInDown", Value: "zoomInDown"}, {Text: "zoomInLeft", Value: "zoomInLeft"}, {Text: "zoomInRight", Value: "zoomInRight"}, {Text: "zoomInUp", Value: "zoomInUp"}, {Text: "hinge", Value: "hinge"}, {Text: "jackInTheBox", Value: "jackInTheBox"}, {Text: "rollIn", Value: "rollIn"}, }).FieldOnChooseHide("", "animation_duration", "animation_delay"). FieldOptionExt(map[string]interface{}{"allowClear": true}). FieldHelpMsg(`see more: https://daneden.github.io/animate.css/`) formList.AddField(lgWithConfigScore("animation duration"), "animation_duration", db.Varchar, form.Number) formList.AddField(lgWithConfigScore("animation delay"), "animation_delay", db.Varchar, form.Number) formList.AddField(lgWithConfigScore("file upload engine"), "file_upload_engine", db.Varchar, form.Text) formList.AddField(lgWithConfigScore("cdn url"), "asset_url", db.Varchar, form.Text). FieldHelpMsg(template.HTML(lgWithConfigScore("Do not modify when you have not set up all assets"))) formList.AddField(lgWithConfigScore("info log path"), "info_log_path", db.Varchar, form.Text) formList.AddField(lgWithConfigScore("error log path"), "error_log_path", db.Varchar, form.Text) formList.AddField(lgWithConfigScore("access log path"), "access_log_path", db.Varchar, form.Text) formList.AddField(lgWithConfigScore("info log off"), "info_log_off", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("error log off"), "error_log_off", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("access log off"), "access_log_off", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("access assets log off"), "access_assets_log_off", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("sql log on"), "sql_log", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }) formList.AddField(lgWithConfigScore("log level"), "logger_level", db.Varchar, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: "Debug", Value: "-1"}, {Text: "Info", Value: "0"}, {Text: "Warn", Value: "1"}, {Text: "Error", Value: "2"}, }).FieldDisplay(defaultFilterFn("0")) formList.AddField(lgWithConfigScore("logger rotate max size"), "logger_rotate_max_size", db.Varchar, form.Number). FieldDivider(lgWithConfigScore("logger rotate")).FieldDisplay(defaultFilterFn("10", "0")) formList.AddField(lgWithConfigScore("logger rotate max backups"), "logger_rotate_max_backups", db.Varchar, form.Number). FieldDisplay(defaultFilterFn("5", "0")) formList.AddField(lgWithConfigScore("logger rotate max age"), "logger_rotate_max_age", db.Varchar, form.Number). FieldDisplay(defaultFilterFn("30", "0")) formList.AddField(lgWithConfigScore("logger rotate compress"), "logger_rotate_compress", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: trueStr, Value: "true"}, {Text: falseStr, Value: "false"}, }).FieldDisplay(defaultFilterFn("false")) formList.AddField(lgWithConfigScore("logger rotate encoder encoding"), "logger_encoder_encoding", db.Varchar, form.SelectSingle). FieldDivider(lgWithConfigScore("logger rotate encoder")). FieldOptions(types.FieldOptions{ {Text: "JSON", Value: "json"}, {Text: "Console", Value: "console"}, }).FieldDisplay(defaultFilterFn("console")). FieldOnChooseHide("Console", "logger_encoder_time_key", "logger_encoder_level_key", "logger_encoder_caller_key", "logger_encoder_message_key", "logger_encoder_stacktrace_key", "logger_encoder_name_key") formList.AddField(lgWithConfigScore("logger rotate encoder time key"), "logger_encoder_time_key", db.Varchar, form.Text). FieldDisplay(defaultFilterFn("ts")) formList.AddField(lgWithConfigScore("logger rotate encoder level key"), "logger_encoder_level_key", db.Varchar, form.Text). FieldDisplay(defaultFilterFn("level")) formList.AddField(lgWithConfigScore("logger rotate encoder name key"), "logger_encoder_name_key", db.Varchar, form.Text). FieldDisplay(defaultFilterFn("logger")) formList.AddField(lgWithConfigScore("logger rotate encoder caller key"), "logger_encoder_caller_key", db.Varchar, form.Text). FieldDisplay(defaultFilterFn("caller")) formList.AddField(lgWithConfigScore("logger rotate encoder message key"), "logger_encoder_message_key", db.Varchar, form.Text). FieldDisplay(defaultFilterFn("msg")) formList.AddField(lgWithConfigScore("logger rotate encoder stacktrace key"), "logger_encoder_stacktrace_key", db.Varchar, form.Text). FieldDisplay(defaultFilterFn("stacktrace")) formList.AddField(lgWithConfigScore("logger rotate encoder level"), "logger_encoder_level", db.Varchar, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: lgWithConfigScore("capital"), Value: "capital"}, {Text: lgWithConfigScore("capitalcolor"), Value: "capitalColor"}, {Text: lgWithConfigScore("lowercase"), Value: "lowercase"}, {Text: lgWithConfigScore("lowercasecolor"), Value: "color"}, }).FieldDisplay(defaultFilterFn("capitalColor")) formList.AddField(lgWithConfigScore("logger rotate encoder time"), "logger_encoder_time", db.Varchar, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: "ISO8601(2006-01-02T15:04:05.000Z0700)", Value: "iso8601"}, {Text: lgWithConfigScore("millisecond"), Value: "millis"}, {Text: lgWithConfigScore("nanosecond"), Value: "nanos"}, {Text: "RFC3339(2006-01-02T15:04:05Z07:00)", Value: "rfc3339"}, {Text: "RFC3339 Nano(2006-01-02T15:04:05.999999999Z07:00)", Value: "rfc3339nano"}, }).FieldDisplay(defaultFilterFn("iso8601")) formList.AddField(lgWithConfigScore("logger rotate encoder duration"), "logger_encoder_duration", db.Varchar, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: lgWithConfigScore("seconds"), Value: "string"}, {Text: lgWithConfigScore("nanosecond"), Value: "nanos"}, {Text: lgWithConfigScore("microsecond"), Value: "ms"}, }).FieldDisplay(defaultFilterFn("string")) formList.AddField(lgWithConfigScore("logger rotate encoder caller"), "logger_encoder_caller", db.Varchar, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: lgWithConfigScore("full path"), Value: "full"}, {Text: lgWithConfigScore("short path"), Value: "short"}, }).FieldDisplay(defaultFilterFn("full")) formList.HideBackButton().HideContinueEditCheckBox().HideContinueNewCheckBox() formList.SetTabGroups(types.NewTabGroups("id", "debug", "env", "language", "theme", "color_scheme", "asset_url", "title", "login_title", "session_life_time", "bootstrap_file_path", "go_mod_file_path", "no_limit_login_ip", "operation_log_off", "allow_del_operation_log", "hide_config_center_entrance", "hide_app_info_entrance", "hide_tool_entrance", "hide_plugin_entrance", "animation_type", "animation_duration", "animation_delay", "file_upload_engine", "extra"). AddGroup("access_log_off", "access_assets_log_off", "info_log_off", "error_log_off", "sql_log", "logger_level", "info_log_path", "error_log_path", "access_log_path", "logger_rotate_max_size", "logger_rotate_max_backups", "logger_rotate_max_age", "logger_rotate_compress", "logger_encoder_encoding", "logger_encoder_time_key", "logger_encoder_level_key", "logger_encoder_name_key", "logger_encoder_caller_key", "logger_encoder_message_key", "logger_encoder_stacktrace_key", "logger_encoder_level", "logger_encoder_time", "logger_encoder_duration", "logger_encoder_caller"). AddGroup("logo", "mini_logo", "custom_head_html", "custom_foot_html", "footer_info", "login_logo", "custom_404_html", "custom_403_html", "custom_500_html")). SetTabHeaders(lgWithConfigScore("general"), lgWithConfigScore("log"), lgWithConfigScore("custom")) formList.SetTable("goadmin_site"). SetTitle(lgWithConfigScore("site setting")). SetDescription(lgWithConfigScore("site setting")) formList.SetUpdateFn(func(values form2.Values) error { ses := values.Get("session_life_time") sesInt, _ := strconv.Atoi(ses) if sesInt < 900 { return errors.New("wrong session life time, must bigger than 900 seconds") } if err := checkJSON(values, "file_upload_engine"); err != nil { return err } values["logo"][0] = escape(values.Get("logo")) values["mini_logo"][0] = escape(values.Get("mini_logo")) values["custom_head_html"][0] = escape(values.Get("custom_head_html")) values["custom_foot_html"][0] = escape(values.Get("custom_foot_html")) values["custom_404_html"][0] = escape(values.Get("custom_404_html")) values["custom_403_html"][0] = escape(values.Get("custom_403_html")) values["custom_500_html"][0] = escape(values.Get("custom_500_html")) values["footer_info"][0] = escape(values.Get("footer_info")) values["login_logo"][0] = escape(values.Get("login_logo")) var err error if s.c.UpdateProcessFn != nil { values, err = s.c.UpdateProcessFn(values) if err != nil { return err } } ui.GetService(services).RemoveOrShowSiteNavButton(values["hide_config_center_entrance"][0] == "true") ui.GetService(services).RemoveOrShowInfoNavButton(values["hide_app_info_entrance"][0] == "true") ui.GetService(services).RemoveOrShowToolNavButton(values["hide_tool_entrance"][0] == "true") ui.GetService(services).RemoveOrShowPlugNavButton(values["hide_plugin_entrance"][0] == "true") // TODO: add transaction err = models.Site().SetConn(s.conn).Update(values.RemoveSysRemark()) if err != nil { return err } return s.c.Update(values.ToMap()) }) formList.EnableAjax(lgWithConfigScore("modify site config"), lgWithConfigScore("modify site config"), "", lgWithConfigScore("modify site config success"), lgWithConfigScore("modify site config fail")) return } func (s *SystemTable) GetGenerateForm(ctx *context.Context) (generateTool Table) { generateTool = NewDefaultTable(ctx, DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver). SetOnlyNewForm()) formList := generateTool.GetForm().AddXssJsFilter(). SetHeadWidth(1). SetInputWidth(4). HideBackButton(). HideContinueNewCheckBox() formList.AddField("ID", "id", db.Varchar, form.Default).FieldDefault("1").FieldHide() connNames := config.GetDatabases().Connections() ops := make(types.FieldOptions, len(connNames)) for i, name := range connNames { ops[i] = types.FieldOption{Text: name, Value: name} } // General options // ================================ formList.AddField(lgWithScore("connection", "tool"), "conn", db.Varchar, form.SelectSingle). FieldOptions(ops). FieldOnChooseAjax("table", "/tool/choose/conn", func(ctx *context.Context) (success bool, msg string, data interface{}) { connName := ctx.FormValue("value") if connName == "" { return false, "wrong parameter", nil } cfg := s.c.Databases[connName] conn := db.GetConnectionFromService(services.Get(cfg.Driver)) tables, err := db.WithDriverAndConnection(connName, conn).Table(cfg.Name).ShowTables() if err != nil { return false, err.Error(), nil } ops := make(selection.Options, len(tables)) for i, table := range tables { ops[i] = selection.Option{Text: table, ID: table} } return true, "ok", ops }) formList.AddField(lgWithScore("table", "tool"), "table", db.Varchar, form.SelectSingle). FieldOnChooseAjax("xxxx", "/tool/choose/table", func(ctx *context.Context) (success bool, msg string, data interface{}) { var ( tableName = ctx.FormValue("value") connName = ctx.FormValue("conn") driver = s.c.Databases[connName].Driver conn = db.GetConnectionFromService(services.Get(driver)) columnsModel, _ = db.WithDriverAndConnection(connName, conn).Table(tableName).ShowColumns() fieldField = "Field" typeField = "Type" ) if driver == "postgresql" { fieldField = "column_name" typeField = "udt_name" } if driver == "sqlite" { fieldField = "name" typeField = "type" } if driver == "mssql" { fieldField = "column_name" typeField = "data_type" } headName := make([]string, len(columnsModel)) fieldName := make([]string, len(columnsModel)) dbTypeList := make([]string, len(columnsModel)) formTypeList := make([]string, len(columnsModel)) for i, model := range columnsModel { typeName := getType(model[typeField].(string)) headName[i] = cases.Title(textLang.Und).String(model[fieldField].(string)) fieldName[i] = model[fieldField].(string) dbTypeList[i] = typeName formTypeList[i] = form.GetFormTypeFromFieldType(db.DT(strings.ToUpper(typeName)), model[fieldField].(string)) } return true, "ok", [][]string{headName, fieldName, dbTypeList, formTypeList} }, template.HTML(utils.ParseText("choose_table_ajax", tmpls["choose_table_ajax"], nil)), `"conn":$('.conn').val(),`) formList.AddField(lgWithScore("package", "tool"), "package", db.Varchar, form.Text).FieldDefault("tables") formList.AddField(lgWithScore("primarykey", "tool"), "pk", db.Varchar, form.Text).FieldDefault("id") formList.AddField(lgWithScore("table permission", "tool"), "permission", db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: lgWithScore("yes", "tool"), Value: "y"}, {Text: lgWithScore("no", "tool"), Value: "n"}, }).FieldDefault("n") formList.AddField(lgWithScore("extra import package", "tool"), "extra_import_package", db.Varchar, form.Select). FieldOptions(types.FieldOptions{ {Text: "time", Value: "time"}, {Text: "log", Value: "log"}, {Text: "fmt", Value: "fmt"}, {Text: "github.com/GoAdminGroup/go-admin/modules/db/dialect", Value: "github.com/GoAdminGroup/go-admin/modules/db/dialect"}, {Text: "github.com/GoAdminGroup/go-admin/modules/db", Value: "github.com/GoAdminGroup/go-admin/modules/db"}, {Text: "github.com/GoAdminGroup/go-admin/modules/language", Value: "github.com/GoAdminGroup/go-admin/modules/language"}, {Text: "github.com/GoAdminGroup/go-admin/modules/logger", Value: "github.com/GoAdminGroup/go-admin/modules/logger"}, }). FieldDefault(""). FieldOptionExt(map[string]interface{}{ "tags": true, }) formList.AddField(lgWithScore("output", "tool"), "path", db.Varchar, form.Text). FieldDefault("").FieldMust().FieldHelpMsg(template.HTML(lgWithScore("use absolute path", "tool"))) formList.AddField(lgWithScore("extra code", "tool"), "extra_code", db.Varchar, form.Code). FieldDefault("").FieldInputWidth(11) // Info table generate options // ================================ formList.AddField(lgWithScore("title", "tool"), "table_title", db.Varchar, form.Text) formList.AddField(lgWithScore("description", "tool"), "table_description", db.Varchar, form.Text) formList.AddRow(func(panel *types.FormPanel) { addSwitchForTool(panel, "filter area", "hide_filter_area", "n", 2) panel.AddField(lgWithScore("filter form layout", "tool"), "filter_form_layout", db.Varchar, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: form.LayoutDefault.String(), Value: form.LayoutDefault.String()}, {Text: form.LayoutTwoCol.String(), Value: form.LayoutTwoCol.String()}, {Text: form.LayoutThreeCol.String(), Value: form.LayoutThreeCol.String()}, {Text: form.LayoutFourCol.String(), Value: form.LayoutFourCol.String()}, {Text: form.LayoutFlow.String(), Value: form.LayoutFlow.String()}, }).FieldDefault(form.LayoutDefault.String()). FieldRowWidth(4).FieldHeadWidth(3) }) formList.AddRow(func(panel *types.FormPanel) { addSwitchForTool(panel, "new button", "hide_new_button", "n", 2) addSwitchForTool(panel, "export button", "hide_export_button", "n", 4, 3) addSwitchForTool(panel, "edit button", "hide_edit_button", "n", 4, 2) }) formList.AddRow(func(panel *types.FormPanel) { addSwitchForTool(panel, "pagination", "hide_pagination", "n", 2) addSwitchForTool(panel, "delete button", "hide_delete_button", "n", 4, 3) addSwitchForTool(panel, "detail button", "hide_detail_button", "n", 4, 2) }) formList.AddRow(func(panel *types.FormPanel) { addSwitchForTool(panel, "filter button", "hide_filter_button", "n", 2) addSwitchForTool(panel, "row selector", "hide_row_selector", "n", 4, 3) addSwitchForTool(panel, "query info", "hide_query_info", "n", 4, 2) }) formList.AddTable(lgWithScore("field", "tool"), "fields", func(pa *types.FormPanel) { pa.AddField(lgWithScore("title", "tool"), "field_head", db.Varchar, form.Text).FieldHideLabel(). FieldDisplay(func(value types.FieldModel) interface{} { return []string{""} }) pa.AddField(lgWithScore("field name", "tool"), "field_name", db.Varchar, form.Text).FieldHideLabel(). FieldDisplay(func(value types.FieldModel) interface{} { return []string{""} }) pa.AddField(lgWithScore("field filterable", "tool"), "field_filterable", db.Varchar, form.CheckboxSingle). FieldOptions(types.FieldOptions{ {Text: "", Value: "y"}, {Text: "", Value: "n"}, }). FieldDefault("n"). FieldDisplay(func(value types.FieldModel) interface{} { return []string{"n"} }) pa.AddField(lgWithScore("field sortable", "tool"), "field_sortable", db.Varchar, form.CheckboxSingle). FieldOptions(types.FieldOptions{ {Text: "", Value: "y"}, {Text: "", Value: "n"}, }). FieldDefault("n"). FieldDisplay(func(value types.FieldModel) interface{} { return []string{"n"} }) pa.AddField(lgWithScore("field hide", "tool"), "field_hide", db.Varchar, form.CheckboxSingle). FieldOptions(types.FieldOptions{ {Text: "", Value: "y"}, {Text: "", Value: "n"}, }). FieldDefault("n"). FieldDisplay(func(value types.FieldModel) interface{} { return []string{"n"} }) pa.AddField(lgWithScore("info field editable", "tool"), "info_field_editable", db.Varchar, form.CheckboxSingle). FieldOptions(types.FieldOptions{ {Text: "", Value: "y"}, {Text: "", Value: "n"}, }). FieldDefault("n"). FieldDisplay(func(value types.FieldModel) interface{} { return []string{"n"} }) //pa.AddField(lgWithScore("db display type", "tool"), "field_display_type", db.Varchar, form.SelectSingle). // FieldOptions(infoFieldDisplayTypeOptions()). // FieldDisplay(func(value types.FieldModel) interface{} { // return []string{""} // }) pa.AddField(lgWithScore("db type", "tool"), "field_db_type", db.Varchar, form.SelectSingle). FieldOptions(databaseTypeOptions()). FieldDisplay(func(value types.FieldModel) interface{} { return []string{"Int"} }) }).FieldInputWidth(11) // Form generate options // ================================ formList.AddField(lgWithScore("title", "tool"), "form_title", db.Varchar, form.Text) formList.AddField(lgWithScore("description", "tool"), "form_description", db.Varchar, form.Text) formList.AddRow(func(panel *types.FormPanel) { addSwitchForTool(panel, "continue edit checkbox", "hide_continue_edit_check_box", "n", 2) addSwitchForTool(panel, "reset button", "hide_reset_button", "n", 5, 3) }) formList.AddRow(func(panel *types.FormPanel) { addSwitchForTool(panel, "continue new checkbox", "hide_continue_new_check_box", "n", 2) addSwitchForTool(panel, "back button", "hide_back_button", "n", 5, 3) }) formList.AddTable(lgWithScore("field", "tool"), "fields_form", func(pa *types.FormPanel) { pa.AddField(lgWithScore("title", "tool"), "field_head_form", db.Varchar, form.Text).FieldHideLabel(). FieldDisplay(func(value types.FieldModel) interface{} { return []string{""} }) pa.AddField(lgWithScore("field name", "tool"), "field_name_form", db.Varchar, form.Text).FieldHideLabel(). FieldDisplay(func(value types.FieldModel) interface{} { return []string{""} }) pa.AddField(lgWithScore("field editable", "tool"), "field_canedit", db.Varchar, form.CheckboxSingle). FieldOptions(types.FieldOptions{ {Text: "", Value: "y"}, {Text: "", Value: "n"}, }). FieldDefault("y"). FieldDisplay(func(value types.FieldModel) interface{} { return []string{"y"} }) pa.AddField(lgWithScore("field can add", "tool"), "field_canadd", db.Varchar, form.CheckboxSingle). FieldOptions(types.FieldOptions{ {Text: "", Value: "y"}, {Text: "", Value: "n"}, }). FieldDefault("y"). FieldDisplay(func(value types.FieldModel) interface{} { return []string{"y"} }) pa.AddField(lgWithScore("field default", "tool"), "field_default", db.Varchar, form.Text).FieldHideLabel(). FieldDisplay(func(value types.FieldModel) interface{} { return []string{""} }) pa.AddField(lgWithScore("field display", "tool"), "field_display", db.Varchar, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: lgWithScore("field display normal", "tool"), Value: "0"}, {Text: lgWithScore("field diplay hide", "tool"), Value: "1"}, {Text: lgWithScore("field diplay edit hide", "tool"), Value: "2"}, {Text: lgWithScore("field diplay create hide", "tool"), Value: "3"}, }). FieldDisplay(func(value types.FieldModel) interface{} { return []string{"0"} }) pa.AddField(lgWithScore("db type", "tool"), "field_db_type_form", db.Varchar, form.SelectSingle). FieldOptions(databaseTypeOptions()). FieldDisplay(func(value types.FieldModel) interface{} { return []string{"Int"} }) pa.AddField(lgWithScore("form type", "tool"), "field_form_type_form", db.Varchar, form.SelectSingle). FieldOptions(formTypeOptions()).FieldDisplay(func(value types.FieldModel) interface{} { return []string{"Text"} }) }).FieldInputWidth(11) // Detail page generate options // ================================ formList.AddField(lgWithScore("title", "tool"), "detail_title", db.Varchar, form.Text) formList.AddField(lgWithScore("description", "tool"), "detail_description", db.Varchar, form.Text) formList.AddField(lgWithScore("detail display", "tool"), "detail_display", db.Varchar, form.SelectSingle). FieldOptions(types.FieldOptions{ {Text: lgWithScore("follow list page", "tool"), Value: "0"}, {Text: lgWithScore("inherit from list page", "tool"), Value: "1"}, {Text: lgWithScore("independent from list page", "tool"), Value: "2"}, }). FieldDefault("0"). FieldOnChooseHide("0", "detail_title", "detail_description", "fields_detail") formList.AddTable(lgWithScore("field", "tool"), "fields_detail", func(pa *types.FormPanel) { pa.AddField(lgWithScore("title", "tool"), "detail_field_head", db.Varchar, form.Text).FieldHideLabel(). FieldDisplay(func(value types.FieldModel) interface{} { return []string{""} }) pa.AddField(lgWithScore("field name", "tool"), "detail_field_name", db.Varchar, form.Text).FieldHideLabel(). FieldDisplay(func(value types.FieldModel) interface{} { return []string{""} }) pa.AddField(lgWithScore("db type", "tool"), "detail_field_db_type", db.Varchar, form.SelectSingle). FieldOptions(databaseTypeOptions()). FieldDisplay(func(value types.FieldModel) interface{} { return []string{"Int"} }) }).FieldInputWidth(11) formList.SetTabGroups(types. NewTabGroups("conn", "table", "package", "pk", "permission", "extra_import_package", "path", "extra_code"). AddGroup("table_title", "table_description", "hide_filter_area", "filter_form_layout", "hide_new_button", "hide_export_button", "hide_edit_button", "hide_pagination", "hide_delete_button", "hide_detail_button", "hide_filter_button", "hide_row_selector", "hide_query_info", "fields"). AddGroup("form_title", "form_description", "hide_continue_edit_check_box", "hide_reset_button", "hide_continue_new_check_box", "hide_back_button", "fields_form"). AddGroup("detail_display", "detail_title", "detail_description", "fields_detail")). SetTabHeaders(lgWithScore("basic info", "tool"), lgWithScore("table info", "tool"), lgWithScore("form info", "tool"), lgWithScore("detail info", "tool")) formList.SetTable("tool"). SetTitle(lgWithScore("code generate tool", "tool")). SetDescription(lgWithScore("code generate tool", "tool")). SetHeader(template.HTML(`

    ` + lgWithScore("generate table model", "tool") + `

    `)) formList.SetInsertFn(func(values form2.Values) error { table := values.Get("table") if table == "" { return errors.New("table is empty") } if values.Get("permission") == "y" { tools.InsertPermissionOfTable(s.conn, table) } output := values.Get("path") if output == "" { return errors.New("output path is empty") } connName := values.Get("conn") fields := make(tools.Fields, len(values["field_head"])) for i := 0; i < len(values["field_head"]); i++ { fields[i] = tools.Field{ Head: values["field_head"][i], Name: values["field_name"][i], DBType: values["field_db_type"][i], Filterable: values["field_filterable"][i] == "y", Sortable: values["field_sortable"][i] == "y", Hide: values["field_hide"][i] == "y", InfoEditable: values["info_field_editable"][i] == "y", } } extraImport := "" for _, pack := range values["extra_import_package[]"] { if extraImport != "" { extraImport += ` ` } extraImport += ` "` + pack + `"` } formFields := make(tools.Fields, len(values["field_head_form"])) for i := 0; i < len(values["field_head_form"]); i++ { extraFun := "" if values["field_name_form"][i] == `created_at` { extraFun += `.FieldNowWhenInsert()` } else if values["field_name_form"][i] == `updated_at` { extraFun += `.FieldNowWhenUpdate()` } else if values["field_default"][i] != "" && !strings.Contains(values["field_default"][i], `"`) { values["field_default"][i] = `"` + values["field_default"][i] + `"` } formFields[i] = tools.Field{ Head: values["field_head_form"][i], Name: values["field_name_form"][i], Default: values["field_default"][i], FormType: values["field_form_type_form"][i], DBType: values["field_db_type_form"][i], CanAdd: values["field_canadd"][i] == "y", Editable: values["field_canedit"][i] == "y", FormHide: values["field_display"][i] == "1", CreateHide: values["field_display"][i] == "2", EditHide: values["field_display"][i] == "3", ExtraFun: extraFun, } } detailFields := make(tools.Fields, len(values["detail_field_head"])) for i := 0; i < len(values["detail_field_head"]); i++ { detailFields[i] = tools.Field{ Head: values["detail_field_head"][i], Name: values["detail_field_name"][i], DBType: values["detail_field_db_type"][i], } } detailDisplay, _ := strconv.ParseUint(values.Get("detail_display"), 10, 64) err := tools.Generate(tools.NewParamWithFields(tools.Config{ Connection: connName, Driver: s.c.Databases[connName].Driver, Package: values.Get("package"), Table: table, HideFilterArea: values.Get("hide_filter_area") == "y", HideNewButton: values.Get("hide_new_button") == "y", HideExportButton: values.Get("hide_export_button") == "y", HideEditButton: values.Get("hide_edit_button") == "y", HideDeleteButton: values.Get("hide_delete_button") == "y", HideDetailButton: values.Get("hide_detail_button") == "y", HideFilterButton: values.Get("hide_filter_button") == "y", HideRowSelector: values.Get("hide_row_selector") == "y", HidePagination: values.Get("hide_pagination") == "y", HideQueryInfo: values.Get("hide_query_info") == "y", HideContinueEditCheckBox: values.Get("hide_continue_edit_check_box") == "y", HideContinueNewCheckBox: values.Get("hide_continue_new_check_box") == "y", HideResetButton: values.Get("hide_reset_button") == "y", HideBackButton: values.Get("hide_back_button") == "y", FilterFormLayout: form.GetLayoutFromString(values.Get("filter_form_layout")), Schema: values.Get("schema"), Output: output, DetailDisplay: uint8(detailDisplay), FormTitle: values.Get("form_title"), FormDescription: values.Get("form_description"), DetailTitle: values.Get("detail_title"), DetailDescription: values.Get("detail_description"), TableTitle: values.Get("table_title"), TableDescription: values.Get("table_description"), ExtraImport: extraImport, ExtraCode: escape(values.Get("extra_code")), }, fields, formFields, detailFields)) if err != nil { return err } return tools.GenerateTables(output, values.Get("package"), []string{table}, false) }) formList.EnableAjaxData(types.AjaxData{ SuccessTitle: lgWithScore("generate table model", "tool"), ErrorTitle: lgWithScore("generate table model", "tool"), SuccessText: lgWithScore("generate table model success", "tool"), ErrorText: lgWithScore("generate table model fail", "tool"), DisableJump: true, }) formList.SetFooterHtml(utils.ParseHTML("generator", tmpls["generator"], map[string]string{ "prefix": "go_admin_" + config.GetAppID() + "_generator_", })) formList.SetFormNewBtnWord(template.HTML(lgWithScore("generate", "tool"))) formList.SetWrapper(func(content tmpl.HTML) tmpl.HTML { headli := html.LiEl().SetClass("list-group-item", "list-head"). SetContent(template.HTML(lgWithScore("generated tables", "tool"))).Get() return html.UlEl().SetClass("save_table_list", "list-group").SetContent( headli).Get() + content }) formList.SetHideSideBar() return generateTool } // ------------------------- // helper functions // ------------------------- func encodePassword(pwd []byte) string { hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost) if err != nil { return "" } return string(hash) } func label(ctx *context.Context) types.LabelAttribute { return template.Get(ctx, config.GetTheme()).Label().SetType("success") } func lg(v string) string { return language.Get(v) } func defaultFilterFn(val string, def ...string) types.FieldFilterFn { return func(value types.FieldModel) interface{} { if len(def) > 0 { if value.Value == def[0] { return val } } else { if value.Value == "" { return val } } return value.Value } } func lgWithScore(v string, score ...string) string { return language.GetWithScope(v, score...) } func lgWithConfigScore(v string, score ...string) string { scores := append([]string{"config"}, score...) return language.GetWithScope(v, scores...) } func link(url, content string) tmpl.HTML { return html.AEl(). SetAttr("href", url). SetContent(template.HTML(lg(content))). Get() } func escape(s string) string { if s == "" { return "" } s, err := url.QueryUnescape(s) if err != nil { logger.Error("escape error", err) } return s } func checkJSON(values form2.Values, key string) error { v := values.Get(key) if v != "" && !utils.IsJSON(v) { return errors.New("wrong " + key) } return nil } func (s *SystemTable) table(table string) *db.SQL { return s.connection().Table(table) } func (s *SystemTable) connection() *db.SQL { return db.WithDriver(s.conn) } func interfaces(arr []string) []interface{} { var iarr = make([]interface{}, len(arr)) for key, v := range arr { iarr[key] = v } return iarr } func addSwitchForTool(formList *types.FormPanel, head, field, def string, row ...int) { formList.AddField(lgWithScore(head, "tool"), field, db.Varchar, form.Switch). FieldOptions(types.FieldOptions{ {Text: lgWithScore("show", "tool"), Value: "n"}, {Text: lgWithScore("hide", "tool"), Value: "y"}, }).FieldDefault(def) if len(row) > 0 { formList.FieldRowWidth(row[0]) } if len(row) > 1 { formList.FieldHeadWidth(row[1]) } if len(row) > 2 { formList.FieldInputWidth(row[2]) } } func formTypeOptions() types.FieldOptions { opts := make(types.FieldOptions, len(form.AllType)) for i := 0; i < len(form.AllType); i++ { v := form.AllType[i].Name() opts[i] = types.FieldOption{Text: v, Value: v} } return opts } func databaseTypeOptions() types.FieldOptions { opts := make(types.FieldOptions, len(db.IntTypeList)+ len(db.StringTypeList)+ len(db.FloatTypeList)+ len(db.UintTypeList)+ len(db.BoolTypeList)) z := 0 for _, t := range db.IntTypeList { text := string(t) v := cases.Title(textLang.Und).String(strings.ToLower(text)) opts[z] = types.FieldOption{Text: text, Value: v} z++ } for _, t := range db.StringTypeList { text := string(t) v := cases.Title(textLang.Und).String(strings.ToLower(text)) opts[z] = types.FieldOption{Text: text, Value: v} z++ } for _, t := range db.FloatTypeList { text := string(t) v := cases.Title(textLang.Und).String(strings.ToLower(text)) opts[z] = types.FieldOption{Text: text, Value: v} z++ } for _, t := range db.UintTypeList { text := string(t) v := cases.Title(textLang.Und).String(strings.ToLower(text)) opts[z] = types.FieldOption{Text: text, Value: v} z++ } for _, t := range db.BoolTypeList { text := string(t) v := cases.Title(textLang.Und).String(strings.ToLower(text)) opts[z] = types.FieldOption{Text: text, Value: v} z++ } return opts } func getType(typeName string) string { r, _ := regexp.Compile(`\(.*?\)`) typeName = r.ReplaceAllString(typeName, "") r2, _ := regexp.Compile(`unsigned(.*)`) return strings.TrimSpace(cases.Title(textLang.Und).String(strings.ToLower(r2.ReplaceAllString(typeName, "")))) } ================================================ FILE: plugins/admin/modules/table/table.go ================================================ package table import ( "html/template" "sync" "sync/atomic" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/service" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/paginator" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/template/types" ) type Generator func(ctx *context.Context) Table type GeneratorList map[string]Generator func (g GeneratorList) Add(key string, gen Generator) { g[key] = gen } func (g GeneratorList) Combine(list GeneratorList) GeneratorList { for key, gen := range list { if _, ok := g[key]; !ok { g[key] = gen } } return g } func (g GeneratorList) CombineAll(gens []GeneratorList) GeneratorList { for _, list := range gens { for key, gen := range list { if _, ok := g[key]; !ok { g[key] = gen } } } return g } type Table interface { GetInfo() *types.InfoPanel GetDetail() *types.InfoPanel GetDetailFromInfo() *types.InfoPanel GetForm() *types.FormPanel GetNewForm() *types.FormPanel GetActualNewForm() *types.FormPanel GetCanAdd() bool GetEditable() bool GetDeletable() bool GetExportable() bool GetPrimaryKey() PrimaryKey GetData(ctx *context.Context, params parameter.Parameters) (PanelInfo, error) GetDataWithIds(ctx *context.Context, params parameter.Parameters) (PanelInfo, error) GetDataWithId(params parameter.Parameters) (FormInfo, error) UpdateData(ctx *context.Context, dataList form.Values) error InsertData(ctx *context.Context, ddataList form.Values) error DeleteData(pk string) error GetNewFormInfo() FormInfo GetOnlyInfo() bool GetOnlyDetail() bool GetOnlyNewForm() bool GetOnlyUpdateForm() bool Copy() Table } type BaseTable struct { Info *types.InfoPanel Form *types.FormPanel NewForm *types.FormPanel Detail *types.InfoPanel CanAdd bool Editable bool Deletable bool Exportable bool OnlyInfo bool OnlyDetail bool OnlyNewForm bool OnlyUpdateForm bool PrimaryKey PrimaryKey } func (base *BaseTable) GetInfo() *types.InfoPanel { return base.Info.SetPrimaryKey(base.PrimaryKey.Name, base.PrimaryKey.Type) } func (base *BaseTable) GetDetail() *types.InfoPanel { return base.Detail.SetPrimaryKey(base.PrimaryKey.Name, base.PrimaryKey.Type) } func (base *BaseTable) GetDetailFromInfo() *types.InfoPanel { detail := base.GetDetail() detail.FieldList = make(types.FieldList, len(base.Info.FieldList)) copy(detail.FieldList, base.Info.FieldList) return detail } func (base *BaseTable) GetForm() *types.FormPanel { return base.Form.SetPrimaryKey(base.PrimaryKey.Name, base.PrimaryKey.Type) } func (base *BaseTable) GetNewForm() *types.FormPanel { return base.NewForm.SetPrimaryKey(base.PrimaryKey.Name, base.PrimaryKey.Type) } func (base *BaseTable) GetActualNewForm() *types.FormPanel { if len(base.NewForm.FieldList) == 0 { return base.Form } return base.NewForm } func (base *BaseTable) GetCanAdd() bool { return base.CanAdd } func (base *BaseTable) GetPrimaryKey() PrimaryKey { return base.PrimaryKey } func (base *BaseTable) GetEditable() bool { return base.Editable } func (base *BaseTable) GetDeletable() bool { return base.Deletable } func (base *BaseTable) GetExportable() bool { return base.Exportable } func (base *BaseTable) GetOnlyInfo() bool { return base.OnlyInfo } func (base *BaseTable) GetOnlyDetail() bool { return base.OnlyDetail } func (base *BaseTable) GetOnlyNewForm() bool { return base.OnlyNewForm } func (base *BaseTable) GetOnlyUpdateForm() bool { return base.OnlyUpdateForm } func (base *BaseTable) GetPaginator(ctx *context.Context, size int, params parameter.Parameters, extraHtml ...template.HTML) types.PaginatorAttribute { var eh template.HTML if len(extraHtml) > 0 { eh = extraHtml[0] } return paginator.Get(ctx, paginator.Config{ Size: size, Param: params, PageSizeList: base.Info.GetPageSizeList(), }).SetExtraInfo(eh) } type PanelInfo struct { Thead types.Thead `json:"thead"` InfoList types.InfoList `json:"info_list"` FilterFormData types.FormFields `json:"filter_form_data"` Paginator types.PaginatorAttribute `json:"-"` Title string `json:"title"` Description string `json:"description"` } type FormInfo struct { FieldList types.FormFields `json:"field_list"` GroupFieldList types.GroupFormFields `json:"group_field_list"` GroupFieldHeaders types.GroupFieldHeaders `json:"group_field_headers"` Title string `json:"title"` Description string `json:"description"` } type PrimaryKey struct { Type db.DatabaseType Name string } const ( DefaultPrimaryKeyName = "id" DefaultConnectionName = "default" ) var ( services service.List count uint32 lock sync.Mutex ) func SetServices(srv service.List) { lock.Lock() defer lock.Unlock() if atomic.LoadUint32(&count) != 0 { panic("can not initialize twice") } services = srv } ================================================ FILE: plugins/admin/modules/table/tmpl/choose_table_ajax.tmpl ================================================ {{define "choose_table_ajax"}} NProgress.start(); let info_table = $("tbody.fields-table"); info_table.find("tr").remove(); let tpl = $("template.fields-tpl").html(); for (let i = 0; i < data.data[0].length; i++) { info_table.append(tpl); } let trs = info_table.find("tr"); for (let i = 0; i < data.data[0].length; i++) { $(trs[i]).find('.field_head').val(data.data[0][i]); $(trs[i]).find('.field_name').val(data.data[1][i]); $(trs[i]).find('select.field_db_type').val(data.data[2][i]).select2(); } let form_table = $("tbody.fields_form-table"); form_table.find("tr").remove(); let tpl_form = $("template.fields_form-tpl").html(); for (let i = 0; i < data.data[0].length; i++) { form_table.append(tpl_form); } let trs_form = form_table.find("tr"); let pk = $(".pk").val(); for (let i = 0; i < data.data[0].length; i++) { $(trs_form[i]).find('.field_head_form').val(data.data[0][i]); $(trs_form[i]).find('.field_name_form').val(data.data[1][i]); $(trs_form[i]).find('input.field_canedit').iCheck("check"); if (!(data.data[1][i] === pk || (pk === "" && data.data[1][i] === "id"))) { $(trs_form[i]).find('input.field_canadd').iCheck("check"); } if (data.data[1][i] === "created_at" || data.data[1][i] === "updated_at") { $(trs_form[i]).find('select.field_display').val("1").select2(); } $(trs_form[i]).find('select.field_db_type_form').val(data.data[2][i]).select2(); $(trs_form[i]).find('select.field_form_type_form').val(data.data[3][i]).select2(); } $(".hide_filter_area.ga_checkbox").bootstrapSwitch('state', true); $(".hide_new_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_export_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_edit_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_pagination.ga_checkbox").bootstrapSwitch('state', true); $(".hide_delete_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_detail_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_filter_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_row_selector.ga_checkbox").bootstrapSwitch('state', true); $(".hide_query_info.ga_checkbox").bootstrapSwitch('state', true); $(".filter_form_layout.ga_checkbox").bootstrapSwitch('state', true); $(".hide_continue_edit_check_box.ga_checkbox").bootstrapSwitch('state', true); $(".hide_reset_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_continue_new_check_box.ga_checkbox").bootstrapSwitch('state', true); $(".hide_back_button.ga_checkbox").bootstrapSwitch('state', true); let detail_table = $("tbody.fields_detail-table"); detail_table.find("tr").remove(); NProgress.done(); {{end}} ================================================ FILE: plugins/admin/modules/table/tmpl/generator.tmpl ================================================ {{define "generator"}} {{end}} ================================================ FILE: plugins/admin/modules/table/tmpl.go ================================================ package table var tmpls = map[string]string{"choose_table_ajax": `{{define "choose_table_ajax"}} NProgress.start(); let info_table = $("tbody.fields-table"); info_table.find("tr").remove(); let tpl = $("template.fields-tpl").html(); for (let i = 0; i < data.data[0].length; i++) { info_table.append(tpl); } let trs = info_table.find("tr"); for (let i = 0; i < data.data[0].length; i++) { $(trs[i]).find('.field_head').val(data.data[0][i]); $(trs[i]).find('.field_name').val(data.data[1][i]); $(trs[i]).find('select.field_db_type').val(data.data[2][i]).select2(); } let form_table = $("tbody.fields_form-table"); form_table.find("tr").remove(); let tpl_form = $("template.fields_form-tpl").html(); for (let i = 0; i < data.data[0].length; i++) { form_table.append(tpl_form); } let trs_form = form_table.find("tr"); let pk = $(".pk").val(); for (let i = 0; i < data.data[0].length; i++) { $(trs_form[i]).find('.field_head_form').val(data.data[0][i]); $(trs_form[i]).find('.field_name_form').val(data.data[1][i]); $(trs_form[i]).find('input.field_canedit').iCheck("check"); if (!(data.data[1][i] === pk || (pk === "" && data.data[1][i] === "id"))) { $(trs_form[i]).find('input.field_canadd').iCheck("check"); } if (data.data[1][i] === "created_at" || data.data[1][i] === "updated_at") { $(trs_form[i]).find('select.field_display').val("1").select2(); } $(trs_form[i]).find('select.field_db_type_form').val(data.data[2][i]).select2(); $(trs_form[i]).find('select.field_form_type_form').val(data.data[3][i]).select2(); } $(".hide_filter_area.ga_checkbox").bootstrapSwitch('state', true); $(".hide_new_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_export_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_edit_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_pagination.ga_checkbox").bootstrapSwitch('state', true); $(".hide_delete_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_detail_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_filter_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_row_selector.ga_checkbox").bootstrapSwitch('state', true); $(".hide_query_info.ga_checkbox").bootstrapSwitch('state', true); $(".filter_form_layout.ga_checkbox").bootstrapSwitch('state', true); $(".hide_continue_edit_check_box.ga_checkbox").bootstrapSwitch('state', true); $(".hide_reset_button.ga_checkbox").bootstrapSwitch('state', true); $(".hide_continue_new_check_box.ga_checkbox").bootstrapSwitch('state', true); $(".hide_back_button.ga_checkbox").bootstrapSwitch('state', true); let detail_table = $("tbody.fields_detail-table"); detail_table.find("tr").remove(); NProgress.done(); {{end}}`, "generator": `{{define "generator"}} {{end}}`} ================================================ FILE: plugins/admin/modules/tools/generator.go ================================================ package tools import ( "bytes" "fmt" "go/format" "os" "path/filepath" "regexp" "strings" "text/template" "github.com/GoAdminGroup/go-admin/modules/db/dialect" "github.com/GoAdminGroup/go-admin/modules/language" "golang.org/x/text/cases" textLang "golang.org/x/text/language" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/template/types/form" ) type Param struct { Connection string `json:"connection"` Driver string `json:"driver"` Package string `json:"package"` Table string `json:"table"` RowTable string `json:"row_table"` TableTitle string `json:"table_title"` TableName string `json:"table_name"` HideFilterArea bool `json:"hide_filter_area"` HideNewButton bool `json:"hide_new_button"` HideExportButton bool `json:"hide_export_button"` HideEditButton bool `json:"hide_edit_button"` HideDeleteButton bool `json:"hide_delete_button"` HideDetailButton bool `json:"hide_detail_button"` HideFilterButton bool `json:"hide_filter_button"` HideRowSelector bool `json:"hide_row_selector"` HidePagination bool `json:"hide_pagination"` HideQueryInfo bool `json:"hide_query_info"` FilterFormLayout form.Layout `json:"filter_form_layout"` HideContinueEditCheckBox bool `json:"hide_continue_edit_check_box"` HideContinueNewCheckBox bool `json:"hide_continue_new_check_box"` HideResetButton bool `json:"hide_reset_button"` HideBackButton bool `json:"hide_back_button"` TablePageTitle string `json:"table_page_title"` TableDescription string `json:"table_description"` FormTitle string `json:"form_title"` FormDescription string `json:"form_description"` DetailTitle string `json:"detail_title"` DetailDescription string `json:"detail_description"` ExtraImport string `json:"extra_import"` ExtraCode string `json:"extra_code"` Fields Fields `json:"fields"` FormFields Fields `json:"form_fields"` DetailFields Fields `json:"detail_fields"` PrimaryKey string `json:"primary_key"` PrimaryKeyType string `json:"primary_key_type"` DetailDisplay uint8 `json:"detail_display"` Output string `json:"output"` } type Config struct { Connection string `json:"connection"` Driver string `json:"driver"` Package string `json:"package"` Table string `json:"table"` Schema string `json:"schema"` Output string `json:"output"` Conn db.Connection `json:"conn"` HideFilterArea bool `json:"hide_filter_area"` HideNewButton bool `json:"hide_new_button"` HideExportButton bool `json:"hide_export_button"` HideEditButton bool `json:"hide_edit_button"` HideDeleteButton bool `json:"hide_delete_button"` HideDetailButton bool `json:"hide_detail_button"` HideFilterButton bool `json:"hide_filter_button"` HideRowSelector bool `json:"hide_row_selector"` HidePagination bool `json:"hide_pagination"` HideQueryInfo bool `json:"hide_query_info"` FilterFormLayout form.Layout `json:"filter_form_layout"` ExtraImport string `json:"extra_import"` TableTitle string `json:"table_title"` TableDescription string `json:"table_description"` FormTitle string `json:"form_title"` FormDescription string `json:"form_description"` DetailTitle string `json:"detail_title"` DetailDescription string `json:"detail_description"` HideContinueEditCheckBox bool `json:"hide_continue_edit_check_box"` HideContinueNewCheckBox bool `json:"hide_continue_new_check_box"` HideResetButton bool `json:"hide_reset_button"` HideBackButton bool `json:"hide_back_button"` DetailDisplay uint8 `json:"detail_display"` ExtraCode string `json:"extra_code"` } func fixedTable(table string) string { if utils.InArray(keyWords, table) { return table + "_" } return table } var keyWords = []string{"import", "package", "chan", "const", "func", "interface", "map", "struct", "type", "var", "break", "case", "continue", "default", "defer", "else", "fallthrough", "for", "go", "goto", "if", "range", "return", "select", "switch"} func NewParam(cfg Config) *Param { ta := camelcase(cfg.Table) dbTable := cfg.Table if cfg.Schema != "" { dbTable = cfg.Schema + "." + cfg.Table } fields := getFieldsFromConn(cfg.Conn, dbTable, cfg.Driver, cfg.Connection) tt := cases.Title(textLang.Und).String(ta) pkey, ptype := fields.GetPrimaryKey() return &Param{ Connection: cfg.Connection, Driver: cfg.Driver, Package: cfg.Package, Table: fixedTable(ta), TableTitle: tt, TableName: dbTable, HideFilterArea: cfg.HideFilterArea, HideNewButton: cfg.HideNewButton, HideExportButton: cfg.HideExportButton, HideEditButton: cfg.HideEditButton, HideDeleteButton: cfg.HideDeleteButton, HideDetailButton: cfg.HideDetailButton, HideFilterButton: cfg.HideFilterButton, HideRowSelector: cfg.HideRowSelector, HidePagination: cfg.HidePagination, HideQueryInfo: cfg.HideQueryInfo, FilterFormLayout: cfg.FilterFormLayout, HideContinueEditCheckBox: cfg.HideContinueEditCheckBox, HideContinueNewCheckBox: cfg.HideContinueNewCheckBox, HideResetButton: cfg.HideResetButton, HideBackButton: cfg.HideBackButton, RowTable: cfg.Table, Fields: fields, FormFields: fields, DetailDisplay: cfg.DetailDisplay, Output: cfg.Output, ExtraImport: cfg.ExtraImport, ExtraCode: cfg.ExtraCode, TablePageTitle: utils.SetDefault(cfg.TableTitle, "", tt), TableDescription: utils.SetDefault(cfg.TableDescription, "", tt), FormTitle: utils.SetDefault(cfg.FormTitle, "", tt), FormDescription: utils.SetDefault(cfg.FormDescription, "", tt), PrimaryKey: pkey, PrimaryKeyType: ptype, } } func NewParamWithFields(cfg Config, fields ...Fields) *Param { ta := camelcase(cfg.Table) dbTable := cfg.Table if cfg.Schema != "" { dbTable = cfg.Schema + "." + cfg.Table } if len(cfg.Output) > 0 && cfg.Output[len(cfg.Output)-1] == '/' { cfg.Output = cfg.Output[:len(cfg.Output)-1] } tt := cases.Title(textLang.Und).String(ta) detailFields := make(Fields, 0) if len(fields) > 2 { detailFields = fields[2] } return &Param{ Connection: cfg.Connection, Driver: cfg.Driver, Package: cfg.Package, Table: ta, TableTitle: tt, TableName: dbTable, RowTable: cfg.Table, Fields: fields[0], FormFields: fields[1], DetailFields: detailFields, HideFilterArea: cfg.HideFilterArea, HideNewButton: cfg.HideNewButton, HideExportButton: cfg.HideExportButton, HideEditButton: cfg.HideEditButton, HideDeleteButton: cfg.HideDeleteButton, HideDetailButton: cfg.HideDetailButton, HideFilterButton: cfg.HideFilterButton, HideRowSelector: cfg.HideRowSelector, HidePagination: cfg.HidePagination, HideQueryInfo: cfg.HideQueryInfo, FilterFormLayout: cfg.FilterFormLayout, HideContinueEditCheckBox: cfg.HideContinueEditCheckBox, HideContinueNewCheckBox: cfg.HideContinueNewCheckBox, HideResetButton: cfg.HideResetButton, HideBackButton: cfg.HideBackButton, DetailDisplay: cfg.DetailDisplay, Output: cfg.Output, ExtraImport: cfg.ExtraImport, ExtraCode: cfg.ExtraCode, TablePageTitle: utils.SetDefault(cfg.TableTitle, "", tt), TableDescription: utils.SetDefault(cfg.TableDescription, "", tt), FormTitle: utils.SetDefault(cfg.FormTitle, "", tt), FormDescription: utils.SetDefault(cfg.FormDescription, "", tt), DetailTitle: utils.SetDefault(cfg.DetailTitle, "", tt), DetailDescription: utils.SetDefault(cfg.DetailDescription, "", tt), } } type Fields []Field func (fs Fields) GetPrimaryKey() (string, string) { for _, field := range fs { if field.IsPrimaryKey { return field.Name, field.DBType } } return "", "" } type Field struct { Head string `json:"head"` Name string `json:"name"` DBType string `json:"db_type"` FormType string `json:"form_type"` Filterable bool `json:"filterable"` Sortable bool `json:"sortable"` InfoEditable bool `json:"info_editable"` Editable bool `json:"editable"` Hide bool `json:"hide"` FormHide bool `json:"form_hide"` EditHide bool `json:"edit_hide"` CreateHide bool `json:"create_hide"` Default string `json:"default"` CanAdd bool `json:"can_add"` ExtraFun string `json:"extra_fun"` IsPrimaryKey bool `json:"is_primary_key"` } func Generate(param *Param) error { t, err := template.New("table_model").Parse(tableModelTmpl) if err != nil { return err } buf := new(bytes.Buffer) err = t.Execute(buf, param) if err != nil { return err } c, err := format.Source(buf.Bytes()) if err != nil { return err } return os.WriteFile(filepath.FromSlash(param.Output)+"/"+param.RowTable+".go", c, 0644) } const ( commentStrEnd = "example end" tablesEnd = "generators end" ) func GenerateTables(outputPath, packageName string, tables []string, isNew bool) error { if len(outputPath) > 0 && outputPath[len(outputPath)-1] == '/' { outputPath = outputPath[:len(outputPath)-1] } outputPath = filepath.FromSlash(outputPath) fileExist := utils.FileExist(outputPath + "/tables.go") if !isNew && !fileExist { return nil } var ( tableStr = "" commentStr = "" tablesContentByte []byte tablesContent string err error ) if fileExist { tablesContentByte, err = os.ReadFile(outputPath + "/tables.go") if err != nil { return err } tablesContent = string(tablesContentByte) } for i := 0; i < len(tables); i++ { lowerTable := strings.ToLower(tables[i]) if !strings.Contains(tablesContent, `"`+lowerTable+`"`) { tableStr += fmt.Sprintf(` "%s": Get%sTable, `, lowerTable, cases.Title(textLang.Und).String(camelcase(tables[i]))) if commentStr != "" { commentStr += ` ` } commentStr += fmt.Sprintf(`// "%s" => http://localhost:9033/admin/info/%s`, lowerTable, lowerTable) } } commentStr += ` // // ` + commentStrEnd tableStr += ` // ` + tablesEnd content := "" if tablesContent != "" && strings.Contains(tablesContent, "/") { replacer := strings.NewReplacer(`// `+commentStrEnd, commentStr, `// `+tablesEnd, tableStr) tablesContent = replacer.Replace(tablesContent) keep := `// example: //` keep2 := `, // ` + tablesEnd replacer2 := strings.NewReplacer(keep, keep, keep2, keep2, `// // `, "//", `// //`, "//", `// // "`, `// "`, `, `, ",") content = replacer2.Replace(tablesContent) } else { content = fmt.Sprintf(`// This file is generated by GoAdmin CLI adm. package %s import "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" // The key of Generators is the prefix of table info url. // The corresponding value is the Form and Table data. // // http://{{config.Domain}}:{{Port}}/{{config.Prefix}}/info/{{key}} // // example: // %s var Generators = map[string]table.Generator{ %s } `, packageName, commentStr, tableStr) } c, err := format.Source([]byte(content)) if err != nil { return err } return os.WriteFile(outputPath+"/tables.go", c, 0644) } func InsertPermissionOfTable(conn db.Connection, table string) { table = strings.ToLower(table) InsertPermissionInfoDB(conn, table+" "+language.GetWithScope("query", "generator"), table+"_query", "GET", "/info/"+table) InsertPermissionInfoDB(conn, table+" "+language.GetWithScope("show edit form page", "generator"), table+"_show_edit", "GET", "/info/"+table+"/edit") InsertPermissionInfoDB(conn, table+" "+language.GetWithScope("show create form page", "generator"), table+"_show_create", "GET", "/info/"+table+"/new") InsertPermissionInfoDB(conn, table+" "+language.GetWithScope("edit", "generator"), table+"_edit", "POST", "/edit/"+table) InsertPermissionInfoDB(conn, table+" "+language.GetWithScope("create", "generator"), table+"_create", "POST", "/new/"+table) InsertPermissionInfoDB(conn, table+" "+language.GetWithScope("delete", "generator"), table+"_delete", "POST", "/delete/"+table) InsertPermissionInfoDB(conn, table+" "+language.GetWithScope("export", "generator"), table+"_export", "POST", "/export/"+table) } func InsertPermissionInfoDB(conn db.Connection, name, slug, httpMethod, httpPath string) { checkExist, err := db.WithDriver(conn).Table("goadmin_permissions"). Where("slug", "=", slug). First() if db.CheckError(err, db.QUERY) { panic(err) } if checkExist != nil { return } _, err = db.WithDriver(conn).Table("goadmin_permissions"). Insert(dialect.H{ "name": name, "slug": slug, "http_method": httpMethod, "http_path": httpPath, }) if db.CheckError(err, db.INSERT) { panic(err) } } func camelcase(s string) string { arr := strings.Split(s, "_") var res = "" for i := 0; i < len(arr); i++ { if i == 0 { res += arr[i] } else { res += cases.Title(textLang.Und).String(arr[i]) } } return res } func getType(typeName string) string { r, _ := regexp.Compile(`\(.*?\)`) typeName = r.ReplaceAllString(typeName, "") r2, _ := regexp.Compile(`unsigned(.*)`) return strings.TrimSpace(cases.Title(textLang.Und).String(strings.ToLower(r2.ReplaceAllString(typeName, "")))) } func getFieldsFromConn(conn db.Connection, table, driver, connName string) Fields { columnsModel, _ := db.WithDriver(conn).Table(table).ShowColumnsWithComment(conn.GetConfig(connName).Name) fields := make(Fields, len(columnsModel)) fieldField := "Field" typeField := "Type" if driver == "postgresql" { fieldField = "column_name" typeField = "udt_name" } if driver == "sqlite" { fieldField = "name" typeField = "type" } if driver == "mssql" { fieldField = "column_name" typeField = "data_type" } for i, model := range columnsModel { typeName := getType(model[typeField].(string)) isPrimaryKey := false if columnKey, ok := model["Key"].(string); ok { isPrimaryKey = columnKey == "PRI" } head := cases.Title(textLang.Und).String(model[fieldField].(string)) if comment, ok := model["Comment"].(string); ok && comment != "" { head = cases.Title(textLang.Und).String(comment) } fields[i] = Field{ Head: head, Name: model[fieldField].(string), DBType: typeName, CanAdd: true, Editable: true, IsPrimaryKey: isPrimaryKey, FormType: form.GetFormTypeFromFieldType(db.DT(strings.ToUpper(typeName)), model[fieldField].(string)), } if model[fieldField].(string) == "id" { fields[i].Filterable = true } } return fields } ================================================ FILE: plugins/admin/modules/tools/template.go ================================================ package tools const tableModelTmpl = `{{define "table_model"}} package {{.Package}} import ( {{.ExtraImport}} "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template/types/form" ) func Get{{.TableTitle}}Table(ctx *context.Context) table.Table { {{if eq .Connection "default"}} {{if eq .PrimaryKey ""}} {{.Table}} := table.NewDefaultTable(ctx, table.DefaultConfigWithDriver("{{.Driver}}")) {{else}} {{.Table}} := table.NewDefaultTable(ctx, table.DefaultConfigWithDriver("{{.Driver}}").SetPrimaryKey("{{.PrimaryKey}}", db.{{.PrimaryKeyType}})) {{end}} {{else}} {{if eq .PrimaryKey ""}} {{.Table}} := table.NewDefaultTable(ctx, table.DefaultConfigWithDriverAndConnection("{{.Driver}}", "{{.Connection}}")) {{else}} {{.Table}} := table.NewDefaultTable(ctx, table.DefaultConfigWithDriverAndConnection("{{.Driver}}", "{{.Connection}}").SetPrimaryKey("{{.PrimaryKey}}", db.{{.PrimaryKeyType}})) {{end}} {{end}} info := {{.Table}}.GetInfo(){{if .HideFilterArea}}.HideFilterArea(){{end}} {{if .HideNewButton}}info.HideNewButton(){{end}} {{if .HideExportButton}}info.HideExportButton(){{end}} {{if .HideEditButton}}info.HideEditButton(){{end}} {{if .HideDeleteButton}}info.HideDeleteButton(){{end}} {{if .HideDetailButton}}info.HideDetailButton(){{end}} {{if .HideFilterButton}}info.HideFilterButton(){{end}} {{if .HideRowSelector}}info.HideRowSelector(){{end}} {{if .HidePagination}}info.HidePagination(){{end}} {{if .HideQueryInfo}}info.HideQueryInfo(){{end}} {{if not .FilterFormLayout.Default}}info.SetFilterFormLayout(form.{{.FilterFormLayout.String}}){{end}} {{- range $key, $field := .Fields}} info.AddField("{{$field.Head}}", "{{$field.Name}}", db.{{$field.DBType}}){{if $field.Filterable}}. FieldFilterable(){{end -}}{{if $field.Sortable}}. FieldSortable(){{end -}}{{if $field.InfoEditable}}. FieldEditAble(){{end -}}{{if $field.Hide}}. FieldHide(){{end -}} {{- end}} info.SetTable("{{.TableName}}").SetTitle("{{.TablePageTitle}}").SetDescription("{{.TableDescription}}") formList := {{.Table}}.GetForm() {{- range $key, $field := .FormFields}} formList.AddField("{{$field.Head}}", "{{$field.Name}}", db.{{$field.DBType}}, form.{{$field.FormType}}){{if ne $field.Default ""}}. FieldDefault({{$field.Default}}){{end -}}{{if not $field.CanAdd}}. FieldDisableWhenCreate(){{end -}}{{if not $field.Editable}}. FieldDisableWhenUpdate(){{end -}}{{if $field.FormHide}}. FieldHide(){{end -}}{{if $field.EditHide}}. FieldHideWhenUpdate(){{end -}}{{if $field.CreateHide}}. FieldHideWhenCreate(){{end -}}{{$field.ExtraFun}} {{- end}} {{if .HideContinueEditCheckBox}}formList.HideContinueEditCheckBox(){{end}} {{if .HideContinueNewCheckBox}}formList.HideContinueNewCheckBox(){{end}} {{if .HideResetButton}}formList.HideResetButton(){{end}} {{if .HideBackButton}}formList.HideBackButton(){{end}} formList.SetTable("{{.TableName}}").SetTitle("{{.FormTitle}}").SetDescription("{{.FormDescription}}") {{if eq .DetailDisplay 1}} detail := {{.Table}}.GetDetailFromInfo() {{else if eq .DetailDisplay 2}} detail := {{.Table}}.GetDetail() {{end}} {{- range $key, $field := .DetailFields}} detail.AddField("{{$field.Head}}", "{{$field.Name}}", db.{{$field.DBType}}) {{- end}} {{if ne .DetailDisplay 0}} detail.SetTable("{{.TableName}}").SetTitle("{{.TablePageTitle}}").SetDescription("{{.TableDescription}}") {{end}} {{.ExtraCode}} return {{.Table}} } {{end}}` ================================================ FILE: plugins/admin/router.go ================================================ package admin import ( "net/http" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/trace" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" "github.com/GoAdminGroup/go-admin/template" ) // initRouter initialize the router and return the context. func (admin *Admin) initRouter() *Admin { app := context.NewApp() route := app.Group(config.Prefix(), admin.globalErrorHandler, admin.traceIDMiddleware, admin.themeMiddleware) // auth route.GET(config.GetLoginUrl(), admin.handler.ShowLogin) route.POST("/signin", admin.handler.Auth) // auto install route.GET("/install", admin.handler.ShowInstall) route.POST("/install/database/check", admin.handler.CheckDatabase) checkRepeatedPath := make([]string, 0) for _, themeName := range template.Themes() { for _, path := range template.Get(nil, themeName).GetAssetList() { if !utils.InArray(checkRepeatedPath, path) { checkRepeatedPath = append(checkRepeatedPath, path) path = "/assets" + path admin.handler.AssetsTheme(path, themeName) route.GET(path, admin.handler.Assets) } } } for _, path := range template.GetComponentAsset() { route.GET("/assets"+path, admin.handler.Assets) } authRoute := route.Group("/", auth.Middleware(admin.Conn)) // auth authRoute.GET("/logout", admin.handler.Logout) authPrefixRoute := route.Group("/", auth.Middleware(admin.Conn), admin.guardian.CheckPrefix) // menus authRoute.POST("/menu/delete", admin.guardian.MenuDelete, admin.handler.DeleteMenu).Name("menu_delete") authRoute.POST("/menu/new", admin.guardian.MenuNew, admin.handler.NewMenu).Name("menu_new") authRoute.POST("/menu/edit", admin.guardian.MenuEdit, admin.handler.EditMenu).Name("menu_edit") authRoute.POST("/menu/order", admin.handler.MenuOrder).Name("menu_order") authRoute.GET("/menu", admin.handler.ShowMenu).Name("menu") authRoute.GET("/menu/edit/show", admin.handler.ShowEditMenu).Name("menu_edit_show") authRoute.GET("/menu/new", admin.handler.ShowNewMenu).Name("menu_new_show") authRoute.GET("/plugins", admin.handler.Plugins).Name("plugins") if config.IsNotProductionEnvironment() { authRoute.GET("/plugins/store", admin.handler.PluginStore).Name("plugins_store") authRoute.POST("/plugin/download", admin.handler.PluginDownload).Name("plugin_download") authRoute.POST("/plugin/detail", admin.handler.PluginDetail).Name("plugin_detail") } authRoute.POST("/server/login", admin.guardian.ServerLogin, admin.handler.ServerLogin).Name("server_login") formats := config.GetURLFormats() // add delete modify query authPrefixRoute.GET(formats.Detail, admin.handler.ShowDetail).Name("detail") authPrefixRoute.GET(formats.ShowEdit, admin.guardian.ShowForm, admin.handler.ShowForm).Name("show_edit") authPrefixRoute.GET(formats.ShowCreate, admin.guardian.ShowNewForm, admin.handler.ShowNewForm).Name("show_new") authPrefixRoute.POST(formats.Edit, admin.guardian.EditForm, admin.handler.EditForm).Name("edit") authPrefixRoute.POST(formats.Create, admin.guardian.NewForm, admin.handler.NewForm).Name("new") authPrefixRoute.POST(formats.Delete, admin.guardian.Delete, admin.handler.Delete).Name("delete") authPrefixRoute.POST(formats.Export, admin.guardian.Export, admin.handler.Export).Name("export") authPrefixRoute.GET(formats.Info, admin.handler.ShowInfo).Name("info") authPrefixRoute.POST(formats.Update, admin.guardian.Update, admin.handler.Update).Name("update") authRoute.GET("/application/info", admin.handler.SystemInfo) route.ANY("/operation/:__goadmin_op_id", auth.Middleware(admin.Conn), admin.handler.Operation) if config.GetOpenAdminApi() { // crud json apis apiRoute := route.Group("/api", auth.Middleware(admin.Conn), admin.guardian.CheckPrefix) apiRoute.GET("/list/:__prefix", admin.handler.ApiList).Name("api_info") apiRoute.GET("/detail/:__prefix", admin.handler.ApiDetail).Name("api_detail") apiRoute.POST("/delete/:__prefix", admin.guardian.Delete, admin.handler.Delete).Name("api_delete") apiRoute.POST("/edit/:__prefix", admin.guardian.EditForm, admin.handler.ApiUpdate).Name("api_edit") apiRoute.GET("/edit/form/:__prefix", admin.guardian.ShowForm, admin.handler.ApiUpdateForm).Name("api_show_edit") apiRoute.POST("/create/:__prefix", admin.guardian.NewForm, admin.handler.ApiCreate).Name("api_new") apiRoute.GET("/create/form/:__prefix", admin.guardian.ShowNewForm, admin.handler.ApiCreateForm).Name("api_show_new") apiRoute.POST("/export/:__prefix", admin.guardian.Export, admin.handler.Export).Name("api_export") apiRoute.POST("/update/:__prefix", admin.guardian.Update, admin.handler.Update).Name("api_update") } admin.App = app return admin } func (admin *Admin) globalErrorHandler(ctx *context.Context) { defer admin.handler.GlobalDeferHandler(ctx) response.OffLineHandler(ctx) ctx.Next() } func (admin *Admin) traceIDMiddleware(ctx *context.Context) { traceID := ctx.Headers(traceIDHeaderKey) if traceID == "" { traceID = trace.GenerateTraceID() } ctx.SetUserValue(trace.TraceIDKey, traceID) ctx.SetHeader(traceIDHeaderKey, traceID) ctx.Next() } const ( traceIDHeaderKey = "x-request-id" ) func (admin *Admin) themeMiddleware(ctx *context.Context) { theme := ctx.Query(context.ThemeKey) if theme == admin.config.Theme { ctx.Next() return } if theme == "" { theme = ctx.RefererQuery(context.ThemeKey) if theme == "" { ctx.Next() return } } cookieTheme := ctx.Cookie(context.ThemeKey) if cookieTheme != theme { ctx.SetCookie(&http.Cookie{ Name: context.ThemeKey, Value: theme, }) } ctx.Next() } ================================================ FILE: plugins/example/controller.go ================================================ package example import ( "html/template" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/page" template2 "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/chartjs" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/themes/adminlte/components/chart_legend" "github.com/GoAdminGroup/themes/adminlte/components/description" "github.com/GoAdminGroup/themes/adminlte/components/infobox" "github.com/GoAdminGroup/themes/adminlte/components/productlist" "github.com/GoAdminGroup/themes/adminlte/components/progress_group" "github.com/GoAdminGroup/themes/adminlte/components/smallbox" ) func (e *Example) TestHandler(rawCtx *context.Context) { page.SetPageContent(rawCtx, auth.Auth(rawCtx), func(ctx interface{}) (types.Panel, error) { components := template2.Default(rawCtx) colComp := components.Col() /************************** * Info Box /**************************/ infobox1 := infobox.New(). SetText("CPU TRAFFIC"). SetColor("#3583af"). SetNumber("100"). SetIcon(``). GetContent() infobox2 := infobox.New(). SetText("Likes"). SetColor("#6a7c86"). SetNumber("1030.00$"). SetIcon(``). GetContent() infobox3 := infobox.New(). SetText("Sales"). SetColor("#d8cd68"). SetNumber("760"). SetIcon(``). GetContent() infobox4 := infobox.New(). SetText("New Members"). SetColor("#6cad6e"). SetNumber("2,349"). SetIcon(``). GetContent() var size = types.Size(6, 3, 0).XS(12) infoboxCol1 := colComp.SetSize(size).SetContent(infobox1).GetContent() infoboxCol2 := colComp.SetSize(size).SetContent(infobox2).GetContent() infoboxCol3 := colComp.SetSize(size).SetContent(infobox3).GetContent() infoboxCol4 := colComp.SetSize(size).SetContent(infobox4).GetContent() row1 := components.Row().SetContent(infoboxCol1 + infoboxCol2 + infoboxCol3 + infoboxCol4).GetContent() /************************** * Box /**************************/ table := components.Table().SetInfoList([]map[string]types.InfoItem{ { "Order ID": {Content: "OR9842"}, "Item": {Content: "Call of Duty IV"}, "Status": {Content: "shipped"}, "Popularity": {Content: "90%"}, }, { "Order ID": {Content: "OR9842"}, "Item": {Content: "Call of Duty IV"}, "Status": {Content: "shipped"}, "Popularity": {Content: "90%"}, }, { "Order ID": {Content: "OR9842"}, "Item": {Content: "Call of Duty IV"}, "Status": {Content: "shipped"}, "Popularity": {Content: "90%"}, }, }).SetThead(types.Thead{ {Head: "Order ID"}, {Head: "Item"}, {Head: "Status"}, {Head: "Popularity"}, }).GetContent() boxInfo := components.Box(). WithHeadBorder(). SetHeader("Latest Orders"). SetHeadColor("#f7f7f7"). SetBody(table). SetFooter(``). GetContent() tableCol := colComp.SetSize(types.SizeMD(8)).SetContent(row1 + boxInfo).GetContent() /************************** * Product List /**************************/ productList := productlist.New().SetData([]map[string]string{ { "img": "http://adminlte.io/themes/AdminLTE/dist/img/default-50x50.gif", "title": "GoAdmin", "has_tabel": "true", "labeltype": "warning", "label": "free", "description": `a framework help you build the dataviz system`, }, { "img": "http://adminlte.io/themes/AdminLTE/dist/img/default-50x50.gif", "title": "GoAdmin", "has_tabel": "true", "labeltype": "warning", "label": "free", "description": `a framework help you build the dataviz system`, }, { "img": "http://adminlte.io/themes/AdminLTE/dist/img/default-50x50.gif", "title": "GoAdmin", "has_tabel": "true", "labeltype": "warning", "label": "free", "description": `a framework help you build the dataviz system`, }, }).GetContent() boxWarning := components.Box().SetTheme("warning").WithHeadBorder().SetHeader("Recently Added Products"). SetBody(productList). SetFooter(`View All Products`). GetContent() newsCol := colComp.SetSize(types.SizeMD(4)).SetContent(boxWarning).GetContent() row5 := components.Row().SetContent(tableCol + newsCol).GetContent() /************************** * Box /**************************/ lineChart := chartjs.Line(). SetID("salechart"). SetHeight(180). SetTitle("Sales: 1 Jan, 2019 - 30 Jul, 2019"). SetLabels([]string{"January", "February", "March", "April", "May", "June", "July"}). AddDataSet("Electronics"). DSData([]float64{65, 59, 80, 81, 56, 55, 40}). DSFill(false). DSBorderColor("rgb(210, 214, 222)"). DSLineTension(0.1). AddDataSet("Digital Goods"). DSData([]float64{28, 48, 40, 19, 86, 27, 90}). DSFill(false). DSBorderColor("rgba(60,141,188,1)"). DSLineTension(0.1). GetContent() title := `

    Goal Completion

    ` progressGroup := progress_group.New(). SetTitle("Add Products to Cart"). SetColor("#76b2d4"). SetDenominator(200). SetMolecular(160). SetPercent(80). GetContent() progressGroup1 := progress_group.New(). SetTitle("Complete Purchase"). SetColor("#f17c6e"). SetDenominator(400). SetMolecular(310). SetPercent(80). GetContent() progressGroup2 := progress_group.New(). SetTitle("Visit Premium Page"). SetColor("#ace0ae"). SetDenominator(800). SetMolecular(490). SetPercent(80). GetContent() progressGroup3 := progress_group.New(). SetTitle("Send Inquiries"). SetColor("#fdd698"). SetDenominator(500). SetMolecular(250). SetPercent(50). GetContent() boxInternalCol1 := colComp.SetContent(lineChart).SetSize(types.SizeMD(8)).GetContent() boxInternalCol2 := colComp. SetContent(template.HTML(title) + progressGroup + progressGroup1 + progressGroup2 + progressGroup3). SetSize(types.SizeMD(4)). GetContent() boxInternalRow := components.Row().SetContent(boxInternalCol1 + boxInternalCol2).GetContent() description1 := description.New(). SetPercent("17"). SetNumber("¥140,100"). SetTitle("TOTAL REVENUE"). SetArrow("up"). SetColor("green"). SetBorder("right"). GetContent() description2 := description.New(). SetPercent("2"). SetNumber("440,560"). SetTitle("TOTAL REVENUE"). SetArrow("down"). SetColor("red"). SetBorder("right"). GetContent() description3 := description.New(). SetPercent("12"). SetNumber("¥140,050"). SetTitle("TOTAL REVENUE"). SetArrow("up"). SetColor("green"). SetBorder("right"). GetContent() description4 := description.New(). SetPercent("1"). SetNumber("30943"). SetTitle("TOTAL REVENUE"). SetArrow("up"). SetColor("green"). GetContent() size2 := types.SizeXS(6).SM(3) boxInternalCol3 := colComp.SetContent(description1).SetSize(size2).GetContent() boxInternalCol4 := colComp.SetContent(description2).SetSize(size2).GetContent() boxInternalCol5 := colComp.SetContent(description3).SetSize(size2).GetContent() boxInternalCol6 := colComp.SetContent(description4).SetSize(size2).GetContent() boxInternalRow2 := components.Row().SetContent(boxInternalCol3 + boxInternalCol4 + boxInternalCol5 + boxInternalCol6).GetContent() box := components.Box().WithHeadBorder().SetHeader("Monthly Recap Report"). SetBody(boxInternalRow). SetFooter(boxInternalRow2). GetContent() boxcol := colComp.SetContent(box).SetSize(types.SizeMD(12)).GetContent() row2 := components.Row().SetContent(boxcol).GetContent() /************************** * Small Box /**************************/ smallbox1 := smallbox.New().SetColor("blue").SetIcon("ion-ios-gear-outline").SetUrl("/").SetTitle("new users").SetValue("345¥").GetContent() smallbox2 := smallbox.New().SetColor("yellow").SetIcon("ion-ios-cart-outline").SetUrl("/").SetTitle("new users").SetValue("80%").GetContent() smallbox3 := smallbox.New().SetColor("red").SetIcon("fa-user").SetUrl("/").SetTitle("new users").SetValue("645¥").GetContent() smallbox4 := smallbox.New().SetColor("green").SetIcon("ion-ios-cart-outline").SetUrl("/").SetTitle("new users").SetValue("889¥").GetContent() col1 := colComp.SetSize(size).SetContent(smallbox1).GetContent() col2 := colComp.SetSize(size).SetContent(smallbox2).GetContent() col3 := colComp.SetSize(size).SetContent(smallbox3).GetContent() col4 := colComp.SetSize(size).SetContent(smallbox4).GetContent() row3 := components.Row().SetContent(col1 + col2 + col3 + col4).GetContent() /************************** * Pie Chart /**************************/ pie := chartjs.Pie(). SetHeight(170). SetLabels([]string{"Navigator", "Opera", "Safari", "FireFox", "IE", "Chrome"}). SetID("pieChart"). AddDataSet("Chrome"). DSData([]float64{100, 300, 600, 400, 500, 700}). DSBackgroundColor([]chartjs.Color{ "rgb(255, 205, 86)", "rgb(54, 162, 235)", "rgb(255, 99, 132)", "rgb(255, 205, 86)", "rgb(54, 162, 235)", "rgb(255, 99, 132)", }). GetContent() legend := chart_legend.New().SetData([]map[string]string{ { "label": " Chrome", "color": "red", }, { "label": " IE", "color": "Green", }, { "label": " FireFox", "color": "yellow", }, { "label": " Sarafri", "color": "blue", }, { "label": " Opera", "color": "light-blue", }, { "label": " Navigator", "color": "gray", }, }).GetContent() boxDanger := components.Box().SetTheme("danger").WithHeadBorder().SetHeader("Browser Usage"). SetBody(components.Row(). SetContent(colComp.SetSize(types.SizeMD(8)). SetContent(pie). GetContent() + colComp.SetSize(types.SizeMD(4)). SetContent(legend). GetContent()).GetContent()). SetFooter(`

    View All Users

    `). GetContent() tabs := components.Tabs().SetData([]map[string]template.HTML{ { "title": "tabs1", "content": template.HTML(`How to use:

    Exactly like the original bootstrap tabs except you should use the custom wrapper .nav-tabs-custom to achieve this style.

    A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine. I am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.`), }, { "title": "tabs2", "content": template.HTML(` The European languages are members of the same family. Their separate existence is a myth. For science, music, sport, etc, Europe uses the same vocabulary. The languages only differ in their grammar, their pronunciation and their most common words. Everyone realizes why a new common language would be desirable: one could refuse to pay expensive translators. To achieve this, it would be necessary to have uniform grammar, pronunciation and more common words. If several languages coalesce, the grammar of the resulting language is more simple and regular than that of the individual languages. `), }, { "title": "tabs3", "content": template.HTML(` Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. `), }, }).GetContent() buttonTest := `` popupForm := `
    ` popup := components.Popup().SetID("exampleModal"). SetFooter("Save Change"). SetTitle("this is a popup"). SetBody(template.HTML(popupForm)). GetContent() col5 := colComp.SetSize(types.SizeMD(8)).SetContent(tabs + template.HTML(buttonTest)).GetContent() col6 := colComp.SetSize(types.SizeMD(4)).SetContent(boxDanger + popup).GetContent() row4 := components.Row().SetContent(col5 + col6).GetContent() return types.Panel{ Content: row5 + row2 + row3 + row4, Title: "Dashboard", Description: "dashboard example", }, nil }, e.Conn) } ================================================ FILE: plugins/example/example.go ================================================ package example import ( c "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/service" "github.com/GoAdminGroup/go-admin/plugins" ) type Example struct { *plugins.Base } func NewExample() *Example { return &Example{ Base: &plugins.Base{PlugName: "example"}, } } func (e *Example) InitPlugin(srv service.List) { e.InitBase(srv, "example") e.App = e.initRouter(c.Prefix(), srv) } ================================================ FILE: plugins/example/go_plugin/Makefile ================================================ all: build build: go build -buildmode=plugin -o plugin.so main.go ================================================ FILE: plugins/example/go_plugin/main.go ================================================ package main import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" c "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/service" "github.com/GoAdminGroup/go-admin/plugins" ) type Example struct { *plugins.Base } var Plugin = &Example{ Base: &plugins.Base{PlugName: "example"}, } func (example *Example) InitPlugin(srv service.List) { example.InitBase(srv, "example") Plugin.App = example.initRouter(c.Prefix(), srv) } func (example *Example) initRouter(prefix string, srv service.List) *context.App { app := context.NewApp() route := app.Group(prefix) route.GET("/example", auth.Middleware(db.GetConnection(srv)), example.TestHandler) return app } func (example *Example) TestHandler(ctx *context.Context) { } ================================================ FILE: plugins/example/router.go ================================================ package example import ( "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/service" ) func (e *Example) initRouter(prefix string, srv service.List) *context.App { app := context.NewApp() route := app.Group(prefix) route.GET("/example", auth.Middleware(db.GetConnection(srv)), e.TestHandler) return app } ================================================ FILE: plugins/plugins.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package plugins import ( "bytes" "encoding/json" "errors" template2 "html/template" "net/http" "plugin" "time" "github.com/GoAdminGroup/go-admin/template/icon" "github.com/GoAdminGroup/go-admin/template/types/action" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/auth" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/db" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/menu" "github.com/GoAdminGroup/go-admin/modules/remote_server" "github.com/GoAdminGroup/go-admin/modules/service" "github.com/GoAdminGroup/go-admin/modules/ui" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/types" ) // Plugin as one of the key components of goAdmin has three // methods. GetRequest return all the path registered in the // plugin. GetHandler according the url and method return the // corresponding handler. InitPlugin init the plugin which do // something like init the database and set the config and register // the routes. The Plugin must implement the three methods. type Plugin interface { GetHandler() context.HandlerMap InitPlugin(services service.List) GetGenerators() table.GeneratorList Name() string Prefix() string GetInfo() Info GetIndexURL() string GetSettingPage() table.Generator IsInstalled() bool Uninstall() error Upgrade() error } type Info struct { Title string `json:"title" yaml:"title" ini:"title"` Description string `json:"description" yaml:"description" ini:"description"` OldVersion string `json:"old_version" yaml:"old_version" ini:"old_version"` Version string `json:"version" yaml:"version" ini:"version"` Author string `json:"author" yaml:"author" ini:"author"` Banners []string `json:"banners" yaml:"banners" ini:"banners"` Url string `json:"url" yaml:"url" ini:"url"` Cover string `json:"cover" yaml:"cover" ini:"cover"` MiniCover string `json:"mini_cover" yaml:"mini_cover" ini:"mini_cover"` Website string `json:"website" yaml:"website" ini:"website"` Agreement string `json:"agreement" yaml:"agreement" ini:"agreement"` CreateDate time.Time `json:"create_date" yaml:"create_date" ini:"create_date"` UpdateDate time.Time `json:"update_date" yaml:"update_date" ini:"update_date"` ModulePath string `json:"module_path" yaml:"module_path" ini:"module_path"` Name string `json:"name" yaml:"name" ini:"name"` Uuid string `json:"uuid" yaml:"uuid" ini:"uuid"` Downloaded bool `json:"downloaded" yaml:"downloaded" ini:"downloaded"` ExtraDownloadUrl string `json:"extra_download_url" yaml:"extra_download_url" ini:"extra_download_url"` Price []string `json:"price" yaml:"price" ini:"price"` GoodUUIDs []string `json:"good_uuids" yaml:"good_uuids" ini:"good_uuids"` GoodNum int64 `json:"good_num" yaml:"good_num" ini:"good_num"` CommentNum int64 `json:"comment_num" yaml:"comment_num" ini:"comment_num"` Order int64 `json:"order" yaml:"order" ini:"order"` Features string `json:"features" yaml:"features" ini:"features"` Questions []string `json:"questions" yaml:"questions" ini:"questions"` HasBought bool `json:"has_bought" yaml:"has_bought" ini:"has_bought"` CanUpdate bool `json:"can_update" yaml:"can_update" ini:"can_update"` Legal bool `json:"legal" yaml:"legal" ini:"legal"` SkipInstallation bool `json:"skip_installation" yaml:"skip_installation" ini:"skip_installation"` } func (i Info) IsFree() bool { return len(i.Price) == 0 } type Base struct { App *context.App Services service.List Conn db.Connection UI *ui.Service PlugName string URLPrefix string Info Info } func (b *Base) InitPlugin(services service.List) {} func (b *Base) GetGenerators() table.GeneratorList { return make(table.GeneratorList) } func (b *Base) GetHandler() context.HandlerMap { return b.App.Handlers } func (b *Base) Name() string { return b.PlugName } func (b *Base) GetInfo() Info { return b.Info } func (b *Base) Prefix() string { return b.URLPrefix } func (b *Base) IsInstalled() bool { return false } func (b *Base) Uninstall() error { return nil } func (b *Base) Upgrade() error { return nil } func (b *Base) GetIndexURL() string { return "" } func (b *Base) GetSettingPage() table.Generator { return nil } func (b *Base) InitBase(srv service.List, prefix string) { b.Services = srv b.Conn = db.GetConnection(b.Services) b.UI = ui.GetService(b.Services) b.URLPrefix = prefix } func (b *Base) SetInfo(info Info) { b.Info = info } func (b *Base) Title() string { return language.GetWithScope(b.Info.Title, b.Name()) } func (b *Base) ExecuteTmpl(ctx *context.Context, panel types.Panel, options template.ExecuteOptions) *bytes.Buffer { return Execute(ctx, b.Conn, *b.UI.NavButtons, auth.Auth(ctx), panel, options) } func (b *Base) ExecuteTmplWithNavButtons(ctx *context.Context, panel types.Panel, btns types.Buttons, options template.ExecuteOptions) *bytes.Buffer { return Execute(ctx, b.Conn, btns, auth.Auth(ctx), panel, options) } func (b *Base) ExecuteTmplWithMenu(ctx *context.Context, panel types.Panel, options template.ExecuteOptions) *bytes.Buffer { return ExecuteWithMenu(ctx, b.Conn, *b.UI.NavButtons, auth.Auth(ctx), panel, b.Name(), b.Title(), options) } func (b *Base) ExecuteTmplWithCustomMenu(ctx *context.Context, panel types.Panel, menu *menu.Menu, options template.ExecuteOptions) *bytes.Buffer { return ExecuteWithCustomMenu(ctx, *b.UI.NavButtons, auth.Auth(ctx), panel, menu, b.Title(), options) } func (b *Base) ExecuteTmplWithMenuAndNavButtons(ctx *context.Context, panel types.Panel, menu *menu.Menu, btns types.Buttons, options template.ExecuteOptions) *bytes.Buffer { return ExecuteWithMenu(ctx, b.Conn, btns, auth.Auth(ctx), panel, b.Name(), b.Title(), options) } func (b *Base) NewMenu(data menu.NewMenuData) (int64, error) { return menu.NewMenu(b.Conn, data) } func (b *Base) HTML(ctx *context.Context, panel types.Panel, options ...template.ExecuteOptions) { buf := b.ExecuteTmpl(ctx, panel, template.GetExecuteOptions(options)) ctx.HTMLByte(http.StatusOK, buf.Bytes()) } func (b *Base) HTMLCustomMenu(ctx *context.Context, panel types.Panel, menu *menu.Menu, options ...template.ExecuteOptions) { buf := b.ExecuteTmplWithCustomMenu(ctx, panel, menu, template.GetExecuteOptions(options)) ctx.HTMLByte(http.StatusOK, buf.Bytes()) } func (b *Base) HTMLMenu(ctx *context.Context, panel types.Panel, options ...template.ExecuteOptions) { buf := b.ExecuteTmplWithMenu(ctx, panel, template.GetExecuteOptions(options)) ctx.HTMLByte(http.StatusOK, buf.Bytes()) } func (b *Base) HTMLBtns(ctx *context.Context, panel types.Panel, btns types.Buttons, options ...template.ExecuteOptions) { buf := b.ExecuteTmplWithNavButtons(ctx, panel, btns, template.GetExecuteOptions(options)) ctx.HTMLByte(http.StatusOK, buf.Bytes()) } func (b *Base) HTMLMenuWithBtns(ctx *context.Context, panel types.Panel, menu *menu.Menu, btns types.Buttons, options ...template.ExecuteOptions) { buf := b.ExecuteTmplWithMenuAndNavButtons(ctx, panel, menu, btns, template.GetExecuteOptions(options)) ctx.HTMLByte(http.StatusOK, buf.Bytes()) } func (b *Base) HTMLFile(ctx *context.Context, path string, data map[string]interface{}, options ...template.ExecuteOptions) { buf := new(bytes.Buffer) var panel types.Panel t, err := template2.ParseFiles(path) if err != nil { panel = template.WarningPanel(ctx, err.Error()).GetContent(config.IsProductionEnvironment()) } else { if err := t.Execute(buf, data); err != nil { panel = template.WarningPanel(ctx, err.Error()).GetContent(config.IsProductionEnvironment()) } else { panel = types.Panel{ Content: template.HTML(buf.String()), } } } b.HTML(ctx, panel, options...) } func (b *Base) HTMLFiles(ctx *context.Context, data map[string]interface{}, files []string, options ...template.ExecuteOptions) { buf := new(bytes.Buffer) var panel types.Panel t, err := template2.ParseFiles(files...) if err != nil { panel = template.WarningPanel(ctx, err.Error()).GetContent(config.IsProductionEnvironment()) } else { if err := t.Execute(buf, data); err != nil { panel = template.WarningPanel(ctx, err.Error()).GetContent(config.IsProductionEnvironment()) } else { panel = types.Panel{ Content: template.HTML(buf.String()), } } } b.HTML(ctx, panel, options...) } type BasePlugin struct { Base Info Info IndexURL string Installed bool } func (b *BasePlugin) GetInfo() Info { return b.Info } func (b *BasePlugin) Name() string { return b.Info.Name } func (b *BasePlugin) GetIndexURL() string { return b.IndexURL } func (b *BasePlugin) IsInstalled() bool { return b.Installed } func NewBasePluginWithInfo(info Info) Plugin { return &BasePlugin{Info: info} } func NewBasePluginWithInfoAndIndexURL(info Info, u string, installed bool) Plugin { return &BasePlugin{Info: info, IndexURL: u, Installed: installed} } func GetPluginsWithInfos(info []Info) Plugins { p := make(Plugins, len(info)) for k, i := range info { p[k] = NewBasePluginWithInfo(i) } return p } func LoadFromPlugin(mod string) Plugin { plug, err := plugin.Open(mod) if err != nil { logger.Error("LoadFromPlugin err", err) panic(err) } symPlugin, err := plug.Lookup("Plugin") if err != nil { logger.Error("LoadFromPlugin err", err) panic(err) } var p Plugin p, ok := symPlugin.(Plugin) if !ok { logger.Error("LoadFromPlugin err: unexpected type from module symbol") panic(errors.New("LoadFromPlugin err: unexpected type from module symbol")) } return p } // GetHandler is a help method for Plugin GetHandler. func GetHandler(app *context.App) context.HandlerMap { return app.Handlers } func Execute(ctx *context.Context, conn db.Connection, navButtons types.Buttons, user models.UserModel, panel types.Panel, options template.ExecuteOptions) *bytes.Buffer { tmpl, tmplName := template.Get(ctx, config.GetTheme()).GetTemplate(ctx.IsPjax()) return template.Execute(ctx, &template.ExecuteParam{ User: user, TmplName: tmplName, Tmpl: tmpl, Panel: panel, Config: config.Get(), Menu: menu.GetGlobalMenu(user, conn, ctx.Lang()).SetActiveClass(config.URLRemovePrefix(ctx.Path())), Animation: options.Animation, Buttons: navButtons.CheckPermission(user), NoCompress: options.NoCompress, IsPjax: ctx.IsPjax(), Iframe: ctx.IsIframe(), }) } func ExecuteWithCustomMenu(ctx *context.Context, navButtons types.Buttons, user models.UserModel, panel types.Panel, menu *menu.Menu, logo string, options template.ExecuteOptions) *bytes.Buffer { tmpl, tmplName := template.Get(ctx, config.GetTheme()).GetTemplate(ctx.IsPjax()) return template.Execute(ctx, &template.ExecuteParam{ User: user, TmplName: tmplName, Tmpl: tmpl, Panel: panel, Config: config.Get(), Menu: menu, Animation: options.Animation, Buttons: navButtons.CheckPermission(user), NoCompress: options.NoCompress, Logo: template2.HTML(logo), IsPjax: ctx.IsPjax(), Iframe: ctx.IsIframe(), }) } func ExecuteWithMenu(ctx *context.Context, conn db.Connection, navButtons types.Buttons, user models.UserModel, panel types.Panel, name, logo string, options template.ExecuteOptions) *bytes.Buffer { tmpl, tmplName := template.Get(ctx, config.GetTheme()).GetTemplate(ctx.IsPjax()) btns := options.NavDropDownButton if btns == nil { btns = []*types.NavDropDownItemButton{ types.GetDropDownItemButton(language.GetFromHtml("plugin setting"), action.Jump(config.Url("/info/plugin_"+name+"/edit"))), types.GetDropDownItemButton(language.GetFromHtml("menus manage"), action.Jump(config.Url("/menu?__plugin_name="+name))), } } else { btns = append(btns, []*types.NavDropDownItemButton{ types.GetDropDownItemButton(language.GetFromHtml("plugin setting"), action.Jump(config.Url("/info/plugin_"+name+"/edit"))), types.GetDropDownItemButton(language.GetFromHtml("menus manage"), action.Jump(config.Url("/menu?__plugin_name="+name))), }...) } return template.Execute(ctx, &template.ExecuteParam{ User: user, TmplName: tmplName, Tmpl: tmpl, Panel: panel, Config: config.Get(), Menu: menu.GetGlobalMenu(user, conn, ctx.Lang(), name).SetActiveClass(config.URLRemovePrefix(ctx.Path())), Animation: options.Animation, Buttons: navButtons.Copy(). RemoveInfoNavButton(). RemoveSiteNavButton(). RemoveToolNavButton(). Add(types.GetDropDownButton("", icon.Gear, btns)).CheckPermission(user), NoCompress: options.NoCompress, Logo: template2.HTML(logo), IsPjax: ctx.IsPjax(), Iframe: ctx.IsIframe(), }) } type Plugins []Plugin func (pp Plugins) Add(p Plugin) Plugins { if !pp.Exist(p) { pp = append(pp, p) } return pp } func (pp Plugins) Exist(p Plugin) bool { for _, v := range pp { if v.Name() == p.Name() { return true } } return false } func FindByName(name string) (Plugin, bool) { for _, v := range pluginList { if v.Name() == name { return v, true } } return nil, false } func FindByNameAll(name string) (Plugin, bool) { for _, v := range allPluginList { if v.Name() == name { return v, true } } return nil, false } var ( pluginList = make(Plugins, 0) allPluginList = make(Plugins, 0) ) func Exist(p Plugin) bool { return pluginList.Exist(p) } func Add(p Plugin) { // TODO: 验证插件合法性 pluginList = pluginList.Add(p) } func GetAll(req remote_server.GetOnlineReq, token string) (Plugins, Page) { plugs := make(Plugins, 0) page := Page{} res, err := remote_server.GetOnline(req, token) if err != nil { return plugs, page } var data GetOnlineRes err = json.Unmarshal(res, &data) if err != nil { return plugs, page } if data.Code != 0 { return plugs, page } plugs = GetPluginsWithInfos(data.Data.List) page = data.Data.Page for index, p := range plugs { for key, value := range pluginList { if value.Name() == p.Name() { info := pluginList[key].GetInfo() info.CanUpdate = utils.CompareVersion(info.Version, plugs[index].GetInfo().Version) info.OldVersion = info.Version info.Downloaded = true info.Description = language.GetWithScope(info.Description, info.Name) info.Title = language.GetWithScope(info.Title, info.Name) info.Version = plugs[index].GetInfo().Version plugs[index] = NewBasePluginWithInfoAndIndexURL(info, value.GetIndexURL(), value.IsInstalled()) break } } } for _, p := range plugs { exist := false for _, pp := range allPluginList { if pp.Name() == p.Name() { exist = true break } } if !exist { allPluginList = append(allPluginList, p) } } return plugs, page } func Get() Plugins { var plugs = make(Plugins, len(pluginList)) copy(plugs, pluginList) return plugs } type GetOnlineRes struct { Code int `json:"code"` Msg string `json:"msg"` Data GetOnlineResData `json:"data"` } type GetOnlineResData struct { List []Info `json:"list"` Count int `json:"count"` HasMore bool `json:"has_more"` Page Page `json:"page"` } type Page struct { CSS string `json:"css"` HTML string `json:"html"` JS string `json:"js"` } ================================================ FILE: plugins/plugins_test.go ================================================ package plugins import "testing" func TestLoadFromPlugin(t *testing.T) { LoadFromPlugin("./example/go_plugin/plugin.so") } ================================================ FILE: template/chartjs/assets.go ================================================ // Code generated by go-bindata. DO NOT EDIT. // sources: // assets/chart.min.js package chartjs import ( "bytes" "compress/gzip" "fmt" "io" "io/ioutil" "os" "path/filepath" "strings" "time" ) func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { return nil, fmt.Errorf("Read %q: %v", name, err) } var buf bytes.Buffer _, err = io.Copy(&buf, gz) clErr := gz.Close() if err != nil { return nil, fmt.Errorf("Read %q: %v", name, err) } if clErr != nil { return nil, err } return buf.Bytes(), nil } type asset struct { bytes []byte info os.FileInfo } type bindataFileInfo struct { name string size int64 mode os.FileMode modTime time.Time } func (fi bindataFileInfo) Name() string { return fi.name } func (fi bindataFileInfo) Size() int64 { return fi.size } func (fi bindataFileInfo) Mode() os.FileMode { return fi.mode } func (fi bindataFileInfo) ModTime() time.Time { return fi.modTime } func (fi bindataFileInfo) IsDir() bool { return false } func (fi bindataFileInfo) Sys() interface{} { return nil } var _assetsChartMinJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\xbd\x7b\x9f\xdb\x36\xb2\x28\xf8\xff\xf9\x14\xdd\x3c\x89\x86\x68\x41\x6c\x49\x76\xdb\x6d\xaa\xd1\x5a\x27\x8e\x27\x99\xc4\xb1\xc7\x76\x1e\x8e\x46\xb7\x07\x22\x21\x09\x63\x0a\x50\x08\xa8\x1f\x91\xf8\xdd\xf7\x87\x02\x40\x82\x92\xec\xe4\xec\xdd\xbb\x1b\xff\xd2\x22\x01\x10\x8f\x42\xa1\x50\x2f\x14\xce\xcf\x4e\xff\xeb\xe4\xec\xe4\xeb\x25\x2d\x75\xf2\x1f\x75\x72\xfb\x28\x19\x26\x03\x93\xb4\xd4\x7a\xad\xd2\xf3\xf3\xbb\xbb\xbb\x24\x33\xd9\xff\x51\x89\x2c\x17\x26\x2b\xce\xd0\xc9\xb0\x3f\x1c\x34\x9f\x7d\x2d\x85\x2e\xf9\x6c\xa3\x65\xa9\x4c\x89\xb7\xac\x60\x54\xb1\xfc\x64\x23\x72\x56\x9e\xe8\x25\x3b\x79\xf5\xdd\xfb\x93\x1f\x78\xc6\x84\x62\xff\x75\x72\x76\xfe\x5f\xa7\xf3\x8d\xc8\x34\x97\x22\xd6\x98\xa1\x6d\x24\x67\xff\x61\x99\x8e\x08\xd1\x0f\x6b\x26\xe7\x27\xec\x7e\x2d\x4b\xad\x3a\x9d\xc8\xd4\x31\xe7\x82\xe5\xd1\xa9\xcf\x5c\xc9\x7c\x53\xb0\xb1\xfd\x49\x5c\x51\xc2\x62\x94\x46\xbe\xda\xa6\x26\xfb\x75\xa7\x63\x7f\x13\xba\xca\xc7\xf6\x31\x66\x28\x8d\x35\x39\xd6\xc0\xa2\x90\x33\x5a\xbc\x5f\x72\x35\x6e\x1e\x53\xbd\xdb\x29\x56\xcc\x51\x02\x03\x37\xed\x55\xb1\x5e\x72\x85\xe3\x7a\x30\x68\x1b\x6d\x14\x3b\x51\xba\xe4\x99\x8e\x46\x99\x14\x4a\x9f\xb4\xda\xa8\xfb\x75\xc7\x45\x2e\xef\xc6\x0d\x1c\xd0\xb6\x64\x7a\x53\x8a\x13\x1d\xa3\x2a\xb5\xd9\x49\xc9\x7e\xdf\x30\xa5\x9f\x0b\xbe\xa2\xa6\xd8\xcb\x92\xae\xd8\xc8\x7f\x74\xc2\x62\x86\x39\x16\x68\x6b\x5b\x92\x44\xec\x76\xb1\x26\xd7\xcf\xcb\x92\x3e\x24\xeb\x52\x6a\x69\x9a\x4b\x54\xc1\x33\x96\x64\xb4\x28\x62\x8d\xd0\xa8\x60\xfa\x44\x91\xd3\x01\xa6\x64\x32\x1d\xb9\x66\xeb\x9e\x24\x49\x22\xd0\x96\x12\x19\x0b\x84\xd5\x6e\x17\x2b\x72\xda\xc7\xda\x7e\x6e\xfb\x85\xe3\x18\x91\xeb\x2d\xd4\xc1\x12\xba\x5e\x17\x0f\x31\xc7\x14\x55\x08\xa1\xaa\xaa\xbb\xc7\xed\xec\x9a\xe6\xf8\x41\x33\xf5\x78\xd9\x38\xce\x0a\x46\xcb\xf7\x7c\xc5\xe4\x46\xc7\x1c\x61\x4e\x14\xd3\xfe\xdd\xd4\x81\x52\x1d\x23\xcc\xaa\xca\x0e\x54\x10\x4d\xae\x23\xa5\x69\x69\x70\x86\xe8\x71\x54\xb0\xb9\x8e\xd2\x88\x89\xdc\x25\x94\x7c\xb1\x34\x29\x19\x13\x9a\x95\x11\x96\xc4\x54\x84\x39\x6a\x7f\xc8\x82\x6f\x78\x1a\xb3\x2e\x47\xe7\x43\xac\x82\xc2\xb6\x22\x57\xc0\x57\x07\xaf\xae\x74\xca\x46\xb7\xb4\x3c\xa1\x44\xb0\xbb\x93\xac\xa0\x4a\xd9\xe9\x28\x37\x99\x96\x65\x8c\xb6\x06\x49\x92\x1b\x37\x95\x44\x6c\x8a\x02\xdb\x24\x58\x59\x0a\xbe\x7b\x45\xd7\x2e\xb1\xdc\x08\xc1\xc5\xc2\x80\xd6\x26\x14\x54\xe9\x17\x54\x33\x72\x2b\x79\x7e\xd2\xaf\x6e\x84\xd4\x7c\xfe\x60\x7b\x18\x4e\x3e\x4b\x0a\xae\x34\x13\xac\x54\x13\x31\xc5\x8a\xb0\x24\xdf\x94\x80\x37\x23\x99\xcc\x65\xf9\x0d\xcd\x96\x71\x2c\xc8\xb5\x88\xb7\xd0\x76\xaa\x31\x17\x5c\x73\x5a\xa4\x2c\x71\x4f\x58\x6c\x56\xef\x34\x5b\xab\x54\xe1\x6c\x53\x96\x4c\x68\xf3\x9a\xbe\xa2\x7a\x99\xac\xb8\x88\x79\x8f\x25\x00\x41\xac\xec\x84\xdf\x94\x6c\x5e\x32\xb5\x8c\x7d\x57\x18\x31\x3d\x1f\xb1\x7a\xd0\xbb\x5d\xcc\x82\x91\xf5\x71\x93\x45\x8e\x21\x16\x4b\x6e\x36\xeb\x9c\x6a\x66\x26\x7d\x0f\x74\x4d\x45\x9d\x0e\xe4\xb9\xb6\x6d\x57\xdc\x67\x9a\x18\x88\x25\x42\xde\xc5\x68\xaf\x57\x80\x8d\xa4\x6f\x7a\x67\xe1\xdf\x40\x26\x16\x58\x9a\xe6\xf9\x3c\x3e\x15\x89\x6b\x65\xb7\x3b\x15\x09\xd7\x6c\xa5\x92\x82\x89\x85\x5e\x22\x8b\xb7\x6e\x75\x2b\xe2\x72\xa1\x62\x8a\x4b\xe2\xcb\xf5\x06\xb8\x20\xa7\x83\xd1\x5c\x96\xf1\xa8\xbc\x26\xfd\x51\xaf\x57\x22\x4a\xd4\xa4\x9c\x62\x9a\xdc\xd0\x4c\xf3\x5b\x36\x8e\x69\x72\xa3\xa5\xa6\xc5\xb5\xa8\xa7\xab\xd3\x89\x9b\x17\xe2\x0b\x20\x4c\x13\xcd\xb3\x8f\xb1\x46\xa6\xe6\x3e\x4a\x63\x53\x17\x51\x93\xa6\xc9\x29\x56\xc9\x5a\xae\x63\xb3\xca\x3b\x9d\x58\x26\x79\x49\xef\x2c\x14\x1d\xda\x48\x2c\xb0\xc6\xd1\xba\x94\x8b\x92\x29\x15\x21\x84\xfd\xe7\xbb\x5d\x5c\x0f\xdb\x2e\xed\xbd\x8f\x32\xb9\x5a\x17\x4c\xb3\x08\x61\xe1\xf1\x85\x9c\x0e\x10\xe6\xdd\x7a\xd8\x15\x82\xd6\x6a\xac\xd5\xb8\x4f\x08\xe1\x9d\x4e\x0b\x05\x06\xa8\xba\x59\x30\x20\x6c\xca\xd0\xbe\x70\x8a\xfc\xc4\xb8\xa9\x62\xc9\x82\xe9\x58\x23\x4f\x41\xf8\x6e\x17\x73\xb2\x75\x55\xa5\xa7\x83\x1a\x87\x4f\xfb\x18\xa6\x22\x9d\x4c\x71\xbd\x14\xd2\xad\xef\xb5\x49\xf6\xc3\x4e\x27\xd3\xaa\xc2\x2c\x51\xa6\x6a\xcc\x11\xc2\xbc\xb2\x9f\xb8\x95\xef\x56\x6d\xd0\xc7\x60\x75\xb1\x69\xb2\xde\xa8\x65\xcc\x51\x45\xf3\xdc\x52\x39\x66\xd0\xd1\x82\xa0\xd3\x39\xfc\xd8\x62\x10\x7c\x95\x24\x09\x43\xd5\x92\xaa\x90\xe8\x7f\xe2\x03\x5b\xe1\x75\xbf\x82\x15\xf7\x29\x48\x79\x08\x31\x80\x72\x6b\x9d\xc1\x77\xc1\x6a\xc0\x0d\x51\x20\xcc\x35\x52\xb2\x7c\x93\xb1\x38\x86\x81\x90\x6b\xbb\xd2\xe9\xbd\x79\x4d\x6e\x7c\x69\x84\x70\x1f\x79\x1a\xe5\x17\x1d\xaa\x5c\x63\xa6\x67\x66\xd9\xb4\x68\x98\x5b\x29\xa7\x83\xd1\xe7\x3a\xed\x0a\x9d\xc6\x00\xc1\x60\x6d\xb7\x16\x5d\xa5\xb4\x5c\xff\xd9\xf8\x4d\x0f\xd8\x6e\x77\xca\x3e\xb3\x60\xb9\x1f\x36\xa0\x97\x20\xbc\x5e\x3b\x76\xa5\x0a\xbb\x52\x05\xe2\x13\x31\x4d\x32\x2a\x32\x56\xc4\x68\xe4\x3e\x22\x93\xa9\x83\x41\x40\x85\x03\xe8\x06\x4b\xa4\x2a\xd9\x4a\xde\xb2\x83\x49\x76\x5d\xce\x99\x29\x16\x6b\x54\x55\xa3\xff\x72\x9c\xd8\xff\xf5\x71\x53\x7e\x2c\xd8\x79\x26\x0b\x59\x9e\xdc\xf6\x93\x41\xf2\x2c\x64\xc7\x16\x5c\x2f\x37\xb3\x24\x93\xab\xf3\xb0\xe4\x7f\x97\x8c\xe6\x2b\x16\x70\x67\xfd\x93\x7f\x6c\x3e\x7e\xa4\x27\xdf\x6f\xca\x8f\xac\xa0\x7f\x8d\x2b\xb3\xf0\x29\xc9\xb6\x9f\xf6\xf1\x20\x1d\xe0\x61\x3a\xc4\x8f\xd2\x47\xf8\x71\xfa\x18\x5f\xa4\x17\xf8\x49\xfa\x04\x3f\x4d\x9f\xe2\xcb\xf4\x12\x3f\x4b\x9f\xe1\xe7\xe9\xa0\x8f\xbf\x4a\x07\x03\xfc\x75\x3a\x18\xe2\x17\xe9\xe0\x11\xfe\x26\x1d\x3c\xc6\x2f\xd3\xc1\x05\xa6\x26\x77\x66\x72\x33\x93\x9b\x9b\x5c\x66\x72\xe7\xe9\xe0\xa2\xc2\x05\x89\xfa\x83\xe1\xa3\xc7\x17\x4f\x9e\x5e\x3e\x7b\xfe\xd5\xd7\x2f\xbe\x79\x19\xe1\xcc\x6c\xec\xc5\x64\x70\xd1\xd1\x53\xbc\xb4\x2f\xf1\xf0\x71\xbf\xa3\xd1\xf5\xf5\xe3\x69\xd7\x67\xe5\x26\xab\xc9\x20\x24\x36\xe9\xa8\xe1\x8c\x36\x06\xec\x66\x5b\x66\xe4\x08\x8b\x95\xc7\x3a\x29\x51\xa7\x63\x7e\x17\xee\x77\xe6\x7e\xa9\x61\xeb\xd0\x38\x4b\x97\x9e\xe0\xe8\x71\xf4\xdf\x51\x97\xc1\x37\xf0\xb3\xb0\x3f\x33\xd4\x35\xe5\xaf\x86\x17\x17\x63\x06\x5f\xa6\x51\x84\x52\xdd\x30\x40\xf3\x70\xf2\xbb\xc9\xc5\xae\xef\x18\x98\x45\xc3\x60\xd4\xab\xad\xde\x60\x0d\x3d\xc2\x2c\x18\xcc\x3a\xa8\x66\x11\xcf\xe3\x61\x72\x71\x71\xa6\x11\xee\xe3\xe1\xc5\x05\x6a\x9a\x5b\xed\x97\x3b\x5e\xec\x7e\xaf\x98\x3e\x37\x15\xa2\xf3\x41\xbf\x8f\xfb\x78\x10\x94\x9c\xed\x95\x1c\xf4\xfb\xb6\xc2\x41\xbf\x8f\xdc\x50\x6e\xc8\xf9\xff\x2a\x17\x33\x3a\xfe\x57\xfc\x2f\x75\x16\x4f\x7a\xdd\xe4\x5f\xf9\xb4\x8b\xe2\x2f\xd1\x78\xf2\x2f\x85\xa7\x5d\x48\x63\x9f\x4f\x8c\xc7\xa9\x49\x3f\x3f\xc8\x40\xe3\x7f\xa9\xb3\x7f\xa1\x2f\xce\xdd\xf2\x7d\x20\xe7\xff\x2b\x5e\xaa\x82\x8e\x77\xcb\xbb\xd9\x6e\xa9\x6e\x51\xd3\xb0\xfb\x6c\x9c\xe6\x6c\x71\xa4\xa1\x2f\x0f\x53\x5c\xbb\x9f\x69\xb6\x06\xc6\xad\xdf\x19\x3c\x0f\xca\xce\x1a\x9e\x08\x0f\x7a\x1c\x19\x26\x93\xc1\x9f\xae\x3e\x7f\xd4\x47\x5f\x0e\x86\x88\x5c\xf3\x9e\x38\x3b\x9c\x64\xd9\x7b\x84\x9f\xf5\x24\x1e\x20\xdc\x1b\x78\x22\x38\x91\x71\x1f\x61\x19\x5f\x9a\x3f\x8f\xd1\xb4\x99\x89\xbb\xfd\xc6\x0d\xaf\x42\x62\xd1\xd5\xe7\x4f\xfa\xe8\xcb\x27\xd0\x0e\x3f\x63\xc7\x5a\xc2\x8f\x6d\x3b\xfd\xba\x19\x11\x5f\x20\x2c\xe2\x47\xe6\xcf\x20\x6c\xe6\xd5\x7e\x33\x66\xd0\x03\x9c\x5c\x58\xa1\x41\x02\x89\x64\x5d\x7e\x3d\x30\xcc\x05\x19\x9c\x03\x0f\x8c\xd9\x19\x91\x98\x9f\x11\x69\x40\xd0\x1f\xc9\xab\x47\x23\xd9\xed\x22\x31\x91\xd3\x33\x32\xe8\xb1\x1e\xc7\xe6\xb9\x4b\x98\x5f\x53\xa2\x69\xf3\x63\x8b\xaa\x27\xe5\xf9\xf0\xe2\x02\x73\xa2\x93\x05\x3c\x09\xa2\x93\x19\x3c\x49\x52\x0f\xce\x72\xbe\x58\x91\x7a\x94\x2e\x85\x92\x58\x76\x15\x3a\x1f\x42\x7f\x4b\x5c\xe0\xcc\x37\x29\x4f\x09\x51\x9d\x4e\x9c\x11\xd9\x53\xb8\x20\xf4\x3a\xb9\x18\x67\xe7\xf1\xb0\x27\x7b\x0a\xa5\xd9\x39\x7c\x89\x4b\x22\x09\x21\x6c\x1c\xf3\x9e\x40\xe7\x59\x37\xe6\x57\x62\xfc\x24\xed\xa3\xd4\xa4\xf3\x71\x2c\x7a\xcc\xa4\x0f\xd3\x98\xf5\xb8\x79\x7a\x8c\x4b\xf2\xa4\x7f\x56\x76\x93\x0b\x84\x27\xfd\x5d\x89\x8b\xdd\xae\x8f\x69\x00\xd7\x77\x0d\xb7\x6e\x7b\x13\x5b\x11\x8d\x2b\xf8\x8d\x19\x1a\xeb\x98\x4d\xfa\x53\xcc\x26\x03\xf3\x67\x38\x35\x22\x8f\xfd\x04\x25\x2b\xba\x8e\x57\xc1\xba\x7c\xe3\xa7\xc9\x0d\xed\x5d\x7c\x8b\x6d\x4a\x53\xe6\x45\xb3\x76\x63\xfd\xe5\xa3\x27\xfd\xee\x23\x83\x29\x8f\x9e\xf4\x9b\x32\x5f\x87\xa0\x7f\x48\xd8\x3d\xcb\xcc\x36\x0a\x7c\x17\x16\x64\x78\x71\x61\xb7\x54\xbf\x83\xb2\xc9\xc5\xf4\xd4\x32\x73\x82\xb0\xc9\x93\xe9\x78\x1d\x77\x4d\x22\x4a\x57\xee\x01\x8d\xbc\x38\xf2\xc2\xa4\x0c\xa7\x66\x96\xba\x6c\xf2\x68\x0a\xf4\x85\x9a\xe7\xc7\xf0\x5c\xf3\x73\x24\x5a\xde\xcd\x8c\x48\x65\xc6\x3e\x0e\x35\x03\xad\x21\xbe\xf2\x43\x8c\x25\x56\xd8\x10\xdb\xa5\xba\xfd\xf3\xcf\xee\xf6\x3f\x7b\xe3\x1e\xf0\xb6\x4c\xb9\x01\xf9\x22\xe5\x06\xe8\xb3\x94\x4f\x86\x53\x4c\x53\xe1\xc5\xcc\xd7\x64\x7b\x9f\x46\x39\x2d\x3f\x46\xf8\xb7\x34\x2a\x40\x12\xc4\x1f\xd2\xa8\x64\x11\xfe\x35\x8d\x66\xc5\x26\xc2\xbf\xa4\xd1\xa2\x8c\xf0\xcf\x69\xb4\x62\x39\xdf\xac\x22\xfc\x53\x1a\xa9\x82\x6a\x16\xe1\xe7\x69\xc4\x58\x84\xdf\xa7\x91\x2c\x22\xfc\x2e\x8d\x64\x19\xe1\xaf\xd2\xa8\xa4\x11\xfe\x3a\x8d\x4c\xa1\x45\x84\x5f\xa4\x91\xa9\x59\x45\xf8\x6d\x1a\x71\x11\xe1\x7f\xa6\x91\xde\x94\xbf\x6f\x24\x57\x11\xfe\x26\x8d\x96\x3c\xc2\x6f\xd2\xa8\x94\x11\x7e\x9d\x46\xb4\x88\xf0\x8f\x69\x54\xb0\x08\xbf\x4a\xa3\x9c\x45\xf8\x87\x34\x7a\x60\x45\x21\x23\xfc\xd2\x88\xb3\x11\xfe\x3e\x8d\xb2\x65\x84\xff\x9e\x46\xb4\xfc\xa8\x22\xfc\x6d\x1a\x31\x1a\xe1\xef\x6c\x43\x8b\x08\xff\x23\x8d\xee\x96\x51\x85\x9f\x93\xed\x6b\x9e\xb1\x5f\x59\x1a\xcd\xfb\xf3\xcb\xf9\x3c\xc2\x54\x68\xfe\xfb\x86\xdd\x7d\xa3\x4d\x22\x65\xb3\xfc\x69\x84\xe9\xef\x1b\x9a\x46\xf3\x39\x14\xf8\x7d\x43\x57\xb4\x7c\xcb\xd2\xe8\xe9\x7c\x3e\xcf\x1f\x47\x98\xfe\xb1\xf9\x00\x35\x40\x81\x19\xe3\x0b\xf3\xed\xc5\xfc\x22\xcf\x22\x3c\xe3\xea\xf7\x8d\x79\x9f\xb3\xc7\xd9\xe3\x08\xcf\x0a\x9a\x7d\x4c\xa3\x3e\x3c\x89\xef\x59\xfe\x7a\x25\x45\x0e\xf9\xb3\x2c\x8f\x30\x74\x66\x6e\x7e\x6f\xf9\x7b\xa6\xd3\xe8\x92\x0e\x67\x6c\x18\xe1\xd9\x9b\x3b\x91\x46\xf4\x62\x48\x87\x34\xc2\xb3\x4d\x59\x3c\xdc\x49\x99\x1b\x18\xcc\x2e\x2f\x9f\x46\x38\xa3\xaf\xb4\xf9\xfa\x62\xfe\x8c\xd1\x7e\x84\xbf\xa7\xa5\xfe\xb0\x51\xae\xa3\x7d\x93\x22\xb3\xf7\xd4\x0c\x2c\x1f\x3e\x79\x36\x60\x11\xce\xde\xbd\x36\xad\x3d\x9d\x5f\xf4\xcd\x8b\x98\x17\xf2\x8e\x95\xa6\x92\x27\x8f\x9f\x5d\xb0\x1c\x12\x15\x2f\x3e\xc2\xe8\x2f\xcd\x78\xb2\x92\xaf\x94\x14\x69\x94\x67\x83\xc7\x8f\x4c\xc2\x03\x15\x1e\x38\xf7\xe6\xd3\xcb\x59\x84\xef\x6d\xea\xe5\x0c\x5e\x16\xef\x5f\x89\x37\x79\x1a\xcd\x2e\x2f\x9f\xf4\x4d\xc2\x2f\xf4\x21\x8d\xe8\x33\xf3\xcf\x64\x7f\x78\x69\x1a\x34\x3d\xbc\x5f\x7c\x08\x73\x3e\x2e\xe9\x47\x9e\x46\xb3\x7c\xf6\xf4\x89\xf9\x6e\x45\x17\x2f\x35\x35\xf5\xf6\xfb\x50\xf3\x7b\x7e\xcb\xe0\xf3\x8b\x8b\x27\xb3\xa1\xe9\xc1\x3b\x2a\x00\xfc\xf3\xcb\x0c\x2a\x7c\x97\x7d\x93\xa7\xd1\xb3\x67\x8f\x86\x59\x16\xe1\xfb\x0f\xb9\xfd\x1a\xf2\x94\x81\x7d\x1a\xb1\x67\xcf\x9e\x3c\xa5\xe6\xfd\x5b\xa8\xeb\x72\x3e\xcb\x2e\x4d\x5d\x3f\x99\xe1\x3c\xbe\x7c\x94\x43\x5b\x3f\x41\xaf\x87\xf3\xc7\xf3\xc7\x90\x09\x5d\xad\x5f\xff\xc9\xd2\x28\x63\xf9\x20\xc2\xf7\x6e\xe2\x9e\x3d\xee\xf7\xf3\x47\x11\xce\x9f\xaf\xd7\x6f\x01\x82\x83\xc7\xcf\xec\xbb\xfa\xf8\x60\xaa\x9e\x01\xd0\x72\xbe\x82\x9a\x9f\x3c\x33\xff\xe0\x1d\xaa\xae\xdf\x65\xbe\xb0\x93\x32\x60\xcf\xfa\xe6\x8b\x39\xff\x30\x2b\xb9\x41\xa3\xd9\xd0\xfc\x17\xe1\x79\xf1\xee\xb5\xc3\xd9\xf9\x9c\xce\xfb\x11\x9e\xcb\x0f\x4a\xff\xf2\x5c\xa4\xd1\x70\x78\x39\x83\x32\x9b\xef\x15\x07\x3c\xee\x43\x2d\x0b\xfa\x56\xcd\xde\x49\x33\x93\xe6\x5f\x84\x17\x4b\xa9\xb4\xab\xe5\xd2\x2e\x87\xc5\x7b\x40\xcd\xfc\xa9\x81\x97\x9f\xc6\x9c\xd2\x8b\x61\x3f\xc2\xd0\xeb\xcb\xbe\xf9\x17\x61\x0b\x39\x80\xeb\xe2\xc3\xcb\x1f\xee\xd2\x88\xe6\xf3\xb9\x99\x12\x18\x8c\x2f\xb6\x94\x82\x3d\xbc\xba\x73\xcb\x05\x12\xb4\x83\xce\x93\x67\xb3\xc7\x11\x7e\x9b\x73\x2a\xcc\x2c\x65\xf9\x45\x76\x91\x41\xc2\x42\xa6\xd1\x63\x33\xe5\xc3\x08\xf3\xdb\x77\x0f\x16\xdd\xcc\xd7\x0e\x41\xe6\x7d\xf6\xe4\x32\x8b\x70\x41\x6f\x5f\xbe\x2a\xd3\x88\x3d\x61\x4f\xe6\xd4\xbf\xff\xaa\x96\xf0\x45\x7f\x7e\x61\x92\xee\x04\xf4\xf5\x69\x36\x07\x0c\xf9\x71\x25\x45\xf6\xcd\x7c\x2e\x2d\x16\x53\xb3\x08\x7f\x33\xd0\xa6\x79\x7e\xc9\x9e\x44\xf8\x37\xbb\x4a\xdc\x00\x7e\xb3\x98\xcd\xdc\x6a\xff\xcd\x02\xc5\x8c\x77\x4e\xe7\x34\x1f\x46\xf8\x37\x80\x4b\xfe\xc8\xfc\x33\x05\x4c\x63\xcf\xfa\x8c\x3d\xeb\xc3\x5b\x98\xe7\x46\x3e\x7b\x92\x0d\x22\xfc\x9b\x43\xc7\xf9\x9c\xf6\x0d\x3a\xfe\xe6\xd0\x71\xd8\x9f\x0d\x29\xbc\x5b\xac\xb9\x7c\x9a\x31\x33\xb8\xdf\x2c\x42\x3e\x7d\x7a\x79\xf9\xec\x99\x79\x85\xba\xeb\x57\xa5\x9f\x17\x80\x64\xfd\xec\xb1\x21\x93\xbf\x41\x1f\xe7\xf3\x39\xeb\x47\xb8\xe0\x2b\x66\x31\xc1\x3e\x43\x43\x8f\x86\x59\xfe\x68\x18\xe1\xe2\xed\x4b\x18\x4d\xdf\x8c\xde\x2f\x39\x8f\x35\x2b\xfa\xc6\x74\xd2\xcc\xb4\xf9\xf8\xe7\x80\x1e\x3e\x79\x92\xe5\xa6\xa3\x3f\x9b\x66\x0d\x18\x7f\xb6\x8b\x6f\x46\x2f\x2e\xcc\x70\x7f\x5e\x6f\xca\xf5\x8f\x69\xf4\xec\xd1\xd3\x7e\x3e\x8b\xf0\xcf\x6e\x80\x8f\xb2\xd9\xa3\xa7\x83\x08\xff\x0c\xeb\xed\xe9\xec\xc9\xa5\xd9\x36\x7e\x56\xeb\xf2\xed\x02\x0a\xcc\xe9\x33\x53\xed\x3f\x61\x35\xe6\x03\xb3\x90\x7f\x86\x45\x06\x78\xf2\x74\x70\x71\x79\x11\xe1\x15\xcf\x85\xa1\xef\xb0\x50\x9e\x0d\x9e\x3d\xed\x47\x78\xf5\x56\x67\x1f\xe8\x0a\xa8\xf1\xdc\xc0\x6c\xc5\x95\x7e\x78\xa3\x1c\x3d\x66\x83\x08\xaf\x64\x96\x51\xf5\xd6\x26\xcc\x2e\x22\x2c\xe8\x2d\xfd\x8f\xf4\x8b\x29\x67\x34\x87\x34\xc0\xe1\x08\xbf\xcf\x0b\x9a\x99\x9c\x7c\x7e\x61\xc0\x63\x08\x90\xc5\x6e\x03\x0d\xf3\x96\x7f\x35\x4b\xa3\x27\xb3\x4b\x36\x7c\x14\xe1\x9a\x1a\xd1\x0b\x93\x0f\xaf\x1f\x60\x49\x3d\xb6\x09\x00\xa0\x9c\x3e\xed\xe7\x4f\x22\xbc\x7e\xcd\xfc\x1a\x63\x8c\x5d\x1a\x58\x9a\x24\x40\xa0\xcb\xf9\xec\xd9\x25\xbc\x1b\x30\xd0\x39\x63\x06\x48\xeb\xd7\xac\x06\x44\x3e\x7b\xda\x37\xf4\x65\x4d\xd7\xf4\x81\xde\x7d\xb3\x86\x31\xcd\xf3\x8b\x08\xaf\xbf\xfd\x7e\xbd\x99\xcf\x61\x40\x74\xf6\x2c\xc2\x6b\x56\x6e\xcc\x1c\x5d\x5e\x3c\x9a\x47\xd8\xa1\x61\xd6\xcf\x66\x11\x5e\x17\x9b\x55\x1a\xe5\x39\xed\xe7\x79\x84\xd7\xf2\xee\x55\x69\xd1\x88\x01\x3e\xb8\x39\x34\xe3\x35\xf0\xf8\x30\x63\x59\x46\x5d\xe2\x93\x27\x8f\x1e\x19\xdc\xb3\x23\xb4\x08\xf2\x46\x3d\xcc\x4a\x69\xb6\x2e\x43\x54\x0d\x59\x7d\xf3\xf0\x1a\xe8\xea\xe0\xc9\x33\x33\x01\x8a\xe6\xf9\x8f\x76\x73\xbb\x9c\x3d\xbe\x18\x3c\x8a\xb0\x5f\x08\xf4\xb2\xff\x74\x68\x4a\x88\xfc\xc1\x96\x98\x3f\xa6\x8f\x9f\xf4\x23\xec\x97\x06\xbb\x9c\x5d\x3c\x35\xaf\x6a\xc9\x8a\x02\xf0\xfb\xc2\xc0\x45\xf1\x97\x82\xa6\x11\xed\x5f\x0c\x87\xb9\x79\x2d\x6e\x59\x99\x46\x59\xdf\xfc\x8b\x70\xb0\x92\xd8\x2c\xc2\x80\x77\x4f\xe8\x05\xac\x7d\xb7\xaa\xfa\x97\x7d\xb3\x60\xdd\xa2\x72\x6f\x4a\xc8\x3b\x47\x62\x69\x84\x03\x04\x9d\x3f\x9d\x47\xd8\xaf\xb8\xc7\x4f\x2e\x87\x86\x94\x69\x43\x28\xf2\xe1\xec\xb1\x21\x4d\x9a\xbd\xb6\x78\x12\x61\xfd\x8d\xd2\x3f\xa6\x51\x7e\x39\x9b\xe7\x97\x11\xd6\x72\x45\xb5\x04\x0a\xf8\xe8\xf1\xd3\x08\x03\x9a\xf7\x59\x3f\xef\x47\xd8\x6d\x25\x8c\x5d\x0e\xcd\xb0\xfe\xf1\xad\x36\xb8\x9c\xb3\xd9\xa3\x08\xd7\xf4\x1e\x08\x91\x79\x53\x2b\xf9\xd1\xb1\x1e\x86\xd4\xf9\x05\x6f\xa6\xe1\x87\x3b\x8b\x46\x14\x96\x78\x05\x4c\xee\xfb\x46\xba\x7b\x6b\x58\xe1\xf7\xbb\x5d\xfc\x9e\x04\x26\x0a\x6f\xc1\xd9\x56\x98\x91\xd7\x60\xa4\x4a\x3e\xb2\x07\x15\x3f\x47\x98\xb7\x12\x5e\x5b\xb6\x59\x60\x60\x2e\x71\x09\x92\x92\x20\xfd\x91\xb8\xf2\x6a\xc1\x91\xe8\x76\xd1\xd6\xa4\x53\x52\x12\x36\x11\x53\x27\x2d\x79\x15\x14\x08\x4d\x8a\xf0\x89\x9c\xe2\x92\x94\x49\xc9\xd6\x66\xad\xc5\x0a\xbf\x9e\xa8\x29\x1a\x29\xb2\xa6\xa5\x62\xdf\x09\x1d\x3f\x9f\xd0\x29\x1e\x3c\x41\x58\x4f\xca\x29\x99\xa8\xeb\xeb\xc1\x93\x8e\x11\x92\xd4\xf5\xf5\x25\x3c\x0c\x2f\x2e\x3a\x6a\x5a\x79\xed\x43\x15\x23\xfc\x3e\xd1\x25\x15\x6a\x4d\x4b\x26\x34\x99\x18\x69\xbf\x8f\xfb\x53\x54\xab\xe7\xde\x4f\x74\xa2\xe5\x0f\x86\x05\xfa\x9a\x2a\x16\xa3\xda\x3a\xc4\x3a\x9d\x6d\x99\x32\xcb\x2e\x33\xcb\x2e\x33\xcb\x2e\x3f\x36\x2c\xb8\x1b\xc1\xd8\x30\xfa\xe9\xf0\xe2\x22\xb0\x02\xfd\xe0\x59\x72\x0e\xea\x10\xab\x75\x33\x42\xdf\x48\x4c\xd8\xb4\x91\xe9\xfa\xb8\x16\xe6\x4c\x46\xd7\xfc\x39\xe3\xa0\x3d\x66\xe3\x47\x4f\xfa\xe9\x00\x21\x2c\xc8\x9b\x58\x20\xac\x93\x92\x08\xd3\x19\x9d\x2c\x88\x30\xdd\xd1\xc9\x8c\x88\xc9\x70\x1a\x34\xfc\x8d\x55\xcc\xd6\x5a\x1c\x37\x5d\x54\x29\xbe\x10\x31\xdb\xed\xb6\x15\xd6\x2d\x7d\xcd\x77\x8d\xd6\x68\x5b\xa6\x7d\xbc\x48\xfb\x78\x96\xf6\x31\x85\x21\x79\x58\xb4\x45\x37\x8d\xc6\xda\xab\x69\xc9\xa3\x4e\x27\x86\x6f\xb5\x85\x94\xb6\x90\xd2\x16\x52\xa6\x12\x5c\x17\x86\xb2\x09\x25\xab\x58\x4f\x1e\x4d\x11\x42\x69\xcc\x88\xe9\xf3\x5e\xd3\x83\x0a\x21\x28\xc6\x12\x8a\x30\x6b\x7a\xfb\x47\x23\xe1\x45\xd6\x24\x05\xb6\xda\xe7\x3a\xee\xa3\x96\x61\xd1\x4f\xef\xcd\xbe\x84\x67\x90\xd5\x4b\x79\x0c\x26\x88\x4d\x9e\x82\x84\xd7\xa0\x7e\xd7\x24\x8d\xa0\x58\x27\x66\x93\x4b\x23\xf3\x69\x94\x5a\xdd\x52\x55\xcb\x70\x5d\x40\x0a\x61\x45\x3d\x2c\x09\x48\x83\x98\xfb\xcf\x86\xe6\x33\x8e\x52\x8e\xac\x5c\x69\xd2\x1e\x9b\x34\x81\x52\x81\xb0\xf4\x69\x20\x52\x4a\x94\x4a\x2b\x9e\xe1\x45\x2a\xf0\x2c\x95\x98\xa6\xaa\xaa\x2a\xd3\xb0\x91\x59\x2b\x30\xb3\x9d\xbc\x6c\x19\xda\xac\x06\x5a\x9f\x70\xa1\x34\x15\x19\x93\xf3\x93\x97\xc8\x4f\x7e\xa3\x81\xb6\xe6\x57\x6d\x41\x00\x96\x3b\x00\xc3\xa8\xb1\x41\x13\x36\xe6\xc4\xa0\x42\x1a\x29\x5d\x72\xb1\x80\xb4\x4e\x27\x56\x24\x16\x44\x23\x37\x81\x38\xfa\x6f\x93\x61\xd0\xb0\xd3\x89\xcd\x2a\x50\xbb\xdd\x85\xf9\x19\x4b\x83\x02\x66\x44\x83\xa7\x67\xe5\xc4\xe0\xa7\x41\x86\x20\x61\x38\x35\x68\x11\x24\x3c\x9a\x1a\x04\xb1\x5f\xbb\xa4\xc7\x53\xbb\x92\xd2\xa7\x56\x71\xf1\xec\x14\x5a\x88\xa1\x72\x57\xeb\xd5\xd5\xe3\x9d\xaf\x6f\x91\xba\x8a\x7c\xe2\x63\x68\xc4\x3c\x5d\x34\x89\x4f\xa0\xa1\x67\xd0\x90\x79\x7f\xda\x64\x5d\xba\x06\x91\xa1\x6d\x72\xb7\x33\x24\x71\xb7\x33\x58\x56\xeb\xfd\x17\x33\xc2\xdd\xf3\x2d\x2d\x78\x4e\x4e\x4f\x79\xb5\x60\xfa\x04\xde\xe2\x3d\x4d\x37\x24\x42\x76\xb9\x98\xc5\x76\x65\x69\x83\xe2\xbe\xb2\xda\xa6\xa3\x3b\x9d\x58\x27\x94\xdc\x83\x1a\x15\x61\x5d\x29\xf7\x95\xae\xed\xa7\x8b\x19\x4c\x4a\x55\x2e\x66\xef\x60\x5a\x8e\x36\x37\x8e\x35\x69\xea\xb7\xd5\x82\x86\xf6\xdf\xe5\x62\x46\xe3\x2f\xb6\x3a\x29\x2b\x7c\x62\x7e\x17\xee\x77\x06\xbf\xb6\xe9\x0a\xfd\x3b\x35\x25\x3f\x51\x10\xfd\x1b\xa5\x75\xed\x80\x3c\xba\x5a\xb2\xfb\xcf\xf5\x67\x13\x0c\xb7\xf9\xb6\x5a\xaa\xe2\x73\x5f\x85\xcb\x17\xec\x2a\x6d\x23\x06\x03\x02\x8a\x39\x01\x8a\x2c\xc8\x2c\x36\xcb\xcf\xac\xa3\x19\x2c\xb6\x06\xb0\x7e\xf4\x4b\x55\x98\xd1\x73\x18\x8a\xa8\xbe\x34\x3f\xd2\xfe\x04\x23\x5f\xaa\xe2\x48\x21\xf4\xef\xea\xf8\x20\x56\xfc\xde\xd2\x58\x6f\x5a\x01\x0b\xab\xa5\xf3\x5e\x83\xc8\x93\x72\x31\xc3\x92\x68\xf3\x6b\x5d\x0f\xdc\x20\x28\x61\x80\x86\xc9\x45\xca\x70\x49\x86\x67\x14\x4c\xa6\x22\xa1\x3d\x99\x50\x9c\x91\x38\x2e\xcf\x0a\x42\x7a\x83\x71\x99\xc6\x65\xb7\x40\xe7\xf1\xa0\x5b\x9e\x15\x08\x75\x07\xe8\x7c\x38\x52\x64\xd0\xcb\xb0\x48\x4a\xa0\x1e\xd9\x99\x48\xca\xae\x3a\x93\x49\xd9\x4d\x2e\xb0\x48\x16\x75\xf2\x02\x92\x17\x36\x79\x56\x27\xcf\x20\x79\x66\x93\x29\xa1\x67\x22\xa1\xdd\x78\xd0\xa3\xe8\xcc\x74\x00\x7a\x4e\x44\x4d\xe3\xaa\xac\x90\x82\x35\xf3\x25\xd8\xdd\xc9\x4b\x0b\x18\x03\x97\x8a\x16\xeb\x25\x3d\x30\xf7\x94\x8b\x99\x25\xf2\x76\x11\x55\xe0\xeb\xc0\xca\xe3\xe5\xce\xc8\xa0\xa7\x6d\xb9\x45\xc9\x1e\x54\x46\x0b\x16\xb0\x21\x75\x49\xcc\xc8\x3c\x4e\x1e\x9d\x69\x18\xeb\xb3\x33\x6d\x06\x37\x18\x9c\xe9\x24\x58\x53\x49\x49\xcc\xf6\x68\x76\x46\x66\xeb\x94\x6b\xfa\xfb\xe6\x33\x6d\x77\x5d\xdb\x82\x2d\xc0\xf8\x7e\xd8\x70\x58\xf9\xf0\xe2\xa2\xa7\x93\x12\xf6\x60\xfb\xbc\x80\x6d\xd8\x3e\xcf\x6c\x55\xa0\x34\x63\xa1\xf1\xe5\x87\x06\x97\xf0\x10\x7b\xb0\xe4\xb4\xfc\xf8\x99\x62\x3d\x5f\x4e\x51\xbd\x29\xc1\xc4\x7f\xb4\xe4\xa0\xa9\x90\xfd\x69\xd1\xba\xd2\x52\xea\x76\xb9\xb6\x7b\x92\x59\xe7\xdc\xb2\x2c\x7c\xd2\x9f\x92\x17\xb1\xf9\xe9\x32\xb3\x00\xdf\xc4\xdc\xb2\x23\xdc\xb3\x23\xdc\xb3\x23\xdc\xb0\x23\x41\x83\xbe\xb5\x66\x07\xff\x39\x68\xd2\x61\x93\x37\xab\x7c\x45\x34\xb9\x6e\x6d\x66\x5f\x53\x71\x4b\xd5\xdf\x4b\x9a\x73\x26\xf4\x6e\x77\x24\xf3\x0d\xd5\x9a\x95\xa2\xe1\x6a\x7f\x09\x1a\xf8\x0a\x58\x95\xd4\xb4\xd9\xf4\xe0\xdb\xe3\x05\x92\x1a\x76\xc9\x05\x4a\xdc\xdc\x24\x03\x94\x04\xc4\xae\xa9\xe4\xc7\x18\x6d\x5d\xb7\xff\x13\x72\xcf\x66\xb1\x6b\xd2\xff\xb4\xeb\x8f\xee\x76\xab\x2a\x0e\x2c\x5d\x5f\x84\x00\xd9\x14\x05\x21\x01\x77\xf6\xc1\x11\xc3\x16\xff\xd5\xe9\xec\xb3\x63\xde\xea\xdc\xaf\x69\xa5\x63\xfc\x1a\x7f\x28\x2d\xed\x20\xbc\x4b\x94\xeb\x61\x34\x09\x78\x80\x44\x6d\x66\x4a\x97\x71\x1f\x3f\x45\x9d\x4e\x04\xb5\x4f\x5b\x39\xbd\x27\x01\x0c\x7e\xda\xeb\xf9\x29\x21\xba\xd3\xf1\x35\x9e\xd8\x2e\xc0\xf7\x7f\xda\x1b\x07\xca\x5f\xc1\xc6\x19\x89\xcd\x6a\x06\x1e\x47\x9e\x73\xd9\x9b\xf9\x1f\x21\x1f\x75\x3a\x5c\xbd\xe4\x82\x6b\x16\x77\x43\x43\xe8\xef\x2d\x26\xf8\x57\x3b\xc5\x01\x13\xf9\x7d\x2b\xdf\xba\x18\x39\xcf\x28\xed\x3a\xf2\x77\xe2\x1c\x03\x1a\x76\xc8\xf7\xa5\xd3\xd1\x09\x13\xb9\xfa\x85\xeb\x65\x1c\x7d\x19\xa1\x31\x48\x28\x2f\x0b\x49\x75\xac\xc1\xa4\x98\xea\x73\x86\x7f\xfb\xdf\xaa\xe2\x8c\xa5\x5d\xdd\x0c\xe9\x9f\xa1\x40\xd1\xe9\x1c\x71\xfa\xb3\x3e\x45\xa8\xd9\x03\x9d\x87\x1a\x0b\x26\xec\x1f\x8d\x49\x06\x4c\x5b\x46\x6c\x33\x5b\x97\xc1\x32\xc4\xe7\xb1\x22\x9e\x53\xc7\x02\x19\xa1\x4d\x12\xd5\x1b\x8c\xe4\xb5\x11\xd9\x7a\x3d\xe4\xfc\xe9\x38\xd6\x46\x5c\x93\x68\xc4\x0a\xc5\x4e\x6c\x41\x23\xd4\x29\x90\xe6\x8e\x97\xe2\xf3\xd8\xe0\x0b\xb2\xb2\x60\x28\x46\x6a\x84\x15\xa1\xbe\xe1\x4f\xd4\x44\x27\xd2\x70\x71\x13\x39\x0d\xc6\xa3\x75\xe0\x6d\x67\x59\x7b\x30\xde\xe8\xdd\xee\x94\xed\x76\x7e\x30\xa7\x8d\xb0\xd6\xb8\x67\x98\x7e\x70\xd2\x07\x5b\x9b\x13\x45\xf9\x95\x18\x75\xbb\xdc\x40\x42\x12\x3d\xe1\xe0\x4f\x66\x7e\x64\x92\x53\x4d\x15\xd3\xdf\x89\x9c\xdd\x1b\x9e\xb4\x95\xb0\xdb\xc9\x84\xd7\x39\xf0\xd4\xb4\xe3\x57\x66\xd3\x6b\xf0\xdb\xd8\x7a\xb0\xd7\x13\xb6\xa2\xeb\x98\x59\x87\x0e\x00\xd4\x76\x6f\x29\x67\x25\x33\xc4\xc9\x2c\xb4\x7d\x41\x5c\x1b\x09\xa3\x96\xa8\x61\x6a\x49\xdf\xba\x76\x48\x18\x93\x44\x6c\x62\x44\xec\x29\x31\x8d\xdb\xc7\x7a\xd3\x64\x8d\xc0\xdc\xb8\x31\xea\x66\x6d\xf7\x06\x84\x90\x49\x74\x73\x03\xcb\xf7\xe6\x26\x02\x4f\x2a\xbb\x90\x23\x1c\x05\xf2\x48\x34\xb5\xa3\x7f\x3d\x6f\x11\x5c\xa1\x1b\xbc\x33\xd3\x03\x95\xb7\x99\x3b\x49\xd8\x44\x1b\x78\xf3\x89\x9e\x8e\x7e\x8a\x25\xea\x74\x7e\x8a\x15\x1a\x4b\x0d\xa6\x2b\x81\x52\x53\xc0\x74\x5f\x05\x35\x4b\xbd\x6f\xbc\xfd\x10\x33\x34\x66\xe9\x84\x19\x81\x4c\xd4\x33\x3b\x8f\x4f\x7f\x0a\xa1\x5d\x7b\xb2\xc5\x9c\x70\x23\x15\xa3\x64\xc5\xca\x05\x2b\x77\x3b\xa1\x01\x72\xe0\xda\x46\xfa\x23\x7a\x25\x47\xdd\x2e\xb5\x3d\xff\x29\x66\x44\x4c\xe8\x14\xa1\x4c\x0a\xcd\xc5\x86\xd5\xfd\x0f\xe7\x83\xa1\xba\x0a\x41\xfa\x98\x12\x59\xab\x43\xae\xe8\xa8\xdb\x15\x48\xc5\x72\x22\xa6\xde\x4c\x77\x08\x7f\xa5\x5b\x34\xca\x8d\x73\x6b\xfb\x98\x52\x5d\x05\x40\xa0\x3a\x20\x0e\xc7\x80\x2b\x2c\x70\xa5\x07\xae\x00\xe0\x4a\x34\x56\x1a\xdc\xff\xd2\x03\xf2\xbc\xa4\xea\xf5\x9d\x78\x53\xca\x35\x2b\xf5\x83\x5d\x85\x0c\x1b\xd1\x28\xf6\xd3\x20\x51\xd0\x85\x52\xef\xf1\xc4\x35\x1e\x44\x49\x84\x99\x47\x35\xc0\x24\x5e\xeb\x0e\x52\xde\xd4\x50\xb8\x1a\xf8\x3c\x8e\x60\xc7\x69\xa6\xca\x79\x2f\x62\x41\x4a\x30\x0f\x5b\xe0\x8e\x74\xa7\x23\xae\xf9\x08\x69\xa2\x27\xf5\xfe\xc4\xb1\xe8\x71\x64\x84\x70\xd1\x1d\x04\x5f\x1c\x42\x38\xd3\x21\x4b\xd8\x68\x11\x12\x2d\x7f\x5a\xaf\xbd\x32\xa8\xab\xad\x23\x71\x3c\xf0\x5b\xd4\x52\x9b\x3d\xca\x6e\x1a\x66\xc3\xc3\x39\x24\x1c\xa3\xc8\x78\xa3\xfd\x1e\x00\x74\x3b\x51\xfc\x0f\x06\xc4\xc8\x3c\xb4\x49\x91\x83\xdc\x89\xf9\x0e\x81\x01\xda\x4c\x42\xcc\xd1\x11\x4a\x82\xe7\xfa\x28\x51\x58\x1c\x4d\x0e\x7c\x6a\x1a\x18\x9f\xb2\xfd\xa5\xc0\x4d\xb7\xd6\x05\xd7\x66\xca\x1a\xfc\x65\x00\xf8\x9a\xb6\x30\x20\x27\x2c\x10\x75\x26\x6c\x3a\x32\x53\x20\xa6\xbb\x5d\x6c\x7e\x8e\xf5\xe1\x18\x8a\xaf\x74\xdb\x6e\x7d\xb0\x4d\x32\xb3\xf8\x5d\x9f\x31\x47\xa9\x7f\x8b\x22\x64\x76\x35\xc3\xa1\xde\xeb\x4f\x78\x20\x7b\x11\x9a\x7a\x2f\x72\xe7\x49\x6c\x05\xf9\x19\xcd\x3e\x2e\x4a\xb9\x11\xf9\xd7\xb2\x90\x25\x89\x40\x4e\x76\xba\xc1\x64\x80\x22\x57\x4c\x96\x39\x2b\x3f\x5b\x24\xb3\x99\xff\xfd\xe4\xc9\x13\x97\xe2\x36\x06\x45\xb6\x95\x4b\x60\xb7\x3c\x63\x6f\xf8\x3d\x2b\xde\x9a\xae\x00\x93\x6b\x4f\x18\x24\xeb\x82\xea\xb9\x2c\x57\xc9\x82\xe9\x17\x7b\xe5\x62\xa7\x81\x60\x05\x5b\x31\x11\x54\xc8\x6e\xe1\x75\x12\xad\xe4\x46\x81\xbf\x5d\x84\xed\xb3\xdc\x68\x43\x90\x0b\x9e\x7d\x8c\x70\xa4\xe5\x26\x5b\x5a\xbf\x6f\xf7\x02\x65\x9d\x33\xdf\x5c\x0a\x4d\xb6\x73\xba\xe2\xc5\x43\x1a\xfd\xed\x5b\x56\xdc\x32\xcd\x33\x7a\xf2\x23\xdb\xb0\xbf\xe1\x93\x26\xc5\xbc\x3c\x2f\x39\x2d\xfe\x86\x4f\x14\x15\xaa\xa7\x58\xc9\xe7\x11\x36\x48\x9c\x0e\x86\x58\xe9\x87\x82\xa5\x91\x90\xe5\x8a\x16\x11\x2e\xb8\x60\xdf\x32\x23\x02\xa5\x83\x64\x88\xef\xec\xa3\x41\x03\xd7\xff\xa5\xbc\x65\x65\x3d\x1a\x78\xfb\x6a\x6f\x42\xdc\xaa\xf9\x36\x66\xfb\x73\x85\xc2\xaf\x82\xf9\x09\xbf\x68\x92\xc3\xd2\x07\xe5\xb2\xa0\x04\x90\xab\xe7\xf7\x5c\x91\xe8\x3e\xf2\x49\x9a\x95\x14\x70\x95\x6c\x57\x32\x37\x43\x34\x62\xac\xd2\x11\x86\x3c\xc5\x32\x9d\x9a\xe5\x08\xc5\x57\x94\x0b\x4d\xb9\x78\xae\xd6\x2c\xd3\x76\xa6\x4f\x1d\xbe\x49\xf1\x2d\x8c\xb9\xf1\x83\x97\xe2\x6b\x33\x4b\x41\x8a\xe1\x00\x9d\x07\xab\x7d\x2f\x36\x0b\x2e\x9a\x59\x2f\x99\x5a\x4b\xa1\xf8\x2d\xab\x8b\x80\xa8\xdc\x42\x6c\x48\x69\xbe\x51\x4b\x79\xf7\x03\x17\xcd\x17\x39\x53\x59\xc9\x67\xe0\x82\x69\xdd\x80\x9b\x3d\xc6\xac\xc7\x25\x57\x66\x4f\x42\x95\x75\x2e\xf5\x59\x6b\x9f\x85\xaa\xa6\x86\xf6\xa7\x0b\x6d\x3f\x34\xe3\x2c\x79\x7e\x90\x3f\x77\xf9\xa5\xdc\x68\x76\xe8\xc7\xdf\xb4\x80\x55\xfd\xc2\x11\xa6\x24\xba\x89\xba\x6c\xe4\x68\x8a\x3d\x52\xe2\xf6\x25\xce\x54\x2c\xf1\x76\x42\xa7\xe9\xf6\x96\x16\x1b\x96\x4a\xb3\xed\xdf\x95\x5c\xd3\x59\xc1\x60\x6a\x26\x6c\x9a\x6e\x99\xd8\xac\x58\xe9\xd2\xb0\x19\x5a\x5b\xca\x9f\xd0\x29\x66\x44\x4d\x44\xad\xfa\x37\xbc\xc2\x9e\xee\x7c\x5b\x61\xb3\x03\xa6\x56\x78\xa8\xb0\xb2\x10\x72\xdf\x13\x5d\x55\x15\xaa\xaa\x78\x7b\x63\xe0\xb3\xb6\x3d\xd0\xe4\xfa\x54\x5b\x77\x64\xc7\xeb\x4b\x11\x21\x7c\x03\xd8\xe6\x4b\x44\x76\x3d\x47\xb0\x99\x00\xa6\xa6\xdb\x9b\x39\x2d\x8a\x19\xf8\x8c\x04\x68\x18\x55\x38\x78\x4b\x5b\x4d\x9d\x0e\xc2\x6a\x4f\x07\x55\xe5\x4d\x1c\x33\x6d\xed\x0d\x6f\xbe\xc3\x37\x9a\x0c\xcf\x66\x1a\x3f\x68\x72\xa3\xbb\x33\x8d\x6f\x35\xb1\xb2\x54\xf2\xe6\xf5\xbb\xef\xde\x7f\xf7\xf3\x37\x37\xdf\xfd\xf8\xf2\xbb\x1f\xbf\x7b\xff\x01\xdf\x69\x32\xd3\xe7\x83\xcb\x3e\x7e\x05\x4f\x43\xfc\x11\x7e\x1f\xe3\x77\xb6\x9a\xf3\x47\xf8\x8d\xab\xbb\x90\x8b\x41\x1f\xbf\x70\x6f\x06\x5e\xcd\xae\xf3\x75\xcb\x85\x1b\x0a\xac\xe5\x5d\x3c\x70\xb6\x8f\x79\x21\x65\x19\xbf\x01\xae\xc5\xf0\xb5\xfa\xdc\x3b\xcc\xc5\xfc\x8a\x0c\xc6\x83\x94\x5f\x91\xe1\x78\x68\x7e\x2e\xc6\x17\xe9\xa0\x8f\xce\x02\x59\xee\x75\xab\xf6\x89\xd9\xf9\x6d\x1f\x7e\x07\xd7\x71\x6b\xa0\x72\x86\xa9\xc1\x48\x5c\x71\xb0\x48\xe9\x2f\x05\x21\x7d\x30\x46\x80\x7b\xba\x40\xd8\x3d\xe9\x73\x81\x1a\xb7\x7b\x42\x48\xdc\xdf\x71\xd4\xe9\x30\xef\xfd\x8e\x59\xa2\x64\xa9\x6b\xcf\x71\xdd\x63\x08\xd9\xf3\x07\xa1\xa1\xe2\x79\xb0\x7e\x4e\xb9\xfa\x91\xfe\x18\xb7\x64\xbc\x50\x78\x0d\x79\xe5\xf7\x7b\xbb\xe2\x09\x8c\x86\xce\x54\x6c\x1a\xba\x0a\x38\xa6\xb7\x7b\x3c\x17\x14\x04\x42\x19\x1e\x1c\xe8\xb1\x2b\x23\x94\xf3\x2e\xbb\x0e\xf5\x0a\x3f\xd4\xcd\xd4\x16\x3c\x6f\xbd\x03\xbd\x65\xcd\xae\x4a\x80\x97\x82\x0d\xde\x88\x42\x76\x28\x0a\x38\xc1\x64\xc5\x45\xe0\x8d\x68\xfe\x62\x65\x00\xb4\xa2\xf7\x81\xdf\xa2\xf9\x8b\x55\xc8\x2e\x7e\xd3\xe2\xbd\xce\x62\x8b\x67\x41\x81\xef\xf6\x0a\x0c\x2e\xfb\xe7\xb3\x10\x4c\x7f\x78\x19\xea\xf4\xd7\x80\xdd\xb5\x0c\xcb\x00\x73\x2f\xfd\x84\x30\x39\x63\xe8\xdc\x70\x5f\x7a\x84\xd8\x19\x19\xf4\x31\xef\x76\x6b\x30\x35\x35\xbf\xdc\x03\x2b\x4b\xee\x7b\x3a\xb9\xc7\x82\xb0\xe4\xa1\xa7\x93\x07\xef\x93\x09\x18\xc6\xcf\x78\x57\x9c\x09\x7f\xbe\xcc\x4e\x96\xa6\x62\x18\x8b\x80\xed\x54\x57\xbd\xe4\xe2\x6c\xa6\x3b\x9d\x58\x75\xc9\x8d\x46\x78\x4b\xc5\xa2\x60\xa9\xc2\x39\xb7\x5a\x8d\x54\x86\x3a\xb2\x36\x65\x6e\x9a\xab\x57\x8f\xef\xd5\x10\x75\x83\x34\xdb\xbf\x61\x08\xea\xaf\x5a\x55\x19\x24\xea\x3e\x68\xf4\xe5\x8d\xee\xcd\x02\x74\xf8\x45\xb7\x3c\x27\x6f\x74\xf7\x06\x0a\x05\x4a\xb3\x03\x49\x0b\xbe\xc1\xd2\xfc\x32\x43\xb5\x7f\x81\x63\x6c\xd4\xfc\xca\x9e\x40\xb8\x34\x4f\xca\x3c\x15\xe6\x49\xf4\x24\xc2\x99\x7d\x52\x35\x64\x04\x21\x44\xee\x76\xc2\x5a\x92\xe8\x75\xd9\xe9\x14\x57\x59\xa0\x66\x3b\xba\x1c\xac\x3b\x6c\xe0\x89\xac\xc3\x21\xff\x27\x44\x1e\xa8\xa0\xf7\x68\xf8\xf4\xc9\x25\x36\x7f\x9f\x06\x05\xbf\x08\xd7\xa8\xde\xed\xbe\x70\x2c\x3a\xb2\x8f\x96\x37\x42\x63\xb3\x47\xa7\x26\xcb\xf0\x39\x63\xf7\xdb\x8d\x4e\xa2\x34\x8a\xc0\x1d\xde\xb2\x38\x63\xff\x50\x67\xd9\xda\xba\xd1\xfa\xfe\x24\xea\xfa\xfa\x02\xdd\x5e\x2d\x16\x63\x69\xd7\xa1\x22\x6c\x22\xeb\x4d\xc8\x9e\x43\x34\x29\x44\x27\x2b\x46\xd5\xa6\x64\xef\xd9\xbd\x11\xbd\x92\x3b\x9e\xeb\x25\xe6\x96\x28\x49\x84\xb0\xba\x86\x13\x54\x44\x21\x1c\xf8\x19\xff\xa4\xf7\x34\x3e\x24\x16\x44\x58\x79\xd7\x30\xaa\x44\xc0\x0f\x98\x85\x15\x11\xc9\x82\x96\x33\xba\x60\x5f\xcb\xa2\x60\x99\x3e\x48\xd8\xed\x26\xd3\x91\x00\xd6\xf1\xd4\x9a\x07\xa5\xab\x81\x1c\xaf\x60\x32\xc5\xb6\x38\x61\x08\xeb\x44\xd1\x5b\x66\xd8\x5a\x97\x34\xf2\x32\xb6\x3f\x85\xd1\x52\x61\x14\x38\xc3\x4b\x9c\xe3\x8d\x95\x45\x48\x7f\x54\x5c\x95\xa3\xa2\xdb\x35\xe2\x51\x4e\xf8\xa4\x98\x62\xab\x75\xcc\x3b\x9d\x53\x23\x8b\x7d\x88\x73\x84\x28\x01\xb8\x5a\x97\x84\xbc\x51\x3e\x41\x26\x48\x5a\xa4\x8f\x97\x24\xf7\x4d\x65\x57\xcb\x51\xd6\xed\xa2\x0d\xc9\x27\x99\xad\x91\x90\xcd\x6e\xf7\x21\xde\x18\x22\xd7\xaa\x6e\x83\xd0\x48\x1b\x4e\x4c\xcb\x92\xc5\x7e\x83\x9d\xd7\xe7\xc0\xce\x87\x23\x3e\x8f\xe7\xd7\x7e\x1c\xd6\xf3\xc1\x76\x7d\x0e\x5d\xb7\x27\x60\x4e\xe4\x44\x4d\x8a\xe9\x74\xa4\x40\xe4\xca\x58\xdc\xc7\xf3\x5a\x46\xa2\xcd\xfc\xfd\x7a\xb0\xea\x74\xe2\x0e\x28\xee\x8b\x0b\x58\x12\x03\x03\x3e\xae\x57\x08\x3f\x1f\xe2\xe4\x02\xa5\xb5\x32\x3a\xa0\x86\x31\xeb\x49\x74\x26\xd0\xb9\xe8\xca\xa6\xb9\xdf\x1d\xb1\x88\x19\x01\xf5\xd9\x82\xe9\xaf\xa5\xd0\x06\xe7\xa2\x61\x1e\x21\xe4\x67\x90\x19\x20\x30\xfd\xbe\xa4\x42\x19\xf9\x05\x92\xc0\xca\xf3\x96\x65\x1a\xc4\x24\xed\x70\x54\x27\x4b\x58\x15\xee\x23\x0b\xb9\x40\x17\xbb\x8f\xa1\xd6\x95\x04\x17\x0e\xb8\x19\x61\xc9\x5a\x72\xa1\xdf\x99\x55\x87\x97\x84\x25\x60\xb9\xe0\x52\xe0\xdc\xbc\xd0\x9c\x6f\xec\xb9\xa6\x0d\x89\x97\xbb\x5d\x1f\x9d\xdd\x69\x33\x0d\x59\xa7\x73\x70\xc6\x3a\x03\x94\xcd\x6a\xf5\x73\x8c\x70\xad\xae\xfe\xf6\xfd\xab\x1f\xbe\x5b\xd1\x05\xfb\xc6\x0a\x5c\xa0\xb8\x96\xbb\x5d\xab\x80\xb5\x39\xb4\x4a\x04\x2a\xbc\x1a\xbf\xc1\xe7\xa4\x30\xe2\x2f\x78\xe8\xeb\xc4\x59\x5b\x36\xe6\x39\x2f\xe9\x1d\x34\x14\x67\xb8\x97\x59\x30\x9d\x0f\xcd\xa3\x85\xd4\xf9\x10\xbb\x54\x9c\xd5\xc0\x03\x2e\x3f\xc4\x3d\xb3\xf7\xc5\x76\x37\xce\xd1\x6e\x97\x5f\x91\x3e\x42\x5b\x75\xc7\x75\xb6\x8c\x75\x32\x63\x0b\x2e\xde\x50\xbd\x8c\x11\xce\xd0\x36\x67\x73\xba\x29\x74\xaa\x13\x5a\x66\xa6\x53\x38\xc7\x7d\x6c\x76\x22\x9d\x64\x85\x54\xcc\x16\x1d\xcd\x4a\x46\x3f\x8e\x32\xaa\x58\xa4\x4b\x0e\x9b\x54\x94\xea\xc4\x08\x8e\xef\x65\xcc\xbb\x8e\xbf\x13\xf1\x06\x9d\xe5\x58\xf4\xe0\x3d\x93\x0a\xde\x11\xde\x74\xc9\x3b\x8d\x75\x62\x64\xc0\xff\x13\xe5\x3f\xd9\xd9\xd2\xc8\x5c\x06\xb3\x59\x1e\xa5\x05\x49\x2e\x06\x4f\xce\x72\x5c\x92\xbc\x57\xf8\x13\x13\x50\x4b\xf7\xa3\x46\x67\x25\xa6\xa4\x69\xc8\x25\x39\xc8\xf4\x14\x16\x3d\x8a\x0b\xbc\xe9\xcd\x34\xde\xf4\x5e\x01\x88\x20\xab\x4b\xb1\xe8\x29\xc8\x7a\xa5\xf1\xa6\x49\x57\x58\x74\xe1\x13\xbc\xe9\x06\xe5\x7b\x14\x8b\x2e\x94\xef\x9a\xf2\xdd\xd9\xe7\xa0\x6d\x06\x10\xa5\x66\x52\x97\x68\x5b\xda\xee\xbd\xfb\xe7\xdb\xf7\x83\x9b\xe1\x59\x6e\x10\xc8\xac\x2b\xde\x2b\xb1\xe8\x95\x78\x78\x06\xff\xbb\x0a\xaa\x4d\x97\x7c\xd4\x21\x1c\x74\x94\x86\x83\x36\xa0\x0c\x47\x8c\xa0\x46\x3f\xa7\x76\xc4\x28\x9c\x05\x18\x68\x2b\x05\x86\x18\xa6\xd8\xc1\x7d\x66\x40\x59\x29\x95\x82\xae\x04\xdd\x83\xc4\xff\xcd\xce\xd5\x5d\xa9\x91\xf2\xa0\xbb\xae\x73\x61\x77\x8c\x10\xf6\xff\x59\xc3\x18\x86\x8c\xff\x7f\x18\xa6\xc9\xfa\x7f\x65\x98\x61\xa5\x39\x55\xcb\x90\x0a\x58\x92\xd6\x5e\xb3\x75\x5b\xa2\xbd\x86\x51\xa5\x93\x39\x2f\x0a\xd8\x21\xac\x66\xe6\x17\x43\xda\xae\xfb\x9d\x8e\x61\xa5\x4a\xf9\xd1\xec\x07\xcd\x86\xf0\xf7\x7d\x8e\x0f\x14\xf4\xc9\x05\x06\xab\xd9\xfd\x35\x4b\x0a\x36\xd7\x3d\x0e\x6f\x57\x2c\x81\x58\x05\x5d\x78\x7d\xb8\x66\x89\x96\x6b\x9b\xf7\x70\x65\xda\xd3\x5a\xae\xba\x01\x77\xff\x9b\xdb\xe1\x02\x5a\x1d\x52\x4a\xb7\xce\x6c\x1b\x18\x6a\xc3\xae\x89\x5e\x9d\x68\x6b\xed\x41\xae\x5d\x00\x7c\x1d\x6e\x69\xff\xb4\x8a\x81\x63\xbb\xdd\x3f\x5a\x2c\x5f\x5b\x0f\x5b\x03\x34\xb9\xc7\x3c\x79\x00\x0a\x1f\xad\x78\x9e\x17\xcc\xee\x33\xcd\x39\x38\x96\xdc\x77\x79\x72\x8f\xce\x87\xa3\xfa\x33\x81\x59\xf2\x10\xcc\x8b\x80\x4a\x2a\xc3\xfe\x44\x74\xee\x02\x38\xc8\x53\x72\x7a\x2a\xc6\x75\x21\xe6\xda\x4a\x5b\xad\x9b\x8a\x46\x07\xfd\x09\xcc\x6e\xac\x6d\xcf\xf9\xcc\x18\x0c\x78\xff\xe0\xac\xfc\x7a\x53\x02\xee\x88\x31\x4b\xb2\xf5\xe0\x3e\x35\x3f\xc3\x7b\xec\xde\x1f\xec\xfb\x03\x16\x63\x0e\x19\x29\x87\x62\xfe\xfd\xc1\xbe\x3f\xe0\xc3\xce\x30\xd6\x80\x14\x2b\xb2\xad\x3c\x9c\x68\x68\x0b\x2a\x89\x72\xc8\x56\x63\x5f\x14\x81\xb9\xce\xa6\x82\x72\xd0\xb3\x9d\xc0\x70\xd6\x18\xa2\xea\xdd\x1c\xa2\x14\x84\x9b\x7b\x2b\x6b\xd2\x9f\xb6\xcb\x82\x77\xd2\x17\xb1\xaa\x19\x16\x64\x78\x2a\xc7\x09\x04\xa9\x9e\x1f\x96\x89\xd5\x80\x63\xa7\x56\x06\x47\x2e\xb3\x76\x80\xf5\x21\xca\x2b\x2c\x55\x62\x38\xb2\xe7\x05\x5f\x08\x28\x52\xbf\x91\x20\xc7\x17\xfb\x8a\x2a\x56\x40\x34\x18\x57\xd2\x27\x90\x76\xbe\x91\xd2\x0c\x9b\xea\xed\xb0\xa3\x6e\xb7\x80\xd9\xcd\x08\x35\x9c\xb6\xe9\x4d\x0b\x58\x50\xa1\x7d\xf7\xfd\x0b\x72\xed\xc0\x03\x88\x1b\x5e\xda\xa2\x07\xbc\xb6\xa7\x03\x64\x03\x78\x05\xf9\x26\x83\xd9\x54\x86\x89\xb5\xd9\x00\x22\x5e\x14\xc7\x73\x31\xd4\xc5\x3f\x32\xbd\x2c\xe5\x66\xb1\xdc\xed\x54\x02\x07\xbe\x61\x5c\xc1\x31\xcb\x50\x86\xca\x8c\xe8\xca\x7b\x2c\xa1\x99\xde\xd0\xe2\x2b\xc3\x3b\x70\xb1\xf8\x4a\xde\xff\x60\x56\x39\x25\xbc\x7b\x24\xef\xad\xa1\x04\xb8\x24\xe2\xd8\x87\xcf\x55\xc6\x84\xc6\x05\x11\xc7\x3e\x7d\xc1\x6c\xb6\x1b\x7a\xd3\xdd\xb1\x75\xf3\x1a\xa6\xc5\xa8\x0d\xd0\x60\xf2\x0f\xc8\x54\x08\xc8\x9c\x65\xd2\xc6\x2b\x80\x94\xdd\x6e\xd8\x10\x78\x89\x97\x01\x4d\xa0\x38\x00\x75\x8c\x2a\xd1\x25\x32\x69\xf4\xf5\xd5\x51\x9a\xc5\x59\xa0\x10\xd9\xde\xa7\x1c\x3f\xa4\x02\xdf\xa5\x12\x2f\x53\x85\x2d\xff\x9d\xd2\x8a\xb0\x51\xcd\x27\x19\xca\x08\x60\x14\xc1\x73\xf3\x64\xd8\xa7\x99\xc6\xa7\xfd\x70\x1b\x31\x5b\x59\x8f\x3a\xe2\x6a\x8a\x05\x7c\x57\x90\x7a\x50\x0c\xb7\x5e\x66\x1a\xbf\xda\xaf\xb9\x2b\xeb\x0f\xec\xfc\x39\xc6\xc5\x56\x7e\x24\x73\x2f\xa5\xfd\xf6\x4a\xe3\xfe\x41\x03\x7e\xa0\x6f\x2d\xb3\x1e\xd6\xed\x53\x5b\x45\x70\xf0\xd8\x07\x78\xec\xd5\x18\x80\x30\x34\xa4\xb3\xda\xd2\x4b\x6c\x48\x90\x6b\x3d\xe1\xd3\x2b\x56\x3b\xe2\xd7\xaa\xbb\xde\x00\xab\xda\x07\xa0\xa7\xae\x07\x23\x24\x88\xea\xca\xeb\xeb\x01\xe6\xb1\x40\x63\x45\x44\x2a\x89\x70\xb2\xe1\xb6\x90\xa9\xc2\x4b\x9e\x4a\x7f\x10\x54\xb2\xe6\xbc\x3e\xb4\xcb\x71\x2c\x4c\x7b\x62\x3a\x61\xd3\x2b\x8e\x10\x56\x9f\x2d\x72\x4d\x38\x0a\x8c\x8f\x94\xb5\x34\x8e\x6d\x3d\xa3\x8d\x42\x71\x25\x3b\x1d\xf3\xf1\x15\x1b\x21\xd1\xed\xba\xce\x5f\x1b\xa2\x3b\x91\xbd\xc1\xf4\x9a\x8f\x90\xec\xf5\x6a\xdd\xd1\x75\x7f\xb7\x93\x57\xbe\x92\xb1\x37\xd5\x82\x49\xdb\x3b\xf2\x94\x8c\x4c\xa2\xf5\x46\x2d\x23\x1c\xad\xe5\x3a\xc2\x91\x5a\xf2\xb9\x36\xbf\x20\x79\x47\x38\xda\x08\x9b\x34\x6d\x3a\x5b\x30\xcf\x26\xdc\xb8\x50\x60\xe3\xe6\xb1\x09\x8a\x62\xd5\x2f\x0c\xa5\xf1\x31\xfb\xc4\x43\xac\x71\xe4\x3f\x8a\xb0\x59\x40\x73\xbe\xd8\xd4\x86\x88\xd0\x2c\x31\xc0\xd6\x82\xb1\x6d\x62\xb8\x4c\xd8\xb4\xaa\x10\x2e\x59\x13\xac\x87\x91\xeb\x5a\x2f\x19\xdd\x48\xf1\x82\x6a\x1a\x75\x33\x50\xc0\x09\xa2\x27\x6c\x7a\xd4\x50\x62\x23\x76\xfc\x95\xf6\x6d\x9c\x96\x26\xb4\x96\xf3\x22\x02\x6b\x0c\x0b\xbc\x2c\x8f\x80\xa2\xee\xa4\x26\xd7\xdb\x63\xd6\xf0\x09\x9f\x9a\x89\xe4\x53\x17\x0c\x06\x21\x2c\xab\xca\xc6\x30\x6a\xac\xf2\x6c\xdf\x91\xc0\x37\x05\x02\x2f\xdf\x77\x6c\xe0\x4d\x0f\xc0\xdf\xc3\xbb\x1d\x30\x34\xea\x0d\x4e\x09\x91\x9d\x8e\xf0\x3a\x16\x08\x08\x20\xea\xf0\x32\xbb\x5d\xbc\x0f\x5b\xa7\x9d\x31\x80\x34\xdd\xf3\xaf\x75\x1f\x82\x8e\x2e\x59\x68\x77\x10\xec\xee\xe4\x1d\xd3\xfe\x8c\xc1\xe7\x9c\x8b\x58\x02\xe1\x73\x26\x7c\x0a\x1c\x9e\xf5\x05\x20\x84\x88\x7d\x83\xbc\x0c\x02\x95\xb1\x36\x78\xa5\xb3\x55\x38\x20\xd6\x9d\xca\x99\x3f\x6d\x62\x76\x0f\x7b\xe6\xe5\x47\x99\xb3\xe0\x44\x4b\xad\xcd\x78\xb7\xa4\xb9\xbc\x7b\x2b\xa5\x76\x1e\x7e\x8d\x4e\x04\x0e\x74\xb0\x64\x29\x95\x6e\xd9\x34\x36\xed\x25\x3c\xfa\x84\xdd\x5e\x8f\x63\xd1\x9c\xda\xd1\x78\xd0\x47\x18\x26\x23\xf0\x0a\xf9\x32\x42\xa0\xae\x14\xd6\xd7\x2d\xe8\xab\x01\x0c\x4a\x05\xd1\x58\xb8\x25\x3c\x67\x44\x93\x6b\x17\x1d\x0e\x54\x52\xab\xf5\x46\xb3\x1c\x76\xc6\x58\xe3\x3d\x2f\x87\x45\xdb\xf6\x38\x37\x30\x31\x9f\xf9\xc5\xf0\x33\x20\x3a\xf3\xfe\x1c\x6b\x43\x20\x34\x50\x06\x1b\xf6\x0c\x47\x96\xdc\x47\xd8\x46\x58\x0b\xc8\xc2\x8a\xed\xab\xe3\xb6\xd5\x88\x13\x3e\x8e\x7a\x51\x97\xa7\x51\x54\xbb\x4d\x58\x2f\xb6\xc7\xe0\xc5\xb6\xf5\xbe\x46\x6b\xd0\xee\x8a\x89\x9a\x92\xd0\x16\x34\x61\x5d\xf3\xbd\xea\xf2\x29\xda\xed\xfa\x5e\x0d\x28\xac\x0e\x08\x9c\x98\xe6\xba\x2b\xac\x18\x82\x85\x53\x09\x11\x61\xb6\x88\xae\x70\x9b\x53\xa8\xf5\xbd\x6f\xed\xd8\x19\xa8\xac\x52\x8e\x3f\xa1\x38\x4c\x45\x45\x18\x96\x64\xce\x62\x8e\xb0\x22\x91\x95\xd2\x7a\x33\x79\x0f\x22\x43\x32\x93\xf7\xef\xf8\x1f\x86\x31\xa5\x64\x65\x96\x51\xb4\xa6\xb9\xe1\x6a\x22\x84\x4b\x97\x62\xbf\x89\x70\x04\x7d\x8e\x10\xde\xde\xa7\x05\x7e\x48\x33\x3c\x93\xf7\xe9\xb2\x22\x6d\xef\xe2\x66\x79\x0b\xaa\xf9\x2d\xdb\xed\x34\x78\x99\x80\x97\x02\x83\xa5\x6c\x16\xae\x23\xec\x86\xb5\x4e\x39\xde\xca\xf9\x5c\x31\xfd\x6b\xaa\xb0\x7d\xfa\x60\xd8\x0e\xd9\x44\xbd\x20\xa7\x03\xb3\xa4\xe2\x7a\x53\x8a\xb5\x59\xe6\xec\xba\x6f\x90\xed\x94\xef\x76\xa7\x3c\x51\x35\xde\x23\x14\x2b\x4c\x31\x4f\x34\x2d\x17\x4c\x23\x54\x12\x88\x91\x01\x2a\xe3\xda\x40\x0c\xa1\xb8\x3c\x1f\xf7\x75\xc1\x99\xd0\xa0\xe3\x44\xa3\x92\x48\x23\xfb\x31\xa1\x7f\xed\x69\x2b\x1c\x16\x75\xd2\x87\x9e\x06\xe9\x31\x23\xa7\x7e\x46\xb7\xf7\x69\x89\x1f\xd2\x02\x40\x92\x55\x95\x0d\x7a\x93\x83\xeb\xe3\x5c\x77\xe3\x65\xa7\x53\xc2\x23\xc2\x1b\x02\x0c\x80\x4b\x33\x72\xa6\x19\xe5\x16\x80\x9b\xce\xb1\xc5\x80\x74\x51\x35\xc1\x45\x54\xa7\x13\xcf\x7b\x84\x5a\xa4\xe9\x96\x4e\x81\xb8\x30\x49\xb6\x78\xb7\xac\x95\x89\xdb\xfb\x34\xd4\x05\x17\xbd\x1c\x9d\xcf\xcf\xb8\x53\x45\x0a\x84\x1f\x5a\xf9\x59\x6f\x83\xce\x17\x67\xdc\xeb\x27\x05\xf2\x4c\xc2\x0c\x96\x66\x50\x76\xd0\x3f\x03\xff\xd5\x66\xcd\xdc\x1c\xb1\xf6\xc3\x9a\xc4\xca\xe1\xce\x8a\x96\x0b\x2e\x22\x84\x29\xd9\xb0\x58\xd6\x8c\x3d\x44\x5f\x03\x60\xfe\x62\x91\x6a\xb7\xbb\x35\xcc\xb7\x2f\x64\x99\xd6\xa6\x94\x7d\x77\xc5\x0a\xb2\x1f\x1d\xc3\x71\x48\x06\x43\x6a\x97\x5f\xb6\xdb\xd5\xcf\xbc\x59\xa8\x40\x47\x4d\x41\xd5\x38\x0a\xa8\x4f\xe1\x01\xa6\x66\x3c\xca\xad\x05\x7a\x64\x2d\x14\x2e\xa3\x5e\x36\x23\x43\x9e\x21\xb7\x57\xb8\x5f\x3f\x61\x66\x4d\x58\x30\xf7\x0a\xff\xe0\x27\x0e\x0b\x33\x76\xda\x00\x48\xed\x01\x08\xcb\xba\x80\x03\x8e\xda\x07\x0e\x28\x04\x60\x7b\x08\xbe\x84\x56\xc3\x72\x1e\x63\x2d\xc2\x31\x8f\x70\x1c\xfb\xa6\x53\x01\x50\xae\x1b\x4a\xa5\x79\x07\x9c\x06\x7f\xbb\x06\x5b\x33\xff\xf1\xb2\x22\x05\xe8\x34\x32\x29\x34\x13\xfa\x08\x81\x69\xa0\xfd\x09\xaa\xc2\xf6\x09\xd0\x28\xeb\x11\xe6\x70\xde\x5b\x1c\x96\x26\xc9\xe1\xbc\x07\xa6\x27\xaa\x59\x78\xf6\x32\xeb\x29\xfb\x09\xc2\xcb\x30\x5d\x8c\x03\xcf\x84\xec\x5c\xa0\x74\xd9\x53\xf5\xe2\xc9\xc8\x8c\x35\x91\x86\x32\x4c\x71\x11\x4a\xaa\xcb\x56\xf6\x12\x97\x36\xdb\x82\x09\x21\x9c\x75\x3a\xa7\xcb\x4e\x27\x86\x72\xd9\xf9\x10\x21\x7c\x08\xa9\x86\x96\x3f\x1c\x6c\x39\x9f\xb4\x00\x19\x6c\x1e\x60\x4f\xef\x25\xb6\xb5\x2a\x5f\x2b\xad\x88\x1e\x49\xbf\x7b\xd0\x33\x81\xa5\xdb\x61\xd4\x99\xc0\x3a\xc9\xf4\x7d\xd2\xb2\xe9\x08\x70\x76\x83\xbf\x08\x4b\x6b\xf6\xec\x74\x62\x43\x46\xdd\x9b\xab\xac\xd3\xa9\x13\x2c\x38\x21\x0a\x63\x58\x82\xd0\x6e\xb4\xbe\x8f\x70\xab\x18\x51\x90\xe8\x37\xe2\x5b\x76\x78\x8e\xe2\x74\x30\xd2\xe5\x43\xcd\x66\x6d\x17\x4c\x9f\xac\xa9\x52\xfc\x36\x38\x93\xa4\xc9\x69\x1f\x9f\x0e\xaa\x6a\xe4\x78\x04\x9a\xe7\xdf\xdc\x32\xa1\x7f\x70\xac\x61\x1c\x69\xf0\xda\xb2\xb1\x34\x11\xae\x03\xcd\x1a\x21\xf9\x73\x25\xab\x8c\x82\x35\x05\x6d\xc3\x33\xc5\x0d\x6d\xbb\xdb\xe3\x56\x1d\xeb\x61\xb6\xb2\x4e\x87\x27\x2b\xf8\xfa\xfc\x7f\xc5\xff\xca\xbb\x28\xfe\x57\x62\x7e\xc6\xeb\xfb\x2f\xce\x1b\xf3\xf7\xb8\x2b\x26\x83\x69\xea\xc2\x9c\x36\x31\xa9\x5a\x3c\x4c\x64\x37\xc9\x88\x8b\x13\x3d\xde\xde\xa7\x3a\xb9\xc7\x0f\xa9\x4e\x1e\xaa\xd4\x6d\xf5\x41\x64\xa9\x7d\x72\x6b\xfe\xea\x52\x16\x05\x2b\x53\x89\x73\xaa\x69\xaa\xf0\x8d\x92\xa5\x66\x39\xe0\x04\x36\xfb\xd8\x4d\x46\xb3\x25\xcb\x5f\x31\x4d\x13\xfe\x2e\xa3\x05\x33\x4b\xb5\xec\x74\x0c\x6b\x5a\x26\xf4\x9e\xab\x4e\x87\x76\x3a\x75\x7c\xc1\x7a\xa5\x96\xc9\x4d\xc9\x6e\x59\xa9\x2c\x26\xaa\xb1\x62\xa9\x84\xaf\x4f\x1b\x96\x36\x56\x96\x2c\xf0\x79\x2c\x93\x1b\xb5\xa4\x25\xcb\x5f\xaf\x4d\x87\x55\x83\xd8\x6a\xd2\x9f\x62\x49\x8e\xc8\x0e\xc2\xd0\xde\xb7\x54\x2c\x98\xe1\x0a\xfc\xb3\x61\xf2\x4d\x85\xc1\xd2\xb0\xed\xf4\xa4\x21\xca\xee\xa5\x2b\x51\x20\xe3\x8a\xa4\x90\x46\xcc\xa5\xc9\x92\x57\x55\x55\x35\x39\x7d\x93\xdc\x04\x15\x0d\x96\xe0\x3b\x16\x2a\x6d\xfd\x1e\x01\xd6\xd1\x77\x00\xc6\x9f\xb9\xe2\xb3\x82\xbd\xb0\x9e\x9f\x06\x86\x0a\xb6\x05\xf0\x8d\xf5\x1c\xa1\x26\x7d\xcc\x6b\x4b\xf1\x48\x5f\xf1\x51\xb7\xeb\x45\x88\x2d\x30\xc6\x29\xb7\xf3\x53\x56\x44\x4d\xf4\x14\x9b\x6e\x15\xa6\x5b\x59\x45\x3e\xb2\x18\xd2\x18\xa6\x58\xa2\xa0\xd6\x62\xa4\xaf\x48\x16\xd4\x75\xc2\x48\x39\xd1\xd3\x11\x4b\xd4\x47\xbe\xde\xed\x6c\x9c\x30\x8d\xaa\x60\x48\x6f\x8e\x6c\xca\x93\x29\x4c\xda\xdf\x75\xcc\xb0\xf3\x4f\x7d\x5e\x32\x8a\x75\x72\xb3\xe2\xe2\x8d\xa5\xb8\xb5\xb1\x53\x7a\x14\x7e\x67\x05\x7f\x16\x84\x84\x36\xef\xca\x08\xcf\x5c\xb8\x89\xb2\x4a\x65\x2c\x50\xa7\xe3\x64\x97\xad\x73\x6b\x4d\x35\x0e\x8f\x52\xa4\x1c\x5b\x50\x28\x23\x19\x82\x56\x24\x90\x6f\x5e\x1c\x9d\x89\x63\xc7\xbe\xf7\xe5\x8d\xfb\x08\x61\x7e\x90\xfa\x10\xa1\x83\x83\x5a\xba\x15\x5e\x78\xdc\xb8\x5f\x25\xf7\x3d\x91\xdc\xa3\xb4\x8f\x95\xb7\xb2\xdb\xf4\x87\x9e\x48\x1e\xf6\xcd\xec\x6d\x77\x1d\xd9\x72\xd4\x51\xe0\xa2\x53\xc5\x76\x9f\x3c\xa1\x9f\xf6\xc1\x2b\xff\x87\xb3\x52\xfe\xc9\xac\x58\x95\xae\xe8\x74\x4e\x0f\x27\x47\xee\x9d\x1a\xc8\x2c\x8a\x7f\x0d\xd1\x9f\xdf\x48\x2e\x74\x2c\xcd\xf6\xa6\x62\x86\x33\x34\x5a\x5e\xd1\x71\x5c\x92\xc9\x9f\x4d\x64\x51\x4d\x31\x25\x4b\x94\x2e\x09\x21\xd4\xb0\xb3\x7f\x69\xfe\x0b\xd0\x0c\xe0\x32\x08\xdc\x76\x04\x67\x5f\x31\x38\x96\x80\x21\x46\x29\x25\x1c\x08\x15\x2e\x49\x04\x9c\x05\x1d\x47\x5c\xfc\x0a\xa3\x8c\xd2\x88\x8b\x0f\xf6\xd1\xaa\xf9\x49\xed\x51\x7f\xf2\x29\xd9\xe4\xf3\x0b\x7c\xd4\xf6\x9c\xf3\x6b\x9c\x36\x5e\x2c\x1a\x0e\x7b\x68\xb4\x8d\xdd\xfa\x16\x76\x7d\xcb\x0a\x4e\x62\xa0\x3d\xda\x20\xf7\x69\x83\x22\x12\x0e\xc5\xb8\x85\xcc\x62\x85\x05\x2c\xe4\x58\xe3\x46\xc8\xd9\xea\x49\x39\x8d\xe5\x84\x4e\x61\x7d\xa9\xcf\xc3\x97\x39\xf8\xf2\x0a\xe1\x06\x07\x64\x72\x8f\xa5\x5b\xa0\x31\xc4\x59\x86\x13\xf1\x49\xed\xe7\xdc\xe9\x9c\x16\xe3\xc9\x34\x55\xe0\x76\xff\x9a\x59\x8f\x68\x95\xda\x81\x7d\x6e\x62\xec\x9c\xec\x76\xd1\x7d\x04\xb0\xa9\xab\x1c\x03\x11\x72\x87\x7b\x5e\xf8\xe7\xd3\x01\x06\xdf\xb1\x46\xf7\xe1\x2d\x12\xe3\xf8\xcf\x66\xa4\xad\x24\xf1\xa4\x80\x4e\xfa\xee\x58\x12\xb0\xb9\x06\x1a\x86\x2e\xf3\x4e\xc7\x48\x83\x1f\xf9\xfa\x10\x27\x79\x1b\x66\xda\x7f\x6e\x21\xe8\x30\x13\xa5\x93\x69\xe5\x0b\xfe\x35\x08\x3c\x44\x6e\xc1\xff\x35\x30\x98\x95\x4f\x6b\x7d\x15\x6a\x8f\x28\xec\x21\x76\xd8\x1a\x80\x23\x66\xd6\xc3\x6b\x04\xf1\xee\x03\x44\x33\xd8\xd5\xd8\x78\x34\xa2\xfb\x63\x37\x28\x77\x14\x65\x74\x15\xb8\x28\x61\x70\xca\x49\xeb\x71\x93\x6b\x18\x87\x1f\x75\x38\x66\x33\xa1\xce\x73\x3e\x2c\xff\xe2\x93\xe5\x03\xe8\x98\x6f\xef\xc3\xaf\x62\x5b\x12\xdc\xf4\x03\x8a\x60\x44\xd6\x63\xa5\x1e\xda\xa5\xaa\xca\x11\xb7\xe7\x56\x67\xf7\x96\x2d\xbe\xb9\x5f\x1b\x16\xcd\x9e\x5e\xd8\x19\x56\x2d\x1e\xa7\x8e\x57\x43\xf1\xfa\x7e\xc7\x56\xbb\x2f\xd1\x18\x7d\x71\x8e\xf0\xfb\x4f\x7c\xc5\x35\x2d\x78\xb6\x73\x31\xb9\x77\x5c\x2c\x59\xc9\xf5\x6e\x23\x14\xd3\xbb\x58\xce\x0a\xfe\xfb\x86\xc5\x27\xbd\xf1\xa4\xdf\x7b\x36\xb5\x7f\x21\x5c\x2b\x32\xd5\x06\x01\x79\xf6\xf8\xc9\x38\x8a\xba\x1a\x39\x3e\xf2\xb9\x65\x77\x4e\xf9\x6e\xe7\xcf\x5a\x18\xa9\x75\x32\x98\x7a\xea\x3f\x48\x86\x67\x6c\xe4\x5d\x80\x48\x17\x62\x3b\xf2\xc9\xa3\x29\xda\x82\x1d\x7f\x7d\x1f\xa5\x8d\x92\xd1\xa4\x7c\x19\xa5\xfa\x9c\x0c\xfa\xb5\xd2\x89\x9d\x85\x4e\xc2\x7b\xdd\xd9\x56\x58\x90\x9f\x62\x66\xe4\x4c\x31\x6e\x1f\x78\x4b\x19\x56\x04\xdc\xe6\xc5\x98\x93\xeb\xef\x41\xc3\x89\xf5\x84\x4d\xf8\x74\x8a\x52\x46\xae\xf5\x84\x4d\xd3\x18\x91\x6b\x1d\x1c\x78\xd2\x27\x72\x7e\x22\x91\x41\x3a\xd2\x55\x10\x7c\xa3\x7f\xc4\x29\xf7\x9b\xd6\x81\x76\xd3\xad\xad\x96\xeb\xd4\x4c\x2f\x68\xc5\x52\x83\x0e\x56\x11\x06\x89\x05\x9b\x43\x5a\x78\x4c\xee\xbb\x83\x3a\x40\xef\xf7\x03\x9b\xdb\xf3\x31\xd6\x1c\x53\xab\xff\x5c\x7a\x60\xfa\x89\xc2\xa3\xa7\x7f\xb4\xf4\xbf\xd0\xbf\x46\x59\x6b\xc5\x1b\xeb\x30\xd0\x75\xfe\x03\xb8\x96\x85\xc0\x71\xa0\xeb\xfd\x08\x42\x05\xeb\x4b\x6f\x76\x20\x1a\x5c\x32\xc1\x0d\xef\xde\x9a\x87\xdd\x31\xb8\xef\x9d\x8f\x2a\x76\x87\xc8\x46\x07\xea\x57\x6e\x64\xb4\x46\xff\xca\xf1\xa0\xef\xee\xbf\x10\xf6\x6b\x30\x28\x32\xfb\x8b\x46\x86\x19\x30\x78\x26\x3c\x9e\xbd\x67\x66\x13\x30\x23\x93\x46\x52\xa3\xa5\x88\xff\xf6\x9d\x80\x10\x1d\x27\xa6\x23\x27\xf0\xe1\x89\x5a\xb3\x8c\xcf\x39\xcb\xd3\x93\xe8\x6f\x5d\xd1\xfd\x5b\xf4\x37\x23\xf8\x44\x51\x13\x0d\xd5\x9f\x2e\xfa\xbe\x76\xa6\xc5\xcc\x7b\xd5\x86\xc7\x84\xde\xb2\xf8\x7b\x67\x1c\x76\x6a\x0b\x16\xbc\x20\xcc\x91\x3d\x6b\xc4\xdd\x51\x23\xe1\x0f\x15\x7d\x5f\x3b\xdf\x62\xe6\x1e\x10\xb6\xf0\x48\xa3\xa8\x0e\x5e\xe4\x0d\xeb\xe4\x0b\x60\x61\x02\x86\xf2\x67\x76\xd4\xfb\x90\x9c\x5a\xcb\x99\x24\x86\xd9\xab\x55\xf8\xf2\x4a\xc1\x59\x5a\x43\x96\x09\x1c\x6e\xae\x8f\x01\xd2\x4e\x27\xae\x5f\xd8\xd1\x03\xda\xa6\x08\x25\x86\x30\x9b\x06\x06\xa8\xf9\x98\x77\x3a\x1f\x62\x8a\x6c\xfe\x84\x7f\xe9\x69\xfe\x74\xbf\x20\xad\x19\x3d\x33\x6b\x25\x5c\x99\x00\x82\x1b\x9d\x15\x0c\x8a\x06\xbe\xa3\x5f\xb5\xb4\xc0\x2b\x2e\xac\xfa\x26\x15\x15\xd1\x5e\x22\x82\xd4\x5e\xcd\xcb\xfe\x06\x87\x25\x91\x2d\xd6\x35\x6f\x8d\xaa\xef\x17\x46\x26\x56\x21\x8e\x8f\xab\xcb\x03\x3d\xf9\xb7\x6d\x15\x3c\x18\xb2\x35\x2b\x61\x5f\xd6\xc9\x5a\x2a\x38\xe0\x19\x46\x53\xf8\xcc\x07\x70\x68\xf4\x17\xd6\x9c\x2c\x36\x15\xa0\x4e\x47\x27\x33\x79\x6f\xc9\xfc\x5e\x6d\xff\xd9\xaf\xad\x3e\xb0\x01\xfc\x52\x7d\x28\x76\xcc\x53\x8d\x0d\x93\xaf\xd3\xfa\xae\x16\xe1\xf0\x08\x14\x53\xce\xb1\xdb\x99\x95\x7a\xee\x94\x77\xea\xcb\xf4\x7c\x89\x2a\x6c\xfd\x0b\xb6\x1f\xf8\xb8\x71\x5a\x07\xa2\x08\x26\x8e\x6e\x90\x26\x4c\x9a\x08\xa9\xcb\x87\xda\xfe\xa8\xe5\xba\x51\x4d\x69\xe7\x90\xe4\x1c\x8f\xcc\x6c\x84\x99\xce\x3f\xa9\x70\xc6\x73\x3b\x2f\x61\x01\x4f\x71\xdc\x03\xf8\x3b\xc1\x60\x83\x32\x9e\x58\xc1\x6f\x18\xec\xe1\x40\x11\xc5\xcd\x04\x80\x15\x77\x45\xef\x9d\x24\x32\xfa\x29\xe6\x30\x3f\xbb\x5d\xcc\x81\x42\x75\x3a\x66\xd4\x26\x6d\xda\x23\x36\xc9\x6c\xf7\x60\xf5\xe2\xc9\x52\x96\xfc\x0f\x29\x34\x2d\xc6\xde\xb0\x91\x0a\xef\x39\xec\x3e\xeb\xd6\x9f\x81\xec\xef\x5a\xea\x74\x3e\xb0\x58\xb6\x92\xe2\x3a\x12\xb3\x0a\xd5\x79\x2c\x91\x1b\xed\xdc\xce\x7a\x5f\x98\x8f\x34\xf6\x98\x6c\x71\x18\x21\xef\x22\xd7\xfa\xc2\xd2\x9f\xfa\x13\x8b\xf5\x0e\xdb\x0d\x07\x48\x14\x88\x93\x77\xb8\x20\x14\x9e\x9a\xf0\xf9\xc9\x1d\x51\x58\x27\x4b\x42\x71\x6b\x90\x5b\x45\x57\x2c\x2d\xb1\xd4\x4b\x56\xa6\x45\x95\xda\x84\xc2\x25\x94\x81\x8c\xfe\x2b\xdb\x3f\x88\x12\x80\xb9\x71\x09\x08\xe3\x0e\x6d\x61\xdf\xeb\x63\xb3\x37\xf6\xdd\xce\xd8\xf7\xfb\x62\xbf\x6a\x7a\xd7\x62\x94\x85\xd9\x7c\x9b\x73\x15\x86\xff\x03\xf1\xc4\x70\xb9\x75\x24\x20\x11\xeb\xf1\xa4\x0d\xb5\x69\x3a\x69\xc3\x24\xc4\xe0\xdf\x0f\xd0\x65\x32\x1d\xb5\x1c\xbc\x9d\x9f\x55\x9b\xc6\x82\x17\x92\xa7\xb3\x5b\x47\x65\x4b\x42\x01\xd5\xca\xc4\x5d\x75\xe3\xac\x1c\xbb\x1d\x4b\xee\xb0\xb7\x6f\x98\xb7\x25\xfe\xd5\xe4\x36\x00\xc7\xcc\xe3\x84\x05\xb4\x72\x80\x5e\x56\xe4\x27\x7b\x93\x14\x45\xa3\x62\x47\x54\x63\x6e\xc2\x19\xc9\x76\xbb\x25\x2e\x93\xf9\xa6\x28\xde\xf1\x3f\xd8\x6e\x27\x2c\x93\x4c\x6b\x06\xb8\xe8\x74\x7e\x67\xb1\x80\x11\xee\x76\xc1\x81\x95\xef\x8f\x2c\x13\xa7\xad\x6e\x0f\x9f\x18\xb9\x3b\x23\x2c\x79\xf8\xdc\x56\xb3\x07\x81\x70\x68\xe3\xd8\x5a\x8b\x48\xd3\xd1\xb1\xb5\x15\xa6\xce\x55\xb1\x74\xab\x3b\x28\xc0\xc3\xb5\xe0\x4c\x8a\x69\xcd\xa8\xdc\x61\x30\x36\x91\x0c\x97\x9e\x7a\x64\xb5\xd9\x08\x3b\x13\x05\x71\xd5\xf6\x6c\xf3\x38\x23\xbe\x30\x4a\x7d\x97\x8a\xba\xed\xa2\x36\x45\xd9\xaa\x5b\x9d\x35\x78\x6a\x9d\x2c\xeb\xf6\x0e\xfb\xea\x56\x61\xd3\x59\xcb\x3d\x99\x0a\x1d\x43\xe5\x3f\xee\x41\x13\xb8\xf0\x3d\x44\x23\x96\xdc\x93\x02\xb3\xe4\x81\x64\xd5\xbd\x86\x9b\x6f\xa2\x82\x3e\xc0\x39\xe9\xad\x9b\x96\x74\x7b\x7c\xb9\x58\x26\xb2\x5f\x55\x08\x82\x9e\xfd\x9d\x91\x2d\xcd\xf3\xaf\xe4\xbd\x27\xcd\x33\x79\xcf\x14\xb8\xb5\xc1\x13\x99\x4c\x91\xe1\x6f\x5c\xf7\x09\x0b\xf0\x07\x2e\x16\x5a\x4b\xc5\xb5\xbd\x83\xc6\x3f\xee\x76\x76\x05\x79\xee\x85\xf8\x87\xdd\xae\x6f\x6f\x14\x7a\x60\xa5\x22\xf5\xd3\x6e\x77\x10\x50\x68\xb2\xfd\x23\xed\x63\xb8\xf2\x48\xa3\x2d\x4b\xdc\x53\x55\x4d\x2b\xec\x7a\xe6\xdd\x54\x2a\x6c\x55\xde\xf5\x18\x1a\x55\x07\x94\x1b\xfb\xf2\x8d\x17\x45\xda\x1b\x58\x47\x0a\xee\x36\x5c\x56\x1f\x59\xe1\x78\x80\x2a\xec\x9d\x4a\x6a\xb4\x0f\x20\xc0\xeb\xc7\x70\xf4\xbc\x7e\x6c\x86\xcd\xfd\x46\x8a\xfd\x65\x56\xa1\x7f\xa9\xde\x8f\x15\x62\x98\xef\x44\x5a\xfd\x71\x62\xe7\xd3\x2f\x32\x23\x70\xb3\x9e\xb3\x6c\x60\x4a\x78\x4f\xd6\xf8\x7b\x54\x53\x78\x2c\xcd\x91\x2a\xd0\x33\x06\xbe\x1c\x31\x1c\x80\x42\xfb\x1e\x1d\x2e\x56\x8c\x3b\x21\x5a\xab\x72\x67\xf2\x3e\x95\x78\x2d\x55\x2a\x9b\x11\x37\xcb\x37\x95\x09\x57\xdf\xd6\xaf\x31\xf2\x4c\x6d\xc3\x54\x34\x01\x5a\x6c\xe0\xbb\xff\xb0\x98\xb5\x59\x29\xc3\x01\x79\x18\x23\xab\x2e\x15\xa6\xd8\xb7\x86\xb6\x59\x6a\xed\x94\xa8\x4d\x6a\xbd\xe5\xa9\x26\xcd\x20\xa1\x2d\x48\x9b\xc4\x70\xa7\xfb\x11\x52\xee\xc1\x98\x69\x9f\x1b\xdd\xe9\xd6\xf7\x20\xe5\xb0\x66\x9e\x8b\xfc\xbd\x5c\xa7\x22\xc9\xa4\xc8\xa8\x06\xd3\xa8\x69\xf3\xb9\xc8\xbf\xb2\x6b\x4b\xfa\xac\x02\xf9\x27\x5a\x3f\x95\x08\xd7\x6a\xce\xd4\xf6\xa4\x7e\x8f\x10\xbe\x65\xa5\xe6\x19\x2d\x9a\xfa\x25\x6a\xaa\x0b\x01\xac\x8e\xd5\x5d\x55\x7e\xbd\x22\x20\x14\xbe\x3a\x20\x63\xcd\xc7\xa3\x7f\xf8\x62\xf8\x93\x0e\x4d\xc9\x8c\xcd\x65\xc9\x7e\x00\xfc\x83\xe5\x11\xbc\xc3\xe5\x6c\x0e\x61\x97\xa4\xd8\xbf\x6f\x8a\xc1\xd4\x39\x14\xee\x74\x4e\x07\xe0\x82\x13\xa4\x25\x39\x57\xeb\x82\x3e\x8c\x75\xaa\xbb\x70\x91\xc9\x6e\x37\xc0\xb9\x0f\xae\x31\x2f\x19\xfb\x83\xc5\xdb\x86\x9a\xa7\x0c\x07\xe4\x32\xe5\xd8\x93\x37\x89\xe9\x2d\xe5\x85\x11\x11\x7e\x71\x16\xc1\x3a\xc1\x15\xa6\xf8\xf6\x2b\x79\xff\xca\xdb\x76\xd5\xf9\xf0\x7c\x89\x97\x36\xc9\x17\x39\x1f\x56\x08\x6f\xc8\xc1\xa1\x78\x89\x46\x1f\x58\xbc\xc1\x7f\xb0\x58\xa0\xe6\x48\xdc\x5e\xb9\x86\x75\x49\x37\xf8\x2e\x55\x78\x99\x52\x7c\x9f\x4a\xbb\x85\x3c\xa4\xd2\x50\x6e\xa8\x6c\xef\x9a\xcc\x63\xeb\xf0\xc0\xa7\xca\xad\x40\xd9\xda\x1d\xbd\x75\x53\xb6\x56\x49\xa7\xc3\x92\x36\x3c\xb0\x6c\x04\xf3\xd6\x98\x51\x5a\xd7\xc1\x92\x10\x40\xcd\x17\x9f\xa9\xdb\xd5\x51\xc5\x85\x47\xbe\x0c\xe1\x1c\xe1\xdf\x59\xdc\xec\x71\x78\xee\x92\x8a\xfa\x29\x83\x27\x60\x2f\x5c\xe2\x31\x0a\xa5\x8f\x32\x83\x3c\x0e\xf8\x8e\x80\xa3\xe3\xd3\x1e\x00\xa8\xdf\xb8\xf0\x4d\xf8\xb4\x4b\x04\x16\x95\x4e\x1e\xba\x84\xc7\x8e\x04\xe8\xe4\x1e\xde\x1c\xe9\xe0\xb1\x27\x17\xe6\xd1\x13\x84\x2a\x9e\x23\xfc\x3d\x73\x9b\xbd\x5d\xee\xae\xab\xe6\xf3\x79\x72\x87\xe7\xa6\xd6\x79\xb2\xb4\xc5\xda\xcb\xdf\x16\x0d\x8c\x19\x8e\x6f\x9d\x5b\x64\x30\xbb\xf1\xdc\x32\x05\x80\x79\x36\xb9\x6b\x6a\x75\x5b\x33\xe4\x76\x4d\xed\x4e\x62\x30\x8f\xce\x37\x26\xb9\xab\xf0\x3f\xe2\x32\xb0\x94\xb4\xbc\x26\x61\x8d\x8d\xda\xc8\xc9\xc3\xbe\x18\xd9\xc4\xed\x41\x76\x1c\x4b\xb3\x90\xab\x6a\x64\xc3\xef\xfe\xc6\xb6\x34\xfb\x7d\xc3\x4b\xe6\x0f\x46\x02\x96\x56\xa5\xbd\x69\xac\x4e\xac\x8f\x15\x0f\xaa\x03\x6b\xb4\xdb\x28\xab\x63\xf6\x67\x9f\x77\x34\x1e\x8c\x17\x27\x07\x26\xfb\x15\xbd\xe7\xab\xcd\xca\x60\xd1\x81\xbc\xc9\x5a\xc2\xcc\x6e\xa7\xbd\x9b\x03\xb8\x0d\x7b\x9f\x08\xbc\xef\xde\xf1\x29\x17\x08\x76\x2e\x50\xca\x51\x55\x71\xf5\x5c\x6b\x30\x14\x07\x23\xec\x57\x2e\x34\xf1\x3f\xd9\x09\xbb\xd7\x4c\xe4\x47\xc1\xd4\x88\xe3\x86\x54\x36\x27\x4b\xdb\x6f\xf6\x9c\xe9\x6e\x07\xe1\x62\x9c\xe6\xe1\x1f\x8c\x6c\x9b\x58\x36\xa9\x0d\x75\x93\xcb\x3b\x11\xe1\x3a\xaa\x4d\x1a\x06\xc3\xb1\x5e\x64\x22\x77\x89\x9b\x75\x64\xb5\xd5\xac\x04\x5b\x96\x4b\x76\x97\xa4\xba\x9c\x1c\xa2\xd5\x07\x55\xbb\xf4\x83\xca\x5d\xfa\x66\x7d\x58\x7b\xc1\x68\x5d\x18\x58\x4c\x97\x2e\x37\x3a\x48\xad\xb0\xe6\x44\x93\x6b\x7b\xd2\x98\xe8\xdd\x0e\x02\x5e\xd5\xe1\x9a\x39\x39\x3d\xbd\x65\x9d\xce\xd6\x39\x3a\xa4\xa7\xfd\x2a\x58\xe2\xbc\xbe\xac\x31\xb1\x9e\x1e\x47\xfd\x18\x0c\x3e\xb0\xf0\x6a\x24\xc1\x8f\xf8\x91\xc0\xf7\xd6\xd9\x2e\x37\xe4\x7b\xb7\x13\xd8\xdd\xcd\xba\xb1\x87\x53\x5e\xcf\x14\x2b\x6f\x1d\xbf\x51\x53\x9f\x9c\xc5\x12\x8d\xf6\xc4\xc8\x20\xe2\xd9\x48\x5c\xe9\x84\xe6\x39\xcb\x7f\x94\x39\x53\xad\x58\xf0\x8d\xfd\xbc\x29\x30\x11\xd3\x91\xb2\xde\xba\xe6\x87\xed\x76\x3c\xd6\xde\x2d\xaf\x32\xeb\xaf\x89\xc9\xa1\x12\x69\xfb\x14\xe7\x32\xdb\xac\x98\xd0\x78\x9b\x2d\x79\x91\x9b\xb1\xa7\xa7\x7d\xac\x36\x33\x5d\x32\x00\x1b\xc2\x2a\x88\x15\xf7\x57\x20\x00\x1a\x76\x79\x70\xdd\xe9\x27\x21\xf2\x09\x18\x30\xd2\x1f\xb1\x2b\xed\xa6\xa6\x0d\x05\x66\x4f\xb0\xb7\x33\x27\x6c\x0a\x3e\xc0\x5b\xee\x4f\x51\x7e\x72\xd8\xb2\x3d\x5e\x18\xa4\xeb\x28\xf7\xf7\xea\x5a\x33\x13\x84\xc1\xa8\x43\xb4\xf1\x20\xea\x8d\xf3\x80\xd9\x0f\x4d\x35\xd2\xa7\x84\x50\xde\xe9\xc4\x94\x13\x8d\x15\x0f\xee\x89\x75\xc6\x46\xfe\x29\xef\x23\x1b\xfc\x93\xc5\x7b\x0e\xdd\x05\x07\xc3\x73\x60\x18\xab\xa1\xae\xcc\x7c\x5b\x54\x32\x50\x57\x6d\xa8\x53\xd2\x70\x4b\x35\xf9\x56\xa1\xd7\xda\x48\xb8\xd0\x60\x57\xad\xe4\x4e\x47\x98\x4e\x38\x2f\x1f\xc3\xbc\x5a\x9b\x8d\xe2\x7f\xb0\xe3\xe8\x0c\x81\xeb\xcd\xde\xe0\x3c\xd3\xde\x9a\xcd\xc1\x0a\x10\x62\x2f\xd5\x52\xca\x91\xbb\xde\xd5\xfc\x88\xdd\x8e\xc2\x91\xc8\x60\xb2\xca\x7a\xb2\x54\xb8\x7d\x9b\x9d\x42\x59\x5d\xd6\x6e\xf7\x49\x5f\xa5\x12\x7a\x1a\xe1\x12\xd4\xde\x89\x0f\xd3\x54\xc5\x1a\xd3\x96\x41\x3c\xab\x11\x1a\xbc\x8d\x72\xae\x32\x29\x84\xf5\x49\xf4\xb5\xd8\x28\xee\x21\x07\xa1\x78\x73\x0d\x27\xde\xef\xcd\x51\x97\xa8\xa0\x43\x55\x2b\x56\xcd\xf2\x73\x73\xcb\xac\x4b\xbd\x8f\x0b\x9b\x64\xfa\xde\xcc\xcc\x71\x5b\xfb\x3f\xd8\x44\x27\x86\xaf\x9e\x9a\xed\xc9\x3c\xe0\xed\x7d\x2a\x0c\x63\x58\x11\xe7\xe3\xe4\xa5\x0d\x93\x9b\x72\x2b\x23\xa4\x0c\x5b\xdf\xa8\x54\xe3\xfb\xb4\xd6\x93\x8b\xb1\x80\x80\x63\xf8\xa1\x49\x93\x63\x69\x83\x90\x55\x60\x71\x34\x18\xa2\xf1\x01\x1a\xf8\xdb\x02\x8d\xc4\xea\xdc\x8d\xeb\xa7\x0f\xd3\x60\x8a\xf7\xbd\x4b\xf5\xe1\x4c\x7a\x1a\x1c\x4b\xf0\x87\x31\xcb\x14\xf6\xc9\x9c\x7f\x6e\x9f\x6c\xc9\xe5\x7f\xbe\x55\xd6\xc6\x32\x83\x02\x16\xf8\xf6\xa2\xee\x4f\x39\x35\x58\xf3\x8f\xb0\x06\xe3\xe7\xda\xde\x62\xcf\xe2\x68\xe9\x1c\x44\x41\xa1\xdb\xce\x72\xde\x97\x10\xe4\x3c\xf9\xc2\x9d\x85\x20\x5b\x7f\x05\xf1\xd6\xeb\x6d\x1d\x0f\x26\x9d\x99\x66\xeb\x44\x98\x94\x7b\x61\xa6\xf6\x23\xf5\x1c\x88\xfd\xc0\x39\x1e\x57\x55\x85\xeb\xa2\xa4\x7e\xda\xed\xa2\x59\x21\xb3\x8f\x11\xe6\x8d\xa7\x28\x09\x9e\x4d\x81\xc6\x65\x1d\x6b\x1e\xcb\x20\x7a\x2a\xf8\xe8\xd5\x43\x08\x6d\x34\xb1\xf6\xdc\x3d\xaa\xcc\xd0\xb8\x11\x60\x7c\xfc\x49\xdd\xf2\x5f\x44\x7e\xe5\x7b\xbf\xdd\xf3\x98\xed\x76\x43\x14\xba\x8a\xfb\xa6\x3c\x20\xf7\xdb\xf2\x42\x86\xf5\xdf\xb0\x21\x0d\x01\x21\x0f\x79\xc7\x86\xcb\xb7\x33\x6a\x6f\x24\xac\x41\xbf\x7f\xc7\xb0\x21\x5d\x3e\xcf\x5f\x51\x3d\x9a\xf8\x8e\xf8\xc1\x4f\x8f\xb9\x47\x08\x1b\x13\xf4\x8b\x58\xa0\x31\x73\xcb\xbf\x99\x79\x8d\x52\xb8\x2e\x3a\x48\x71\x84\xae\x51\x6e\x02\x98\x76\xbb\x6d\xad\x5d\x0e\xed\xc2\x62\xcf\x27\xc3\x59\x1d\x27\x7a\x4a\xc4\x44\x4f\xed\xbd\xd9\x5e\xc4\xb2\x14\xd7\x1d\xba\x69\x46\x84\x4f\xfb\x9f\xe4\xa1\x5d\x64\xbc\xa3\x7c\x74\xd3\x49\x9d\x7c\xb1\x2e\xe5\x3d\x77\xda\x3a\xff\x42\xb6\x95\xc1\xf6\x2d\x05\x9e\x36\x15\x1c\xe7\x0c\x9e\x24\xc7\x96\xe6\xa5\x05\xaf\x26\x86\x26\x2d\xb9\xbd\xb8\x45\xc6\x75\xc4\xd6\xe3\x6d\x06\x0b\xed\xd3\x6d\xba\xa8\x99\xa1\x8b\xe4\x28\xf6\xdd\xc8\xea\x6e\x64\x75\x37\x32\xd7\x0d\xce\x11\x74\x40\x20\x6c\x6a\xf0\xb7\xe3\x7f\x56\x58\xf8\xc4\x56\xff\x67\x22\x44\xe0\xb6\xbf\xc7\xf6\x07\x4c\x60\x73\x93\xb5\xbd\x83\x3a\x67\x31\x33\xc2\xd2\x2d\x2d\x4f\x36\x7c\x5f\x57\x51\x07\x10\xb6\xb4\xf9\x2b\xaa\xd8\x1b\x17\xff\x32\xfd\x8d\x99\x77\x9e\xd5\x09\xff\x64\xf8\x85\x5c\xd5\xaf\x39\xaf\xe3\xd9\xcd\x81\x7b\xee\x5b\xd6\x79\x60\x7e\xf0\x82\x37\x07\x11\x7b\xb5\x9b\xdd\x10\x0f\xfa\x67\xb1\xee\x91\x01\x42\x67\x75\x50\x02\x88\xa3\x76\x76\xa3\xcf\x39\xc2\x6b\xbe\x77\x27\xb1\xfd\xac\x07\xa7\x18\x8e\x7e\xd2\x1d\xe0\x15\x27\xdb\x82\x0b\x46\xcb\x54\x93\x6b\x8d\xcd\xda\xfd\x4e\xfc\x73\x43\x73\x78\x3f\xb3\x29\xaf\x37\xda\x27\xf5\xb4\xe9\xc5\x10\xb9\x92\x41\x4e\xac\xcf\x49\x72\x81\xae\x06\xe3\xe4\xe2\x4c\x9f\xe9\xb4\x97\x5c\x9c\xc5\x3d\xff\x41\x6f\xe0\xbf\xf9\x7a\x33\xe3\x99\xab\xbe\x69\xa0\x4e\xb5\x83\x34\x59\xdd\x41\xd3\x4a\x90\xdd\x6e\xe6\x4c\xa7\xa6\x1d\xf3\xd5\xd0\x7e\x55\x77\xee\x9f\x1b\xb3\xab\xfa\x86\x5a\x63\xb1\xe9\xbd\xb8\x69\xec\x4c\x37\x3d\x0c\xcb\x1c\xb6\xe7\x87\xd6\x34\x79\x16\x40\xe4\x9f\x1b\x2e\xc2\x46\xc3\x66\x5d\x4e\xd8\x68\x7b\x94\x41\x91\xc3\x56\x0f\x46\xda\x1e\xed\x3b\x2e\x20\x04\xe3\xa0\x89\x33\xa3\xcf\x5e\x69\xe4\x9b\xf7\xf9\x35\x26\x34\xb9\xd0\xb6\xcf\x87\xb1\xd5\x55\xcc\xf4\x99\x0e\xe6\xee\x9b\xfb\xb5\x4c\x3d\xc6\x8e\xfb\xe9\x01\x7e\x0e\x50\xdd\xa0\x2f\x0b\x68\x3d\x1e\xa4\x83\xde\x01\x5a\x36\xad\xfb\xc2\x73\x6e\x23\xdc\xeb\xab\xe4\xc2\x8c\x7d\xaf\x81\x21\x4c\x13\x02\x40\x0c\xf7\xeb\xf3\xb9\x35\xa2\xf1\xd2\xe2\xd9\x35\x19\x8c\x75\xda\x8b\x1b\x67\xd6\x41\x2f\x1c\x97\xc1\x2f\x57\x36\x2c\xe2\xe7\x29\xe8\xa6\x2f\xd6\xcc\x4f\x03\xae\x76\xc5\xe9\x7e\xba\x9f\x37\xd4\x6d\xa0\x59\x50\xa5\x2d\x5a\xfb\x71\x2f\x0c\x1b\x9a\xf4\x9f\x5e\xe0\xe4\x51\x03\xc9\xc3\x72\xeb\x83\x72\x16\x8c\xb6\x64\x48\xda\x92\xc1\x60\x78\x51\x73\x7a\x7b\xe0\x5d\x70\x03\x34\xcc\x70\xf2\xf8\xc2\x74\xb9\x9b\x5c\x9c\xad\xb9\x05\xa4\x4b\xad\x5c\xed\x5f\xd1\xac\x75\xd3\xf3\x20\x79\xda\x1f\x5c\x5c\xd6\x4a\xb8\x33\x7d\x16\xc7\xac\x6b\x00\xd6\x63\xee\xab\xd7\x1b\xfd\xf9\xcf\xea\xa5\xe0\x3f\xed\x32\xd4\x1d\x54\xcd\x80\xfc\xe7\x2e\x1a\xe2\xde\xc7\x7e\x12\x6c\xe3\x83\x6e\xcc\xce\xc8\x20\xb9\x18\x5e\x20\xdb\x8b\xb3\xe4\xa2\xbd\x66\x0e\x0a\x99\xf6\x86\xcd\x18\xe5\x46\x64\x6e\x15\xad\x78\xe2\x87\x00\xa9\x66\x6a\xeb\x19\x71\x49\xc1\xb8\x9e\x26\x17\x4f\x86\x17\x98\x93\x61\xf2\xb4\x06\xb7\xbe\x1a\x9c\xf3\x31\x83\xb5\xab\xaf\x86\xf0\x0c\x43\x4e\x2e\xce\xb9\x69\x3d\x79\x7a\x61\x32\xcc\xab\xcb\x1a\x26\x43\x9f\xf7\xec\xd1\xd3\x8b\xd4\xa7\x3e\x69\x92\x2f\x1f\x3f\x7a\x7a\x11\xc2\xa8\xee\xb5\x9f\x56\xd7\x77\x3f\x20\x33\x9f\x80\x90\x07\x63\xb2\x2b\xa6\x9b\x5c\x54\xf8\x9e\x93\x28\xb8\x5e\x2e\xc2\x33\x4e\xb6\x33\x29\x0b\x46\x45\x5a\xef\x2c\xfc\x3a\xb9\x18\x1b\x09\x05\xe2\x77\x1c\x84\x51\x8c\xf5\x6e\x77\x0f\x17\xa9\x8b\x04\xbc\xac\x3a\x9d\x5f\x0c\x77\x79\xdf\xc4\x8f\x94\x9d\x8e\xb4\x79\x63\x99\xac\xf8\x3d\x04\x97\x0c\xef\x25\x49\x59\x85\xed\xa5\x19\x4d\xb3\xba\x1b\xb3\x9e\x46\x67\xdc\xeb\x2e\x6f\x78\x3b\x44\xf6\xbe\xc7\x2a\x9b\xf0\xe9\x48\x90\x9f\x59\x0c\x57\xe2\x41\x40\x15\xb3\x7b\xcb\xd5\xb4\xf1\xab\xb0\xb9\x26\x11\x4b\x2c\xa6\x68\x64\xef\x7a\xa1\x99\x0e\x23\x13\xdf\xcc\x0d\xd7\x35\x17\xbb\xdd\x8c\x3b\xc9\x6e\xb7\x73\x76\x13\xe5\x02\x50\xdf\x30\x0a\x01\x8f\x57\xa6\x84\x7d\x9e\xee\x76\x2b\x9e\xd8\xcd\xd5\x15\x02\x9d\x1f\x09\x94\x91\x2f\xa8\x66\x89\x90\x77\x31\x84\x5e\xcc\x19\x48\x08\xfd\xfa\xba\xae\x7c\x63\x43\x61\xb8\xeb\x7b\xb4\xd4\xb4\x08\x3f\xd7\x89\x2f\xe1\xbf\x28\xa4\x5c\x93\xd3\x53\x9d\x98\x07\x97\x66\x55\x4f\xee\x0a\xa1\xc4\xf0\x2d\xeb\xfa\x12\x30\x33\x76\xa2\x7c\x41\x49\x44\x53\x68\xc5\x15\x53\x9e\x2b\xb3\x20\xd9\xbf\xea\xca\xa6\x56\xa1\x99\x33\x50\x48\xb9\xab\xa4\x84\x2f\x87\xb6\x22\xb9\x11\x52\xf3\xf9\x43\x7c\x3a\x68\x3c\xeb\x84\xef\xe2\x44\xd8\xde\xc1\xd5\x09\x3d\xe1\xe0\x85\xa9\x29\xe1\x07\xda\x53\x23\x9f\x41\x38\x0e\x32\x42\xb8\xd4\xba\x5f\x8a\x03\x10\x21\x53\x1c\x60\xd8\x25\xca\x3c\xb7\x81\x05\x99\x0d\xc2\xb0\x00\x61\x4c\x1e\x40\xaa\x85\x30\x6c\x8a\xaa\x2a\xa3\x22\x63\xc5\x5e\x0c\xe6\x91\xf6\x63\xb6\x91\x6a\x78\xf6\x31\x98\x6a\x84\x75\x83\x63\x03\xf3\xd2\x00\x05\x55\x50\x38\x14\x9b\x20\x78\x34\xd1\x3d\xe6\xe1\x21\x08\x6b\x86\x8d\xa5\x79\x33\x50\xc3\x60\x5a\x87\xbe\x51\x30\xb2\x9b\x41\x95\xe6\x49\xdb\x63\xc5\x85\x3d\xa2\xef\x9b\x56\xa7\x84\x94\x9d\x4e\x4c\x77\x3b\x7e\x25\x10\x3e\xad\xb3\x50\xed\xfb\xe9\x27\x46\x4e\x49\x69\x3d\xf7\x58\xd3\xdb\x3e\x1a\xf1\xab\xfe\xb8\x55\x4a\xa5\x71\x41\xf8\xb9\xf8\x72\x88\x0b\x42\x3b\x9d\xe2\x7a\x30\x1e\xf6\x8a\xb4\x00\x1f\x11\xb7\x4a\x9a\x13\x85\x03\x1c\xa8\xe9\x0b\xd8\xb9\xc3\xda\xcc\x78\x44\xac\x70\x69\xf2\xaa\x3b\xca\xf7\x83\x5d\x37\x88\x6a\x04\x93\x36\xe6\x4e\x9a\x4b\x41\x04\xbb\x3b\x79\x63\xd3\x1b\xe5\x9f\x76\x26\xee\x92\xa9\x94\xe1\x92\xfd\x27\xe5\xe0\x0c\x5f\xf9\x01\x86\x93\x30\x8e\x4a\xa6\xa2\x34\x2a\xd9\x7f\x22\xcc\x0f\xda\xfe\xb4\x57\xba\xee\x76\xc1\x21\x78\xc2\xa6\x31\xaa\x6a\xbf\x8d\x3a\x94\x7f\x84\xb7\xb0\xec\x9d\x6e\x07\xfb\x79\x4d\x07\xec\x11\xb6\xe0\x4a\xa3\x90\x6f\x8d\xf0\x5c\xf8\xc2\x66\xb2\xfd\xb3\x99\x6e\xff\xac\x65\xfd\xf4\xb0\x66\xfe\x40\x9e\x5f\x71\x0f\xed\xfb\x56\xee\x75\x73\xb1\x00\x1a\xdd\xeb\x26\xae\x7a\xab\x97\x4d\x14\xef\xfd\xe8\xdc\x78\x2f\x4a\x78\x24\xc5\x9b\x52\x2e\x4a\xa6\x6c\x1c\xf0\x4e\x27\x92\xe2\x6b\xb9\x5a\x1b\x59\xd8\xa7\xcc\x05\x3c\x55\x08\x1f\x80\xc4\x86\x17\x29\x64\xa9\x52\xab\x1f\x8b\xe0\x2d\xc2\xeb\x3a\x54\x7a\x3a\xf1\x69\x51\x10\x20\xdf\xbc\xb5\x03\xec\x47\x53\xbf\x95\xd4\x75\xb9\xeb\x98\xda\x95\xdd\x47\x38\x7a\xa8\x2b\xb3\x07\x90\x71\x64\xc3\x01\x45\x38\xd2\x4c\x28\x03\x05\x88\x61\x72\x1c\x42\xaa\x05\xa2\x00\x72\xc1\x08\x61\x77\xe5\xbe\xb4\x5d\x6b\xe9\xb6\x2e\x9a\x6e\xeb\xc9\x7f\xdc\xef\x57\x95\x17\x98\x8f\x96\x30\xf9\x6a\x29\xef\x82\x5c\x95\xd6\x60\x03\xc4\x68\xed\xe6\x15\xbe\xb5\xa7\x4c\x3c\x1c\xdc\xce\x1e\xe1\xb0\xca\x0a\x2f\x79\xce\x8e\xd7\xa9\xe5\x5f\xad\xd1\xa3\xad\xdd\xfb\x00\x61\x8d\xc8\xb0\xd3\x55\x05\x91\xdc\x61\x03\xbf\x3d\xd8\xc0\xfd\x45\x91\xa0\x2a\x21\x3a\xd8\xae\xec\x3c\x79\x7b\x80\xbf\xac\xc2\xfb\xea\xd8\xe8\x17\xde\x71\xc7\xdf\x6d\xb3\x7f\x6f\x0c\x23\xfb\xf5\x79\xcb\xe9\x82\xe9\xe0\x7e\x98\x1f\xe9\x8a\xa9\x58\x07\xba\x1e\x1e\x28\x98\xb4\x61\x2b\x6c\x03\xe2\xe0\xd6\x9f\x6d\xb5\x7f\x18\xe0\x81\x23\xe9\xf5\x43\xa3\xf8\x43\x2c\x92\xa6\x79\xd4\xe9\x84\xaf\xbb\xdd\x84\x4f\xf7\x34\x4c\xda\xfa\x2a\xd9\xdb\x53\x34\xda\xed\x98\xd3\xa0\x4b\x64\x0d\x2a\xd5\x8d\x9d\x29\xe6\xce\x9f\xee\x3b\x59\x3a\xff\x0b\x2c\xf6\x42\x56\x84\x81\xee\x9c\x2f\x7e\xed\x83\xd4\x8a\x4d\x03\x17\x8a\x35\xfe\x49\x84\xa1\x11\x4f\xbe\xb0\x67\x5e\x61\x6f\xf3\x19\xfc\xd0\x99\x82\xe3\xad\x2b\x69\x88\xc4\x17\x21\x4e\x55\x81\xf2\x99\xdb\xd8\x11\x2d\x0d\xd2\x64\x5a\x03\xd5\xe1\x04\xdc\xbf\xf2\xbc\xae\xa2\x15\x91\x3c\xe8\xd1\x71\x45\xf1\x64\x8a\xc5\xa7\xee\x34\xb2\xd6\x2d\x11\x1a\xb4\x1a\x0b\xc0\x44\x4c\xd8\x74\x3a\x02\x96\xd5\xb3\x40\x9d\x8e\x8f\x54\x9d\xd8\x1d\xa9\xf6\xa3\x74\x5b\x4c\x02\xd7\x7c\xa1\x2a\x70\xeb\x0a\x06\x6f\x98\x5d\xbd\x64\x22\x8e\x63\xbb\x0b\xd5\x10\xac\x10\xb6\x69\x36\x10\xce\xe1\x98\x0f\x6e\xea\x0c\xb1\x19\x0b\x33\x4c\x49\x74\xd8\x98\x55\xd7\x35\xef\xa0\xb1\x53\x7b\xa0\xc0\x94\x34\xcc\x89\x0d\x40\x02\xd0\x29\x49\x73\x82\x78\x54\x5e\x93\xfe\xa8\xd7\x2b\x7d\x07\x0a\xa2\x26\x25\x2c\x85\xe8\x8b\x88\x10\x52\x34\x97\x0e\x35\xd7\x49\x99\x5c\x37\x3c\x28\x63\x38\x40\x00\x5d\x92\x24\x8e\x83\x3c\x44\x5f\xd8\xa6\xe0\xfb\xaa\x8e\x9a\x3c\x29\xac\x13\xdb\x92\x48\xf3\x68\xd3\x73\xc2\xcd\xda\x8d\x0b\xc0\x9d\x25\x60\x75\xde\xe9\x2c\xeb\x99\x42\xdb\xa5\x77\x7f\xc8\x71\x86\x69\x50\xf3\x32\xf1\x8c\x5b\x95\x77\x3a\x79\xcd\x24\x8e\x63\xd3\x00\x59\x02\xad\xb9\xe1\x71\x8e\x35\x2e\x70\x66\x38\x40\xe8\xf8\x12\xa1\x54\x9b\x12\x59\xed\x4b\x1c\xb0\xbf\xd0\x05\x50\x8d\xec\x4d\x4e\x78\x47\x92\xbd\xa3\xaf\xbd\x5a\x02\x0d\x2f\xff\x14\xc6\x07\x66\xa3\x13\x5e\x1f\x23\xa4\x36\x02\x53\x43\x38\x31\x07\xdf\x37\xbf\xe9\x37\x06\xae\x3b\x7e\xc4\x1e\xe3\x66\x07\x0e\xe8\xc0\x55\xaf\xf6\xf4\x3b\x96\xa4\x09\x25\x62\x38\xb5\x31\x83\xa3\xc2\x61\x22\xbd\x37\x89\xde\x90\x65\xdd\x19\xc4\x58\xa5\x12\x33\x91\xa7\x62\x2c\xd3\xf0\xa6\xcc\x57\xfc\xc8\x92\xd4\xc9\x4d\x7d\x08\xb2\x75\xfa\xd1\xc5\x80\xf3\xc7\x51\xad\x3f\xb1\x38\x38\xba\xe2\xee\xbb\x98\x48\x77\x26\x12\x1d\x39\x6d\xf5\x91\x1f\x0a\x87\x16\xf5\xb1\x22\x91\xd9\xa8\x6c\x48\x52\x91\xac\x64\xee\xa2\xb8\x3b\x8f\x6e\x23\xbc\x58\x8b\x1f\xf3\xd7\xbe\xf7\x21\xc0\x80\xeb\x07\xbd\x2a\xeb\xdb\xd4\x0a\xd2\x85\x53\xab\x85\x0d\xbe\x02\x72\x0f\x2d\x8a\x66\x2d\x58\x3b\x78\x46\x74\x02\xc1\xc9\xd4\xa4\x98\xe2\x5f\xe3\x0c\x75\x3a\xb1\xda\xed\x5c\xfc\x96\x17\x3a\x66\x88\x10\xf2\x42\xc7\x19\x82\xd0\x55\x5d\x92\xd5\xf4\x85\x85\xe7\xf8\x3f\x33\x9b\x89\xd2\x34\xfb\xc8\xf2\x1a\x1a\x61\x60\x98\x4e\xa7\x31\xe5\xd8\x82\xc1\x49\xfa\x43\xaf\x02\x50\xd5\xc7\xe6\xc7\xd0\x8e\x9a\xa1\x9e\x70\x93\x6c\x7e\x4c\x72\x70\xa8\xbd\xae\xa1\xd9\x09\x85\xd9\x09\x21\xf2\xd0\x2b\xaa\xb3\x25\x17\x0b\x77\xe0\xd5\xce\x75\x34\xa3\x65\x84\x3c\xe6\xc5\x81\xb5\xcb\x08\x84\x30\xaf\x40\x67\xcc\x46\x78\xdd\xdf\xed\x4e\xcd\xc3\x55\xbf\x3e\x3c\x64\x8b\xd4\xcb\x71\x53\x14\xc1\x31\x6b\xde\x0a\x1e\x05\x56\x56\x8e\x83\xf8\x10\x70\x80\x08\x4b\xc2\x41\xb8\xca\x3e\x2a\x38\xea\xe1\x9e\x81\x5a\x6e\x6d\x04\x89\x54\xe1\x5b\xfb\x40\xdd\x09\xd2\xb2\x22\x02\x17\x44\xd9\x63\xda\x19\xa1\xf6\x61\x79\x10\xab\xc7\xf6\xec\xdf\x5f\x6c\x75\xc2\xf3\x2a\xf9\x62\xcb\xdc\x2f\xb7\xf0\xdf\xed\x38\x28\x15\xaa\x7f\x57\x10\xc3\x49\x20\x08\x06\x1f\xdc\x1e\xb0\xd9\x93\x2e\xf2\x30\x42\x02\xb7\x17\xe2\x6d\x27\xc5\x34\x15\x78\x92\x4d\x53\x55\x11\x3e\xda\x90\xf8\x93\x83\x42\x93\x6c\x4a\xde\xf0\x58\xe2\xa5\x69\x6d\x33\x29\xa7\x44\xe1\x8d\x91\x14\xd7\xe4\x05\x8f\x37\x98\x82\xff\xec\x26\xb9\x71\x9e\xec\x3e\x71\x10\x46\x37\x7e\xbd\x8f\x83\xee\xca\xa6\x63\xc6\x33\x8e\x42\x67\x5f\x23\x11\x05\xa7\x9d\x12\x88\x59\x18\xc6\xe9\x7c\xee\xaa\x76\xb1\xfb\x6f\xe0\x04\x60\xbe\x7f\xb9\x5c\x10\x10\xb5\x1e\x9f\x35\x2f\x06\x18\xcf\x26\x3a\xb1\x53\x97\xf0\x7c\xfa\xc9\x8c\x89\x3b\x18\xed\x0f\xa0\x8e\xbc\xed\xee\x78\x29\xef\xcf\xf5\x1e\x0c\x38\x11\xdc\x20\x10\x39\x0f\x28\x21\x05\x90\x14\x8d\xdf\x72\x7f\x47\x17\x1b\xeb\xf4\x80\x43\xd2\x9e\x19\xfe\xe1\x53\xcc\x70\x9b\x17\xce\xf4\xbd\x75\x3e\x08\xee\xf9\xaa\xf5\x3a\x16\xa9\x0d\x19\x7d\xbd\x0e\x2e\x58\x0b\x90\xdd\xee\x2c\x0b\x77\xa6\xda\xab\x8c\x0c\xea\x91\xfd\xa2\xd6\x6d\xc1\xde\xee\xe5\xf8\x93\xf0\x6a\xae\x9b\xfa\x82\xaf\x81\x57\x55\x51\x4d\xdb\x45\x6c\x68\xbe\x17\x07\xe9\xad\x80\x29\xed\xac\xbc\xa4\x77\xef\x40\xb5\x73\x90\xfc\xb5\xdc\x88\x76\x32\x13\x46\xe0\xb4\xf5\xbc\x5b\xd2\x32\xec\xce\x17\x99\xb5\x3f\xb7\x3e\x70\xc6\x64\xfe\x07\x8b\x51\x15\xbe\xb4\x54\x0a\x98\x41\x9c\xc6\x1a\x12\x23\x1d\x88\x1a\x2e\xac\xe9\x47\xc0\x07\x05\x61\xc0\x6f\x1c\xb1\x25\xef\x78\xcc\x1c\xa6\x60\xb8\x20\x84\xe6\xb9\xbb\x5b\x41\xc5\xc8\x71\x09\xdf\xd9\x08\x03\x6e\x76\xed\x04\xea\x2a\xac\xf2\xb0\x33\x6e\x5b\x6f\x77\xcb\x3b\x3d\xb8\x6d\x33\x46\x58\x92\xe0\xcc\xb8\x8d\x19\xa1\xc7\x2c\x8d\x4a\xfb\x24\x52\x0e\xc7\xf7\xe1\x62\xb8\xef\x5e\x90\xef\x63\xe1\x9f\xf1\x6b\xee\x1c\xe2\x21\xd0\x4b\xf2\x10\x14\x79\x68\x15\x79\xb0\x0e\xf4\x3c\x29\x83\x22\x65\xab\x48\x69\x8a\x14\x10\x14\xc0\xdd\x42\x87\x33\xf3\xe6\x3e\x90\x71\x61\x0f\x0d\x21\xbc\x24\x3c\xb9\x0d\x92\x29\x56\xb8\x34\xf2\xc5\x3d\xc0\xc2\xc5\xac\x30\x8f\x2f\x65\xf9\x5d\x1e\x2b\x84\x79\xf2\x70\x3c\x0f\x5c\x5d\xcb\xe3\x79\x25\x04\x7f\x38\x9e\x97\x99\xbc\xdb\xe3\x79\x4b\xb8\x39\xae\x06\x70\x4b\xf5\x69\x6f\x3c\x34\x48\x5f\xdf\x91\x38\x69\xa6\x74\x5a\xd5\x8b\xec\xc8\x57\x7b\xb1\x0d\x9a\xcf\xa0\xbd\xa0\x03\xfa\xd8\xd7\x96\xc4\x4e\xf4\xb4\x32\xbc\xd3\x6b\xbd\x64\x76\xd8\xfb\x3a\xc3\x16\x0e\xd7\xc1\xa5\xcc\xa6\x6f\x41\x31\xf6\xc8\x9a\xfa\x94\x0a\x88\x58\xec\xc5\x70\xc7\xd6\x3a\xd2\x86\xaa\x9b\x9c\x29\x5d\xca\x87\x03\x15\x5c\xb8\x56\x6a\x5a\xd0\xe9\x64\x2c\x6e\x5e\x61\x05\x82\xe2\xd3\x2d\x97\x4e\xc7\x90\x78\x53\x2b\xd5\xf4\xeb\x25\xcb\x3e\x1e\x43\xfd\x16\x82\x1b\x81\xd6\x5e\xf0\x13\xdb\x07\x50\xf1\xfd\x14\x73\x34\xd6\x8e\x00\x1d\xf3\x2e\xdf\xbb\x5b\xd8\xba\x15\xda\xbb\xc6\xeb\x8b\x94\x47\xc7\x2e\x0e\x63\xe1\xc5\x61\x70\xcf\x2d\x61\x13\x31\xc5\x7c\x22\xa6\x64\x7b\x9f\x2a\xfc\x90\xea\x89\x9a\x56\x81\x24\xcb\x51\xea\xfa\x62\x45\xf7\x58\x7b\x70\xc4\x06\x1e\x1e\x18\x08\x9b\xd1\x87\xa0\x43\x08\xf3\x4e\xc7\xf5\x95\xab\x6f\xee\x41\xe7\x34\x2b\x58\xcc\x51\xa7\x63\x7e\xe0\xfa\x79\x37\x4e\x8e\xaa\x16\x75\xf9\x33\x0a\x16\x42\x19\x6b\x8f\xb2\xee\xfb\xf7\x0f\x6b\x06\xb7\xc7\xb9\x64\x00\xd0\xb1\x42\xa8\x9a\x6d\x78\x91\xbf\x2e\x7f\x02\xd4\xa8\x9b\x3f\xd4\x56\xb3\x3d\x52\xc5\x5a\x33\xe9\x2e\x75\x3e\x1d\x8c\x58\xbb\x67\xbc\x45\x4d\xfd\xc2\x34\x12\x8d\x63\x95\x4e\x0d\x9f\x0e\x4f\x70\xf7\xcd\x69\xdf\xc0\xb1\xc9\xf6\x99\x40\x97\x4b\xa6\x1e\x44\x16\x74\x12\xcb\x4e\xe7\x6b\x43\xa3\xb8\xe7\x27\x42\xc5\xd1\xa7\x08\xaf\xa3\xfe\x35\xf6\x29\xb3\x44\xe5\x9a\x7d\x0f\xf8\x64\xb7\x4f\xe4\x87\xe8\x76\x23\x93\xaf\xe2\x7d\xf4\x35\x2c\xd5\x28\x50\xa5\xb8\x4b\x65\xdf\x32\x25\x8b\x5b\x56\xc6\x02\xb7\x3c\xe2\xac\x9d\xc0\x6f\xb4\x0d\x73\xef\x52\x2a\x18\xc2\xa1\x4e\x00\x6f\x5b\xec\x2d\xbe\xa9\xa3\xf4\x04\xac\xac\x07\x73\x4a\x0d\x13\x5b\x3a\x26\x36\xbc\xa9\x8a\x80\x18\x6b\x43\xa6\x79\x81\x67\xb7\x13\x89\x0b\xb6\x86\x37\x44\x5f\xf7\x3b\x1d\xe1\x41\x39\xd1\xbd\x81\xd5\x8c\xc1\xb5\xc8\x75\xc7\x51\x5d\x82\x48\x5c\x7f\x6e\x66\x6e\x49\xa4\xf5\x38\x5b\x92\x0f\xb1\x9c\xe8\x29\x1a\x73\x18\x1c\x83\xc5\x69\x00\x17\x83\xd5\x0e\x33\x94\xfe\xd4\x2e\xf1\xba\xe6\x2d\x9a\x22\x2e\xeb\x4d\xc9\x57\xdc\xc8\xff\xad\xdc\xe6\x8a\x6c\x54\x3b\xab\x67\x93\x72\xba\xdb\x6d\x3a\x1d\xf3\x70\x65\x98\xe0\xe0\x72\x2e\x06\x77\x06\x34\xc3\x2b\xba\x7a\x4a\x32\xb2\x34\x62\x5b\x6e\x64\x36\x88\x2c\x9c\x43\x9c\x82\x0d\xc9\xd0\xa8\x19\x5b\x5e\x51\x40\x34\x8e\x97\xa8\x3a\xd2\xa7\xbd\x90\x76\x6e\x52\xa4\x97\x2f\x94\x91\x48\x28\x91\x3e\xfc\x93\x13\x30\x0a\x22\x0d\x76\xfc\x40\x67\xac\x30\x9c\x47\x46\x24\x21\xc4\xc8\x1b\x0d\x3d\x73\x57\xf7\xe5\x78\x83\xe7\x30\x96\x9c\xf4\xf1\x86\x88\x51\x7e\xb5\x19\x75\xbb\x39\x9a\x93\xbc\xcb\xf1\x72\x92\x4f\x09\x5c\x35\x9a\xed\x76\xd2\x82\x2d\x2e\x26\xf3\x29\x9e\x23\x3c\x29\xa7\xa9\x72\x69\xcc\xa6\xd5\x04\x6e\x59\xed\xcd\xcf\xde\x50\xee\xfd\x50\x1e\x5a\x43\x39\xe8\x20\x88\xd7\x78\xe9\xb4\x4c\x7d\x5c\x10\x31\x2a\xaf\x8a\x51\xb7\x5b\xa2\x8c\x94\xa6\x8b\x84\x4d\xb2\x29\xa6\x46\x32\xd9\xde\xa7\xbe\x93\xcb\x49\x7f\x8a\x33\x84\x1f\xea\x2e\x2e\x27\x03\x93\x52\x77\x91\x56\xfb\x08\xf2\x57\xfa\xb8\x05\x46\xe5\x7b\xf6\x90\x52\x08\xc6\xf3\xe0\x5f\x4b\x12\x3d\x44\x15\x69\x31\xbd\xa6\xbb\xfb\x23\x0a\x6f\x77\xb3\x77\xb2\x09\xb8\x8c\xad\xdb\xcd\x50\x4e\xb2\x2e\xc7\x1b\xc2\x26\xf9\x14\x17\x46\xf4\x0a\x46\x54\x68\x23\x58\xc1\x61\xaa\x66\x50\x90\x58\x9a\xc4\x7a\x5c\x45\x05\xa1\x01\x0c\x2e\xee\xf3\x05\x21\xdb\x5e\xaf\xc6\xa9\xe7\x5d\x1c\x01\xfc\xdc\x47\x10\x45\x4a\x4f\x2b\x88\x8f\xfe\x4e\x83\xc7\xc5\xa1\x2d\xd7\xf1\xa1\xf2\x60\xd7\xc7\x0a\x44\x29\x83\xa5\x75\x9c\xab\x8f\x3c\xde\x9a\x1d\x37\x7d\xc5\x63\x01\xb2\xa4\xd5\x7a\xa4\x9e\x61\x56\xfe\x8b\x0a\x2b\xec\x62\x51\x60\x7b\x33\x31\xaf\x3c\xb7\x0c\xf1\xbc\x5e\x96\x72\xe5\x07\xbe\xaf\xc8\xe1\x13\xe6\xda\xb5\x37\x0e\xba\x95\x2d\xc7\x3f\xd2\x1f\x53\x59\x3b\xdf\x8b\x4e\xa7\x96\x0f\xeb\x2f\x04\xc4\x80\x8c\x85\xd3\xc7\x10\x8a\x75\xfb\x0e\x50\xed\xef\x00\xd5\xed\x3b\x40\xb5\xbb\x03\x14\x2b\xf2\x91\x5b\x0a\xb3\x0f\x51\x37\x1c\x5a\x14\x70\xa8\x01\xfd\x4f\xab\x06\xfe\x91\x8b\x57\x74\xff\x6c\xb3\x21\xf0\xc2\x90\xd7\x00\xfc\x60\x41\xb7\xf3\x0e\x5a\x32\x47\x87\x3a\x1d\x0d\x6a\x2d\x4b\x5f\x82\x7b\xfb\x81\x81\x3f\x60\x1e\x71\x41\x20\x20\x65\xc3\xa0\xd5\x13\xc8\xdd\xd4\x07\xd3\x68\x6f\xc0\xce\x08\x04\x5d\xf9\x64\xc4\xbf\x15\xbd\xf7\x99\x3f\x7e\xf3\xf7\xe7\xad\xcc\x0a\xc3\xb7\x4b\x28\x94\x57\x87\xac\x1b\x64\x33\xc8\xe6\x78\xc5\xc5\x0b\xb8\x05\x20\x4f\x85\x49\xf2\x2f\xb2\xb2\x5c\xe2\x4f\x8a\x95\x10\xcf\x58\xc5\x28\x8c\x07\x23\xc6\xec\x93\x3d\x80\xaa\xe5\x98\x7f\xb2\xff\x55\x15\x97\x76\x79\x6f\xf0\x1c\x2f\xf0\x3a\x08\x9e\xde\x70\xf6\x0b\x22\x27\x9b\x29\x9e\x93\x85\x47\x69\xbc\x26\x8b\x49\xe9\x9e\x4f\x7f\x8d\xe7\x68\xb7\x5b\x5e\xaf\x77\xbb\xfc\x6a\x5d\x19\x0a\xb1\x21\xfd\xd1\xe6\xca\x60\xdf\x2a\xb6\xc1\x45\x8e\xe3\x7b\x86\x35\x5e\xe0\x02\xe1\x53\x85\xd0\xa8\xdb\xdd\xb8\x38\xce\xb6\x0e\xda\x1b\x8c\x36\x56\x2d\xbf\x81\x5b\xf6\x57\x31\x42\xdb\x3f\xab\xcb\x29\x22\x7d\x08\x61\x83\x69\xcf\x8b\xc2\x16\x82\x68\xf2\x07\xfc\xdc\x31\x02\x83\xb9\x3f\x57\xfe\x17\xb9\xe6\x1a\x36\xbf\xc6\xaa\x31\xa1\xa8\x40\x63\x6b\x7d\x78\x5f\xdf\xb2\x72\x5e\xc8\xbb\x38\x38\x74\xe8\xb7\xbd\xe7\xc2\xf6\xf0\x73\x1d\x04\x3e\xcd\xa1\xbc\x61\xca\x1c\x0b\x29\x6b\xdd\x47\x4d\x43\xeb\x40\xaa\xa6\xea\x94\x8f\xa3\xa8\xcb\xeb\x1d\xf6\xa5\x2c\x6d\x53\x72\x62\xa3\xaf\x4d\x51\x1a\x45\xee\x5e\x0b\x61\xca\x8a\x63\x65\x45\x53\xb6\xaa\xbc\x04\xf5\x27\xec\xf1\x88\xb5\x14\x0c\xec\x98\x26\x87\x79\x3b\x86\xde\xed\x22\x77\xfd\x61\x04\xfc\x72\x56\xf0\x75\x6b\xed\x80\x4d\xcb\x46\x15\x6d\x5d\x00\x1e\x1b\x8e\x56\xcb\x35\x28\x12\x5c\xf4\x7d\x52\x47\xd1\xb1\xd7\x97\xcc\x35\x4a\x19\xe1\x44\x10\x49\x5c\x54\x32\xe6\x0e\xae\x72\x7f\x5e\x55\xd8\x50\x12\xb2\xaa\xe2\xef\xe3\xda\xc2\x08\xf7\x86\xe1\x7d\xcd\x67\xcd\x0e\xee\x3b\xf9\x0b\x02\xd6\x08\x70\x14\xbb\x03\x96\xbc\x39\x11\x23\xd7\xa9\x4c\x98\xc8\x5d\xc3\x02\x9e\x67\xfe\xac\xbd\x75\x81\x81\x2e\x08\xfb\x52\x55\xb1\x57\x19\xd4\xfa\x01\xec\xd4\xcd\x01\x3a\x21\x84\xaa\x66\x42\x2a\x88\x2c\x71\x54\x6e\xd2\x36\x02\xa1\x25\x79\x62\x4f\xeb\x22\xeb\x4b\x66\x27\xe0\xa5\x14\x1c\xcd\x35\xe2\x28\x2e\x4d\xf9\x5a\x8d\xb5\xdb\x19\xde\x46\x07\x1a\x2c\xc3\x6f\x39\x9b\x9a\xbd\xa1\xcb\xc6\x8d\x11\x5e\xb4\x30\x14\xd8\x3d\xda\xe0\x17\x0c\x5b\xf7\x17\x9c\x91\x72\x94\x5d\x95\xdd\x02\x78\x8a\xba\xe3\x72\x92\x4d\x47\xda\x99\xbc\xc6\xd4\xdf\xa5\x91\x36\x9f\xa3\xca\x31\x25\xa3\x2c\xbc\x10\x2b\x43\x74\x92\x4d\x83\x52\x0b\xa6\xfd\x25\x14\xa1\x0d\x79\x1c\xd9\xba\xa3\xb4\x46\xbc\x51\x68\xc8\x72\x72\xc2\x51\xa6\x42\x31\x3d\xf6\xf7\xfd\x1b\x19\xe7\x45\x4b\xa4\xf4\x46\x3f\x23\x33\xef\x15\xda\x2b\x01\x80\xe4\xd0\xc5\xe0\x68\xd1\x3e\x83\x02\x93\x73\x20\x67\x82\x42\x58\x5f\x93\x7e\xa7\xa3\xaf\xc4\x41\x17\xf7\x42\x40\x33\x72\x58\x64\xa2\xa7\x23\x05\xa7\x52\x6c\xdb\xa0\x7f\xa8\x35\x8c\xc7\xb5\xfd\x7b\xf6\x3d\xf7\x66\x05\xbe\x18\xae\xcc\xb6\xde\x1f\xa7\x03\x08\x4f\xe9\x63\x53\x5a\xe2\xea\x9d\x77\x4a\x7a\xe7\x1f\x9b\x60\x9e\x2e\x6e\x27\x06\x56\xa9\x9e\x12\xeb\xe8\x13\x99\xba\xa2\x0a\x55\xb1\x68\x49\x92\x20\x02\x21\xec\xd8\xcb\x9c\x88\x16\x21\xc4\x2a\x29\xe9\x1d\x91\x35\x1f\x08\x51\xf5\x0d\x27\x11\x8c\x58\x1c\x1f\xf1\xff\xc3\xf1\x2a\xa6\x6b\x87\xa7\x63\xd1\x39\x3f\x33\x3c\xc5\xb4\x1b\x61\xad\x4d\x6b\xc6\xe9\x8c\x41\x30\x56\xaf\xcd\x90\xcd\xa9\x53\xef\x74\x77\xca\xb0\x02\x73\x1f\xe1\x58\x55\x9f\x45\xce\x7d\xb6\xd9\x15\xde\x2f\x65\xf2\x0e\x15\x26\x09\xcf\xb1\x46\xd5\x67\x10\x3b\x8c\xec\xf6\x57\xea\xdf\xab\x9c\x99\xea\x3f\xf5\x0d\x66\xa4\x01\xe0\xe1\x5a\xf1\xeb\x9a\x10\xc2\x2c\xdf\xd8\xde\x77\x30\x25\x1a\xee\x72\x61\x46\x08\xb5\xb6\x4d\x71\x4c\xeb\xde\xe9\x2c\x75\x6c\x1d\x38\x4a\x6f\x95\x7b\xcb\x63\x43\xb5\xea\xe8\xcb\xa2\xad\x4c\x59\x92\x6c\x0f\x5c\x8d\x4e\x45\x58\x9d\x0a\xd6\x08\xe7\x44\x8e\x27\xba\x1b\x7d\x2b\x6f\xe1\xe6\x84\xa5\xfd\xd5\x38\x8a\xa6\xe9\x04\x7e\x8c\xf0\x7d\xa0\x79\x69\x93\x01\xbc\x44\x78\xbe\xef\xf2\xe6\x16\x94\x9a\xe8\x29\xc2\x0b\x92\x79\xea\xf3\x23\x5d\xd5\xc6\x89\xd8\xb0\x7d\xe0\x92\xd1\x5a\x4e\x1c\x4b\x64\x64\x33\x8f\x57\x8b\xc0\x21\xa6\x7e\x26\x05\x36\x30\xdb\x3b\x36\xf4\x96\xc7\x0b\xeb\xe7\xb8\xa8\xa7\xad\x6d\xe2\x3f\x4a\xd4\xec\x5e\x74\x7c\x8e\x1a\x57\xb3\x60\xaa\x5a\x73\x51\x36\xde\x9f\xa7\x70\x8d\x54\xbd\x69\x37\x7e\x7f\xc1\x2d\x59\xad\x89\x52\x8e\x2c\x28\xa6\xeb\x7e\x1e\x4e\x15\xf8\x90\xc8\x3f\x9b\x06\x85\x46\x70\xa5\x4c\x5b\xeb\x45\x71\x0b\xb8\x10\xe8\x1b\xa1\xda\xf5\xc3\x48\xda\xb7\x3c\x96\xb8\xe8\x74\x8a\xa6\xc3\x0d\xe3\x08\xe9\x37\x75\xe0\xc8\x4e\x27\x3e\x02\xf7\x0c\x21\x0c\xac\xee\xbb\xd0\xf8\xe4\x9c\xc5\xb4\x9f\x33\xd4\x5a\x89\x2d\x3b\x55\xed\x5e\xda\xb6\x5e\x1d\xb1\xe8\xa1\x8a\x8b\xac\xd8\xe4\xec\xc8\x1a\x3f\x65\xbb\xdd\x7b\x0e\x9e\x5c\x81\x46\xff\xa6\x19\xd5\x0b\xae\xcc\x20\x72\xc7\xa9\xd4\xb2\xbb\x97\x7b\xdf\xc3\x6d\x77\xfb\xbe\x23\x7e\x03\x3d\x82\x51\x0c\x0b\x54\xf3\x8e\x66\x0b\xb5\xcf\x7b\x60\x70\xe7\x0f\x3b\x9d\xd3\xf7\x3c\x66\xc8\xef\xe6\x87\xd5\xf9\xdd\xa8\x5d\xe7\x8d\x0a\x58\x07\xdb\x51\xcf\x91\x10\xd1\x76\xe4\xaa\x99\x0c\xd3\xb1\xd1\xa7\x7b\xcd\x5b\xfd\xde\x3a\x84\x4d\x4f\x85\xeb\xdb\xc1\x54\x4a\xb4\xdb\xc9\xca\x9f\x65\x04\x82\x11\x74\xc9\xdb\x34\x82\x8e\x72\xec\x09\x20\x58\xb5\x15\xd3\xff\xc3\x8f\xfa\x40\x79\x4d\x6b\x0e\xc5\x83\xef\x3f\x6d\x22\xf1\xab\x69\x54\xf3\x4c\x41\xf5\x0e\xbc\xad\x8e\x99\xfc\xff\x73\x0d\xd8\x41\xec\x29\xca\x3f\x2b\xae\x84\x5c\x93\x73\x45\x6f\x12\x46\xe2\x9a\x8f\x59\x72\xc3\x85\x62\xa5\xae\xab\xe4\x58\xf4\x38\xd6\x28\x15\x57\xe0\xce\xe8\xe0\x56\xe7\x0b\xcc\x7b\xa2\x39\x10\x50\xab\x49\xc0\xc9\x4f\x9a\x2f\xac\x5e\xac\x8f\x25\xaa\xf6\x2b\x87\xb9\x22\xa7\xfd\x23\x74\xb3\xad\xa4\xb2\x94\x0c\xb6\x35\xe6\xdc\xdc\xbc\x2f\x9b\x0f\x77\xe1\x83\x31\x75\x09\x03\x56\x3e\x74\x7f\xa3\xa3\xb2\xd7\x43\x7a\x52\x4e\x89\x9e\x94\x3d\x36\xb5\xde\x9e\x85\xbd\x2d\x49\x8f\x4a\x08\x90\x5f\x22\x65\x4a\x18\xb2\x25\xf6\x77\xec\x91\xa8\x75\x88\x9d\x4e\x11\xcb\xda\x0c\x81\x45\xd2\x68\xf3\x31\x37\x42\xc0\xa6\x6d\x62\x51\x86\x85\xc3\xb5\x2d\x6e\x2f\xb7\x5e\x76\xd5\x3e\x64\x8f\xb8\x0c\x06\x92\xa7\x21\x7e\xa1\x66\x33\x8c\xf3\xe8\xfa\xe6\x03\xe4\x81\x12\x9d\xb7\xcd\x77\xf6\x3c\xad\x45\x88\xa0\x58\xe5\x2e\x73\x7c\x63\x44\x91\x06\x51\x69\xb9\x80\x08\x27\xcd\xad\x21\xd0\xf4\xfe\x6c\xba\xd5\x5d\x6f\x1b\x21\xbe\xf5\x34\xf0\x3b\xae\x7a\xb9\xae\x6d\x95\xfb\xa3\x3e\xb6\x26\x9a\xbb\x44\x07\x75\x1d\xef\xac\xdf\xc9\xf1\x5a\xfa\x61\xc1\x66\x78\x9f\x68\x12\x6c\xfe\x47\x47\x84\xf7\x47\xde\x1b\xd6\xf5\xfe\x24\x54\xab\x0b\x7b\xdf\xf6\x0f\xbe\x45\x55\xf5\x03\x4f\x1c\x5b\x07\xba\x81\x1f\x78\x02\x47\x91\xcd\x4e\x7c\x84\x07\x05\x9d\xe8\x61\xa1\xfd\x12\xce\x11\xe5\x9b\xb6\x23\x8a\xeb\xd6\x7d\xcb\x8f\xe2\xa1\xf5\x16\x1c\x64\xf9\x94\xb7\x48\xe8\x80\xea\xdc\x12\xb5\x94\x85\xe6\xeb\x37\x2e\x94\x60\xa3\xf4\x33\xbc\xff\x43\xca\xab\x46\x5f\x53\xca\xb5\x8a\xbd\x8b\xfe\x14\x37\x8a\x1b\x5f\xb4\x5a\x52\x65\x15\x30\x35\x2f\xfd\x5c\x5b\x1c\xb8\x47\x9d\x8e\x7f\x7e\x00\xf9\xd1\x56\x77\x4c\xa9\xba\xdf\x55\xef\x48\xd4\xdc\xfc\xc3\x43\x4f\xef\xe3\xe1\x67\x6b\x6f\xef\x4e\x47\x80\x8f\x93\x73\x45\x1d\xc3\xdb\x8d\x96\x70\x25\x81\xbb\x2e\xf4\x9b\xf6\x44\x36\xaf\x6f\xe5\x46\xd7\x67\xaf\x5c\xa3\xdf\x35\xf1\x70\x9a\xb8\xed\x7c\x4f\xea\x6c\x8b\x66\xe0\x3c\xb5\xad\x1a\xc7\xd2\xee\x3f\xde\xbd\xfe\xd1\xc5\x0f\xe7\xf3\x07\xef\x66\x29\xc8\x77\xd6\x93\xb6\x71\xa9\x16\x46\xe4\x83\x06\xbf\x13\xba\x48\xac\x86\xf4\xa5\x2c\x57\xd4\x46\xf5\xc0\xdf\xd9\x60\x2e\xf6\xba\x02\x51\x81\x0a\xc7\x80\x02\x0a\x78\xf6\xed\x25\x27\x5b\xa7\x30\xd6\xe4\xfa\x83\x3d\x7a\x1a\x45\x5d\x8d\xe1\xb6\x56\x9e\x05\x8a\x22\xd0\x23\x38\x48\x47\xfd\x68\x74\x68\x7a\x68\x82\x64\x4a\xb8\xd3\xc9\x79\x88\x12\x0d\xde\x81\xfe\x6a\x89\x41\xb3\x7d\xd5\x6a\xf5\x3a\x26\x38\x9f\xf4\xa7\x56\xdf\x8f\x70\x90\xc8\x6b\xda\xe0\x73\xd1\x28\x66\x57\x03\xd6\x7b\xbc\xdb\xb1\xeb\x01\x1b\x5c\xc0\x35\x60\x24\x52\x19\x67\x42\xf3\x39\xcf\x22\x84\x15\x39\x12\xde\xaf\x56\x80\x5e\x3f\x1a\xb3\xc9\xd0\x55\xd8\x63\x13\x5f\x77\xda\x3c\xf6\x58\xdd\x9f\x51\xd3\x1d\x74\x3d\xe8\x74\xf4\x29\x69\x9d\xf4\x43\x10\x08\x5f\xf7\x5a\x69\xfb\x3e\xf4\x95\x37\x78\xbc\xd1\xcd\x98\x15\xb8\xec\xb4\x61\x61\x36\xd7\xde\xe0\x2c\xa8\x8c\x22\x3c\xec\x23\xdc\x47\xb8\x20\x5b\xe1\x6e\x73\x4f\x25\x5e\x71\xc1\x57\x9b\xd5\xcb\x92\xc2\x40\x5f\xf0\x05\xd7\x2a\x2d\xf1\xca\x86\x5b\xd8\x4f\xdf\x0f\x9c\xe1\x78\xd4\xa2\x45\x1c\xe0\x40\x9c\x72\xd8\x82\x30\x60\xb1\xc0\x05\xaa\x70\x21\x17\xb4\xe4\x7a\xb9\xfa\x6b\xa8\x71\x5e\x1f\x00\x1f\xf4\x71\x30\x98\x37\x06\x07\x1b\xe8\x0c\x6c\x64\xa3\xa1\xfd\xb9\x30\x3f\xe3\x97\x3c\x71\x38\x98\x64\xb4\x28\xec\xad\xc0\xb6\x49\x50\xde\x42\x98\xdc\x9f\x39\xd9\xda\x5e\x6a\x56\xaa\xf4\x25\x0f\x62\x97\x7d\x75\xe0\xfc\xd8\x1a\x1d\x58\x69\x56\xf4\xfe\xbd\x79\xf9\x81\xaf\xb8\x0e\xc2\xdd\xb6\xa2\xa2\xf8\xcf\x6c\x5c\x1e\xeb\xe7\x65\xaa\x80\x48\x16\xc8\x6a\x20\x2d\x46\x9d\xf3\x6e\xcc\xc6\xfd\x74\x60\xe3\xda\xdc\xac\xe8\xfd\x0f\x2e\xa3\x75\x5d\x53\x78\x08\x12\xb8\x28\x89\x20\xd8\x11\xf8\xb9\xae\xe8\x7f\x64\xe9\xc4\xf8\x7c\xfc\xf9\x80\xb1\x9f\x0a\x53\xc9\xbb\x5d\xa4\x27\x7c\x6a\x2b\x03\xfe\xcc\xec\xf5\x3c\x0c\xf2\xca\x50\x0a\x2a\xd2\xda\xea\x44\x89\x9c\xf4\xa7\xb8\x24\x72\xa2\x7a\x83\x29\x2e\xdc\x75\x50\xea\xba\x26\xb0\x6d\x5d\x5a\x70\x8f\x81\xbd\x8a\x68\xd2\x9f\x3a\x43\x83\x0d\x4f\xc0\x78\x11\x0b\x33\xaa\xfe\xa8\xb9\x39\x1b\x6e\xa9\x95\xf6\x7a\xa6\xd8\x75\x4c\x4f\xe4\x14\x61\xd5\xed\x42\x2d\xea\x4c\x4c\x91\xa1\x58\x05\x96\x58\x9d\x0b\x84\x8b\x5a\x4f\xb1\xaf\xcd\xf3\xa8\x76\x7c\xea\x02\x17\x5d\x03\x2d\x3e\x8f\xd9\xd5\xb0\xd1\x75\xdb\xbe\xba\x80\x5c\x83\x11\x07\xa7\x02\x0e\xf1\xd2\x5c\x14\xcb\xde\x60\x7a\xda\xdc\x96\xdc\x5c\xe2\x24\xdc\x74\x79\x5a\x72\xce\xdb\x77\xd0\xd5\xab\x59\xe2\x41\xe3\xdb\xf0\x5a\xc7\xa2\x7d\x0f\x13\x0b\x8f\x70\xe8\x2b\x06\xc7\x11\xeb\x01\xa8\x89\x86\x19\x60\xd7\xb2\x3e\xf2\x59\x1d\x6b\xa1\x8a\x25\x04\x6a\xb1\xd3\xd5\x77\x17\x1a\x62\x5e\xaf\x44\x75\x3d\x18\x87\x97\xac\x96\x3d\x8a\xce\x63\x05\xa1\x1a\x80\xbb\x30\x9d\xfa\x85\x03\xcc\x33\x0c\x01\x7a\xfa\x29\xed\x09\x4c\x11\x76\x77\xc9\x41\x07\x39\x74\xb0\x2e\x08\x37\x46\xc9\x89\xee\x0e\x9a\xb3\x9c\x75\x66\x89\x5d\xa0\x1f\x3b\xc0\xb4\xec\x9a\x99\xac\xf6\x8a\x99\xa4\x7a\xcd\xfe\xc2\x8f\x5d\xb9\xf6\x7d\x2c\x70\xbf\x09\x9a\xcf\x45\xfc\x7d\x2c\xb1\x9f\x5d\xd4\x3c\x85\xbe\x0b\xee\x3a\x7a\x1e\xa0\x22\x07\x0f\xa3\xb8\x24\xb2\x27\x30\x27\xe5\x79\xb0\x18\xcb\x73\x8e\x10\xce\x88\x1a\x65\x57\xfd\x11\x5a\x76\xbb\xd8\xdd\xde\x69\x21\xa6\xba\xcb\x33\xee\xe6\xae\xa1\xd5\x0a\xf7\xd1\xa8\xb8\xa2\xa3\xa2\xdb\x45\xe0\xb2\x12\xe2\x74\x31\x45\xf8\x13\x15\xa1\xfa\xa0\x29\xb8\x0b\x46\xb8\x0e\x5f\x75\xda\x77\xf7\x0d\xa7\xa7\x03\xec\x7c\xee\xcd\xe3\x8c\x2d\xb8\x78\xae\x7f\x63\xa5\x84\x57\xb0\xa5\xa6\x11\xd0\xb2\x08\x2f\x4a\x9a\xb1\xb4\x8f\x17\x25\xcf\xd3\xb0\xae\x82\x0b\x17\x88\x77\x00\x61\xbb\xbf\x82\x03\x94\x26\xc7\xbc\xbd\x16\x5f\xd7\xc1\x8f\x5d\x12\xd0\x43\xf3\x62\x6a\xb6\xd4\x2b\xbd\x84\x17\x5b\x4d\x1d\x52\xb8\xae\x19\x32\xe1\x34\x67\x93\x09\x67\x12\x83\x81\xd8\x73\x9b\x2f\xa8\x5a\x1a\xa2\xd3\xbc\xbd\xb6\x25\xfa\x38\x38\xd8\x99\x0e\x2a\xac\xb9\x0e\x63\x7a\x19\xe6\x95\xdd\x1b\xd6\x04\xb7\xe2\xa8\x3f\xf6\x76\xa7\xc7\x55\x05\xdd\x50\xe9\x76\xc5\xc5\x5b\xbf\x3d\xf6\xcd\x36\x58\xbf\x5d\xf4\xf1\x8a\x97\xa5\x2c\x7d\x7d\xef\x74\x29\x3f\x3a\xf0\xf4\x83\x14\x3b\x98\xa0\xb1\x47\x38\x00\x29\xdd\x68\xf9\xee\xe3\xff\xcd\xde\xbb\x36\xb9\x6d\x63\x8b\xa2\x7f\xa5\x5b\x95\x68\x08\x0b\x62\xab\xbd\xcf\xcc\x3e\x87\x32\xac\xf2\x23\x4e\x9c\x38\x89\x63\x3b\x33\x49\x54\x2a\x1d\x36\x09\xb5\x30\x61\x03\x0a\x09\xb5\xa5\x48\xfc\xef\xb7\xb0\x16\x00\x82\x14\xd5\x76\xf6\xde\xf7\xc3\xad\xba\x5f\xba\x45\x10\x00\xf1\x5c\xef\x87\xd8\x84\xbf\xdf\xfa\x8a\xa0\xad\xf4\xd3\xca\x9c\xc3\xe9\x3f\x45\xdc\x20\x2a\x6b\xd1\x60\x70\xb7\x2a\x93\x43\x4d\x01\x4c\x9b\x1f\x69\x21\x6e\x65\x32\xc8\x6c\xb8\xd0\xac\x54\x55\xf5\x0c\xcb\xd0\x55\xb3\x5a\xab\x8f\xa0\xd4\x7c\x9e\x66\xbf\xe7\xa5\xda\xc0\xea\xda\xdf\x76\xdc\xe5\xed\x4d\x1a\x3d\xfe\xfb\xdf\xe9\x45\xf3\x67\x12\xff\xe7\xdf\xc9\xc0\xd7\x74\xe3\x7d\x6c\x1d\x66\x4b\x05\xb1\xd7\xe0\x30\xc6\xf6\x4c\x79\x0f\x5e\xff\xf3\xb4\xaa\x39\x6f\xed\x9a\xa1\xbb\xef\xd9\xfa\x6d\x9f\xe0\x4f\xb6\x82\xd3\x70\x76\x40\x8d\xb3\xaf\xbb\x4b\x6d\x57\xe8\xb6\xf3\xf3\xa5\x46\xad\x64\xf5\x2f\xa1\xd7\xd1\x00\xa3\x68\x0f\x08\x24\x29\x0c\x5f\xa4\x2b\xb3\x03\x64\x38\x1c\xb8\x3d\x74\x9e\xd1\xc0\x77\x97\xf0\x14\xfa\x59\x6b\xf6\x74\xd0\x1c\x6c\x57\xd9\xac\xe5\xf3\x76\x69\xd7\x45\x19\x0d\x86\xdb\xee\xc9\x38\x13\xef\x11\xfe\x4d\x10\x3a\x0a\x62\x27\xa3\x37\x12\x06\x4e\x36\xbf\x67\x7a\xce\x17\x23\x91\x98\x7f\x63\xd1\x10\x41\x3f\xf4\x7b\x75\x59\xa4\xc5\xad\x5a\xd9\x23\xc9\xca\x42\xcd\x69\xf5\x44\x4d\xab\x11\x93\xce\x85\x4b\xcf\x03\x58\x59\x91\x45\x9f\x23\xd7\xbf\x7b\x42\x9e\x22\x21\x69\x09\x8c\x40\x70\xc4\xa9\x1c\x5f\x13\xc8\x41\x81\x41\x13\x20\x56\x18\x4d\xcd\x33\x97\x39\x3e\x95\xec\x9a\x8f\xff\xe1\x8c\x1e\xd1\x8e\x04\xde\xbc\x52\xa5\x01\x53\x2e\x96\x67\x24\x20\x8f\x20\x50\x91\x33\x0f\x9b\xb3\x71\x45\xd3\x71\x46\x12\x70\x25\xb1\xf9\xfc\x5a\xcd\xaf\xc9\x38\x23\x57\x8f\x93\x28\x1b\xf7\xf4\x6d\x70\xe3\xd5\x63\x9a\x8d\x98\x7a\xc2\x67\x45\x32\x2e\x68\xf6\xa4\x1a\x97\xc7\x63\xf6\x34\x1d\x95\xc4\x67\x47\x0a\xf2\x71\x7c\x21\x42\x7d\x54\xec\xe1\xe9\x0c\x57\xc2\x82\xd3\x20\xf5\xee\xaf\xa2\xf1\xf7\xd5\x2e\x06\xa1\xeb\x78\xe2\x19\xc3\x57\x3c\xc2\xbc\x5c\x98\xef\x17\x32\x12\xb8\x14\x04\x2e\xd6\xce\xaf\x91\x8e\x0d\x08\x23\x33\xfc\xef\xd0\xee\x35\x79\x24\x82\x04\x57\x23\x97\xf9\x26\x48\xb6\xe3\x37\x0e\xed\x7e\x65\x63\x7c\x61\x96\xd6\x06\xe5\xc6\x50\xb9\x97\x4d\x01\xb8\x06\x01\xd7\x65\x38\x6b\x7f\x16\xf5\xcc\xbe\x4f\x9a\x7a\x7a\x86\xaf\x13\x4d\x22\x05\xbc\x35\x4a\x33\x7e\x69\x82\x53\x76\x04\x1b\x9a\x1c\xaa\xed\x86\x97\xce\x0b\x46\xe4\x4c\x83\xb6\xce\x3c\xa0\x47\xcc\x27\x5c\x60\x3a\xbe\x38\xd6\x51\xc7\xaa\x6a\xb0\x1b\xb5\x69\xb5\xb0\xae\x54\x61\x11\xe4\x17\x09\x0b\x30\xcf\x48\x58\x82\x01\x05\xc3\x12\x1b\x7b\xb1\xe5\x22\x83\x69\xe7\x2b\x9f\x34\xc7\xe5\xff\xc0\x6c\x20\x3e\x69\x0e\xd6\x76\x09\xbe\x5b\x5d\xf8\xb4\xde\xad\x52\x7b\x0a\x3e\x74\xa6\x62\x8b\x9f\x9f\xce\xc8\xbe\x79\xd3\x9d\x98\x2d\x7f\x77\xf2\x05\xf0\x02\x6b\xad\x89\x41\x3f\x0e\xa9\xb6\x87\x28\x64\x77\xc8\xed\x55\x28\x53\x79\xcb\x5b\x45\x00\x20\x0c\x58\xc2\x0a\x06\x3f\xbc\x11\x92\xbf\xd6\xfc\x0e\xad\x05\x5d\xdc\x1c\xf3\xd1\xfe\x52\xc3\x87\xb5\x4b\xe1\xe0\xb3\x66\xe9\x2d\x17\xe6\x4b\x0a\x25\x6f\x79\xa5\x3f\xf0\x9d\x7e\x91\x66\x6b\xde\xf8\x62\x35\xb0\xa8\x3d\x70\x07\x93\x3a\xd3\x09\x53\x51\x37\xae\x56\xdb\x8a\x97\xdf\x77\xa7\x0e\x85\x9d\xf5\x59\x56\xdb\x5b\x33\x10\x9e\x9f\x54\x6f\xde\x74\xdb\xc0\x8a\x75\x26\x84\x78\x07\x64\x6c\xbe\x2c\x6b\xcf\x2c\x4f\x75\x0a\x6c\x6e\x05\x53\xce\xcf\xb9\x62\x81\xe3\x55\x57\xc7\x30\xf5\x76\x44\x0c\xc8\x56\xa7\x0c\xe4\x1d\x7b\x78\x34\xdd\x64\x68\x4a\x46\x79\x33\x6b\xa7\x20\x00\xbb\x4a\xe2\xdf\xa4\xbb\xf0\x4d\xba\x43\x7f\xad\x70\xea\xcd\xeb\xb0\xb8\x53\xaf\xd5\x4d\x58\x4c\x42\x23\x7c\x07\x96\xeb\x8e\x39\xa2\x81\x7a\x07\x37\xd2\x44\x53\x37\xb4\x84\xd3\xd6\x58\x12\x41\x5b\xdf\x04\xd7\x54\xb3\x38\xde\x79\xe7\x8f\x48\xd3\x73\xb6\x8a\x84\x72\xf6\x47\xc4\xe9\x39\x63\x47\x42\x05\xfb\x23\x12\x0f\xb4\x97\xec\x8f\x48\x3e\xd0\x1e\xec\x29\xff\x40\xab\xad\xbb\x74\x97\xfc\x01\x3a\xbc\xd0\x32\xf3\x17\xc3\xb4\x06\xc6\x99\xbf\x44\x9c\xd4\xa1\x29\x6b\x67\xd7\x91\x6f\x46\x3b\x4d\x34\xc6\x0c\x7b\xab\xc2\xae\xd2\x1a\x1d\x2c\x5a\x76\x9e\x86\x1b\x1d\x0e\x53\x12\xda\x7b\x62\x3f\x4e\xe6\x59\xb2\xf3\x7e\xc7\x0d\xa7\x5c\xb0\x09\x64\x4c\x71\x94\xca\x93\x0c\x8c\xff\x05\x2b\xe7\xc5\x22\x6e\x52\xce\xc7\xcd\x54\x30\x1b\x2e\x08\x49\x43\x6d\x15\x1c\x3f\x42\xd3\xe3\x31\x52\x2c\x60\xa1\x41\x14\x44\x5a\x96\xa9\x66\xb1\xff\x88\x14\xc8\x4f\x71\x39\x15\xfd\xc3\xca\x6a\xea\x30\x0d\x5c\x3b\xb2\x94\x33\x5a\x34\x60\x5e\x87\xd0\xf6\x78\x44\x68\xaf\x03\x98\x6d\xca\x10\x13\xe8\x16\x00\x36\xe5\x16\x27\xe8\x36\x2c\x3f\x1e\x27\xf0\x75\x20\x2b\x3a\xde\x6b\x00\x19\xea\xc0\x07\xa1\xad\x83\x6c\x5c\xe2\xa6\x61\xab\x26\xb3\x91\x69\xe4\xf4\xe8\xed\x6c\x41\x33\x1d\xef\xb0\xd3\x44\xc7\x7b\xfc\x45\x8e\x47\xed\x1b\xcd\x17\x75\x3b\x1f\xcd\xe1\x73\x81\x90\x6d\x87\x1e\x4b\x11\x39\xfc\x14\xb5\x46\x15\xbe\xa5\xe0\xc1\xb7\x20\x0f\xc4\x33\x03\xad\x62\x5b\xce\x57\x31\x15\x57\xe9\xdd\xa6\xe0\x06\x51\x4c\x65\xdc\xfe\x20\x95\x0d\xba\xd5\xf8\x60\xd1\x2c\xa7\xb2\xc1\xdb\x27\xe1\x53\x3e\x81\xc7\x85\xe9\x18\x91\x1b\x60\x26\x79\x8a\xac\x64\x2f\xba\x93\xa7\xb8\xce\x0d\xf9\x3d\xd7\x2f\xc5\x1d\x86\x3a\xaa\x60\xe4\xd5\x49\x09\xb0\x2d\xa7\x15\x03\x24\x28\xbb\x7b\x6b\x33\x20\x8e\x04\xa6\x3e\x11\xb1\xb3\xeb\x44\x3a\x66\x24\x20\x01\x8a\x70\x96\xa8\xf2\x74\x1b\xc1\xfc\x0c\xc7\xf8\xd2\xbf\x82\xef\xe6\x5c\xf3\xf2\x4e\xc8\x6e\x39\x0c\xb3\x53\x66\xa9\x83\xe7\x3c\x92\xb4\xd9\x44\x90\x6c\x90\xbe\xaf\x32\x48\x40\x65\xbf\xfb\x7c\x2b\x8a\xdc\x5e\x8a\x66\xe5\xe3\x9b\xa0\x18\x4c\x42\xed\xa7\xc3\xea\xde\x0b\xa1\x7a\x22\x5b\x0c\xcb\x54\xc6\xcb\x4c\xc9\x7b\x5e\xe2\x75\xfb\xa0\xec\xc5\x4a\x67\x3f\x88\x48\xba\xf3\x45\x12\xfb\xd3\x7c\x38\xb4\x14\x76\x63\x7b\x91\x16\xd9\xb6\x48\x35\x7f\x13\x52\x4e\x50\x21\x3b\xff\x0a\xc6\x79\xb6\xa9\x72\xcc\x82\x21\xc0\x63\x27\x86\x38\x1e\x07\xe6\xe7\x00\x7c\xc2\x2a\xb5\x2d\x33\xa0\xd0\xdd\x7a\x3c\x17\xb0\xb4\x7e\xb0\xdd\x23\x49\x68\x0a\x1e\x06\xbd\x93\x0e\xda\xe1\xb4\x5e\x09\xb4\xe8\x5b\xd9\xff\x30\xe0\x57\xe1\x83\xbb\x63\x67\xbd\xf8\xa6\xde\x18\x3a\x90\xb3\x5b\xaa\x6a\xaa\xbb\x07\x35\xe2\xd6\x08\xba\x31\x91\x26\x49\xcb\x6c\xda\x1d\x51\x76\x29\x9d\x2f\xab\x23\xe7\x38\x0d\x58\x4b\x26\xcc\x53\x9b\x7c\x93\xd4\xcb\xf1\x99\x18\x43\x75\x90\xc6\x7c\x50\xb6\x42\x33\xc2\x56\x79\xdd\x9a\x6a\x17\x7e\x05\x2f\x3d\xf8\xea\xbd\xcd\xfd\x80\xaf\x55\xc9\x77\xd0\xb9\xf6\xdd\xd0\x86\xdd\x65\x73\x91\xe7\xb5\x87\x74\x2e\x9d\xeb\xc4\xe7\x64\x75\x49\x7b\x92\x28\x08\x3e\xef\x61\x21\xc5\xd4\xb0\x93\x26\xcf\xab\xab\x65\x96\x39\x64\x29\x26\x34\xc4\x6f\xe1\x23\x72\x16\x41\x81\x65\x4e\x26\x75\x1f\xcc\xea\x5d\xc7\xfe\xd5\x58\x66\x69\x51\x7c\xa3\xd4\xef\x27\xa6\x31\x53\x6e\x91\x1e\x06\x0c\x7c\x5b\x6c\x0d\x2c\x37\x78\xa3\x43\xb7\xfe\xd4\x18\xca\xcf\xf5\x82\xce\xb9\xdf\xa5\x10\x46\x79\x9c\xe6\x3e\x37\xe8\xd6\x19\x90\xba\x17\xe2\x1d\xea\x13\x80\x77\xda\x59\xa7\xca\xc0\x0d\x21\x84\x55\xe7\x86\xd0\xd4\x19\x58\x27\xe0\x36\x81\x30\x5f\xd4\x27\x70\xef\xcc\x08\xda\x5d\x41\xef\xe6\xc9\xc2\x81\x17\x00\x1a\x2a\xcc\x09\xd9\x7b\x64\x7b\x2b\xfb\xcd\xba\xe5\x92\x97\xa9\x86\x5a\x16\xb0\xf4\xd9\x33\xb5\x50\x78\xaf\x1b\x8b\x0e\xdd\x58\xe4\x68\x44\x2a\x06\xb9\x8d\x2d\x21\xc3\x7e\x8a\x44\xec\x24\x77\x74\x6e\x45\xae\x54\x52\xbd\xa0\x36\xb8\x18\xa6\x0e\xc2\xc6\x5f\x40\x62\x64\x6c\x4a\xc0\x2b\xdc\xda\xcb\x48\x7a\x4d\xa8\x1a\x8f\xa9\x1c\x8f\x09\xae\xe1\x67\xae\xc6\xf9\xba\x1d\x40\x70\x0e\xc6\xf7\x2f\x6f\x7f\x6d\xdf\xe5\x39\x84\x72\xea\x48\xe1\x42\xcf\x99\xe5\x76\x1a\xd1\x13\x81\x1d\x10\xcc\xae\x17\x43\x95\x56\xa8\x35\x75\x45\x61\x38\x26\xa6\xa6\x28\xc6\x5a\x8a\xca\x12\xf2\x06\xe9\x5e\x06\xb9\x35\xd4\x53\x56\x1d\x8f\xf2\x09\xbb\x3e\x1e\x2f\xbb\x80\xaa\x13\xd1\xae\x2d\x66\x50\x4d\x7a\x43\x0c\x4a\xf5\xc6\xa3\xae\x88\xd0\x9c\xad\x0d\xfc\xe2\x95\xcb\xa4\xb3\x65\xeb\x78\x2d\x6e\xd7\xa6\xc4\x66\xff\x58\xb1\x1f\x74\xe4\x7c\xc6\xa1\xd6\x38\xa7\x13\xda\x00\x45\x32\x4d\x99\xcb\xbe\x32\x6b\x8a\xaf\x64\xb2\xba\x8a\x40\x5c\x99\x8f\xfe\xf1\x14\x13\xab\x43\x49\xe4\x6b\xc7\x7f\x4f\xae\x41\x8b\x1f\xc0\xcc\xf1\x17\x22\x42\x81\x37\x19\xfb\xac\xbc\xe3\x5f\x4d\x21\xc8\xb3\x5d\x1e\x38\xbf\xbf\x2b\x25\xc1\xcb\xaf\x89\x49\x9e\x3f\xca\x47\xdb\x47\x5b\x42\x33\xf6\x5a\x37\xfa\x62\xb4\x1c\xa8\xdc\x2f\x53\x14\x75\xa7\x3b\xfa\x07\xb9\x4a\xa9\x19\x54\x4f\xed\xf2\xaa\x30\xaf\xc6\xcd\xab\xed\x15\x18\x3d\x67\x21\x4f\xe4\xab\x57\x34\x23\xe0\x22\xd9\xde\x92\xac\x7e\x90\x44\xe9\xbd\x0f\x9f\x38\xbd\x01\x61\xd1\x7f\xfa\x5f\x09\xed\x2b\xaf\x4e\xa2\xcd\x52\xce\x6c\x96\xb9\x89\x4b\xfe\x32\xa9\xa9\x0f\x2b\xe5\x8c\x54\x0f\xa8\x29\x92\x56\xcb\xa4\x50\x6b\x56\xd5\xe8\x0c\xdd\x3e\xbf\xb0\xa7\xed\x73\x6a\x4e\x79\xea\x3e\x9c\xb2\x5f\x05\xf0\x8f\xad\x5d\x04\xf3\xee\x59\xc4\x4f\x11\xaf\xcb\xf1\xc2\xbe\x10\x51\x45\x46\xa9\x21\x60\xfa\x10\xae\x6b\xea\xaa\x19\x5a\xda\x11\x7c\xed\x5b\xea\x0c\xb3\x56\xa2\xac\xcc\x2c\x8b\xb4\xd2\x89\xa2\x78\x1d\x92\x8a\xda\x73\x61\x38\xf4\x9e\x9b\x53\xb0\xc7\x8f\xa4\x3b\x9d\x34\x63\x5f\xe9\xee\xd5\x23\x74\xcd\x7c\xb6\x81\xcc\xdc\x35\x9f\xa0\x20\xb3\x3e\x05\x5e\xbd\x20\x63\x54\xb0\xcd\x26\x49\xfe\xc8\x8a\x46\x47\xeb\x47\x2e\x69\xf6\xd4\x4f\x35\x74\xb4\x0d\xe6\xec\x38\x8e\x51\x41\xea\x20\xd9\x4d\xab\xe3\xb5\xef\x38\x0f\x3b\xc6\xe5\x6a\xf7\xeb\x96\xdc\xf2\x37\xa6\x57\xf0\x16\xb3\x67\xd0\x71\xf0\x82\x2a\x9a\xd3\x35\xa9\xcd\xdb\x75\x2a\xf3\x82\x7f\x8f\x6c\x9f\xd9\xff\x90\x7e\xf2\xf4\xa1\x05\x20\xda\x33\x88\x40\x4f\x85\xcf\xa5\xa5\x9b\x9a\x6c\x9f\x2e\xcd\xa7\xee\xe4\xa0\x09\x08\xae\xa6\x7f\x2c\x0a\x3b\xd4\x6a\x13\x3e\xda\x24\xd8\xf5\xe9\x74\x4e\xa3\xe9\x41\xd4\x09\xab\x1e\x45\x0d\x63\xe5\x55\x9b\x69\x4d\x5d\xbe\xe0\xa4\xac\x1b\xdf\x03\x5a\x30\x48\x64\xd5\x3e\x0c\x34\x63\xa0\x7f\xc2\xd0\xd4\x18\xc4\x08\x03\x21\x98\x93\xd0\x4d\x32\xec\x86\x50\xa2\xef\x41\x4b\xbf\x32\x21\x63\x9b\x8f\x75\xcd\x94\xcd\xf1\x7d\x5a\x4b\xb5\x8e\xfa\xf8\xda\xc6\x4f\x80\xa8\x09\x93\x69\x31\xcb\x66\x51\xce\xe4\xa3\x06\xec\x8b\x47\xc1\x4a\xe7\x4c\x3c\xf2\xf0\x7f\xcb\xe4\x23\xee\xa8\xdc\x01\x70\x06\x66\xf4\xd5\x6c\xeb\x76\x22\x19\x70\x99\x63\x59\xee\x08\x62\xd3\x89\xcb\xc2\xf4\x98\xfa\xaa\x57\x8f\x0d\x0b\x16\x12\xbe\x1e\x70\x46\xf9\xb8\x1c\xa5\xe4\x91\x72\xb9\x9b\xec\x8f\x71\x09\xd6\x5b\xaa\x4d\x0f\x37\xcd\xb6\xe3\x75\x6f\xb3\xb5\x69\x86\xb7\xc1\xd9\xaf\xe1\x8c\xae\x1e\x03\xc6\x76\x0f\xd3\x70\x4e\xde\x28\xc8\xad\x85\x9f\x1a\x98\xa9\xb9\x2e\xa8\x64\xe1\x90\x0c\xc5\x2e\x46\x69\x53\x60\x49\x74\x39\x4a\xeb\xba\x7b\x33\x4e\x02\xaa\xdb\x93\x89\x31\x75\xc2\x6b\x11\xba\xcf\x07\x4b\x46\x3b\xd5\x08\x6d\x9f\xf6\x9e\x66\x1f\xd4\xa6\x53\xa9\xd5\xa8\x6c\x2f\x69\x9b\xf5\x38\xa9\xd8\x6a\x6a\xd9\x9a\xd3\xb6\x36\x8b\xec\xe9\xcd\xb3\xd4\x60\x2f\xb2\x72\x6f\x3c\xae\x6a\xdf\x0b\x0b\xb1\xcd\xb5\x49\x74\x73\xfd\xb8\x35\xaa\x75\x71\x7e\xad\x41\x5d\xa0\xef\xb5\x39\x71\xed\x13\x86\x10\xab\x45\xf5\xca\x26\xf8\xed\xc8\x03\x3d\x4a\xb2\xaf\xeb\x7e\xc6\xfe\x94\x69\x7a\x90\xea\x07\xe6\xa9\x87\x88\xa7\xfc\x01\x92\x37\x22\x75\x17\xf5\xf4\x08\x02\x00\x02\xfa\x2a\x68\xdf\x7b\xd6\x80\x2f\x14\xea\xa1\x91\xac\xc5\x8b\x53\xe1\xa3\x05\x0f\x87\x91\x64\x3f\x08\xf0\x53\x80\xed\x0e\x04\x1e\xe8\x4c\xac\xee\x36\x5b\x4b\x8d\xe0\xb8\x24\x95\xde\x92\xdb\xdb\x5c\xf5\xd4\x0b\xc3\x56\xea\x5d\x22\xe8\x89\x56\xc9\xe9\x07\xa8\x62\x60\x68\x67\xcd\xf6\x2c\xb5\x8c\xf1\x48\x30\x6c\x01\xbd\xa3\x3b\x36\xa1\x37\x56\xfb\x9e\xb2\xc9\x34\x05\x5b\x34\x0c\x5d\x9a\x31\x3d\x4f\x2d\x73\x42\xd7\xac\xe5\x94\x63\x56\xfb\x95\x6a\x9c\x0a\x21\xce\x9a\xa1\x41\x98\xa1\x89\xd1\x92\xd8\x80\xbe\x79\xbe\x80\x3f\xc7\xe3\x01\xe2\x0d\x1d\x6a\x7a\x9b\x25\xf3\x45\x4d\x57\x6c\x1d\xa8\x87\xe9\x2d\x33\x5c\xfb\x17\x51\x46\x8e\xc7\x5f\xa3\x8c\xc0\x08\xe0\x47\x13\x0c\x26\x73\xbc\x97\x8b\x09\x73\x07\xb1\x7a\xe8\x17\xd1\x1d\xb4\x32\x7f\xa3\x5b\xf6\xab\x8e\x04\xdd\xa2\x53\xc7\x36\xbe\xcd\xe8\x2d\xbd\x23\x74\x33\x62\x2b\x84\x67\x17\xbd\x55\x32\x42\x37\x6c\x35\x55\x68\x78\x70\x0b\x5e\xb1\xe6\xd7\x86\xd0\x20\x10\xc7\x2d\xdd\x11\x7a\xd3\x3c\x6f\xe8\x0d\xa9\x3b\xd9\xbc\xbf\x8d\x5a\x39\x17\xcd\x09\xba\xcd\xc0\xee\xd3\xda\x3f\x3c\x46\x13\x65\x88\x23\xfb\xd4\x86\x90\x45\x63\x45\x09\xf1\x6b\x6d\x84\x49\x14\x9a\xcf\xc5\x5c\x2d\x16\x53\xe1\x38\xc3\x09\x95\x98\x2d\x36\x92\x4d\xfc\xa2\x25\xb3\xa1\x52\x7e\x5c\x45\x3b\x42\xf7\xac\xf2\x8f\x37\x84\xde\x33\xcd\x9e\x46\x96\x44\x55\x73\xbd\x30\x1c\x95\x25\x54\x2b\x7c\xac\x9b\x3c\xf7\x40\xcf\xdd\x47\x13\x82\x24\xdd\x7d\xc4\x0d\x0f\x62\xe9\xba\xfb\x68\x49\x3c\x69\x77\x1f\xed\x09\x66\x37\xac\x12\x65\x3b\xac\x0c\x41\x7b\x12\x01\x41\xb7\xd5\x60\x0e\xd7\xda\x97\x81\x96\xec\x87\xf4\x07\x53\x01\x5e\xbc\x52\x25\x54\x04\xbf\xfc\x2e\x86\xee\x86\x7a\xc0\x2b\xe8\xd3\xeb\x4c\x8e\x47\xfd\x94\x7b\xfc\x3d\x93\xdb\xa2\x48\xbc\xeb\x40\xeb\xf3\x7c\xae\x9d\x75\x77\xf8\x95\x97\x3c\x13\x77\x69\xd1\x03\xa6\xda\x02\x3c\x83\x77\xd8\xf5\x58\x93\x20\x4f\x61\x20\x00\x1c\xe9\x47\xdc\xd1\x57\x6e\x78\xff\xd6\x90\x6e\x23\x94\xe6\xcd\x7e\x31\x65\x36\xa2\x23\x9d\x40\x26\x6a\xc8\x78\x07\x83\x08\x57\xc2\x0d\x26\xd2\xe3\xae\xee\x98\x5c\x85\x8a\xe8\x69\xc7\x7f\x38\x18\xf3\xec\x7a\xcc\x13\x6e\x3e\x00\xf9\xe9\xa0\xeb\x36\x0c\x3f\xdd\x24\x5b\x6a\x1a\x58\xa7\x0a\x52\xb7\x9f\x83\xf0\x2c\x1a\x54\x57\xbc\xa3\xa8\x7c\x32\x81\x08\xbd\x33\x9e\x40\x8c\x30\xfe\x74\x32\x33\x9c\x52\xe8\xe5\xd9\x23\x93\x81\x9d\x85\x54\x1a\x81\xc3\xbe\xe8\xf8\xe7\xdb\x14\x8f\x3e\xf6\xef\xa7\x3d\xd4\xff\x82\x4f\xbe\x19\x41\xe0\x61\x8f\x3e\xe7\xa6\x10\x1c\xce\x79\xd7\xa5\x5e\x36\x91\xdf\xcf\x05\x07\x88\x20\xe5\xee\xa9\x9f\xba\x62\x9c\x3e\x34\x1a\x49\xe8\xa1\xb2\x71\xaa\x70\x18\xce\x62\x8b\x10\xb0\x4c\x97\x54\xd5\x81\x95\xf8\x59\xf1\x8b\x15\xbd\x88\x5e\xc6\xcb\xea\x2e\xd3\x9b\xaa\xc9\xf7\x66\x10\x99\xea\x94\x1b\x5e\xcc\x94\x57\x7d\x1c\x5e\xca\x78\xdc\x31\x53\x04\xb5\x23\xab\x66\x55\x4b\x68\x32\x4a\x13\x03\xdc\x4d\x71\x47\x96\x90\xfa\x30\xe2\x17\x27\xd2\xe5\xe2\x91\x7c\x5a\x3e\x52\xb3\xf2\x4a\x26\xc5\x95\x4a\x8a\x47\xea\x49\xf9\x48\xce\x8a\x2b\x99\x94\x57\xaa\x0e\x99\xe9\xb6\x3e\xd2\xad\x80\xe5\x6b\x1d\xb9\x03\x0a\x8c\x4b\xc6\xf4\xec\xf2\x52\x7b\x50\xd1\xaf\x21\x76\x9e\x1c\x13\x8f\xa1\xbf\x0e\x35\x6a\xbd\xc7\x18\x4c\x13\xfc\xb6\x83\x0d\xb7\x63\x79\x0e\x28\x08\x68\x28\xb2\xb4\x66\x0a\x22\xbc\x59\xdb\xff\x82\xf1\xce\xfc\x69\xe6\x6e\x86\xf3\x4c\x8c\xca\xd9\x75\x32\x31\x5c\x33\xf0\xee\x34\x37\xd8\x7f\xcb\xaa\x87\xec\x26\x56\x6c\x1b\x37\xd6\xb9\xb3\x6d\x1c\x9a\xc3\x4e\xe8\x2d\x5b\x5d\x3d\xa6\xed\x30\x32\x76\x3f\x7e\xd1\x91\xa4\x1a\x62\xc0\x19\x5c\x76\x47\x77\xf4\x86\x2e\xe9\x9e\xde\xd3\x8f\xf4\x7b\xfa\x3b\x7d\x4f\xdf\xd2\x97\x10\xe8\xdf\xd2\x91\x29\xb9\x63\x9b\x88\x3b\x32\x96\xde\x33\xf7\x7b\xbc\xa6\xdf\xb3\xbb\xf1\x2d\x7d\xcf\x36\x11\x48\xfc\xc9\xe8\x96\xbe\xf4\x7a\x15\x88\x06\x78\x61\xba\x6a\xe8\x50\xd7\x1b\x90\xe2\xef\xad\x2a\xe6\x25\xb4\xb7\x1f\x18\xdf\xd2\x7b\x76\x37\xba\xa5\xdf\x33\xa8\x36\x5a\x37\xfd\x38\x9b\x31\xd7\x8b\xa5\xcb\xf7\xcc\xfe\x1c\xaf\xe9\x47\x18\xd1\xef\xd0\x23\x70\x09\xa3\x5b\xfa\xd6\xa9\x7f\x9a\x9e\xbc\xa9\x99\xeb\x0a\x39\x8a\xdf\x9d\xc6\xe8\x2d\x74\x80\xfd\x8f\x6f\xe9\x1e\x46\xf4\x91\x61\xbd\x70\x48\x40\x54\xa3\x5b\x8b\x33\xc3\xf5\xbd\xe2\xa2\x8c\xfc\xd4\xae\x1e\x8f\xe2\xbf\x13\xdf\xf6\xe7\x28\x25\xcd\x19\x0f\xe3\x19\xa4\x04\x7d\x0c\x20\x54\x09\x8e\xaf\x13\x2c\xf6\x14\xd0\x0b\x42\xea\x66\x41\xbd\x6e\xcb\xad\xe5\xfd\x68\x5d\xfb\x41\xef\x1f\x1e\x34\xcc\xd1\xcd\xfe\xea\xf1\xff\x9b\x23\xde\xc3\x76\x7d\x64\xfb\xf1\x3a\x5c\x7c\xfb\x71\x88\x74\xb3\x63\x93\xe9\x0e\x4c\x38\x76\xcd\xb7\xcf\x5f\x8f\x1d\x21\xa0\xdb\x6b\xec\xcd\x21\xf3\x37\x18\x98\xa7\xac\x8a\x1b\x9b\x5b\x50\xf0\x66\xb0\x54\x6d\xfb\x72\x43\x34\xc7\xde\x84\x9d\x6e\xed\x13\x98\x1b\xd3\x95\x7d\x7a\xde\xee\xe7\xf6\xa4\x18\xfb\x9a\xde\xb0\x7f\x8b\x88\xd3\x1d\x2d\x09\xf5\x91\xfa\x6f\x86\xc3\x68\xc9\xe0\x32\xde\x50\x41\x68\x31\xdb\xb3\x8f\xec\x77\xf6\x96\x2d\x93\x7b\xf6\x3d\x7b\xcf\x5e\xb2\x25\xcd\x6d\x46\x2b\xbd\xbb\x4e\xf6\x54\xef\xaf\x93\x7b\xaa\x77\x8f\x93\x8f\x54\xef\x1f\x27\xdf\xd3\xdd\x75\xf2\x3b\xdd\x5f\x27\xef\xe9\xee\x71\xf2\x96\xee\x1f\x27\x2f\x5d\xd2\x6a\x4c\xe7\x97\xa8\xd0\x92\x3e\x3d\x35\xa4\xcf\x02\x4b\xfd\xd0\x30\x7f\x4b\xdb\x73\x49\x56\xb4\x6f\x72\xc9\x6d\x1d\xe2\xcc\x96\xad\x59\x46\x79\xdb\xd0\xec\x8e\xe6\x6d\xc6\xe8\x33\x60\xae\x87\xb4\x1e\xc4\x2a\x6b\xb7\x5f\xd5\x4c\x02\xae\xea\xc0\xd7\xd2\xab\x27\xac\xe8\xaa\x08\xad\xe2\x33\x2f\xc7\x5a\x3b\xdb\xfe\xbc\x66\x15\xdd\x1a\xe0\x2b\x51\xfa\x6e\xa0\xeb\x68\x4d\x6f\x59\x3e\x1b\x9b\x89\x6f\xd8\xf8\x2b\x73\xc6\x3a\xc8\xf6\xce\x31\x68\xbd\x10\x94\xbe\xa0\x3f\xb2\xc1\x9d\xc8\xf3\x82\x0f\x42\x70\xaa\xc8\xc7\x06\x80\x22\x90\x33\x28\xf8\x97\x67\x3b\x51\x61\x50\x34\x33\x50\x88\x12\x41\xfa\x00\x28\xb6\x37\x60\xe5\xb3\x1b\x3b\xa8\xa9\x9a\xeb\x83\xed\x7e\xed\x69\xb7\x25\xd3\xef\x19\x5a\x04\x43\xa1\x61\x42\xe2\x5d\x7d\x0a\x38\xff\x47\x7a\xeb\x87\x9e\x66\x8e\x3d\xb0\x73\x15\xc0\x21\x75\x06\x0e\x29\x0b\x87\x0c\xb7\x34\xfd\xc8\x3e\x0b\x0a\x8d\x56\xf5\x83\x2b\xf9\x29\xb8\xa9\xc8\x3d\x3b\x85\x9a\xe3\xbf\x3c\xdc\xfb\xcf\x1b\xae\x1f\x6c\xff\x82\x37\x8b\x5d\xdb\xf1\x0e\x87\x51\x23\xeb\x2b\x66\x3f\xa2\x48\xd6\x8b\xf8\x8a\xe1\x30\xfa\x91\xb9\x23\xe6\xd3\xa7\x3f\xb3\x5f\x09\x89\xc3\xa9\x85\xc7\xf4\xa6\xb1\xae\xdb\x3d\xb9\x41\xd0\xbc\x64\xe5\x7c\xb7\xa0\x7b\xb6\xc4\xab\x32\xfd\x2c\x58\x3d\xfd\x1d\x4d\xfa\x5a\x4c\xe2\x8e\x8c\xac\x5e\xd6\x02\xe4\xf7\x8c\x9f\x15\x61\xec\x08\x7d\xcb\xde\x87\x32\x89\x97\xec\xd7\x68\x4f\x66\x7b\x6f\xd2\xee\x59\xbc\x97\x56\x08\x8a\xe8\xa0\xb0\x47\x33\xf0\xe2\x41\xd0\xdf\xf6\xf5\xb1\x29\x3b\xc4\x2a\x4a\x67\xd1\x3d\xfb\x9d\xbe\x60\xfe\x36\xcf\xd0\xcf\x86\x31\x96\x1d\x8f\x06\xb2\x6f\x66\xe3\x97\x8f\xde\x8e\xde\x5e\x3d\x4e\x82\x23\x92\xcd\xc6\xcf\x3a\x54\xf2\xd5\xe3\xb1\x30\x15\x93\x93\x37\xd8\xf8\xa4\xdf\x93\x2e\xfb\x7b\x4c\xba\xc5\x66\x3c\x10\xe2\xf8\xc5\x23\x06\x0e\x7c\xd1\x47\x98\x43\x74\x3d\x7e\x49\x1e\xbd\xbd\x7a\x4c\xa8\x8e\x4f\xfc\x84\x1a\xa8\x0c\xde\x03\x1d\x47\x20\x83\x62\x9f\xd9\xfe\x2b\xb3\xeb\x92\x3d\x43\xae\xc0\x3c\xd9\x78\xe0\x1f\x47\x2f\xc6\x00\xaa\x68\xc5\xee\xc7\x48\x3a\x4d\xab\x8f\x42\x67\xeb\xe8\x47\x72\xc8\xd2\x8a\x3b\x08\x99\xa8\x31\x13\x57\x8f\x31\x96\xe5\x14\xde\xd8\xf3\x08\x6f\x6a\xdb\xea\x7b\xdb\xca\xae\x42\x52\x8d\x99\x6c\xb7\xb2\xae\x04\xe6\x45\xbd\xb5\xd6\xf3\x15\x58\xdb\x29\x8b\x1a\xe5\xc8\x29\x52\xac\x24\x45\x8c\xbc\x78\x1b\x91\x66\x33\x5b\x38\x12\x75\x7d\xe7\x32\x4b\x3a\xcf\xb0\x0d\xba\x6d\x25\x7b\xba\x52\x52\x27\xef\x6d\x43\x49\xab\xc0\x1f\xac\xb0\x4f\x1e\xbb\xf2\x9d\xb6\x68\xf3\x05\xf5\x97\x34\xf9\x1e\x7e\x1b\x76\xdc\x9c\xe0\xe4\x47\x0a\x39\xf9\x0a\xfc\xd0\xfc\x9e\x7e\x5c\x78\x2f\xac\x64\x5b\x7b\x6c\x7b\x57\x9f\x85\x57\x96\x9f\xf7\x28\x53\x5b\x94\xd9\x95\x17\x8b\x55\x64\x30\xdb\xa9\x91\xbe\x53\xad\xbb\x53\xee\xdd\x31\xec\xf2\xda\x0c\x73\x6e\x1b\x1c\x27\xe6\x61\x0c\x47\x8b\xa7\x99\x60\xae\x9d\x05\x35\xf6\x05\xe8\x14\x6c\x5f\x84\x8a\xfa\x1c\x30\xeb\x92\x06\xcd\x94\x84\xf3\xde\x0b\x70\xbb\x74\x18\x5d\x79\x24\x5f\xd5\x75\x40\x44\xa4\x4c\x8f\x2a\xcc\xa0\xda\x81\x6b\x2d\xbe\xd6\x39\x10\xb9\x69\x39\xf4\x29\x66\x6a\x16\x15\x76\x4a\xc0\xc7\xc1\x0c\x46\x15\x49\x22\xff\x34\x4e\xa9\xbf\xb9\x72\x56\x30\xef\xdb\xd2\x5c\x5c\x09\xbd\x78\x97\xbd\x31\x2b\xaf\x1e\x93\xa4\xdd\x33\x70\x23\x24\xf0\x88\x71\x1f\xc7\x02\x5f\xc7\x7f\x1c\x1e\xba\xdf\xb6\x8b\x7f\xf6\xd3\xa3\xe6\xd3\x41\xbf\x88\xc0\x48\xd2\x94\x1e\x9a\xd3\x5a\xd0\x5d\x92\xd5\x6d\x3a\xee\x59\xc9\xd3\xae\x7c\x1e\xc2\x70\xb5\xe5\xef\xb8\x3b\x27\x49\x1c\x83\x74\x28\x3e\x22\xbe\xdd\xe6\x93\x1d\x38\x1e\xc3\x15\x39\xa0\x11\xad\x35\x9d\x06\xce\xc1\x1a\xd4\xfa\x0b\xed\x8c\xa5\x91\x9b\x48\xdc\x81\x16\x2d\xdd\x88\xed\x09\x59\x27\x6b\xa7\xeb\xad\xa9\x2d\x1b\x85\x1d\x59\xc8\x51\xbb\x64\x6c\xc0\x83\xfb\x0c\xa5\x51\x28\xe0\xd7\x8d\xf9\x40\x27\x87\x69\xc2\x6b\xfc\x8a\x00\xb8\x24\x2d\x5c\x52\x5e\xb2\x6b\xa5\x6f\x98\x6b\xb8\x4a\xef\x31\x4d\xcd\x4a\x14\x05\x84\x7d\x02\xd3\x44\xf3\xf4\x8e\x67\x10\xb0\x83\x2a\x8c\x3c\x5d\xf2\x4a\xab\xd2\x09\xf8\xde\x38\xfe\x27\x14\xe6\x9e\x35\x9c\x32\x94\x2f\x2a\x50\xce\x9a\xe3\x74\xdd\xcc\xa4\x97\x64\xac\x84\xcc\x31\x11\x4e\xc4\xd9\x53\x8e\x42\x59\x88\xf1\x40\x50\x56\xce\x26\x5e\x00\x21\xce\x12\x03\x92\x90\x86\x69\x73\x60\x0e\xd7\xf8\xeb\x52\xe4\x9f\x1c\x3e\x0a\x69\xf4\x0e\x33\x28\xb7\x4c\xa5\x41\x88\xd7\xb1\x9e\xe6\xf1\x39\x19\x90\x8d\x33\x4a\x53\xef\x74\xe0\x9d\x29\x0f\x56\x93\x3f\x1c\x0a\xa4\x21\xc0\x5a\xd6\xee\x91\x6c\x86\xef\x34\xfe\x54\xc6\x88\x04\x70\xe7\x6c\x23\xb4\xc4\x7e\x03\x46\x7f\xd5\x3a\x12\x1d\x9e\xd4\xf5\xd4\xf0\x59\x4c\x9c\xf2\xa8\x32\x06\x17\xef\xb7\xa9\x5e\xa3\x55\xba\xba\xe7\x1f\x54\xa4\xe3\x1d\xd5\xf1\xde\xf5\xf1\x41\x45\x3c\xde\x51\x8e\x25\x38\x16\xa8\x1e\x1c\x16\x0c\xb7\xe2\x76\xd9\x90\x78\x18\x9f\xc1\xe7\xc5\xab\x20\x12\x56\x15\x06\xa9\xad\x16\x53\x11\x77\x5c\xc2\x87\xc3\x32\x3a\xec\x12\x1d\xef\xae\xe9\x3e\xd1\xf1\xfe\xba\xa6\xf8\xfc\x18\x9f\x1f\xd7\x54\x13\x2a\x1a\x3f\x47\xdf\x42\xdb\x26\xda\xb7\xd1\xb6\x91\x36\xad\x0e\x0e\x31\x37\x6c\x38\x5e\x9a\x90\x4d\x0f\x38\xdd\x2e\x2b\x7e\xca\xf8\xf6\x33\xeb\x35\xa9\xeb\x46\xae\xd6\x15\xc3\x5a\xc3\x20\x4e\x51\x81\xe7\xef\x37\x48\x01\x65\x8d\x89\xe7\x64\x78\xbe\xbb\xf9\x3f\x2a\x26\x43\xb9\x9d\x6a\xcb\xed\xe0\xfe\x55\x6d\x00\x99\x3e\xd0\xe1\x24\xbc\x30\x18\xa9\x38\xe0\xb7\xc3\xe4\x1f\x3d\x46\xbe\x05\xfb\x45\x47\xdc\x1a\xf6\xd2\x8a\x8c\xab\xab\xc7\x34\x73\x85\x68\x8d\x92\x92\x51\x7a\xf5\x98\xae\x59\xce\x4a\x92\x44\x6b\xf7\x16\x48\x3a\x6c\x91\xbb\x32\x0b\x27\x6d\x93\x82\x65\x0c\xd2\x34\xd9\xab\x21\x82\xab\xd1\x9a\x35\x64\x7a\x69\x2e\x88\x7b\x87\x7b\x2c\x5a\x47\x5c\xb8\x23\x5e\xd0\xb5\xeb\xf1\x83\x8a\x32\x9a\x13\xdf\x0b\x54\xf3\x47\x1b\xf6\xf2\x8c\xd6\x1a\x61\x5d\x1b\x43\xb5\x01\x5d\xa0\x17\x32\x50\x45\x06\x10\x23\x40\x7b\x53\x39\x1c\xfe\x86\x71\x93\x7c\x34\x29\x1e\xfa\x64\x20\xec\x09\x7c\x34\x3a\xdd\x9c\x42\x9d\xcf\xbd\x81\xa0\x17\x00\x2f\x5f\xf0\xd1\x06\x9e\xab\xa1\x5d\x0d\x91\x15\x20\x8d\xe6\x85\x85\x41\xa2\xc1\x21\xc1\xbb\x02\x0d\x2d\xfc\xb3\x06\x0b\x0a\xff\xe8\x2c\x90\x7c\x81\xb5\x17\x21\x94\x73\x40\x45\x13\x8a\xec\x93\x05\x52\x10\xcf\x56\x0e\x87\x3f\x69\xc3\xb8\xe2\xbd\xd7\x8d\x68\xbf\x8b\x29\x1b\xd3\x06\x6b\x6b\x27\x7c\x48\x0b\xb8\x5f\x6e\xe3\xba\x38\xc9\x47\x4c\x79\xc5\x23\x61\x0d\x23\x53\xc3\xb8\x78\x43\x4a\xcc\x72\x06\xd4\x27\x5e\x0c\x56\x05\x1c\xe3\xd5\xe3\x69\x68\x2b\x31\x8b\x8a\x11\x4b\xdd\x91\xfe\x35\x12\xe8\x28\x3d\x1c\x9a\xf2\xb0\xdd\x23\xfb\xaa\xb1\x37\x32\x74\x93\x69\xab\xd5\x06\x07\x75\x80\x89\xfc\x02\x92\x36\x5d\xf0\x5f\x31\x41\x02\xde\xf8\x9c\x7a\x8e\x62\x5b\xb3\xd3\x60\x39\xb6\x03\xb5\x49\x2a\xa4\x18\x52\x47\x97\x94\x96\x20\x29\x6a\xa6\xc3\x7c\x25\xec\xbc\xe2\x25\x5a\x33\x15\x49\x9a\xd2\x82\xd0\x9c\x7d\x23\x6c\x64\x56\x9a\xb1\x62\x9c\xc2\xed\x6e\xca\x72\xa8\x5a\x1a\xb2\x62\xcb\x02\x02\x78\xfc\xbd\x4e\xbe\x47\xcd\x1a\x4c\x6a\xed\x26\x95\x37\x93\xca\xc2\x49\xd5\x18\x87\xa9\xa0\x9c\x96\x64\xca\x21\xe4\x26\xac\x18\x9d\xd0\x09\xad\x1c\x60\x77\x78\xb1\x77\x65\x02\x5e\xe9\x67\x11\x95\x10\xb8\xa6\xcd\x33\x39\x2e\xb2\xcd\x3a\x65\x74\xbd\xa8\xf1\xd0\xf5\x29\x83\x03\x2a\x07\x93\x65\x75\x68\x39\x8a\x45\x96\xf4\xb0\x4f\x0e\x31\xd8\x47\x7b\x98\xed\x93\x87\x34\xa4\x5e\x16\xe9\x9e\x97\xbd\x89\xbc\x4e\xec\xa8\x87\x43\x47\x47\xfd\x79\x3c\x4e\x30\xf3\x54\x29\x72\x53\x6c\xfe\x43\x69\xb3\xab\xed\x71\x63\xcc\x00\xc6\xd8\x2f\xad\x78\x80\x65\xfa\x71\x36\x3f\xfc\x99\x48\x8a\xe1\xe0\xc9\x41\x9f\xce\x4f\x37\xf3\xe3\xee\xc9\x4e\xa8\xae\xa9\x69\x3d\xc2\x18\x30\x91\x6f\x6e\x67\x8f\xaf\x45\xa7\x73\x3b\x7d\x4e\xea\x7a\x91\xcc\x7b\x2a\xe0\xab\xfa\x9c\x76\xae\x8f\xbe\xf3\xaa\x56\xcc\x29\x6c\xeb\xb7\x52\x0b\x63\xae\xae\x74\x27\xaa\xd1\x00\x93\x0f\x0e\xc0\x82\xa6\x07\x9c\x8a\x33\xe0\x14\x82\x48\x2d\xa6\xe9\x5c\x2e\x20\x8b\xae\xc8\x8f\x47\x3d\x1c\x62\xd2\xcc\x4b\xc8\x01\x6a\xcd\x4b\x52\xcf\x7f\xab\xfa\x9c\x3c\xaa\x51\xb6\xbd\xe2\x51\x4f\x98\xb4\x10\x9d\x5b\x6d\x65\xa3\x46\x27\x08\xbd\xea\xe5\x5d\xba\xc3\x18\x6c\xbd\x49\x0d\xce\x7c\x7a\x42\x02\xe0\x74\x16\x12\x38\xfb\x44\x7e\x15\xff\x67\xe2\x85\x47\x61\x32\xe2\x3f\x20\xc2\x03\x9b\x0f\x06\x0b\xc3\x98\x19\x16\x83\x41\xdc\x6c\x3d\x9f\x2c\x08\x39\xac\x0d\xb5\x0e\xce\xb2\xa9\x8c\x06\x3e\x0e\xc9\x80\x6a\xd2\x44\xaf\x3a\xcc\xdf\xef\xef\x6e\x54\x11\x6b\xf5\x1e\xec\x8a\x3e\xa4\xb7\x8b\x64\x80\xe2\xcf\x01\x6d\x42\x3c\x27\x97\x13\xba\xac\x20\xc4\x74\xa2\xe9\xb2\x54\x0a\xa3\x87\x57\x89\xa0\x4d\x8c\x13\x49\x0d\xd7\xfe\x21\x2d\x6f\xb9\x4e\x14\x55\xf7\xbc\x2c\x45\xce\x13\xc5\x9e\xfe\x21\xa2\xb9\xa2\x71\x1c\xeb\x85\x05\x9d\x3e\x6c\x9d\xe4\x1f\x2f\xde\x96\x6a\xb7\x8f\x2a\x7a\x40\xfb\x9c\xb7\x98\xc5\x7b\x9f\x44\x48\xd3\x47\x3e\x31\xac\x58\x50\xf7\x3b\x5e\x42\x46\x69\x67\xd1\x33\x9f\x2c\xcc\xdb\xcb\x09\xa1\xe6\xf3\x11\x26\xe5\xfc\x16\x42\xa6\x62\x44\xf1\x33\xa1\xce\x82\x0c\xb7\x15\x66\xb8\x15\xab\x48\x99\x65\xfb\x4d\x44\x15\x90\xc3\x84\xae\x75\xa4\xbc\x3b\xc3\x4f\x66\xed\x15\x99\x29\x09\x9d\x9b\xdf\x89\x02\xa3\x21\xaa\xa9\x80\x50\xe3\x5c\xff\xf8\x51\xba\x69\xbc\xe4\x18\xb0\xa6\x09\xa7\xf4\x8e\xaf\x0a\x9e\xc1\xb5\xe9\xad\x17\xe9\xd8\x2e\xf7\x7c\xb2\x30\xe0\x1e\xc3\x68\x22\xf0\xf8\x71\x95\x44\xed\x3e\x82\x57\x11\xec\x3f\x5d\xa7\x95\xfb\x56\x29\x23\x4d\x62\x1b\x21\x1b\x92\xcf\xab\x8f\xf2\x3b\xbe\x87\x00\x91\xf0\x92\x1a\x72\xdb\x33\x50\x11\x7c\x5c\xab\x32\xbd\xe5\x90\xcc\xde\x3d\x30\x15\x11\x42\xe6\x7c\xc1\x44\xb3\xea\xdc\x6f\x88\xb6\x1b\x72\x39\x21\x61\x7a\xea\xef\x7a\x92\x81\x1f\xc2\x93\x75\x4d\x97\x1b\xb3\xfd\xe6\x60\x59\x23\x0e\xf4\xd3\xbf\x81\x53\x01\x3e\xfa\x1a\x8e\x17\xff\x78\xf1\x9e\x6b\xba\xcc\xfd\x3a\x55\xc9\xd7\x10\xc9\x10\xa6\xf0\xc2\x35\x66\x4f\x83\x8f\xb6\x8e\xa1\x29\x8f\x5d\x41\xa4\xc8\xf9\xb3\xa8\xfe\xca\x59\xd4\xad\x93\xe7\x16\xf2\x5b\x1c\x44\xcf\xd9\x73\x74\x83\x9d\xb8\x6c\x26\xae\x82\x89\x57\xed\x99\xa6\x8e\x90\x28\x99\x9c\xf3\xc5\x34\xd7\x51\x49\x0c\x08\x14\xd5\x7b\x1f\x0f\x09\x42\x89\x47\xe5\x59\x4a\xc5\x7e\x51\x35\x5f\xac\x82\x2f\xa6\x6e\xa9\xcb\x9a\x41\xf8\xbb\x32\x5e\x03\xd8\x27\x7a\x5d\xaa\x8f\xb0\x3c\x5f\x95\xa5\x2a\xa3\xc1\x3b\x9e\x6d\xc1\x0e\xf4\x22\xe7\x9a\x67\x9a\xe7\xc9\xc5\x60\x34\x8f\xe3\xb8\x5c\xc4\xff\x56\x42\x46\x83\xf1\xd3\x01\x19\x99\xbf\x23\x4d\xa6\x25\x26\xcd\x27\x94\x33\x1e\x55\x34\x3d\x1e\x25\xa1\x65\x8c\x0b\x68\xca\x7f\xc6\xa1\x73\xa6\x64\xa4\xdc\xe9\xb7\xa9\x04\x5b\x41\x0e\x69\x89\xb7\x6c\xfa\x2b\xcc\xbf\x6c\x0c\x43\xff\x1b\xd3\x0e\x17\xda\x4d\x7e\xad\x23\x97\x25\x76\x38\x34\xf7\x84\x70\xc6\xe7\xb6\xe8\x4b\x67\x01\xb7\x08\x74\x48\x1c\x61\xaf\xe7\x4a\xa8\x64\x7e\x2a\x61\x2e\x6e\x7d\xc9\x98\x99\x01\x04\x7e\x6c\xc0\x4f\x61\xc0\x8f\x68\xda\x2b\x69\x93\x29\x16\x64\x6a\x43\xd0\x7d\x67\xe0\x59\x45\xd3\xe1\x30\x9d\xeb\x05\x2d\x09\xa9\xeb\xee\xda\x98\x13\xf1\xda\x05\xb1\x22\x64\xfa\x93\x30\x2f\xf0\x5c\x7c\x67\xc8\x33\x45\xab\xe1\xb0\x32\x57\x37\x6d\x96\xb6\xac\xed\xd9\x7c\x10\x7c\xe1\xc9\xe6\x71\xb8\x60\x71\x5a\x14\x06\x9e\xcc\x1c\x44\x82\x33\x43\x05\x99\x1d\x38\x04\xfc\x74\x18\xc4\xf9\x0c\xdb\x67\x27\xa3\x4b\x3e\x0d\x0d\x0d\x08\xfe\x0b\x20\xd0\xc2\x3f\x1c\x6c\x77\x54\x1e\xfc\x85\x3d\xd8\x32\x0f\x0c\x5d\x52\x67\x08\x1b\xc9\x24\x0d\x2f\x7d\x07\xc0\x7d\x8d\x98\xf8\x10\x04\x25\xbb\x9c\xd0\x26\x8a\xd8\xe5\xa4\xf6\xc7\x30\xa8\x63\x68\xa7\xe6\x31\x0c\x3b\x66\x88\x25\xff\x44\x97\x76\x75\x13\x05\xb2\x79\xf8\x6d\x20\x81\xb5\x29\xf5\x6f\x69\xd8\x77\xf0\x79\x49\x43\xf8\x90\xe4\x86\xcd\x9b\x09\x98\xbc\xa0\xc1\x41\x31\x6f\x24\x99\x49\x78\x23\x5d\xae\xf5\xdf\x7c\x36\x75\x3d\xd3\xa3\x4c\x47\x9c\x24\x9c\xfe\xe4\x4b\xf1\xd6\x0e\xd2\x3c\xdd\x68\x5e\x56\x60\xe5\xd5\xc4\x2a\xfb\xb6\x15\x86\x4a\x32\x83\x2e\x7c\x62\x4b\x4f\xa0\x88\x08\xf0\xab\x04\x2f\x4d\x83\x5e\x30\xbe\xb1\xef\x45\x77\x8d\x0a\x73\x0d\x61\x8d\x61\x7f\x13\x6d\x47\xca\xa5\x1b\xd3\xe5\xc4\xe5\xe1\x46\x63\xe9\x01\x63\xe6\x60\xa8\xd5\x85\x9e\x15\x20\x0a\x21\xf6\xe4\x35\x23\x95\x01\xc8\x68\x2e\xa4\xea\x64\xbc\xe7\x12\x32\x91\x40\x00\x4f\x48\xb8\x90\x1b\xc2\xbc\x49\xb7\x20\x23\x1e\x7b\x72\x08\xf8\x34\x0b\x47\x14\x19\x0e\x15\xa6\x27\x56\x41\xf4\xd1\x0b\xe5\x15\xd7\x90\xb4\x8b\x43\x5e\x17\xb3\x10\x22\xac\x05\x99\xff\x7c\x6a\x36\x3f\xe6\x13\x30\x87\x72\x8d\x86\x38\xa3\xd5\xe9\x90\xa4\x61\xbb\x0d\x98\xd6\x86\x1a\x53\x0b\x5a\x32\x8b\x57\x2d\x88\xb6\xd9\x35\x0b\x56\xc9\xa8\xa4\x29\x15\xb4\x3a\x1e\x83\x28\xd5\xdb\xa2\xb8\x44\x8d\x74\x74\x69\x20\x24\x39\x1e\x2b\x94\xd7\x47\xbe\x4d\x65\x38\x58\x57\x93\x90\xe1\xd0\x90\x7f\x80\x1a\x28\x10\xac\x8a\x56\x88\x16\x3b\xf6\x09\x48\x3a\x46\x4d\x28\xba\x0b\x21\x2f\xb4\x21\x42\xcc\x2d\x3c\xd4\x84\x9a\x1f\x35\x21\xc1\xf5\xab\x3a\x3b\x37\x15\x53\x22\x58\xb0\x9f\x3d\x71\xed\x52\x6b\x4e\xde\xec\xb4\xb0\x3b\x0d\xa2\x0b\x62\x90\x84\x90\x5b\xee\x55\x20\xc2\x86\x6d\x5d\x9b\x0b\xd0\x04\x6e\x6d\x7a\x2c\x9b\x44\x70\xcc\x12\x42\x1e\x67\x1d\x8f\x91\x2f\xec\x8d\x6a\xeb\x36\xa0\x33\x1c\x4d\x9a\x02\x6d\x0a\x42\xb3\x04\x41\x42\x84\xd2\x89\x74\xb8\x1c\x10\x42\x08\xb7\x28\xd7\x0e\xc4\x6c\x00\x5f\xd4\x0d\x69\x49\x08\xe5\xf6\xf2\x14\x92\xd9\x28\x44\x5f\xbd\x7d\xff\xfa\xcd\x8f\x3f\x1c\x8f\xd7\x7c\x7c\xfd\xbf\x68\xe6\x6f\x15\xf7\xe1\x7e\x87\xc3\x4b\x73\x4d\xe3\xea\x77\xb1\x19\x0e\xe1\x4e\xfb\x75\x58\xf7\x9c\x49\x0d\x35\x67\x3c\xd1\xb4\x62\x1c\x98\x3c\x5b\x20\x68\xc9\xfe\xa9\xa3\x8a\x2a\x42\x0b\xf3\x2b\x85\x8c\x35\x5c\x5f\x64\xac\xbc\x8a\xca\x51\x41\xe8\x9a\x15\xf8\x6b\x9a\x31\x51\xfd\x90\xfe\x10\x65\x64\x36\x49\x32\xba\xb6\x8f\x6b\xf3\xb8\xb6\x5b\x95\x33\xf9\x28\x03\xc7\x30\x67\xa4\x7d\xd8\x94\xfc\x5e\xa8\x6d\x95\x1c\x76\x49\x15\xef\xc6\xf9\xa3\x28\x8d\x77\x63\x15\xef\x30\xff\xeb\x1e\x4b\xf6\x63\x15\xef\x49\x4d\xa5\xa1\x0e\xb0\xea\x68\xdb\xad\x8a\x25\xb6\x6a\xb0\xfd\x79\x6f\x94\x62\x2a\x98\x4d\x7a\x0e\x9b\x55\x44\x13\xc3\x09\xbb\x22\x17\x4c\x9d\xa6\xb4\x64\x99\x59\xb7\x09\x5a\x6f\xa0\xbf\x02\x07\x7f\x05\xb1\x8a\x2a\x96\xd2\x94\x95\xae\x92\x1a\x5d\x13\x8a\x5e\x24\x65\xc3\x77\x96\xf1\x6e\x9c\xc6\xbb\xa9\x98\xab\x05\x78\xf9\xe9\x59\x54\xc6\xfb\x71\x1a\xef\xc9\x95\x4e\x26\xb5\x34\x2f\xaa\x59\x39\x7b\xa9\x23\x31\x57\xe3\xeb\x05\xb9\x64\x0c\x1f\x16\x66\x05\x6d\xe9\x08\x9e\xaf\x1e\x27\xf8\x68\xfe\x2d\xda\x5e\x18\xed\x70\x90\x41\xa8\x49\x3b\x17\x70\x1c\x0f\xe7\x63\xde\xad\xd9\x64\xba\x7e\x22\xc7\xd7\xd3\xd1\x68\x4d\x0a\x96\xb9\x3a\x6b\x33\x9d\x62\x38\xcc\x86\xc3\xe8\x83\x8e\xf8\x7c\xbd\xa0\x13\x5a\x48\x32\x13\xf3\xf5\x82\x89\xf9\x7a\x74\xbd\x60\x93\x24\x52\xe6\xf7\xe2\x0a\x2a\x54\xb6\x1c\x9f\x6c\xa4\xf5\x8d\xfa\x18\x29\xfa\x98\x8c\xfc\x53\x45\x1f\x13\x5a\x3e\x61\xff\xe7\x78\x8c\x52\xf6\x1f\x57\x8d\x1b\x76\x49\x28\x74\xaf\x1e\xa5\x8f\xa0\x0f\xfb\x9d\xca\x3e\x13\x88\xde\x8d\xe0\xb2\xed\x81\xd2\x38\x9e\x04\x33\x07\xfd\x1e\x4d\x4f\x66\x5d\xb2\xc9\xb4\x7c\x22\xc0\xa1\xe6\x00\x5c\xa5\x81\xc9\xa9\xab\x59\x9a\xb9\x5f\x56\x1d\x70\x73\xd8\x25\x82\xee\x93\xa2\x66\xd5\x54\x81\xbb\x53\x24\xe0\x08\x5e\xfd\x07\xad\xe2\x6c\x73\xbd\x63\x62\x2c\xf1\xe7\x9e\x15\x63\xf9\x88\xcf\xcb\x05\x04\x7a\x31\x75\xcd\x81\x15\xae\xee\xe3\x1d\x13\x23\xac\xfb\x78\xcf\x8a\x91\xad\x5b\xd7\xc0\x34\x35\xe7\x77\xdb\x45\xb1\xa7\xb1\xeb\x81\x74\xe2\x41\x9b\xd5\x69\xcc\x70\xb3\xfd\x80\x1c\xe3\x6a\x93\xca\xaf\xd3\x0d\xba\x70\xe8\x2e\xa8\xfa\x5d\x6c\x0c\x99\x39\xb8\x53\x52\x69\x25\x31\x21\x5a\x9c\x6d\x6f\x44\xf6\x5a\x6a\x5e\x6e\x14\x4a\x08\xbf\x57\x39\x27\x70\xb7\xa6\x81\xb7\xa4\x9c\xe9\x79\x23\xcf\x5d\x24\xda\x05\x29\x57\x6c\x02\x06\xf3\x2e\x2a\xf9\x93\x0a\xee\x50\xca\xf4\x1c\x10\xdd\xda\xa0\xef\x94\xda\xc8\xa7\x66\x52\x6a\x74\x4d\xab\x71\x24\x21\xc2\x3b\xf9\xb2\x5a\x50\x1e\x6b\x8c\x46\x42\x68\x8a\x8b\x5d\xc6\x0e\x82\xc4\x3b\x2c\xdb\x87\x65\x7b\x28\x7b\x6c\xea\x19\xd0\x61\xeb\x3c\xde\xbb\xe7\x3d\x15\x2c\xad\x79\x9c\xa5\x9b\xe7\xfc\x4f\xc1\xcb\xb7\x4a\x48\x5d\x0d\x87\x3d\x89\x0c\xa8\x3d\x48\xb4\x64\x5f\x6b\xe0\xe4\x5d\x64\x8b\x9e\x88\xf0\xa3\x91\x20\x29\x1c\x28\x03\x1b\x84\xb9\x5c\xc3\x21\x34\x13\xa3\x6b\x10\x1a\x54\x10\xca\x13\x98\xd3\x14\x82\x0a\xc1\x7c\xb6\xd2\xfe\xa2\x68\x93\x40\xbd\x91\xb6\xc2\xc9\xb9\x0a\x7b\x8a\xa6\x41\xde\xb0\x9c\xd0\xd2\x76\xf3\xd8\x77\xf3\xb8\xbf\x9b\xc7\xbe\x9b\xc7\xa7\xdd\x10\x9b\x3a\xc1\x1f\xa5\xdb\xe0\x28\xf9\x4c\x23\x3a\xde\x8d\xc4\xa3\x88\xc7\xbb\xb1\x46\x00\xac\xe3\x3d\x96\xec\xc7\x1a\x00\xb0\xef\x60\xf3\x79\x1d\x38\x29\x34\xd8\x59\x88\x27\xf1\xdf\x67\x3a\xde\x27\x3c\xde\x27\x36\x38\xb0\x7d\x71\xed\xcb\xc5\xd3\xc9\xcc\xfc\xd7\xf1\x3e\xf8\xdc\x5d\x0f\x96\x83\x0f\xc2\x7a\xec\xf1\xc7\xbe\xa6\x95\x29\xe5\xb8\xd8\x7b\xfc\xb1\xaf\x69\xca\x60\xbe\xca\x5c\xa8\xd2\xfc\x36\x7b\x2e\x0c\x06\xbc\x95\x51\x05\xd7\x90\x66\xe6\xb7\x01\xa6\xc2\x60\xc0\x5b\x43\x56\x15\x4d\xc6\x56\xb3\x60\x19\x5d\xb7\xd6\x70\xd7\xbd\xc2\x7a\xd6\x97\x35\xd2\x40\x17\xf6\x54\x8f\xf4\x88\x8f\x85\xe1\x75\x40\x9a\x6f\xb0\x17\x67\xba\x0e\x04\xf9\x9a\x3d\x0d\xcc\x52\xf4\x4c\xf7\x05\x7f\x75\xe6\x27\xbb\xb7\xc5\xd6\x0b\x9c\xf4\x98\x83\x2e\xe4\x95\x2a\xdf\xe8\x32\x28\xad\x31\x67\x89\xc1\xae\x86\x09\x6e\x7d\xbd\xf3\x69\xdd\xe9\x72\xd4\xdb\x65\xb0\x25\x37\xed\x7b\x34\x1d\x14\x1a\x02\x3a\xf3\xe1\x70\x50\xea\xc2\xc6\xba\x8d\x20\xcd\x6c\x2a\xef\xd3\x2a\xae\xf4\x1e\x12\x16\xcf\x85\xcb\x79\x63\xb8\x4e\xb4\xc3\x18\xe4\xa2\xe4\xd0\x31\xa4\xfc\x0d\xde\xbf\x2d\x85\x2a\x85\xde\xb7\xaa\x2c\x28\xd8\x4c\xb8\x3a\xe1\x3b\xca\xe9\x40\xdc\x6d\x54\xa9\x53\xa9\x07\x10\x5b\xa9\xe4\xf7\x1f\xf8\x4e\xbf\x74\x75\x58\x08\x89\x97\x76\x1e\xde\x0e\x9d\x0f\x87\x91\x97\xb0\x9d\xb4\xa5\xed\xe9\x9c\x1f\x05\xc0\x92\xf9\xf5\x22\x24\x9d\xf7\x81\xdb\xc9\x20\x95\xb7\x78\x33\xf4\xec\x70\xc3\xf5\x47\xce\x65\xf2\x8d\xa6\x99\xba\xdb\xa4\x25\x4f\x9e\x6b\x2a\x55\x79\x97\x16\xe2\x4f\x9e\xfc\x4b\xd7\x89\xaf\xe4\xe5\x5d\xfa\x69\x18\x0d\x5a\x90\xe1\x50\x3f\x69\xdc\x39\x51\x93\x65\x7b\x0b\x4e\x4a\xd3\xab\x6e\xef\xe8\xbd\x8c\x0e\x40\xd4\x26\x9a\x72\x99\x27\x9c\x66\x6a\x0b\xf9\x58\x0b\x05\x46\x39\x30\xe3\x44\xd5\xfe\x68\xdb\xda\x5f\x0a\xac\xff\xa5\xab\x39\x1c\x46\x7c\xac\x47\xd7\xe4\x4b\xc1\x0c\x8a\xb0\xed\x9a\x4f\x7d\x6c\xa5\x4f\x76\xa9\x93\x0d\xcd\x6f\xed\xf4\x9c\x0c\xd0\x7c\xd4\x7c\x43\xc1\x17\xaa\x9a\x09\x30\x70\xb7\xe4\xde\xc1\x4d\xaf\xa4\x6e\x71\x8a\x60\x7e\x59\xcd\xf6\x12\xfd\xcc\xa0\x93\x35\x74\x92\xe3\x20\xb7\x76\x58\xab\xae\x96\xd1\xdb\x0a\x3e\x30\x06\xbf\x17\x69\xf0\xb9\xd2\x7d\xae\x68\x12\x84\x3b\x3d\xa4\x1d\x41\x0e\x5d\x6c\x71\x04\xab\x1a\xd3\xfa\xac\x90\x2f\xca\x47\xac\xa0\x5b\xf3\x27\x63\x13\x43\x85\x4f\xb3\x27\xeb\xe1\x30\x8d\xca\x88\xcf\xf3\x2f\x8b\xc5\x5c\x2e\x08\xd8\x35\x41\x66\xe3\x7c\x3c\xa6\xdb\xf1\x78\x9a\x7f\x69\x9a\x7d\xc9\x7c\x56\x88\xed\x93\x7c\x38\x8c\x4c\x47\xa4\xff\xb3\x76\xe2\x1a\x4f\x70\xed\xc4\x50\xf4\xd6\x69\x88\xc0\x99\x9a\xde\xb0\xcb\x6b\xba\xb4\x89\xb3\x00\xe6\xee\x99\x61\x21\x6f\x8e\xc7\x22\x52\x74\x47\x37\x64\x38\x34\x17\xa6\x34\x4f\x84\xde\xc3\xdb\xcb\x9b\xe3\x71\xc2\x4c\x61\x45\x37\xc4\x54\xad\xa0\x6a\x90\xb2\xc3\x90\xe9\xeb\xa9\x7e\xc2\xf2\xe9\x68\xa4\xc9\x1d\xe3\x73\xfd\x65\xba\xa0\x77\x40\xa7\x1c\x8f\xd1\x86\x65\xd1\x1d\xcc\xf6\x86\x15\xd1\x06\x6d\xb9\xcc\x38\x18\x63\xcb\xe1\x70\x0f\xda\xc9\x25\xc3\xcf\x6c\xa8\x22\x33\x9d\x08\xcf\xff\x2e\x87\xc3\x7b\xa8\x71\x8b\x12\xbc\xe6\x58\x2f\x61\x19\xb4\xdb\x7f\x3c\xdd\xa9\x3f\x07\x84\xd8\xe9\x82\xb3\x0c\xdd\xb1\x4d\x97\x09\x5f\x0e\x87\x67\x3a\xcd\x1f\xe8\xf4\xb6\x39\xf7\xdf\xcb\xde\x58\xf2\x15\xbf\x85\xfc\x67\x7e\x91\xac\x07\x75\x98\xee\xc5\xa7\xf2\xf8\x28\x23\xc3\x5b\x18\xc0\x06\x84\x8d\xa1\x58\x2a\xcf\x29\xda\x60\xf3\x71\x1c\x57\x5e\x2f\x17\x30\xe2\xbf\x9f\x50\xd5\xb6\x93\x30\x7a\xa0\xa3\x25\x21\x78\x95\x23\x80\x56\xd1\xa5\xcb\xa0\x32\x5f\x78\x85\xd6\xe5\xa5\x8e\x97\x66\xea\xee\xa8\xa5\xb0\x1c\x65\x9f\xea\xde\x4e\xcc\xf0\xa4\xe3\x6b\x30\xb0\x1a\x0e\x2f\x25\xf0\xdc\x86\xfd\x02\x2e\x57\x21\x97\x3b\x25\x6a\x34\x9a\x36\x6f\x7a\x5e\xa8\x2f\x19\xa7\x62\x38\x8c\xaa\x11\x53\x64\x5a\x3d\x55\xa6\x5a\xf5\x25\x77\x15\xab\xf1\xd8\x67\x45\x36\x75\x0f\xed\x5b\x5c\x43\xcc\x9a\xca\x66\x7c\x01\x11\x96\x97\xff\xbc\x97\xd1\xbc\x3d\x1f\xdc\xde\xaa\x5e\xa0\x90\xa9\xa9\x77\x46\x00\x7e\xd1\x44\x57\x6b\x85\x2d\x60\x9c\x16\x28\x95\xc3\x28\x05\x7c\x74\x3d\x4d\x9f\x30\x81\x81\x0a\xfc\xae\xcc\xd3\x2f\x15\xf8\xc9\xc3\x85\x10\x71\xa5\xd5\x66\x56\xb8\xfb\x21\xcd\xcd\xb4\x2e\xfd\x76\x98\xfc\x4b\x9c\x57\x94\x8e\xaf\xc9\x97\xca\xc2\xe1\x9a\x50\xce\x4a\x66\xdb\xa7\x90\xa6\x86\x24\x51\xc9\x52\x5a\x58\x69\x42\xc4\x59\x4a\x0c\xc8\x12\x75\xfb\xac\x97\xc3\x61\xff\x27\xca\xb0\xfb\xaa\x06\x0a\xbf\x7c\x92\xce\xca\x91\x4a\x4a\x0a\x07\x62\xb5\x2d\x8a\x37\x4a\x6d\x86\xc3\x09\x26\x29\x2a\x19\x63\x6a\x7c\x4d\x60\xf5\x9a\xd3\xf8\xbe\x4b\x42\x09\x73\x80\x1b\xcd\xd2\x70\xc8\x67\xe7\x38\x61\xde\x44\x58\x73\x8a\x6d\x48\x43\x64\xb3\xe7\xa7\xac\x0a\xc4\x3b\x25\x8a\x77\x6c\x4e\x1f\x03\x61\xf9\xbc\xfa\x52\xba\x5d\xa8\x70\x17\xca\x98\xcb\x7c\x9a\x36\x97\x6d\xcd\xf8\x3c\x35\xd5\x0a\xf6\x56\x46\x2d\x33\xcd\x83\x75\x59\xc6\x9b\x3b\xa0\x9b\x49\x92\xd1\xcd\x75\xb2\x36\x37\xfe\x25\x64\x03\x83\xc0\xfe\xad\x25\xac\x60\x01\xd3\xf1\x35\x2e\x60\x19\xc3\xcd\xb1\xe0\xb8\x26\x54\xb3\xc2\xb0\xab\x66\xa1\x32\xb6\x36\x8f\x75\xf5\x24\x35\x6c\xc6\x5f\xe8\xa8\x30\xdb\x02\x9d\x34\x7a\x79\xbb\x78\x49\x90\xb1\xe0\x6d\x40\x8b\x9c\x98\xe3\xa2\x35\x53\x50\x62\xad\x05\x5f\xa4\x9b\xf7\x16\x79\xb4\x0b\xda\x96\x86\x37\x0f\x5a\x19\x9e\x98\x6d\x62\xc1\xb7\x4a\xc8\x76\xe7\xbe\xa4\x95\xda\x46\xb7\x6c\xe5\x02\xdb\xb8\x66\x50\xe8\xa2\xe0\xa7\xfa\xb2\x9d\xc6\x9d\x0f\x87\x9d\x1c\x81\x9a\x5c\x32\x76\x92\x37\xb0\xbe\x4f\xcb\x8b\x17\xb2\x93\x66\xf9\xb0\x5c\x82\x55\xc9\x72\x09\xd7\x89\xf2\xb4\x12\xf2\xf6\xab\xd5\x8a\x67\xba\x4a\xee\x9c\x97\xe1\xbf\xe8\xad\x4d\x66\x8b\x63\xfb\x86\x4a\xb3\x53\x3f\xd0\xad\xc8\x93\x7f\x53\x51\xfd\xb0\x2d\x8a\x1f\xcb\x9f\x65\xce\x57\xc9\x17\x54\x54\x20\xa5\x4a\x7e\xa5\xa2\xc2\xef\x25\x3f\x53\x51\xbd\x12\x52\x68\x9e\xfc\x42\x57\xf0\xe3\xc7\xf2\x25\x26\x4f\x4c\xfe\xa0\x60\x50\xdc\x14\x7c\x47\xb5\x7a\xcb\x4b\xc3\x40\xa4\xb7\x3c\xf9\x9a\x6a\xe5\xe3\x7c\x26\xbf\x35\x49\x74\x7e\xa2\x3c\xcd\xd6\xc9\xb7\x74\xe9\xb2\x83\x7f\xf5\xc7\x36\x2d\x12\xad\x69\x56\x28\xc9\x13\xae\xe9\xf2\x8e\x97\xb7\xbc\x4c\xa4\xa6\xf0\x2b\x51\xf6\xc7\xeb\x55\x52\xf9\xd7\xaf\x57\x49\x0a\xba\xe1\x4d\xc9\xb3\x54\xf3\x3c\x39\x85\x85\x21\x51\x6d\xae\x94\x2a\x78\xfc\x31\x2d\x65\xa4\x47\x7f\x4b\x2e\x06\x7f\x1b\x89\xd1\xdf\x06\x17\xa2\xba\x68\x7a\x89\x2f\xde\x16\x3c\xad\xf8\xc5\xb6\xe2\xa6\x86\x84\x1a\xb2\xd2\x3c\xcd\xff\x46\x6a\x6a\xcd\x3c\x70\x91\xbe\xe3\xfb\xa4\xd0\x74\x99\xa5\x1b\xa1\x2d\xd1\xa7\x69\x6e\x03\xaa\xaf\xb5\x59\x42\x3b\xa8\x24\x07\xfe\xc7\x4e\x77\xab\xa9\x56\xaf\x94\xd4\x68\x86\x91\x7c\x01\xd3\x4a\xab\x6d\xc9\x0d\xb9\x9f\xfc\xaa\x5b\xc1\x68\x92\x9f\x35\xc5\x20\x17\xe0\x93\x95\xfc\x62\x56\x8b\xa7\xe5\x0b\x60\x05\x92\x3f\x34\x98\xf5\x80\xa0\x21\xf9\x4e\xd3\xa5\xa8\xe0\xf7\x6b\x09\x69\xa1\xbe\x36\xb5\xc5\x06\x7e\xff\xa6\xe9\x56\xfa\xa7\x9f\x34\x5d\x56\x9a\x6f\x36\x1c\xac\xad\x3f\xa8\xe4\x5b\x4d\x97\x37\x20\xb6\x78\xb1\x2d\xef\x4d\x89\xe6\xb4\xe4\x32\xe7\x25\x0c\x84\x73\x9a\xe6\xf9\x3b\x73\x31\x79\xfe\x8e\x67\xfa\x6d\xaa\xd7\x89\xe0\x66\xb8\xea\xf7\xed\x26\x91\xfe\xe7\xf3\xbd\x59\x1e\xc5\xe9\xb2\x0c\x0b\x2a\x4e\x97\x28\x1e\x7a\xee\x88\x58\x4e\x0b\x51\x69\x2e\xe1\x0c\x7e\x75\x6f\x4e\x45\x52\x70\xba\x95\xa7\xc5\x19\xa7\xcb\xd4\x3c\xff\x2c\xc5\x1f\x5b\x9e\xac\x39\x5d\xb6\xb3\x9d\x27\x7f\x08\xba\x4c\xb5\x4e\xb3\xb5\x33\x10\xf8\x4e\x74\x6d\x08\x68\xb5\x29\x84\xe4\x30\xc7\x64\x2d\xc3\xc7\xef\xad\x8c\x2a\xc9\x25\x5d\x62\x98\x72\x94\xe3\xbc\xc0\x20\xf5\x28\xce\x49\x56\x68\xfc\xf2\x36\x2d\xb9\xd4\x3f\xa8\x9c\x27\x39\xa7\x2e\xf5\x76\x72\x0b\xbf\xdf\xf1\x22\xd5\xe2\x9e\xbb\x14\xac\xc9\x0e\x8a\xbf\xc7\xbc\x8e\xef\xcd\x71\x59\x9a\xd5\xd5\x42\xa6\xef\x21\x14\xc5\x9e\xd3\x6a\xbb\x31\xdc\x63\x05\x13\x7e\x03\x0b\xc0\x4b\x6b\x4d\x94\xdc\x9b\xea\x69\xfe\x73\xc5\x73\x68\xfe\x91\x83\xbb\x93\x3d\x45\x67\x62\x72\xf0\xd1\xe0\x62\x30\xd2\xa3\xc1\x66\x77\x31\x18\x09\x73\x86\xff\xd8\xf2\x0a\xb2\xcd\xbf\x2a\xd3\x3b\x9e\x68\xaa\xd7\xa5\xd2\xba\xe0\x86\xed\xca\xf9\x8d\xda\xca\x8c\x27\x82\x2e\xb5\x7a\xc3\x57\x1a\xa2\x6f\xbd\x00\xe1\x40\x22\xed\x49\x7c\x6f\x30\xc1\x57\x32\x4f\x14\x5d\x9a\x55\xfe\x25\xa9\xe8\x72\x83\xc7\xce\x1c\xa6\xe4\x56\xfa\xc3\xd5\x12\xf2\x25\x1b\xe9\xce\x58\xbb\xfc\x4e\x52\x4c\xb0\x85\xaa\x89\xe4\x4f\x41\xb5\x7a\xe3\x8d\xa7\x92\x77\xe6\x28\xf1\x34\x07\x96\xfd\x83\x82\x34\xb3\xc9\x1b\x4e\xb5\xfa\xf0\xee\xf9\x9b\xe4\x2b\xf7\xeb\x85\x2a\x25\x2f\xab\xe4\xb5\x29\x70\x69\xb2\xfe\xe4\xf6\xc6\x25\xaf\xb8\xbb\xc4\xc9\x3f\xcd\x69\xca\xf3\xaf\x21\xf5\xda\x73\x4e\xdf\xbe\x4e\x6e\x34\xfd\xf0\xec\xe7\x64\xa9\xe9\xdb\xd7\xe6\xc7\x5e\x53\x97\x9f\x21\xb9\xd7\xf4\xdd\xb3\x97\xcb\xb7\x5f\xbd\x5b\xbe\xfc\xea\xeb\xe4\xa3\xa6\xdf\x3c\x7b\xf3\x6a\xf9\xf6\x75\xf2\xbd\xa6\x3f\xfd\xfc\xec\xdd\x87\xaf\xde\x99\xa7\xdf\x35\xfd\xf0\xaf\x1f\x97\x1f\xbe\x79\xfd\xee\xe5\x7b\x53\xf0\xde\x10\xfd\xb7\xd7\x93\xe4\xad\xa6\x95\xb8\x95\xc9\x4b\x4d\xa5\xc8\xf8\x0f\xdb\xbb\xe4\x85\xa6\xcb\x55\x9a\x69\x55\x9a\x0d\xfd\x51\x03\x6c\x86\xf9\x3f\xd3\x34\x2d\xee\x54\xa5\x01\x66\x54\xc9\x07\xf7\xfc\xaf\xb5\x2a\x78\xf2\xce\x5c\x5e\xc8\x96\xf0\x4c\xe6\xdf\xa7\x3b\xbc\x5e\x6f\x0c\x64\x79\x97\xe6\x22\x95\x55\xf2\x95\x79\x78\xc9\x6f\x4b\xce\xab\xe4\x35\x40\x4b\x08\x82\xf3\xb6\x48\x33\x5e\x25\x7f\x6a\x73\x1c\x9f\xc9\xdb\x82\xbf\x2a\xd5\x1d\xc2\x8f\x57\x9a\xe6\xa2\xd2\xa9\xcc\xb8\xbd\xa0\xf6\xc4\xff\xd3\xc0\x20\x53\xf7\xa5\x58\xad\x92\xe7\x9a\x2e\x3d\xef\x09\x5d\x24\xff\x72\x15\x9e\x37\xe2\x84\x65\x21\xee\x04\xc6\x20\x4a\x7e\x80\x64\x5b\xfa\xfa\x1f\xef\x52\x79\xcb\x93\x7f\xc3\xd7\xdf\xe9\xe2\x19\x2a\x93\x93\x9d\xf4\xb6\x3b\x2d\x99\x47\x72\x23\xa9\x35\x20\x6f\x97\x2f\xcd\x41\x32\xa0\xe8\x3d\x92\x41\xc9\xc7\x4e\x41\x95\x7c\x0f\xb6\x36\x60\xda\xed\xcb\x7e\x97\x35\xb1\xb9\x98\x7f\x94\xed\x94\x45\x41\x4e\x7a\xcc\x50\x84\x59\x0f\x40\x7f\xc6\x5c\xa6\x22\x3b\x46\x26\x6c\x5e\x23\x30\x21\xef\x04\x97\x31\x94\x6e\x2d\xaa\x57\xaa\xfc\xb0\xdf\x84\x41\x9b\x6c\xbd\xc6\x32\x54\x54\x81\x29\x43\x93\x28\x15\xbe\xdf\x54\xa3\x41\x13\x43\x58\xdd\x1a\xc0\x50\xf6\x18\x68\xda\xfe\x4f\x2c\x24\x50\x6f\x31\x8d\x4e\x03\x90\x0c\x44\x3e\x10\xf2\x42\x0f\x87\x03\x97\x2a\x19\x9e\x6b\x12\x09\x08\x3d\xcf\x78\xec\x3f\x28\x48\x68\x53\x0f\x53\x07\x11\xbc\xc8\x41\x30\x02\x0b\x35\x1a\xc4\x83\x51\x65\x5d\x27\x4e\x0c\x89\x70\xe1\x73\xc5\xab\x0b\xa9\xf4\xc5\x3a\xbd\xe7\x17\x02\x8c\x89\xbc\xe6\xf2\xa2\xba\x10\xf2\x42\x1d\x8f\x91\x9a\x57\x0b\xa6\xe9\x39\x22\x5c\xe9\x6e\x50\x1f\x60\x9f\xe7\x62\xb6\xd3\x36\xdb\x72\x72\xa8\xa9\x7d\x40\x93\x5a\x3b\xc5\x05\x99\xda\xfc\x8d\x68\xbc\xdc\xce\x0b\xdd\x95\xd6\x87\x9a\x58\x4e\x9a\x7c\xd4\xc2\xab\xb4\x25\xc3\xb0\x62\x3a\x1a\xc4\x03\x02\x5e\x27\x1b\xb5\x89\x0c\x2d\x3c\xd7\x90\xe1\x24\x4b\x75\x24\x89\xb5\x95\x32\x75\x52\xc6\xe7\x62\x11\xb6\x2a\x59\x6a\x5b\x15\x2c\x6d\x6a\x4e\x7d\x36\xbd\x8a\x2a\x5a\xd0\x92\x40\xd0\x32\xde\x1d\x35\x99\xba\xa4\x74\x80\xe7\x86\xc3\x30\x49\x1d\xd6\xf6\x2f\x41\x26\x9f\x52\xc8\xc3\xe3\x4e\x34\x34\xf0\xd6\x72\x98\xac\xcb\x3f\x57\x84\xd0\xb4\x36\xeb\xa8\xdb\xf1\xad\xe0\x10\xcc\xf5\xa2\xde\xca\x73\xe7\xd2\x1e\x14\x81\x07\xc5\x26\x9c\x86\xb3\x32\x05\x95\x3f\x1f\x0e\x43\x83\x1b\x39\x1c\x42\xf1\x4e\xcf\xe5\xa2\x11\x87\xc2\xa3\x79\xdf\xba\x86\xbe\xe9\x4a\xcf\xc5\x82\xd4\x40\x36\x3f\xc3\xc4\xda\x70\xd6\xfa\xb2\xad\x37\x09\x67\x2a\xa8\xf8\xa3\x8c\xde\x08\x3a\xb0\xa9\xdd\xab\x01\x18\xf7\x41\x4d\x47\xa6\xba\x6a\x5f\x09\x3a\x70\x65\x03\x5b\x67\x83\x51\xe9\x5d\x15\x3c\x2c\x74\x60\x8b\x5d\x2d\x8c\x20\xe0\x2a\xfd\x22\xa8\x4b\x1b\xe8\x92\xda\x9b\xbb\x9a\xbf\x83\x25\x2c\x05\x37\xe7\xa6\x33\xd4\xb0\x9f\xf6\xe8\x16\x75\x9a\xe7\x51\x1c\xc7\xda\xc5\x84\x37\x64\x76\x34\x70\x1b\x32\xa0\xda\x40\x8d\x3b\x75\xcf\x7b\x6a\x35\x1b\x07\xf5\xd2\x3c\x7f\xd1\x7c\xf4\xe1\x5e\x69\x77\x8c\xd0\xdc\x27\xd7\xff\x8c\xb6\x6e\x0a\xd0\xd0\xc5\xf7\xff\x8c\x76\x76\x75\xa1\x19\x10\x4f\x9f\xd5\x0a\x17\x8f\xb8\x40\x69\x38\xe8\xee\x89\x5e\xc2\x29\x3f\x99\x1a\x1d\x34\x0f\x03\xe8\xc2\xce\xf3\xa1\xf6\x6e\x7a\xfe\xd4\x60\x4b\x9c\xe8\x43\x0d\xed\xfc\xdc\x31\xc2\x66\x30\xd1\x87\x5a\xd9\xc3\x61\x63\x99\xb9\x3d\x7f\x78\x3b\x5b\xdb\xdf\xb3\xa1\xd8\xc7\x03\x7b\xda\xd3\x41\xb3\xab\xd8\xfa\xfc\xc6\xf6\x34\xf6\x5b\x8b\x6d\xcf\xee\x6e\x4f\x53\xb7\xbf\x58\xa3\x27\xbd\xd0\x14\xcd\x62\x1a\x10\xce\x3d\x08\x57\x4c\x1c\x8f\x12\x96\xd3\xde\xc2\xbd\xc3\xdf\x9c\x4c\xc5\xf1\xa8\xe2\x06\xa3\x73\x72\x3c\x2a\xc6\x0c\x98\xc7\xd1\x0e\x87\x3c\x16\xf9\x4c\xc6\x4b\xbe\xe3\x19\xe8\xfb\x38\x49\xbe\x8d\x38\xfd\xec\x4f\xb4\xdb\x1a\x18\x4f\xcc\x4c\xb0\xa8\x35\x93\xcc\x9c\xb9\xe9\x4f\x91\x98\xbb\xf4\xa7\x23\xb9\xa0\xf3\x05\xe8\xec\xe7\x7a\x11\x09\x42\xe1\x2d\xaa\x39\xfd\xcb\xba\xef\xcb\x1a\x15\x00\x68\xcc\x34\x99\xf2\x27\xbd\xe0\xc8\x49\x62\x79\x23\x9f\x12\xac\xb7\xe6\x9c\x2f\xd0\x7f\x35\xa4\x7f\x88\x17\x06\x87\x47\xd7\xae\x5d\x6d\x8f\x70\x47\xc2\x86\xc8\xc6\xf4\x85\x8c\x3c\xc8\x48\xbb\x04\xc5\xdf\x06\x7f\x1b\x69\xcb\xc6\x1b\x82\x22\xbd\x70\x87\x82\xe7\x17\x86\xc3\x07\x0c\xea\x93\x7e\xd7\x96\xf2\xfb\x20\xfb\xf0\xc2\x52\x48\xa1\xd9\x7c\x51\x63\xba\x91\xfe\x40\xdc\x53\xbb\xe6\xaf\xa5\xc0\xd8\x0a\x20\x1f\xc3\xa6\x2a\xb6\xec\x68\x63\xcd\x5a\x45\x1a\xd0\x89\x8a\x97\xb6\x57\x5b\x99\x6a\x3a\x10\xb2\xd2\x69\x51\x0c\x02\x27\x0d\x39\x53\x2d\x73\xdb\x48\x7b\xd3\x2f\x49\x92\x93\x77\xe0\x93\xe8\x7a\x76\xf9\xf5\x9d\x9b\x7e\xce\x2b\x5d\xaa\x7d\x30\xca\xa0\xe2\xa0\xd2\x6a\x33\x38\x33\xb0\xad\x6c\x86\x46\xd3\x7a\xd9\x5d\x10\xc9\xe4\xf1\x78\xa8\xa7\x1d\xe3\x49\x1d\xf8\x43\xda\xdd\x9d\x3a\x6b\xc7\x9f\xc0\xac\x8f\xce\x39\x95\xd4\x07\x29\x5f\x80\xa0\x52\xc6\x99\x61\x38\x0a\xb0\x60\xf6\x96\x8f\xf6\xc7\xa4\x16\xf2\x3e\x2d\x84\x4d\xcf\xf3\x45\x14\x24\x26\x23\x2e\xdb\xd9\x52\x15\x39\x66\x82\x0c\xde\xb6\xf2\x28\xe2\x19\x22\x75\x67\xfd\x0e\x62\xd5\xea\xb0\x05\x59\xa1\x68\xda\x22\x65\x6c\x6f\xf6\xf7\xe9\x5e\x93\x76\xb0\x50\x5c\xb7\xf7\x3a\xd5\xfc\xc5\xda\xf0\x3d\x18\x68\xb9\xee\x3d\x26\xa1\x66\x64\x38\xd4\x36\x15\x15\x95\xec\xbb\xc8\xa7\x27\x18\x0e\x9b\x4c\x05\x0e\x47\x1c\x6a\x43\x71\xf6\x99\x1a\x9a\x5b\xdf\x0a\x6f\xf4\xcc\x03\x2c\x24\xca\x5a\xc9\xec\xa7\x4d\x34\x50\xc8\x12\x6f\x8d\xd0\x9f\xc9\xb8\x41\x59\x62\xae\x17\xfe\xb4\x4a\xa6\x5d\x77\x10\x56\xb4\xdd\x97\x0c\xfb\x6a\x12\x01\xcc\xf5\x62\x3a\x06\xf3\x57\x1f\x59\xd7\x30\x1a\xf6\x63\x22\x08\xda\x1c\xf9\x93\x7c\x79\x7d\xc9\xcc\x89\xeb\x0a\xe4\xc3\xbb\x09\x21\x9a\xdb\xfe\xdd\x7e\x40\x36\x20\xb3\x1b\x50\x20\x64\x2f\x19\x9f\xa7\x0b\x5a\xb0\x77\x66\x6e\x65\x2c\xf2\x05\x95\x64\xda\xd8\xbd\x3a\xd1\x37\xce\x33\x29\xbd\x6f\xec\x1b\x19\xf9\x2d\x2a\x69\x41\x2b\x52\xb7\x65\xde\x8a\x4a\x83\x03\xe6\x8b\xba\xff\x18\xb4\x69\x64\x7f\x82\x21\x78\x9d\x68\x9d\x63\x6f\x95\xd9\x36\xad\xe2\x71\xa5\xee\x38\xe0\x30\xb7\x0f\xb1\xc8\x61\x65\xfd\x13\x21\x84\x4c\xc3\xb3\x18\xa1\xb6\x3e\x00\x00\x9d\xb7\xa0\xb9\x87\xb7\x69\x69\xc8\x95\x46\x92\xfd\xae\x23\xc9\x3e\x1e\x61\x5f\xf4\xcc\x9a\x60\x1f\xea\x44\x83\x58\xba\x69\xf2\xa6\x57\x35\x85\xa3\x03\xab\xe5\xef\x90\xa7\x72\x5b\x87\x92\x2e\xb4\x67\x46\xe3\x6b\xef\x33\xd7\x96\xf3\x45\x15\x95\x68\x5d\xdc\xb2\xc4\xbf\x0e\x2d\xf1\xaf\xa9\x33\x97\xbf\x9c\x84\x26\xfc\x5f\x75\xd4\x90\x3b\x8c\x0f\x6d\x48\x7f\x88\xe1\x7c\x70\x0e\x42\x51\xc4\xfd\x1b\x53\x4c\xec\x6b\x82\x27\xf7\xd9\x4e\x54\xc7\x23\x0f\x1f\x44\xf8\x30\xd8\x0d\x9a\x8f\xbe\x6e\x2d\x9e\x0d\xfd\x7e\x3c\x62\x44\x30\x3d\xd3\x09\xba\x4c\x1e\x8f\x3e\x30\x1d\x84\xf9\x77\x0e\xd8\xa4\x13\x20\x65\xb0\x1b\x24\xe7\xc2\xb0\x0c\xf6\x03\x6b\xf1\x0e\x29\x1e\xb3\x75\x5a\x3e\xd3\xd1\x84\xc4\x5a\xbd\x51\x1f\x79\xf9\x22\xad\x78\x84\x51\x6e\x03\xe5\xec\x9f\x1d\xa3\x56\x7b\xce\xc1\x27\xcc\xe5\x8e\x3d\xd4\xe0\x9a\x62\x19\x9e\xef\x22\xde\x82\x41\xdc\x31\x39\xfd\x36\x94\x2b\x3d\xc7\x94\xcf\x66\x0d\xb1\x66\x72\xa8\x6b\xf0\x16\xc5\x47\xb3\xb6\x54\x31\xb3\x3f\x98\x1b\x1a\x0e\x46\x1f\x8f\x9f\xf6\x95\x4e\xdb\x42\x16\x00\x78\x32\x60\xd7\x9b\x48\xe2\x1c\xc0\x10\x2d\x99\xdd\x15\x5a\xb0\x3e\xeb\xa9\x0b\x0d\xce\xe7\x03\xf4\xd6\x58\x0e\x92\xc1\x12\x14\x1f\xcb\x41\x1d\x95\x54\x11\x9a\x19\xb6\xdf\x0f\x7d\x5a\xcd\xcb\x05\x33\x7f\x8e\x47\x4d\xd3\xb9\x5e\xb0\xea\x8c\x88\x02\x53\x07\x94\x35\xe5\x14\x02\xaf\x67\xf3\x62\xb1\x30\x04\x1f\xc5\xb3\xe8\x8f\x5d\x9f\xb0\x41\x31\x01\xcb\x63\x36\x17\x96\xa9\x64\xad\x73\xf7\x95\x8c\x14\x4e\x2a\x5a\xe9\xb9\xb2\x47\x36\x18\x67\xb8\x40\xc5\x99\x05\xea\xb1\x57\xf4\x6e\x28\x7e\x41\xe0\xe8\x0a\xc6\x9b\x85\x61\x90\x35\x3f\x12\x0c\x4f\x38\x87\xc3\x38\xd8\x41\x54\xa9\x48\xd3\xd2\x60\x2a\x31\xe7\xde\x33\x78\x71\x3c\x1a\x8a\xf1\x78\xe4\xd3\x74\xae\x16\x2c\x85\xf1\xf6\xad\x59\xa5\x23\xf3\xd2\xad\x1d\xaf\x29\x18\x22\x14\x73\x8d\x2b\x67\x16\xaf\x1d\x00\xb5\x7f\x62\x10\x10\xb5\xd2\x11\xa7\xf3\x9d\x0f\xec\xc7\xf1\x60\x52\x57\x82\x7b\x91\x82\xea\x32\x80\x1c\xaf\x02\x9e\x2d\xd2\xe6\xfe\x9a\x95\x75\x7b\xc5\x74\x00\x2d\xe6\x0b\x97\x6f\xa9\x62\x61\x9a\x55\xea\x3c\x58\xfe\x89\x42\x8a\xef\xd3\x0d\x7d\x2e\x1b\xa7\x00\xf7\xa9\x7f\xb5\x56\xfe\x9f\xd2\x91\xc3\x8e\x90\x06\xeb\x36\x1e\x11\xfa\x4f\x88\x47\x82\x06\xbb\xcf\x25\x38\x01\x08\x62\x96\x1b\x3f\xf3\x8d\x0c\x82\xe5\x38\xb4\x5d\xa0\x37\xcd\xd4\x6b\xc8\xa4\xa1\x37\xd0\x1f\xc4\x91\xc8\x3f\xc8\x6e\x3e\x77\x8b\x92\x00\xe5\xf5\x84\x32\x6e\x2f\x08\x33\x6b\x05\xbf\x08\x05\xd0\x42\x75\x0d\x7f\x31\xd4\xba\x81\xf0\x48\xb0\xb9\x45\x68\x65\x45\x28\x5b\xef\x0c\xef\x7b\x61\x36\xa8\x13\x5b\xdd\x8e\x05\xf6\xae\xae\x5c\x9d\xce\x48\xad\x28\x17\xfa\x30\xc3\x39\xd3\x87\x79\x05\x7d\x40\x9d\x6e\x1f\x7e\x46\xc0\x87\x5f\x58\x78\x78\xa6\x2b\xfb\x16\x7a\x53\x8d\x0f\x7a\x5f\x1d\x3b\x2e\x0b\x45\xcf\xf4\xe7\xd8\xa4\xad\x4b\x51\xd9\x8a\xc2\x6d\x6b\x21\x92\xb7\x7a\xc1\x6c\x6d\x4e\x06\x2c\x7b\x1d\x16\x1d\xba\xab\x8f\x0d\x5c\x8e\xfe\xf6\xea\xbb\x77\xb5\x3d\xd4\x0d\xbe\x6e\x24\x10\x70\x4a\xc1\xb7\x67\x3e\xf7\xf2\xb3\x78\x30\xd2\x74\x30\x58\x2c\x88\x6f\xfb\x4c\x8a\xbb\xd4\xa3\x76\xec\x24\x80\xb3\xff\x92\xd1\xff\xfd\xe2\xa0\xeb\x18\xe2\x45\x00\xc2\x8b\xbf\x38\xf0\xfa\xff\xba\xbe\xff\xaf\xef\xbb\x53\xad\xb2\xf5\x06\x61\xd1\x60\xc4\x17\xf4\xc1\xf1\x58\x71\xc6\xc3\xa3\x19\x3f\x34\x04\x27\xe2\x70\xdf\x6f\x7f\xcc\xbf\x1d\x8c\xb8\xfb\x74\x97\xea\x69\x61\x5b\x91\x4f\xdb\x5f\x77\x4a\x80\x7a\x8c\xed\xda\x83\x71\xd2\x45\xe8\x3f\x8e\x63\xb8\xbc\x30\xfb\xb4\x08\x69\x28\x03\x71\xe0\xe3\x48\x49\xe6\x96\xb2\x6a\xf3\x1a\x9d\x33\x61\x93\xb1\x88\x0e\xc4\x91\xc3\xe1\x25\x07\xfb\x1f\x77\x63\x85\x05\x3c\xe8\xc0\xd7\xa5\xde\x5a\xe6\x8c\x8e\x68\x96\x18\x6c\x5f\xd9\xc4\x2a\x55\x48\xe6\x36\x83\x13\x04\x02\x43\xa3\xd4\x1e\xb3\xb5\xd9\x41\x34\x11\xc0\x1c\xc0\xe4\x6d\x59\x8e\x41\x3e\x8d\xf3\x71\xeb\xdd\x37\x32\x2a\xd1\xbf\x98\xb4\x5e\x69\xfb\x4a\x52\x7d\xe6\x8d\xc7\xa2\x67\x6b\xec\xf4\xd9\x57\xb7\xf8\xaa\xf6\x5c\x53\xc1\xd0\x39\xce\x2d\xec\x73\x09\xce\xaa\x9c\x0c\x87\x95\x55\x49\x14\x84\x16\x35\x84\xda\x68\x2d\x69\x77\x35\x35\xae\x66\x3b\x3b\xc4\x5c\x9b\xf1\x72\x1c\x6f\x48\xda\xda\xa2\x83\x6d\x63\xc6\x7c\xab\x17\xb5\xbd\xf3\x3f\xa4\x77\x3c\xf7\x11\x33\x90\x66\x87\x78\x13\x81\xcd\xfb\x17\xd5\x3a\x2d\x79\x6e\xc8\x69\x7a\x70\xb0\x22\xa9\x28\xb8\x56\xf3\x95\xd8\x71\xf0\x5b\xff\xb7\x8c\x7a\xc0\x09\xe4\x73\xb0\x1e\xed\xa0\x1e\xea\xa1\x12\x0f\x2d\xe7\xd5\xb6\xc3\xaa\xac\xd9\xd7\xc2\x9c\xc7\x13\x87\x4d\xb1\x8a\x04\xf8\x5c\xe6\x3a\x32\x3b\x45\x8e\x47\x09\xcf\xbf\xe2\xa3\x13\x29\x4c\x3c\x37\x59\x47\x95\x39\x07\x07\x15\xdb\x29\xb1\xcb\xeb\x29\xb8\x4b\x57\x54\x30\xeb\x34\x1b\x91\xc4\xea\xf8\x3a\xac\x87\xa6\x82\xa6\x84\xd4\x1d\x7f\x3d\x4e\x94\x21\xf9\xca\x20\x7d\x86\xaa\x4f\x9a\x72\x2a\x30\x8c\x87\xf7\x56\xf7\x0b\xa9\x1e\x58\xba\xc6\x19\xe0\xe7\x88\x93\xd9\x77\xc2\x90\x78\x36\x7c\x39\x95\xa4\x65\xdf\xfc\x6f\xd9\xf1\xc3\x75\x37\x49\xb6\xae\x6f\xa3\xff\x6a\x94\x7a\x02\xd5\x4e\x36\xf4\x15\x43\xaa\x03\x5d\x60\x2f\x2b\x72\xa8\x58\x33\xda\x3f\x04\x32\x92\xe1\xe6\x8b\x8e\xeb\x4f\x8b\xe1\x68\x82\x52\x0c\xd6\xea\x9e\x97\x03\x73\x2b\x30\xf2\x5e\xa4\x68\x63\x30\x5a\x59\xca\xe5\x0b\x73\xfe\x0c\x2f\x44\x1d\xe7\x43\x6d\x40\x4e\xe7\x87\x30\xc8\x5c\xa4\xbb\x41\xe0\x94\xf8\x6b\x9b\xd3\x72\x21\x53\x5b\x0c\x94\x3e\x1e\x41\x06\xf1\x85\xf4\x42\x08\x4d\x5c\x3e\x3c\xde\x2c\xe5\xcf\x6d\x7e\xc0\x1f\xd9\xc0\xf5\xe4\x42\x98\x5d\x67\xc0\x51\xcc\xc4\x9c\x2f\xc6\x72\xce\x17\x89\x29\x1d\x9b\xb2\x60\x63\x7e\xe9\xb0\x58\x2e\xd0\x66\x13\xf6\x2c\x75\x78\x72\xca\x3b\x39\x8f\x51\x96\xfb\x0e\x6c\x71\x06\x20\xde\x05\x51\x90\x7c\xa1\xee\x36\x05\x87\xe4\xd4\x8b\x16\xad\xfa\xc7\x5f\xf8\x98\xef\xed\x6d\xa9\x6e\x4b\x5e\x55\x27\xbd\x7d\x27\x3d\x71\x32\xd8\x4a\x6b\xe3\x34\xb8\x74\xae\xd6\x1f\x85\xcc\xd5\xc7\xe1\xb0\xef\x5d\xae\xb2\xad\x41\x86\x81\x0f\x7d\xa8\xfa\x30\x3d\x0f\x87\x3d\xce\xdb\x9a\xb9\x96\x71\xa3\x6c\x79\xbe\x7f\x6d\x40\x7b\x02\x02\x32\x1f\x0a\x42\x33\x8c\x83\x82\x62\x33\x30\x8b\xb2\xae\x68\xf8\x40\x3c\xd5\xfd\x9b\x64\x87\x9a\xfe\x24\x59\xc8\x12\xc0\x78\x3a\xdc\x23\xf0\x33\x55\xf4\x9b\x6c\x79\xde\xba\x0e\xcd\x29\x21\x04\xb5\xb5\x8e\x60\xfe\xf6\xc4\x9a\xa0\xa3\x7b\x70\xba\x15\x43\x3e\x23\x6d\xfb\x83\x0c\x1d\xca\xbf\xc6\xe8\x2c\xec\x27\x69\xaf\x5c\x8f\xfe\x1c\x6d\xbe\x2e\x44\x75\x91\x16\x25\x4f\xf3\xfd\x85\x90\x17\xdb\x8a\xc7\x17\x10\xf5\xf1\xe2\xa3\xd0\xeb\x8b\xd7\x2f\x2f\xfe\x36\x18\x55\xb1\xc8\x47\x83\xbf\x5d\xdc\x6d\x2b\x7d\x71\xc3\x2f\xac\x34\x98\xe7\x17\x28\xc0\xbe\xd0\x6b\x7e\x81\xd3\x31\xff\x4c\x95\x92\x6f\x2b\x9e\xc7\x03\xe2\xd1\x2c\xef\x02\x3f\x1b\x02\xaa\x8d\x97\xa8\x6c\xc7\x55\x9c\x5a\xf1\x7e\xaa\x57\xaa\xbc\x63\x12\x05\xcb\x02\xac\x45\xde\xda\x52\xe0\x51\x3d\x4a\x94\xbe\x76\x9c\x66\x7f\x6c\x45\xc9\x5d\x6f\x8a\x96\x71\x5a\x6d\x78\xa6\xdf\x99\xc3\x0a\xf1\xd1\x86\xc3\xc2\x6e\x04\x5d\xb3\x6c\x38\xcc\x5c\x78\xd9\x1c\x9f\x30\x6c\x30\xea\x9e\x73\xf6\x6f\x47\xdf\x66\x7a\xc7\x0a\xfb\x13\xb7\x31\xc3\x27\xcc\xe7\x99\xe3\x83\x4d\xe6\xb9\xb6\x34\xb1\xa3\xd4\x4b\xfb\x1c\x8c\x05\xa9\x97\xa0\xc0\x56\xc1\x58\x63\x6c\x6e\x75\xd5\xcb\x3b\x6e\x19\x44\x5f\x02\x71\x57\x2a\x2b\x94\xc6\xb2\x1b\xb5\xe3\x4d\x8d\x6c\x5b\x96\x5c\xea\x97\xfc\x5e\x64\x98\x57\x0a\xbf\x18\xb6\xf0\xd0\xaf\x55\xba\x4c\x33\x2d\xee\x79\xf3\xad\x22\xad\x34\x98\x93\xb5\xab\x15\xd6\xb8\xac\x32\x17\xc2\x8e\x0a\x62\x7a\x7d\xdf\x1d\xad\x95\xea\xb8\x6a\xf0\xd8\xee\x2b\x54\x81\x7f\x90\x58\xf8\xc5\xa6\x54\x3b\x11\xb4\x5b\xae\x45\x9e\x73\xf9\x5a\xe6\x22\x0b\x8a\xd1\x58\x0f\x50\xb0\x9b\x80\x83\x4b\xd5\x4b\x51\x19\xdc\x9f\xb7\xbe\xe6\x73\x3f\xb5\x86\x90\xab\x77\xbc\x12\x7f\x72\x26\x22\x0c\x8c\x65\x4a\x2d\xc7\x34\x28\xe1\xd5\x80\x10\x5a\xc6\xf8\xfb\x25\x87\x7c\xd6\x13\x42\x7f\x93\x73\x19\x8b\x7c\xc1\x24\x38\x26\xcf\xa2\x34\xc6\xa5\x89\x24\x1d\x64\x16\xba\x0e\xe8\x2f\xe0\x22\xda\xbc\xd9\x58\x48\x39\xa0\x7f\x48\x73\xfe\x83\x13\x0e\xf7\xc1\x4d\x6b\x38\x94\x6e\x18\x84\x24\xce\x0c\x95\xe3\x6d\x7e\x95\x8a\x82\xe7\x17\x5a\x5d\xe0\x2d\xbb\xc0\x80\xa6\xe6\x3a\xfe\x4d\x5f\xd8\x8b\x70\x61\xe7\x7b\xb1\x2a\xd5\x1d\x5c\xda\x5b\x71\xcf\xe5\x85\xd0\xfc\x0e\xf5\xc2\x17\xc1\x11\x3c\x21\x12\x0f\xc1\x4b\x48\x27\x26\xa4\x4e\x85\x7c\x16\x94\xf2\xda\x67\x29\xb1\x21\x8f\x25\x0d\xcf\xb9\xa3\xd7\x1d\x88\xfc\x22\xd2\x64\xc6\x87\x43\x35\x53\x89\x9c\x89\x2b\x99\x60\x56\xb8\x73\x3c\xf6\x83\x2c\x76\xc8\x61\xeb\x87\xb8\xeb\x87\xd8\xea\x13\xae\xba\xb5\x1d\xed\x48\xd8\x5e\xa2\xdc\x41\xb0\x81\x5a\x8f\xd0\xc6\x1f\xa5\xe4\xd5\x46\xc9\x4a\xdc\xf3\x99\xb6\x87\x27\x22\xc9\x9e\x47\x3a\xa8\x94\x77\xee\xa9\xe9\xe0\x46\xc8\x1c\xed\x56\x21\xb6\x5f\x1f\x3a\x77\x1f\xab\xfb\xe0\x63\x4b\xd6\xee\xc1\xe3\xcc\xdc\xb1\xe6\x31\xb9\x34\xf8\xf3\x78\xec\x43\xbc\x3f\xae\x56\x55\x56\x72\x2e\x5f\x58\x8c\xa8\xc1\x94\x39\x95\x59\xcf\x5b\xe8\xf7\x27\x0e\x61\xb7\x72\x51\x5b\xde\xdf\x7d\xff\x0f\x1b\x1a\xcf\x02\x5d\x07\x4d\x11\xae\xd6\x95\x36\x78\xd0\xd5\x4d\xc1\xe1\x03\xea\xdb\xf7\x76\xd5\x60\x42\x69\x5c\x6e\xa5\x84\x34\xc7\xa6\xc2\xcc\x93\xbb\xe2\x4f\xfe\x1c\x76\xe0\x65\x99\x7e\x74\x69\xc0\xb5\x3b\x90\xbc\x4e\xc2\x9a\x28\x97\x0b\x1f\x5a\xec\x2c\xe4\x88\x74\x71\x1d\x0d\x55\x6b\xc7\x6d\x28\xda\x9e\x0b\x60\x68\x9f\x10\x8a\xa7\x4c\x34\xe8\xa8\x6d\xb2\x1b\x41\x88\x2a\x5a\x61\xf8\xd2\x33\x50\x9a\x1a\x7c\xd6\x3d\x12\xc7\x63\xbb\xd3\x6e\xa3\x88\x4c\x6d\x8c\x6a\xc6\x58\xda\x44\xb5\xb6\xe8\xc8\x94\xe1\x4f\x74\x68\x29\x8e\xc7\xc8\xd5\xb7\xb5\xa9\xaf\xec\xaa\x52\xd1\xc6\x57\xed\x69\xee\x79\x24\x68\x01\xda\x69\xd1\x3d\x9e\x16\x62\xd2\x83\xf9\x97\xa4\xb5\xa1\x38\x65\xac\x24\x02\x59\x3a\x17\x34\x05\x73\x03\x11\x00\x3a\xd1\x40\x61\x43\xd2\x89\x18\x2d\xc7\x23\x42\x6a\x2e\xab\x6d\x69\x4d\x39\xbe\x49\xef\xf9\xeb\x97\xe6\x7a\x7f\xdb\x8e\xc6\x18\x28\x01\x22\xab\xf0\x3a\x68\x83\xc0\x79\x4d\x48\x7d\xb3\x15\x45\xfe\x63\xf9\x33\xc0\x52\x6b\x14\xf2\x89\x68\x9e\xd6\x1c\x06\x9c\xdc\xf0\xa7\x62\x1d\xe5\x40\xc9\xf3\x6d\xc6\x23\xf7\x3d\x8c\x48\x64\x30\x11\x21\xf4\x50\x3b\x3e\x68\xbe\x98\x82\xb3\x17\xab\x9c\x29\x5f\x27\x38\xcb\x5d\xba\x69\x4b\x99\x0d\xf9\x4f\xa5\xd7\x2f\x28\x36\x40\x77\x73\x5a\x59\xc9\xb8\x8b\xa5\xef\xe1\x34\xa7\x79\x93\x53\x69\x16\xb0\x36\x49\x35\xf3\xb9\x37\x2c\x03\x94\xa3\x14\x65\x36\x28\xd3\x5c\xa4\xc5\x1b\x01\x59\x06\x4c\xc5\x2c\xd5\xfc\x56\x95\x7b\x53\x15\x4b\xeb\x1a\x04\x1e\xdf\x46\x15\x0d\x74\x08\x55\x70\x41\x52\x66\xc8\x24\xd4\x86\xa4\xe6\x68\x17\xec\xbb\x08\xa5\x4f\x54\xc4\xf0\xad\x40\x54\xdc\x64\x03\x18\x0e\x7f\x95\x51\xf3\x48\x4b\xc2\x18\xfb\x55\x46\x22\xce\x03\xb5\x55\x50\x83\x85\x6f\xa8\x9a\xa7\x0b\x76\x39\xb1\x01\x60\xc0\xd3\x53\xac\xa2\xd4\x10\xb4\x72\x38\x94\xf3\x74\x81\xa2\x5b\xc6\x0a\x92\x31\xf3\x8c\x61\x21\x32\x43\x66\x58\xad\x34\x5a\x44\x15\x84\x44\x07\x91\x27\x29\xca\x43\x0a\x88\x07\xae\x21\x48\x34\x22\x54\x5d\x13\x2a\xe7\x19\xa0\xf9\xac\xce\x62\x03\x6d\x41\x04\x50\xc3\xca\xa8\xe0\xbc\x1d\x8f\xd6\xa0\xd0\x70\x71\xf8\x5a\xa2\x0d\xcf\xd7\x3c\x76\x21\xcd\x00\xe4\x50\xcf\x49\x11\xfa\x35\x44\xdf\x79\xae\x76\x08\x98\x08\xa9\xad\xf3\x80\x25\xa6\x30\x18\x7f\x8f\xd8\xcd\x91\x86\x70\x48\x81\x15\x9d\x4a\xeb\x06\x2e\xe6\x72\xc1\x0c\x43\x49\xcd\x1f\x66\xd0\x0d\x54\x60\xbc\xdb\x7b\x7f\x48\x52\xdf\xb5\x60\x5d\xa5\x92\x75\x5e\x6b\xfc\xd8\x30\x2b\x80\x08\x4d\x81\xc4\x94\x43\xd8\x09\x4e\x34\x18\x9d\x18\xde\x21\x88\xf3\x6a\x18\x17\xee\x52\xe9\x0a\x2a\xc7\x02\x72\xf3\x77\x48\x48\x1e\x57\x98\x6b\x97\xc4\xe6\x4d\xf4\xb3\x8c\x06\xe0\x25\x35\xa0\x03\x98\xcc\x80\x00\x18\xbf\x53\xf7\xfc\x67\x59\xf2\x15\x2f\xb9\xcc\x9a\x0e\x4e\x22\xbe\xfb\x59\x99\xfb\x02\x79\x90\xdd\xa4\x12\x51\xd7\x4c\x4f\xdd\x8c\x9e\x0a\xcf\x1e\x36\x11\x2b\x91\xec\x0e\xa5\x74\x20\xff\x60\x4f\x0f\x13\xc6\x58\x4b\x7a\x01\xaa\xbf\x78\x69\x7b\x27\xc4\xf7\xd6\xbf\x1a\x92\x9c\xc0\xa8\xd0\xec\xee\x64\x7f\x50\xc7\xdf\xde\x16\x17\x5c\x06\x24\x5c\x10\x53\xf6\xfc\xb2\x50\xc9\x26\xa1\x87\xac\x7c\xa2\xa6\xb2\x31\x6b\x50\xcc\x9c\x1e\xe7\x98\x08\xe8\xa6\x35\x58\x1f\xcc\x5e\x79\x4d\x62\xa0\x2d\x01\xde\x13\x7e\x0d\x87\x95\x8b\xb9\x9b\x62\x5e\xf8\xde\xb9\xd3\xde\x8f\x10\x6a\xed\xe8\x53\x5a\x35\xfa\x49\x97\x60\xd9\xeb\x2a\xd3\x86\x8e\x32\x2d\xe0\x78\x30\x85\xff\x8f\xc7\x09\xd5\x71\xdf\x5d\xaa\x20\x0c\x28\x2a\xd6\xd8\x60\x30\x52\x36\xbd\x76\x15\xdf\x63\x4c\x62\x73\x9f\x2a\x3b\x20\x17\xa0\x19\x9a\x34\xd6\x8d\x24\x7c\xb0\x54\x3a\xf6\xde\xa9\x18\x17\x42\xfe\xee\x70\x8e\x85\x42\xf6\x1a\x3f\xf3\xac\xaf\xb5\x26\x4d\x09\x3d\xb4\xb5\x0c\x1f\x00\x58\xc3\x71\x0d\x4b\xca\xba\x65\x79\x90\x2e\xa6\xed\x84\xb5\x41\x00\x69\xec\x31\x6c\x8c\x9f\x75\x16\xa8\x25\xa1\x7d\x9f\x1c\x0e\xdb\xd5\x14\xa9\xdb\xf3\x02\x86\xcd\x86\x54\xb5\x06\x38\xad\xf5\xf1\xd1\x26\xbb\x7b\x60\x4e\x20\x07\xfa\xcb\xf7\x7e\x92\x11\xfe\xdb\xa8\x73\xbe\x69\x64\x63\x34\x1e\x4e\x0e\x8b\x20\xe1\x6a\x43\xb7\x91\x19\x2c\xd8\x2d\xc3\xc3\xc1\x93\x7f\xe1\x17\x91\x12\x3d\xa5\x5d\xb8\x1e\x10\xa7\x2f\xeb\x0d\x63\x8d\x3a\x33\xe1\x59\x33\xca\x1b\x4e\x5f\x74\x65\x1e\xa2\x57\xe6\xd1\xcd\x01\xfb\x6d\xe4\x29\x0e\x20\x05\xbe\xe6\x31\xde\x60\x83\x16\x20\xee\x7e\x60\x38\xc5\x7b\xd9\xdc\xcb\x7e\x49\x60\x2f\xf5\x44\x79\xdc\x4b\x12\x79\x71\x92\xd5\x90\xb4\x48\x15\x1e\xf0\xfd\x98\xfe\xc2\x56\x6a\x3e\xcc\x81\x65\x01\xf9\xd3\x16\x05\xb3\x90\x30\x61\x2b\x5b\xfc\x0c\x6f\xb1\x37\xb0\x7c\xde\xb0\x2c\x30\xd7\xa3\x18\xe8\xb0\x9f\xd5\xc2\x71\x0f\xe8\xe1\x4e\xe5\x3c\xd1\xb4\x31\x02\x04\x83\x9d\x6e\xde\x8d\xce\x7c\x5b\xe0\xf5\x54\x5c\x8a\x9f\x70\x27\xc5\x7e\xca\xe9\x1f\x26\xa1\xa9\x1a\x1c\x88\x3e\xfc\x38\xd5\x4f\x44\x60\xbc\x76\x68\x4e\x68\x22\x6a\x34\x50\x0d\xcf\xb0\x36\x64\xde\xa5\x1c\x0e\x41\xb2\x9c\x06\xd6\x6d\x53\xd1\x1e\xba\x3f\xbf\x8a\xb8\x70\x66\x77\xe9\x2e\x1a\x09\xcb\x6c\xfc\x78\xcf\xcb\x55\xa1\x3e\x46\x84\x96\xa4\xe6\xf1\xf2\x4e\x48\xeb\xc9\xc6\x4a\xb3\xd4\x78\x6a\xdf\xa4\x7b\xb5\x85\xcb\x2f\x8f\xc7\x6f\xa3\x14\x8f\x9d\x6e\xae\x0f\x69\xea\xda\x81\xa2\xf9\x61\x2f\x2f\xda\xd9\x0d\xb0\xe7\xb1\x92\xac\x06\x77\xff\x39\xa0\x83\xa5\xc8\x0d\xda\xc6\xd7\x56\xb4\x34\x1c\xf2\x78\x09\x27\xe7\x9b\x54\xe6\x05\xc8\x09\x9b\xb7\xc0\x62\x70\xcf\x0e\xd4\xed\xf1\xf7\x25\x02\x79\xe0\xd4\x60\xab\x01\x3d\x9c\x39\x2e\x5f\x73\x77\xa9\x0d\x85\x86\x8c\x91\x4f\x3f\xd5\x4a\x2e\xef\x49\x6c\x60\x17\xa1\xe6\x13\x36\x31\x7c\x1a\xd6\x7e\xc2\x26\x53\x1e\x4a\xf3\xbe\x85\xac\xcb\x3b\x77\xc1\xe5\x70\x18\x90\xe9\x8c\x41\x3c\x0b\xa4\x6e\xc1\x6a\xca\x53\x8b\x8d\x31\xa7\x21\x1d\xc3\x85\x75\xe1\x32\x74\xec\x13\x14\x10\x03\xf7\x78\x58\xa9\x21\x56\x3c\x53\x64\xf6\x00\xd8\xa2\x33\x9b\x69\x17\xc9\x2f\x75\xb0\xfd\x5d\x60\x38\x70\x62\xf9\x40\xf6\x8e\x7b\x70\x79\x76\x0f\x5c\x77\x9f\xba\xc1\x9e\x9c\x44\x6a\xe5\xcc\x35\x33\xb4\xcb\x68\x24\x49\xf7\xb0\x46\x92\x8a\x99\x8e\x1c\x36\x05\xcc\x9c\xc8\x9a\x24\xba\xe7\xbe\xc3\xb4\xcf\x8c\xab\x26\x75\x67\x21\xce\x88\x0c\xfa\x6e\xf4\xc1\x50\x9c\x89\xb4\x49\xeb\x35\x85\x2e\x79\x67\xaa\x53\x58\xad\x13\x2e\xba\xb5\x5a\x6e\x50\x0a\xdc\xea\x42\x7c\xb7\x74\x07\x16\xa2\xa9\xf9\x8e\x0d\x1f\x7a\xd2\x65\x38\xcf\xa6\x47\x83\x26\xe5\x69\x86\x24\x1c\xd6\x19\x49\x97\xd5\x25\x9d\x5c\xa4\xe1\x30\x4a\x6d\x20\xf0\x99\x0e\xd8\xfb\xcb\x40\x74\x03\x91\xc8\xc1\x42\x34\xd2\x24\x89\x6c\x3a\x09\x42\x7f\x91\xd1\xc1\xb3\x5c\xc4\xe6\xfa\xe8\x8c\x09\xd8\x0b\xcc\x47\x77\x22\xf7\x71\xa0\x16\xa5\x3f\xdc\x67\x84\xac\x59\x4f\xe5\xa9\x2f\xb3\x26\xad\x3d\x72\x24\x30\x47\x85\x6f\x79\x4b\x97\xe0\xa6\xeb\xe6\xa6\x3b\xf0\xe1\xa0\xcf\x99\x45\x33\x9d\x9e\x87\x3d\x4d\x60\x1b\x7b\x77\x01\xcf\xa0\x5b\x45\xc3\x8f\x18\x76\x2e\xfe\xd3\x40\x17\xc3\x5d\xc1\x13\xe6\x44\x69\x20\x12\x71\x3c\x80\x79\xe1\x2f\x2f\x09\xba\x79\xa8\x6d\xbf\xb0\x11\x86\x8e\x3e\x20\x98\xbc\xa3\x95\xb5\xe3\xc4\x1e\xb9\xcd\xc9\x51\xe1\x02\x9d\x38\x06\xc5\x5d\xe9\xce\x25\x6e\x62\x13\x1b\x06\x44\x0f\x87\x97\xca\x51\xe4\x20\x01\x33\x00\x4f\x05\xc1\x81\x1e\x4e\x25\x72\xe2\xe9\xd4\x33\xf2\x4b\xb0\xea\x6f\xad\xd3\x49\xea\xc3\x07\xb7\xd4\x36\xfb\x9c\xad\xe5\xec\x53\xc9\x4f\x3c\x65\x21\xfc\xda\x8c\xaf\xa7\xe2\x29\x9b\x4c\xc7\x63\x41\xda\x5b\x1a\xf1\xb9\x58\x9c\xdd\xaf\x70\x5c\xed\x29\xf6\xd3\xb4\x90\x13\x4b\xc7\xcb\xac\x10\x1b\xd8\x9a\x06\xc1\x55\x16\x8c\x69\x07\xc6\x90\x3a\xe9\x85\x62\x0f\xc3\x7c\x5c\xa5\xca\x40\x09\xc8\xb2\x85\x19\x5d\x61\x7d\x25\x44\x86\x9c\x4d\x12\x05\x3f\xc6\xf8\x6c\x13\x23\xd9\x1a\xf0\x30\xb3\x78\x39\x51\x36\x63\xa7\x2d\x87\xf4\x8b\xb6\xa2\x56\x1b\xe8\x49\xab\xcd\x18\x9e\x5c\xa6\x25\xfb\x1e\x9f\x66\x0e\xb3\x27\xca\x96\x8c\xdc\x2b\xc3\x3d\x84\x40\xd6\x42\x28\x48\x7c\x45\xab\x0e\x98\x7d\x10\x9d\xb8\x29\x87\x4e\x7f\xd5\x33\x24\x6d\x5e\xa9\xf2\x7b\x95\xf3\x53\x2b\xf7\x1f\x79\x6c\x30\x45\xd5\xc4\x40\xef\x41\xb4\x6a\xa6\x30\x1f\x13\x06\x9f\x4d\xe6\x90\x8c\xa7\x8d\x82\xda\xd7\xb2\x85\x40\xe7\xba\xf1\x14\x70\x72\x11\x6f\xbd\x15\xca\x32\x50\x6a\x81\xad\x42\xd5\xb5\xb7\xed\xc2\xc8\xec\x73\xbd\x60\x68\x1e\x04\xc1\x65\x40\xbe\x32\x5f\x38\xd6\x12\x0b\x03\x22\x18\x9e\x51\xa9\x87\xbf\x77\x68\xd4\x8b\x0f\xfb\xf0\x01\x98\xf9\x84\x1b\x32\xd1\xf3\xf5\x0e\xa1\xba\x81\x25\x9c\x2e\x37\x69\x59\xf1\xdc\x7c\xd4\xc2\x9f\xe4\xf2\xba\xb6\xd6\x65\x9e\xd5\x6a\x01\x05\xa7\x0d\x74\x9e\x40\x5e\x3b\xe8\xf0\x10\x2c\x2f\x84\x4b\x82\x82\x41\x0d\xdb\xd8\xbe\xbb\x2f\xd4\x56\x76\x3b\x7e\xf8\x9a\xdb\xab\x5d\x9f\x88\x18\x3e\xb5\x61\x98\xe7\xce\x7b\x39\x4d\x5b\xe2\xc0\x93\xcd\x77\x47\xe7\x46\xa9\x82\xa7\xc1\xc9\x11\x31\x2e\xfc\xec\xd2\xfd\x4a\x2e\xb9\xfd\x55\x57\xbe\x1b\x18\x95\x28\x84\xde\x23\xc5\xd3\xff\x15\xdb\x8e\x5d\xf2\x5a\xab\xdb\x5b\x9c\x6b\xd8\xd4\x71\xdf\x2d\x0d\xae\x39\x2d\x97\xfd\xe5\xee\x14\xb7\xfb\xb0\x73\x3e\xd3\xa4\x4d\xa0\x75\x07\xde\x21\xd5\xf8\x6c\x50\xad\xd5\xc7\x41\x32\x58\x8b\xdc\x50\x40\xbd\xc4\x5b\xc5\x54\x8b\xcc\xb2\xb6\x4b\xde\x18\xb5\x8a\xbc\x01\xd5\x14\x8c\x19\xfb\x3f\x4e\xbd\x22\x59\xd1\x83\xc5\x65\x09\xaf\x09\xf5\xe2\x03\xcc\xb2\x1a\xd2\xa9\x60\x19\x2f\x9d\x1b\x06\xa9\xd7\xe0\x53\xef\xd6\xf1\xfc\x54\x2f\xaf\x49\x6d\x66\xf6\x59\x75\xad\x3b\x5b\x57\x1e\xd7\x87\x1c\x3c\x7c\x00\x4e\xcd\x3d\xc0\x79\xc4\xd4\xa9\x6e\x95\x20\x4b\x61\xb8\x68\xf6\x03\x11\x09\x52\x31\x05\xed\x49\xed\x2b\x74\x93\x73\x62\x78\x22\x9b\x9d\xd3\xa5\xb3\x69\xe4\x9b\xa8\x35\xa4\xa9\x95\x92\x98\x0d\x43\x9a\xa2\x5f\x5a\xed\x29\x8c\x73\x42\xc8\xa9\x97\x61\xb6\xac\xa0\x31\x6b\x6f\x47\x7c\xf1\x87\x76\x24\xa3\x57\xc9\x95\x1c\x22\x3f\x39\x28\x03\x2f\xad\x95\x08\x80\x30\xd0\x27\xd8\x08\x8d\x27\x08\xdb\x79\x5a\xfa\x45\xfa\x4d\xce\x75\x2c\xf2\x45\xad\xd5\xf3\xb4\xe2\xff\xf8\x5f\xaf\xef\xd2\x5b\xe7\x7d\xdf\xd2\x8d\x63\x3c\x57\xad\xcc\x64\x7e\x7e\xf7\x06\xab\xd4\xe1\x68\x7b\x64\xfb\x5e\x88\x03\x52\x64\x37\x07\x2a\x59\x24\xa9\xc2\xb4\xb8\x69\x9e\xb7\x82\x08\x45\x90\x35\x8c\x50\x43\x97\x31\x55\x53\xe5\xeb\x72\x8c\xb3\x20\xec\x46\xf4\xb6\xf2\x01\x1a\xe4\x82\xd4\x56\xae\xec\xad\xe1\x2c\xea\xe3\xb1\x82\x90\x6a\xbf\x30\x41\xdd\xef\x5f\x99\x34\x74\x79\x5b\x34\x80\x19\x6e\xbf\x0d\x12\x52\xa3\xd0\x09\xd8\x6a\x19\x69\x83\x6b\xfb\x55\xf0\x36\xe9\xc2\xb4\x62\x8d\x28\xd1\xd9\x7b\x79\xed\xbc\x79\x53\x7b\xb1\x11\x24\x9e\x50\xd1\x00\x19\x99\x01\x4d\x4d\xcf\x8d\xd1\xc9\x84\x36\x5a\x7d\x2a\x1b\xc5\x67\x05\x4f\x39\xc7\x46\x66\xc8\x1c\xbb\xd2\x2d\x8b\x15\xd5\x6d\xd1\x7c\xa6\xa6\x22\x16\xd5\x33\x5b\x39\xf2\xb6\x68\xb3\x34\x22\x09\x8f\x08\x26\x03\x69\x8d\xa5\x6e\x1f\xd3\x87\x36\xde\x66\xa3\x6e\x9b\xf1\x80\xbf\x79\xb3\x32\xc1\xd9\xee\xdb\x58\x81\xaa\x2a\x27\x28\x85\x78\x71\x10\xc0\xaa\xeb\x8b\x2d\x66\x83\x8a\x43\xfc\x67\xe8\x67\x10\xc6\xff\x87\xcb\xec\xac\xdf\xbd\xa7\x71\x3f\x3a\x9b\x4f\x16\x2d\x20\x09\xec\xae\x07\x35\xf3\xc1\x72\x30\x92\xa3\x81\x6d\xd2\x0c\x67\xb0\x88\x08\xa1\x29\x9b\x40\x4a\x5d\xe7\xc3\xf9\xa4\xc4\xb0\x95\x15\xd3\xf3\x74\xe1\xe9\x73\x73\x10\x7a\xbe\x5d\xb5\x3f\x1c\x7c\xd6\x2c\x24\x9f\xcb\xd1\xa0\xf5\x41\x1f\xc3\x80\xb6\x5b\x3a\x4d\x06\xa9\x0d\x8e\x7b\x06\xa6\x56\x81\x00\xbc\xc5\xae\xa0\x21\xd6\xf1\x38\x5f\x18\x8c\xdc\xa9\xdb\x0b\xa4\x9b\x16\x40\xc9\x83\x56\xb9\x23\xff\x70\x14\xbc\xa8\x43\x87\x9e\x1e\x61\x24\x10\x1a\xa7\x0e\xf3\x83\x1f\xd4\x85\xed\xf0\x62\xa5\xb6\x32\xbf\x48\xf5\x05\x74\x19\xc6\xe0\xe9\x7e\xd3\x2e\x46\x22\x61\x31\xe6\x62\xe1\x47\x51\x13\x32\xbd\xd4\x20\xab\xc1\xb4\x9d\xce\xfe\x4c\x36\xc2\xc7\x66\x65\x2b\xa8\x47\xea\x36\xf8\xec\x44\x32\x0f\x4d\xca\x62\xe7\x79\x8e\x54\x32\x5c\xed\x9e\x5e\x7b\x42\x3d\x40\x10\x1e\x07\x41\xc0\xe0\x98\x56\x9f\xe1\x47\xdb\x41\xe2\x6d\xac\x6e\x80\x8c\xf0\x6f\xf0\x20\x10\x38\x9b\x15\x48\xf8\x69\xc9\xc4\x4c\x27\xe8\x60\x31\x4d\x3d\xc7\xef\x4c\xc0\x82\x2b\x96\x52\x05\x0c\x82\xc1\xf8\xb4\xc9\x6a\x86\x85\xbd\x2d\x4a\xdf\xc2\xe0\xfd\x16\x44\xed\x23\x91\x0e\x50\x23\xd1\xb4\xe4\x9b\x22\xdd\x9f\x88\xac\x0c\x87\xc8\x9e\x9e\x08\xfe\x8f\xc7\x96\x4d\x86\xd5\x06\x34\xb6\xdb\xe8\x72\x48\x3c\x53\x7d\x46\xe6\x05\xb0\x66\x00\xb8\xa3\x9b\x12\x58\xc4\xcb\x35\x8c\x1b\xea\xe0\x52\x39\x3e\xe4\xb3\xa4\x5f\x41\xdf\x34\xaa\x8e\x47\x69\x18\x5d\x79\xcb\xf3\x96\xd1\x09\x15\xf5\xc9\x77\xda\x6b\x74\xb0\x47\x35\x91\x6c\xbe\xf0\x7e\xdd\xaa\x66\x02\x28\x47\x3c\x33\x29\xe3\x56\x69\x30\x5f\xd0\xc2\x0c\xca\xda\x2a\x58\xca\xfc\x4e\x6d\x2b\xae\xb6\x1a\x72\x61\x59\x9d\x69\x54\x22\x39\x7a\x96\x57\xac\x70\x23\x2b\x83\x8c\x32\x36\xc8\x0a\x91\xfd\x8e\x02\x64\xd3\xc1\x4c\x04\xb2\xf3\x04\x12\xb4\x07\x46\x9c\x40\x8c\x7c\x0d\x0e\x7f\x01\x83\x2f\x42\x25\x81\xb9\x88\x3f\x45\x2a\x56\x12\x8e\x0f\x9d\x6b\x5a\x52\x01\xf6\x3a\x38\xde\xed\x26\x1c\xae\xfd\x7e\xab\x04\xa9\xa0\x3b\x2e\xb7\x4d\xf9\xf1\x88\x9d\xbe\x30\xd5\x83\x4e\x89\x59\x17\xad\xa3\x92\x4a\x42\xa3\xe2\x78\x84\xd4\x7e\xc2\x43\x82\xd2\x8c\xee\xf4\xce\x96\xe0\x1f\xdf\x99\x5d\x46\x0b\x97\x8c\x4c\x2b\x40\xb8\xdf\x46\xdf\xca\xd8\xd9\xad\x21\x89\xa0\xfb\x95\x4d\x84\x50\xae\xd8\x65\x90\xe7\x0b\xcc\x21\x4f\x20\xe0\x87\xb5\xa8\x2e\xee\xb8\x5e\xab\xdc\x85\x0d\x11\x77\x1b\xdc\x2b\x9e\x27\x17\x5c\xe8\x35\x2f\x2f\xa4\xba\xb0\x89\xce\x9c\x79\x34\xc2\x4b\x55\x5e\xa4\xf2\x42\x48\x67\x1b\x7a\x21\xa4\xe6\xb7\x65\x8a\xb1\xe5\xd3\xea\x62\x53\xaa\x7b\x91\x83\x1d\x75\x6d\x95\x6f\x68\x9b\x67\x63\xf5\x0b\x5e\x45\xdf\x4a\x7a\x70\xc1\xc8\x92\x30\x71\x1e\x57\x18\x5c\x35\xd9\xe9\x9a\xfa\x69\xf7\x57\xf9\x4d\xd6\x3e\x66\xde\x99\x2a\x2b\x5d\xd3\xd2\x46\x7c\xe9\xaf\xf1\x4c\xd6\xf4\x9e\x43\x72\xc7\xfe\x0a\x83\xff\x88\x1f\xc7\xd7\x83\x9a\x1a\x1e\x1c\x78\xea\xde\x6a\x3f\x49\xf7\x25\x5e\xf6\xd7\x40\xd2\x96\x3d\x3d\x3c\x43\x37\x55\x78\xa4\x5a\x41\xfe\xe2\x26\x9a\xcf\xa7\x1b\x87\xa1\xac\x6c\x7b\x1f\xd3\x4f\xaa\x5e\xb7\x55\x6f\x19\x7a\x3c\x1e\xea\x1a\x03\x4d\x06\x08\xdb\x1c\x94\x1a\x84\x0f\x2d\xb3\x4b\x28\xc6\xca\xa7\xe5\xe0\x64\xd6\x0e\x20\x6d\x8a\x73\xb1\x5a\xf5\x95\x83\xb4\xfc\xc7\xde\x57\x5c\xe6\xf8\xa2\x5d\x5c\x4b\xd5\x84\x1b\x0c\xfd\x6d\xdb\x76\x02\x52\x85\x81\x02\x49\x0d\x8e\xfd\x4a\xb1\xc3\xd2\x5c\x8b\x44\xaa\xba\xb9\x10\x95\x0a\x09\x8f\xb0\x4f\x03\xcf\xb5\xf5\xc4\x8b\xbf\xb8\x49\xcb\xd0\x77\xe4\x5c\x86\xe8\xc1\x4d\x5a\x5a\xa5\xaa\x60\x41\x00\x90\x1e\xd9\xb0\x1c\x8d\x88\x60\xc2\xd9\xcf\x19\x46\x22\x64\x33\x0d\x31\x55\x14\x6f\x41\xfc\xf3\x4f\x74\xbd\xd0\xc4\xb0\x74\xc1\x88\xd8\x9a\x47\x02\x75\x91\x51\x93\x52\x82\x10\x12\x58\x29\x34\xb5\x6b\x17\xf6\xd0\xe7\xd9\x01\xfa\x19\x47\xe4\xdc\x1b\x80\xa2\xff\x8f\xc7\xff\xf9\x8f\xff\xbc\x64\x4c\x0d\x87\x63\xf3\xfb\x7f\xe3\x6f\xc8\x08\x0a\xda\x90\x26\xd1\x45\x4a\xe1\x67\x7a\x53\x45\x6a\x5c\x91\xe3\x31\x05\x2d\xba\x22\x75\x90\xb7\x87\x77\xf3\xf6\x28\x5c\x42\xb0\xf5\x7c\xa5\x4a\x4c\x3a\x02\xa2\x5f\x5a\x5a\x89\xb1\xf7\x05\x70\xa9\x7f\x30\x35\xf5\xc3\x1d\x7d\x10\xd9\xef\x86\x51\x2d\x1b\x49\x5e\x1a\xa4\xbd\x53\xdd\x2c\x39\x17\xbf\x46\x9a\x3c\x10\x42\x45\xc4\xf6\x0a\xcc\x27\x0b\x30\xaf\x09\x4a\xae\x17\x98\x4c\xb0\x49\xa6\x84\x46\xb0\x5e\x7b\xad\x5c\x32\xb7\x82\xa5\x34\x63\xe5\xd4\xaf\x54\x4a\x9e\xfa\xdf\x90\x98\xb4\x60\x25\xcd\x58\x6a\x78\x51\x01\x51\x2f\x16\x2c\x33\xd4\x62\xb6\xad\xb4\xba\x63\x87\x9b\xb4\x84\xf8\xb2\x49\x41\x6f\xd2\xf2\x2b\x99\x27\x59\x3b\x0b\x06\xbd\x13\x32\x49\xe9\x5d\xba\x4b\x4a\x97\x42\x82\x4a\x92\x34\xfd\xf9\x81\x83\x69\x4b\x90\xb9\x4f\xf5\x05\x24\x11\x60\x3c\x01\x56\x4c\xf7\xf8\x33\x65\xca\xac\xb4\x4d\xa1\x6e\x26\xaa\x18\x63\x15\x2d\x9c\x1a\xc4\xe6\xf7\x47\x6f\x44\x26\xe8\x9a\x89\x91\x9c\x66\x4f\xd6\x90\x1f\x63\xcb\xf8\x3c\x5b\xd0\xdc\x30\x65\xf9\x5c\xd9\x41\x95\x90\xb6\x1c\xc6\x95\x9a\xd7\x19\xa1\x85\x4d\x63\xae\xa2\x2d\xcd\x69\x45\xb3\x26\x45\x6b\x10\x46\xa5\x50\x61\xd4\xb7\xe1\xd0\x1b\x63\xea\xd8\xad\x55\xb7\xf0\x2b\x99\xd7\x08\x11\x33\x75\xc1\x77\x9a\xcb\xbc\xba\x78\x23\x0e\xf0\xf9\xb7\xa5\xb8\x13\x06\x37\xbf\x04\x4b\xfc\xce\x29\x09\xd6\x08\x61\x22\x84\x60\xfe\xbc\xaa\x08\x9a\xda\x75\xad\x6b\x27\xc6\x38\x56\x14\x57\x38\xa9\x6a\xa6\xe9\x01\x44\xc6\xdf\xf1\x7d\x92\xb2\xc1\x6e\x80\x42\x63\xf3\x58\xb2\xc1\x7e\x50\x5b\xd9\xb6\xe9\x59\xc8\x5b\x5a\x58\xdb\x59\x5c\xcf\x59\x9a\x98\x63\x84\x45\x55\x53\xb4\x76\x5b\x94\xd3\x2d\x5d\xd1\x5b\xd8\xa2\x9c\x09\xba\x85\x2d\xca\x9f\x6c\xa7\xa3\x51\x4e\x6e\x19\x9f\xe7\x0b\xba\x32\x5b\xb4\xf2\x5b\xe4\xf6\xa7\xd0\xd1\x2d\x2d\x08\xcd\x09\x5d\xfb\x2d\x82\xc2\x8c\xd0\x15\xad\x68\xde\x6c\xd4\xda\x32\xd0\x10\xd8\x16\x42\xe9\x02\x18\x6b\x16\xa0\xda\x6e\xbc\x7d\xd9\xb9\x4a\x81\x0b\xa6\xbd\x07\x53\x35\x1c\x72\x43\x14\x06\x2e\xd2\x06\xec\xda\x23\x0a\xec\xff\x9d\x90\xcd\x8d\x84\x47\xc3\x24\x08\x08\x69\x7a\x97\xee\x9a\xdb\x09\x8f\xe6\x5d\xba\x43\x3d\x06\x9c\xec\x67\x12\x81\xed\xa9\xf6\xaf\xf9\x1c\x75\x3b\x27\xdc\xce\xc9\x9a\x71\xda\xb0\xf8\x6e\x22\x28\x6f\xb5\x83\xa7\x29\x2b\x54\x54\x91\xd9\x60\x3e\x18\x55\xa8\x2a\x1e\x0d\xe8\x85\x79\xe0\x32\x1f\x0d\x16\x83\x64\x30\x18\x49\x7f\xc9\x3c\x5c\x54\x73\x89\x7b\xe1\x79\x51\x30\xec\x33\xb5\x45\x5f\x6d\x7b\xe3\x89\xa5\x13\xd2\xba\x3e\xef\xfa\xa1\x63\x2e\x0d\x59\x61\x2d\xb9\xd6\x69\x29\xe4\x2d\xbb\x9c\x50\xdc\xa1\xb0\xa1\x47\x3d\xb8\xe6\x60\x39\xda\x32\x72\x8c\x08\x16\x9e\x31\x33\x0b\x5b\x4f\x03\x67\x24\x2f\x00\x40\xce\x92\x4e\xa8\xb5\x8a\xb0\x36\xb9\xda\x89\x63\x1a\x49\x41\x5f\x14\x3a\x5a\x31\x6b\xe7\x06\x56\xe5\x10\x05\xee\xe4\x88\x40\x44\xd9\x5b\xae\x9f\xa7\x15\x3a\x1a\xd8\xd0\xb2\xa2\xfa\x46\x95\xe2\x4f\x25\x75\x6a\x8a\x32\xd3\xf8\x96\xeb\x77\xdb\x02\x18\xa7\x35\x53\xb1\x15\x95\xbf\x6c\xcc\x0e\x9d\x6f\x38\x04\xcc\xcd\x11\x3c\xbe\x07\xe7\x69\xf7\x66\x4d\xe8\x16\xac\x3b\x81\x55\x74\xa5\x92\xe6\x64\xaa\xec\xec\xdb\x0d\x72\x2a\xe9\x3a\xcc\x1a\xc9\xa7\xeb\x27\x7c\x24\xa6\xeb\xc6\x92\x95\xe3\x97\xec\x21\x5b\x13\x2a\x58\x75\x3c\x7e\x11\xf1\x79\x6a\x37\x7e\x76\xb8\x49\x2b\x6e\x2e\x3e\x4f\xf3\xa4\xac\x13\x58\x8a\x22\xdb\x16\xa9\xe6\xcf\x53\x3c\x28\x30\x7d\x18\xe2\x8a\x75\xde\x03\x67\xef\xde\x9b\xeb\x7d\xcb\x22\xee\x6c\x85\x31\xec\x93\xfd\x14\xdd\xb0\xc3\xda\xaf\x1c\x60\xa7\x8a\x27\x22\x36\xff\x28\x9e\xac\xe7\xa0\xde\x7a\x97\xe6\x62\x5b\x25\x97\xb7\xc7\x63\xa1\x22\x8f\xd9\x08\x04\x91\xb4\xf2\x83\xdb\x78\xa9\xd5\xa6\x53\x82\xaa\x4b\xba\x4b\x8a\x99\x88\x61\x3e\xab\x18\xd3\xb2\xd1\x7d\x52\xcc\xdc\x43\x82\x2f\x9d\x79\x84\x79\x01\x7e\x1a\x96\x86\x40\xe5\x6a\x31\xb3\x09\xb7\xf1\x65\x3d\xdd\x0e\x87\xd1\xc6\x53\xc2\xb9\xf9\xf4\xf9\x6d\x5e\x43\x58\x07\xd5\x3e\xb5\x91\x9e\xaf\x17\x74\x4d\x37\x06\xde\xa3\x25\x01\xac\x52\x9f\x65\x7b\x70\x1a\x2d\x7a\xb5\x16\x36\xbd\x94\xa4\xf6\xa1\x24\x21\x42\x50\xe3\x13\x62\xfa\xe7\x39\x78\xee\xd8\x1b\x92\x3a\xf8\x5e\xd2\x02\xce\x0e\xe6\xdd\xac\x7c\xde\xcd\x82\xc9\x79\xb9\xa0\x4d\xfa\x87\x06\x0a\x14\x1d\x9a\xd3\x1e\x2b\x4e\xe6\xad\x37\xa7\x57\x09\x0f\xc0\x54\xac\xa2\x2f\x22\x4d\x8e\x47\x4c\x46\xab\x89\xcf\xe6\x59\x8b\x55\x84\x12\x11\x65\x7d\xcb\x1b\x0b\xc0\x02\xa7\x41\x8e\x47\x1f\xc9\x52\x39\x7c\xcd\x18\x73\xaf\x87\xc3\x14\x51\x8d\x2b\xa0\x85\x3f\x1b\x9a\xdc\x94\x3c\xfd\xbd\xf6\x3e\x56\xb8\x18\xc7\xa3\x6d\x62\x15\x4d\x34\x6d\x76\x05\x95\x9a\x3d\xd1\x62\xed\x9e\x39\xf7\x49\xaf\xcb\xf4\xef\xbc\xb7\x42\x57\xa6\x16\xb7\xb6\x5c\x98\xad\x6a\x56\x79\xd6\xf8\xd2\x73\x92\x8c\xaf\x2d\xf8\x86\xb5\x50\x33\xe9\x8d\x21\x12\x55\x07\xd0\xe6\x21\x0f\x9e\x16\x08\x86\xe3\x63\x4f\x52\x93\x75\x87\xa6\x96\x7c\x9e\x80\xd7\x56\x00\x49\xa7\xd5\x93\x74\x3a\x1a\x55\xc4\x46\xf0\x93\xa7\x24\xb8\x0e\x8e\x40\x45\x1c\xde\xa1\x15\x09\xfd\x9f\x6f\xd2\xf2\xc3\x5a\x64\xbf\x4b\x5e\x39\xdf\xc1\x83\x21\x3f\xcb\xe3\xb1\x52\x91\x24\x74\x03\xa0\x23\x51\x96\x44\x95\x00\x3a\x4a\xfc\x14\x90\xab\x32\x5e\x72\x99\xe3\x73\xe5\x77\x26\xd1\x71\x67\xab\x08\xad\x10\xbf\xd2\xdb\x52\x6d\x37\x3c\x4f\x78\x6c\x7f\x51\x10\x2f\x24\xe5\xec\x3a\xe1\xb1\xf3\xf1\x69\x32\xae\x3c\x82\x61\x36\xcf\x75\x7d\x16\x02\x76\xe5\xce\x87\x7b\x87\xdd\x97\xf6\xae\x01\x7e\x6f\x53\x00\x00\xe7\x94\xa1\xba\x9f\xa7\xe5\x1b\x58\x5e\x43\xbf\xf1\xc0\x85\x88\xb7\x49\x01\x83\x79\x1c\x29\x50\x18\x52\xa0\x24\x0d\xd9\xcc\x52\x87\xb5\xe9\x96\x4d\xe8\x8a\xc9\x19\x8f\xd3\xcd\xa6\xd8\xc3\x6a\x40\x52\x27\x49\x92\x7c\xba\xba\x64\x0c\xf2\xc9\xb1\xd5\x38\xa7\x2b\x96\x43\xf2\xe0\x28\x67\xa5\xa7\x7b\xe9\x0a\x1f\xbe\x92\xf9\x38\x28\x9d\x60\xcb\x97\x3a\xca\x6d\xe6\x63\x57\x8b\x40\x7f\x13\x42\xb7\x23\x96\xbb\x8d\xbe\x65\x5f\x44\x8a\x1c\x8f\xc5\x6c\x9b\x28\x4c\x43\x87\xc0\xaa\x7d\x60\x6e\xc9\x34\x63\x8d\xef\x75\xdc\xa7\xe6\x9e\xf5\xb4\xdb\x8e\x56\x24\xd9\xd0\x35\xcb\xc6\x9b\x06\x2e\x55\xc3\xa1\xe7\x8b\xd6\xe4\x49\x65\x58\x4e\xb6\x7e\x32\x99\x8d\xab\xa4\xa2\x06\x32\x98\xb9\x6f\xc6\x6c\x7d\xf5\xd8\x60\xe9\xcd\x68\xed\xc6\x7b\x67\xa0\xcc\xc4\x80\xa3\x0d\xc8\x60\x4f\xbe\x78\x47\x9a\x9b\x85\x64\x93\x90\x1c\x92\x16\x05\x55\xae\x1e\x4f\xd7\x4f\x27\xb3\x68\x33\x62\x9a\xae\xc7\x4c\x93\x64\xfd\x64\x82\xdf\xd4\x74\x3d\x62\xda\xb1\xd6\xe8\x06\xb8\x46\x84\xb7\x41\x4c\x9b\x51\x8b\x8c\xb2\xd1\xfa\xea\x71\xe7\xc8\x85\x48\xb5\x57\x81\x8f\xa6\xf2\x21\xac\x07\xf2\xb1\xfa\x5d\x6c\x7e\xd8\x16\x05\x4d\xd9\x77\x11\x90\xab\xcf\x83\xfb\x47\xaf\xaf\x26\xc4\xc3\x7e\x48\x3d\x6c\x2f\x48\x03\xa7\xaa\x99\xe8\x5e\x2c\x4d\x12\x1e\x37\x37\xcf\x30\x0d\xab\x82\x5b\x56\x22\xbc\xdf\x0f\xf0\xc6\x3c\xc6\x7b\x6e\x46\x39\xd7\x36\xa5\x1a\xd3\x4f\x27\x33\x35\xd7\xe3\xeb\x05\xda\xb9\x94\x4c\x3f\x51\x1e\xd2\x99\x57\x23\xfb\xca\x47\x3a\x10\x3d\xf7\x77\x6a\xf3\x0b\xa6\x20\x6d\xa8\xc6\x91\x7d\x2e\x67\xdc\x50\xcb\x63\x8e\x04\x74\x52\x8e\x2b\xe2\x93\x11\x96\x20\x68\xae\x46\xd5\x38\x75\xc7\x22\x33\x6d\xab\x71\x20\xae\x28\x09\xb9\x7a\xfc\xc8\x49\xab\x0f\xd9\x7a\x2b\x7f\x4f\x1a\x6e\x7c\x9c\xc2\xeb\x2b\x69\x01\x8c\x68\xc3\x11\x0b\xd2\x32\xcb\x63\x2b\x73\x2b\x1f\x12\x1f\xb4\x60\xa5\x83\xcf\xde\x69\x5c\x91\x59\x54\x31\x6e\x46\xf6\xa8\x6f\x15\x00\x82\xb7\xbe\x4f\x92\xa8\x62\xea\x91\xa1\x6f\xaf\x09\xb5\xa3\xaf\xfc\x68\x53\x3b\x3e\xb7\x37\x73\xbd\x18\x57\xe6\x28\xfa\xd1\x1a\xb6\x3c\xee\xe0\x35\x1b\x2b\x91\x8a\x53\x02\x9f\x56\x33\xed\x6c\x36\xa6\x25\xcb\x2c\xdf\x92\xc5\xf0\xe5\x47\x6b\xf7\xeb\xea\x31\x2d\x42\xa1\x90\xab\x90\xc5\x30\x30\xab\xda\x2d\x59\x0f\xce\x11\x2d\x38\xe9\x71\x8e\x26\xed\x1e\x71\x95\xb8\xed\x6f\xea\x33\xa5\x19\x42\x77\x5c\x5c\x3d\xb6\xc4\xee\xc8\xfc\xb4\xd7\xb0\xa4\x70\x49\x8b\xba\xcf\xea\x96\x86\x21\x60\x4e\xf1\xea\xfd\x7b\x7f\x1b\x81\x2b\x31\x57\x31\x48\x22\x9a\x5a\x8f\x89\xdf\x74\x84\x76\x86\x3c\x34\x37\x4d\x81\xf6\x4a\x89\x0d\x9a\x1b\x62\xd5\xd4\xcf\x70\x38\x54\xf3\xd4\x1b\xab\x2e\x33\xbd\x23\xd3\x9f\x6c\x77\xa4\xae\x33\x15\x8b\x9c\x81\x3c\x91\x66\xca\xe7\xe9\x60\x7d\xae\x54\x97\xd7\x27\xbe\x54\xb6\xe1\xc9\x91\x4a\xe2\xff\x4d\x5b\x27\x2a\x89\xff\x8f\xc7\xae\x97\x13\xda\xf8\xe0\x24\x07\x09\x79\x77\xaa\xc4\x26\xd7\xc3\xc7\x01\xdd\x78\xa1\x7d\x32\x1f\xec\x06\x74\xb0\x1f\xd0\x81\xd9\x88\x01\x1d\x00\xa1\x3d\xa0\x03\xa4\xc3\x07\x8b\xba\xae\xcd\xe8\xbd\x4c\x9e\x1d\x84\xd9\x9a\x14\x13\xd6\xa0\x35\xba\xf5\x7b\xac\xa9\x0b\x81\x6a\x83\x69\xba\xef\x7a\x0f\x5e\x8a\x16\x14\x66\x98\xb7\xa5\xc8\x93\x83\x7f\xae\x6b\x6a\xe3\x6d\xba\x46\xd6\xd7\x97\xde\xf0\x5b\x21\x9f\xe9\xdf\x78\xa9\xa0\x9e\x8b\x4d\xb3\x6e\xc9\x80\x5a\x0c\x32\xa0\xb3\xcf\x66\x8b\x3f\x25\xe5\xd9\x39\x29\xcf\xfe\xbf\x21\xe5\x09\x45\x6c\x67\x04\x6c\x39\x0a\xd8\xac\xf8\xec\xb0\x4b\x02\xc1\x4d\x0e\x6a\x35\x42\xf7\x49\x15\x16\x96\x50\x68\x89\x92\x24\x1f\x0e\xf3\xb8\x1c\x0e\x47\x79\x5c\xd6\x81\xcc\xad\xeb\x81\x63\xe7\x05\xb6\x90\xda\x1b\x28\xf2\xfa\x94\xc9\x47\x29\xf8\x24\x10\x82\x37\x69\xeb\xa7\x12\x0d\x80\x25\x11\x61\x8e\x64\x3d\x97\x8b\x18\x6d\x4f\xae\x1e\x83\x65\x8e\x67\x15\x7d\xa0\xcf\xa7\x93\xe1\x50\xfc\x45\x89\xcd\xce\xd1\x74\xfb\x4f\x4a\x6c\xfa\x64\x2a\xf1\x8e\xd0\x94\xf5\xc9\x66\xe2\x3d\x88\x42\xbd\x88\xaa\x25\xa1\xe1\xd6\x05\xd3\xaa\x8d\xa2\xc1\xa8\x42\x91\x4f\x3a\x8a\xca\x19\xfc\x2a\x93\xc1\x80\x8c\x06\x64\x50\x7f\x86\xd8\x04\x40\x51\xbf\xec\x04\xc4\x26\xff\x2d\x89\x89\x5b\xa3\xd4\xad\x51\x59\xb7\x65\x28\xb4\xf8\xb4\x18\x24\xeb\x13\x83\x14\x28\x41\x39\x11\x83\x64\x8d\xa4\xa3\x60\x7c\x5a\x80\xa4\xa3\x08\x25\x1d\x7a\x5e\x2c\xa8\x60\x97\xd5\x70\x18\x0a\x3d\x0a\xf3\xa1\x6a\x96\x86\xc8\xe4\x25\xa6\xf2\x8a\xe2\xbf\x93\x24\xed\xc3\x32\x3b\x42\x73\x56\xcd\xca\x8e\xfc\x27\x29\xfb\x2a\xef\x09\xdd\xb2\xc3\x2e\xc9\xe8\x3e\xc9\xa9\xa1\xc1\x12\x64\x70\x33\xcf\xea\xe6\xa4\x9e\xae\x0d\xe9\xec\x05\x08\x0f\xad\x4e\x01\xea\x83\xb0\x7a\x5c\x82\x4c\x84\x4d\x7a\xa4\x0a\x9c\x16\x74\x4b\x25\xa9\xfb\xc5\x44\x19\x95\xb4\x20\xf5\xf9\xaf\x9d\x4a\x1f\xc2\x43\x6e\x2d\xa2\x11\x96\x3d\xdc\xc9\x54\xba\x80\x80\x90\xf9\xaa\xad\x67\x3b\xd4\x54\xd2\x26\x06\xe2\x75\x1d\xc4\xcd\x93\x76\x7a\xce\x2a\x00\x35\xdf\x36\x23\x7d\x24\x9b\xc9\x53\xf7\x7b\xc4\xbe\xc3\xa0\x6b\x8e\x4b\x52\x84\xca\xba\x5e\x5b\x3c\xb8\xbd\xb9\x29\xf8\x80\xae\xff\x0b\xa8\x10\xb2\xf0\x0d\xfe\xeb\xa8\xad\xc9\x6f\x3a\xa0\x03\x1c\x2c\x62\xb6\x75\x0b\xb3\x39\xf4\xb5\xeb\xe0\xa0\x9a\xee\xbb\x25\x35\xb5\xea\xfa\xe4\xa0\x95\x2a\xb4\xd8\x24\x07\x97\x13\xd4\x94\x09\x5d\xf0\x24\x22\xec\xe9\x60\x50\x37\x38\x6b\xdb\xc2\x59\x27\xa1\xd5\x60\x3f\xd1\x3e\xf7\x21\x14\x86\x41\xc0\xa4\x74\x42\xb9\x56\xd4\x28\xb5\xd5\xfd\xe5\xd6\x8e\xf1\xb4\xec\x57\x5b\x56\x87\x1e\xe1\x87\x50\x75\x7c\xc6\xa0\x3b\xc2\xb0\xc8\x2e\xfd\x55\x17\x71\x28\x8a\xbe\x42\x8a\x69\x5a\x31\x3d\xe2\x53\x05\x54\x95\x22\x32\xb6\x48\x67\xae\x16\x6c\x24\xe6\x6a\x81\xe2\x13\xa5\x61\x77\x1b\x1d\xf6\x57\xba\x1d\x4e\xa5\xb4\x35\xc6\xff\x67\x82\x5e\x3f\x2f\x44\x99\x6d\xef\x6c\x2c\x81\xf3\xed\xb2\xb0\x1a\x69\x7d\xec\x2b\xb3\x1f\xa0\x37\x47\xdf\xd9\xa5\xa6\x9c\x8d\x97\xba\x65\xc5\x1e\x6a\x81\xa7\xf2\x89\xb5\x52\xe9\xb7\xe9\x1d\x8d\x24\x84\xef\xb4\x75\x7a\x1c\xf6\x43\xf6\xa2\xc5\x74\x37\x86\xbf\x81\xe4\x0e\x55\x10\xad\xe5\x41\xd9\xf8\xe9\xf4\xa7\x3a\xd0\x9c\xd0\x8a\x50\xde\x60\x66\x4e\xab\x51\xea\x79\x5f\xb7\x90\x89\xa6\xad\xb5\x49\xf8\x58\x9f\xc3\x63\xd4\x3b\x98\xd2\x83\x27\x95\x0d\x1e\x16\xa0\x18\x0f\xf1\x8c\x19\x32\x1c\x0d\x2b\x44\xf9\x3e\xdd\x3d\x6f\xee\x60\x44\x46\xae\x14\x13\x16\x47\x6d\xb5\x6b\xe4\x27\x21\xad\xb3\xab\xb4\x2e\x31\x04\x98\x3b\x3a\x69\x71\x16\x5f\x07\x06\x5f\xd9\x56\xab\x2d\xc4\x64\x87\x94\xcf\x1c\x17\x4e\xc8\xdb\x7f\x41\xfb\xc8\x59\xb8\xd1\x43\x7b\xda\x6b\xea\x57\x24\xaf\x5d\xb3\xee\x09\xa1\x07\x60\x5d\x7e\x49\xb6\xc8\xac\xfd\x9a\xac\x2c\x41\xfb\x4b\x72\x6b\x7f\xfd\x9a\x6c\xba\xa9\xda\x5d\xcc\xd2\x6b\xaa\xd8\x35\x45\xb1\x1e\xc8\x39\xf8\x93\xa5\x6e\x92\x76\x68\x5a\xb0\x72\xc4\x69\x86\x33\xcb\x54\x15\x95\x06\xed\xc2\x53\x25\x24\x44\x44\x68\xde\x15\x06\xbf\xf9\x77\x05\xa1\x2b\x0c\x8a\x2e\x09\x7b\xfa\x8d\x8e\x34\x2d\x69\x41\x66\xd7\x49\x70\x00\xf8\x23\x41\x25\x95\x8f\x04\xe8\x03\x4e\x2b\x8f\x5d\x6d\x21\xdb\xb5\x37\x6c\x15\x4d\x68\x46\x73\x42\xef\xd8\x2a\xfa\x5e\xd3\x35\xdd\x12\xba\x63\xb7\xd1\x8d\xc6\xf2\x1b\xf8\x3d\xb2\xaf\xa6\x92\x45\x9b\xf1\xce\xec\x95\x62\xd1\xdd\xf8\xc6\xfc\xaa\xd8\x38\xda\x8c\xa0\x30\x65\xe3\xe8\x6e\x64\x4a\xfd\x81\xc4\x95\x95\x6e\x65\x95\x5f\xd9\xca\xaf\x6c\x5a\xd7\x51\x4e\xd7\xb4\x30\xc3\x70\x67\xc3\x9c\x88\x2d\xdd\x99\x67\x3c\x23\xa6\x60\x45\x6f\x9a\xe3\xe4\xe7\x74\x47\x77\xf6\xf4\x2c\xd9\x6f\xc1\xa1\x41\x84\x40\x6f\x08\xdd\xb3\x68\x39\xf6\x0d\x97\x8f\x0a\x3a\x21\xe4\x0a\x8f\x43\xdb\x67\x06\xcf\xd3\x07\x05\xea\xa6\x69\x63\x26\x7e\xfb\x68\x19\x18\x8a\x6f\x1e\x2d\xa9\x8a\xb5\xa9\x65\xee\x8e\x13\x26\xd9\x66\xa6\x62\x00\xad\x97\xe3\xfd\xa3\xee\x81\xb5\xf7\xc3\x1f\x5b\xde\x82\xfb\xcd\xde\x86\x1d\x8d\xf7\x8f\x32\x0a\xde\xe9\x1d\x1a\xb2\xa2\x13\x5a\x05\x24\xe6\xb2\x75\x07\x3e\x23\xe4\x58\xfb\x8a\x8b\x5e\x10\xd4\xe4\x04\x97\x4d\xc0\x07\xfb\x8b\xc3\x95\xe2\xc7\xe3\xe5\x27\x04\x8e\xc7\xa3\x15\x08\x29\x8f\x29\xf4\x62\x36\x49\x44\xb3\x86\xed\xef\x86\xf5\x1e\x55\x57\xcb\xff\xba\xca\x11\x01\x5c\xc9\xd2\xc0\x12\xb1\x60\xe9\x69\x10\x0b\x9a\xb1\xa8\x04\x77\xc0\x51\x89\xbe\x7e\xe6\x70\xad\x4d\xa1\x56\x9b\x51\x69\x7d\xf6\x4c\x61\xce\xaa\xe1\xb0\x70\x8b\x80\x72\x89\x2d\xcb\xc1\x19\x30\xd8\x4f\xba\xb2\x65\xc1\x66\xd2\xdb\x4f\x93\xec\x9b\x3e\x92\xfd\xd6\x5c\x92\x1e\x92\x7d\x83\xc4\xe3\x8e\xde\x9c\xa0\x15\xc0\x72\x3b\x36\x99\xee\x9e\xf0\xe9\x68\xb4\x23\x37\x23\xe0\x1f\x5a\x2b\xbd\xa3\x95\xab\xc8\x4d\xc5\x91\x80\xaa\x81\x6a\xb3\xa7\x01\x15\x4c\xcf\x77\x0b\x9a\x02\x45\x3e\x52\xee\xba\xd0\x7d\xb2\xf6\x4f\xbf\xa2\xe8\x0b\x53\xef\xde\x50\x2e\x73\xfb\xd3\x00\xc5\x36\x92\xa2\xc1\x0a\x25\x2b\x1a\xac\x61\xb2\xad\xa7\x77\xe0\xee\xed\x68\xfa\xcd\xc3\x4a\xc1\x1d\x28\x05\x6f\x46\x86\x9b\xec\xd0\xf0\x82\xee\x40\x6a\x7f\x86\x86\xdf\x50\x49\x6f\x49\xdd\xbd\xd5\xdd\x54\x06\xcd\x95\xe1\xd6\x0d\xc8\x99\x70\x59\xc6\xda\x30\xd8\xa2\xc9\xe4\x24\x5a\xec\x93\x3f\xd7\x62\xe1\x32\x38\xf1\xe1\xf0\x12\x19\x18\x4e\xac\x67\xc0\xb9\x9b\x84\xe9\x6e\x47\xcc\x4b\x47\x79\x63\x59\x26\xeb\x33\x77\xe9\x21\xf6\x15\x40\x99\xbf\xe3\x86\x8f\xbf\x74\x6a\xc3\xd9\x52\x3f\x8a\xfc\x87\x34\xb9\xe2\x24\x99\xfc\x35\x26\x5f\x04\x8a\x08\x00\x3e\xa8\xfb\x6a\x12\x8d\x28\xf6\xa7\x88\x78\x70\xd7\x69\xa3\x56\x2d\x94\xb9\x57\x1d\x0b\x0b\x09\xe9\x8d\x06\x03\xcb\xc0\xab\xba\x3e\xa5\x46\xba\xc1\x3a\x9c\xd0\xa3\x71\x44\x80\x01\x85\x1e\x22\x28\xa9\xbf\xd4\x04\xe9\xdb\x09\xe8\x72\x7b\xa9\x41\x47\xf2\x8a\x55\x24\x4f\x69\x41\x45\xc8\xc1\x4a\x25\x42\xfa\x4f\x11\xaa\x19\xf6\x85\x90\xa8\x21\x06\x4b\x3c\x00\x65\x18\x7c\x63\x8a\x7a\x54\x1c\x91\xdd\x9b\xc9\xb4\x19\x9a\xee\x0e\xa6\x60\x0f\x71\x8d\x8a\xd0\x01\xdc\x28\xc3\xeb\x15\x31\x32\x4f\xcf\x0a\x71\x2b\x21\x0b\x4e\x20\xeb\x71\x2f\x61\x1d\x8f\xc7\x09\x2d\xd0\xc2\xfc\x79\xab\xb4\xb1\x2a\x12\x75\x8b\xea\xd3\xd6\xf5\x29\x10\x30\x39\x53\xc1\x8e\x91\x60\xfb\x4e\x9d\x1f\xba\x20\xd3\x16\xc9\xab\x2d\x68\xc1\x98\x5b\x30\xb6\x1f\x5d\x41\x90\x95\xad\x17\xe7\xf6\x8f\x6e\x2a\x9e\x68\x18\x52\x70\xef\x4e\xb6\x15\xdd\x46\x46\x8d\x7e\x39\xa0\x40\x45\xb3\x1c\xdd\x0f\x07\x8a\x6d\x3f\x87\xef\xa2\xe0\x43\x5d\xc7\xdb\xf8\x23\x86\x80\xb9\x26\xd4\xf2\x43\x0f\x10\x29\x27\x3a\xf3\xd3\x19\x9f\xf9\x92\xdd\x0d\x72\x3c\x5e\xd7\xf5\x16\xb9\xf9\x5c\x6d\x6f\xd7\x72\xab\x07\x74\xfb\x5f\xe0\xe7\xd3\x32\x0b\xb8\xf9\xe4\xd0\x22\x0f\x1a\x21\x36\xa2\xca\xe4\xf2\xba\xfe\xcb\xac\x7f\x0b\x61\x0c\xe8\xc0\x61\x93\x81\x3d\xdb\x88\x2d\x06\x74\x10\x60\x92\x81\xcd\x10\xe7\x2a\x3a\xf1\x01\x9e\xa1\x8e\x1c\x61\x51\xd7\x14\xb9\x8d\x64\xf0\xf7\xc9\x97\x83\x86\x81\x98\x74\xb0\xd5\x7f\xfc\x63\x42\x91\xc4\x4c\x06\xd7\x13\x53\xd5\x07\x8b\x4b\x06\xe5\xa0\x36\x2b\x18\x08\x21\xc2\x20\xc5\xd7\x8d\x94\xa1\xe0\xb7\x5c\xe6\x09\xc2\xb5\x2a\x39\xdc\x72\xc9\x4b\x88\x38\x74\xd3\xd5\x81\x23\x92\xf1\x61\x76\xb1\x85\x77\xc7\xe1\xdd\x7d\x9d\xf9\x2a\xe8\x9c\xd5\x49\xac\x74\xc2\x9d\x4e\x48\xc7\xe2\x04\x7d\x79\x7c\x3a\x87\x83\xe6\x3b\x9d\x70\xba\x12\x45\x01\xaf\x12\x19\xdf\xa4\xd9\xef\xb7\xa5\xda\xca\xfc\x85\x2a\x54\x49\x2b\x5d\xaa\xdf\xb9\x7f\x0b\xeb\x8a\x6f\x0a\xa7\xd4\xf5\xe5\xf0\xe4\x9c\xf2\x2f\xfb\xd1\x5c\xe8\xbb\x95\xcc\xcd\xde\x58\x9f\x0e\xc7\x82\x39\x4e\xbb\xd7\x19\xdc\x93\xd7\xae\x96\x0b\xa1\x56\xd7\xf4\x53\xd2\x1d\x0a\x6b\xd7\x40\x0b\x9b\x18\xcb\x8b\x0f\x06\x90\x08\x3e\x46\x8b\x7b\x6d\x2d\xc1\xa7\xde\x78\x99\x93\x59\xc4\x7d\x4c\x49\x42\xf9\x7c\xb2\x18\x31\x41\x12\x3e\x62\x82\xf2\x3a\x10\x1e\xad\xfe\xc7\x14\x1e\x0f\xf0\xf7\x2d\x99\xbb\x8f\x92\x80\x71\x13\x20\x21\xa5\x0f\x6d\x50\x19\xc6\x3f\x75\xd8\xb1\x2f\xf6\x9b\xc1\x98\x07\xab\xe5\xa5\x19\x18\x88\x14\xa7\xcc\x71\x83\x66\x03\xed\x9c\xc5\xa9\x36\xa4\x0e\xc6\x4d\xe8\x58\xdd\xa6\x5e\x73\x51\xd6\xc0\x3c\xa3\x45\x1b\x05\x4b\x96\x0c\x0c\xa9\xd7\xf4\x4e\xc8\x97\x18\x43\x3a\xc9\x4d\x91\x7b\xd8\xd6\x68\x46\xf8\x73\x65\xb0\xd5\x56\xe6\x55\x44\xa6\x39\xb8\x79\xfe\xa0\x1b\x8e\x51\xf1\xa8\xa4\xb6\xdf\x8c\xc4\x85\xa2\x62\x26\x13\xc5\x41\xbc\xdb\x23\xa3\xce\x88\xa9\x44\xe8\x84\xca\xf1\x35\x98\xd1\x6f\x67\xbe\xbf\x74\xd7\xea\x6f\x4d\xe2\xb5\x18\x5d\x53\x61\x48\xfe\xb3\x3d\xae\x09\x56\x23\xa0\xfb\x1d\xab\x44\x8e\x95\x37\x60\xb0\xf6\xe3\xb8\xb4\x55\x5d\x47\x82\x2a\x9a\x1a\x76\x14\x22\xab\x80\xd9\x08\x46\x57\x33\x8f\x60\x28\xc0\x0a\x7a\x92\x55\xd5\xe9\x0d\xb8\xd3\x1b\x08\xba\x04\x51\x28\x18\xf6\x56\x89\x34\xeb\xab\xd8\x61\x67\x56\x16\xb4\xb8\x74\x67\x96\x97\x83\x01\xee\xde\x94\x0a\x28\xdd\x9b\x52\x61\x4a\x6b\xeb\xaa\xd9\x78\x31\x04\x1d\x32\x45\x2f\x27\x4d\x76\xe0\xd8\xf4\x0b\x41\x5a\xee\x84\x3c\x1e\xcd\x73\xba\xc3\xe7\x74\x67\x9e\xf7\xf8\x5e\xb8\xf7\x7b\x7c\x0f\x1f\xea\xa4\xb8\x70\xfe\x23\x54\x11\x5a\xd5\x88\x88\x4b\x36\x01\xc5\x87\xc5\x62\x54\xc6\xcb\x1c\x54\x0d\x9a\xe7\xec\xf2\xb2\x0a\x1e\xa9\x8c\x41\xd4\x5c\x31\xe5\xcd\x0f\x78\x48\x6f\x34\xb8\xcd\xcb\xd8\x81\xfb\x77\xa6\x7d\x6b\xf5\xf1\x8d\x90\xfc\x78\x8c\xb2\x10\x7a\xb1\x09\xa1\x59\x5c\xf1\x5b\xd3\x32\x48\x57\x62\x4b\xba\xac\x7a\x24\x5d\x1a\x1c\x87\x19\xf3\xe4\x32\xf5\xee\x7c\x59\x4d\x75\x0f\x7b\xaf\x20\x67\xeb\xff\x94\xea\xa8\xb1\x9d\x2a\xba\x5a\xa4\xec\xd3\x2c\xe9\xba\x8f\x25\xcd\xd0\xc8\xf6\x84\x25\xb5\x46\xb6\x7e\x51\x36\xa9\xfc\x3a\xdd\x18\x76\xf8\x99\x8e\xb6\x64\xb6\x4d\x7e\x00\x14\x1f\xbf\xfd\xf1\xfd\xeb\x0f\xaf\xff\xf9\xd5\xf2\xf5\x0f\xaf\x5e\xff\xf0\xfa\xc3\xaf\xc0\x1d\x9f\x85\x3f\xc7\x63\x75\x3c\x0e\xa4\x92\x1c\xa3\x53\xa3\x0d\x14\x70\x2d\xa1\x2e\x8a\x8f\xaf\x1b\x35\x56\xc6\xf8\x34\xb3\x5c\x6d\x16\xaa\xb1\xb2\x05\x15\x2d\xbb\xdd\xcc\x8c\xfa\x76\xc6\x93\x43\x4d\xef\xd8\x17\xa8\x72\xda\xb1\x6d\xbc\x63\xfd\xda\x2b\x9a\x11\x7a\xc3\xb6\xf1\x9e\x55\xc7\xe3\xdd\x67\xa9\xb1\x8a\x99\x0a\x8d\xc8\x4a\x2a\x68\x41\x12\x11\xef\x69\x46\xa6\x5b\xb0\x2c\x62\xc8\x7f\xed\xbc\x56\xeb\x86\x1c\x8f\x77\x74\x0b\xb1\x28\x58\x06\xaa\xd6\x78\x37\xde\xc4\xbb\xa7\x2b\xba\x45\xe5\x71\xce\x04\xcd\x5b\x8a\xaf\xf5\xc3\x4c\x72\x06\x4c\xf2\xad\xa9\xd4\x55\x73\x65\xa0\xe6\xa2\x1b\x26\xce\xb0\xc9\x6b\x2a\x69\x46\xce\x28\xa1\x5b\x81\x00\x5a\x9c\xa0\x27\x53\x42\x29\x54\x98\x2a\xba\xc3\x7a\xb8\x50\x7c\x90\xb5\xd9\x00\x1f\x7f\xe1\x1d\xbf\xeb\x21\x8e\x9a\x4f\xac\x8a\x5a\x3f\x30\xe7\x09\x38\x41\xab\x79\x63\xfb\xf4\x19\x8d\x9a\xca\x0d\x99\xef\xa1\xbf\x04\xef\xd8\xab\xc7\xce\x98\xa5\x57\x39\x5c\x71\x47\x7e\xd8\x68\xa0\x6f\x01\x20\x85\xc4\x79\x63\xa7\x62\x91\x3b\xf6\x57\xd7\x2b\xa4\xcd\x0d\x09\x35\xa0\xab\x4f\xd0\xe5\xb6\xda\x39\x5d\x9b\x03\x65\x86\x1a\x77\x37\x12\x28\xf1\x55\xaf\xca\xec\x9c\xc5\xc7\x39\xb3\x8e\x86\xac\xb9\xfd\x6b\x3a\xb1\xcf\xd7\x7b\xfd\x35\x75\xfc\xd2\xf9\xb2\x98\x1e\x5c\x14\xde\x4f\xe8\xe8\x3b\x6d\xce\x5b\x27\xb5\x03\x73\xf2\x40\xa8\xea\x49\x0d\x81\x32\xc4\xb1\xc0\x08\x63\xc2\x8a\x0f\xc7\x22\xd6\x6a\x63\x28\x89\x86\x88\x40\x19\x76\xca\xbc\x59\x9c\x39\x5b\x56\xf5\xd1\x98\x05\xcd\xaa\xab\xeb\xc9\xe4\xd1\xe9\x8b\xe4\xda\x4a\xb5\xcf\xc5\x8c\x9a\xea\xd6\x6a\x56\xe3\xf4\x91\x0b\xae\xa6\x5b\xeb\xdf\xaa\x37\x4e\xff\xbb\x22\x57\xd5\xd2\x2d\x9e\x95\xba\xb6\xdd\x42\x4a\x14\xa7\xae\x59\x16\xef\x5e\xa0\x5b\x41\xce\xb2\x78\x6f\x7f\x6f\x59\x66\x7a\x05\x33\x39\xe0\xeb\xa2\x09\x19\xc7\x7f\x7f\x74\x83\xf2\x9c\x15\xbd\x65\x5b\x0b\x18\x36\xec\x3f\xfe\x31\xb9\x52\x31\x90\x53\x76\x61\x9a\x38\x18\x80\x21\x56\x6c\x32\x5d\x81\x70\x74\x45\x6e\x51\x38\xaa\xee\x36\x5b\xcd\xb1\xeb\x15\x05\xf9\x2a\xd6\xe4\xa6\xe6\x48\x4c\x57\x6d\x73\x88\xd5\xc2\x0a\x98\x6e\xe9\x1d\xbb\x1d\xf5\x77\x41\x2d\x0e\xe9\xf0\x29\x2b\x32\x83\xd9\xbc\x14\xe8\x43\xfd\xaa\x54\x77\x38\x4f\x8f\x31\x4a\x8c\x66\xb1\x5a\x90\x64\x32\xbd\x65\x77\x60\xb1\xd0\x16\x3d\x0f\x87\xd1\xce\x10\x24\x45\x5b\x2a\x0f\xc2\x9d\x3b\xb6\xf5\x26\x00\x37\xec\x60\x48\xe8\x7d\x92\xb7\x04\xac\x93\x96\xf0\x75\x17\x0a\x6d\x45\x23\xb4\xbd\x6b\x82\x0f\x3c\x00\x2e\x57\x54\x92\x7a\x7a\x8a\x54\x56\xf4\x06\xdc\x31\xfa\xb7\xa2\x2d\x0d\x6a\x9d\x99\x1e\x47\x25\x27\xb8\xf1\xfc\x30\xc8\x36\x4e\xa2\xe5\x3b\x39\x26\xae\x9f\x5c\x7c\x4a\xb4\x2a\xc9\x70\x28\x46\xa3\x1a\xf2\x12\xb7\xf7\xb0\x27\xf6\xc7\x03\xb6\xd5\x4e\x57\xfd\xb0\x19\x47\x9c\x9a\xae\x8f\x47\x41\x92\x49\x5d\xdf\x22\xa0\xdf\xa8\x22\x2d\x21\x52\x2f\xbd\xed\x42\xfb\xff\x8e\xbc\x65\xf2\xd7\xe5\x2d\x4e\x56\xd2\x12\xa0\x7c\x96\xd0\xc5\x30\xeb\x2d\x81\x48\x78\xa2\x26\xb5\x99\xd9\xff\x2f\x1d\xf9\xff\xb6\x74\x24\xc1\x34\x83\x8d\x64\x11\x57\x74\x8e\x4f\x00\x9b\x17\xa3\x5e\x41\x49\x5d\x37\x46\xa5\xa5\x3b\x80\xad\x0c\x31\x14\x2e\x86\x79\xa8\x92\x43\x2e\x2a\x08\x0c\x63\xe8\x94\xb6\xdd\xa8\xb5\x37\x05\xc9\x5c\x91\x96\x70\xc6\x81\xd2\x79\x63\x4f\x4c\xd8\xb4\x75\x00\x3d\xa1\xb2\x69\x08\x95\xad\x3a\xd4\x1b\x7b\x07\x05\x1f\xd0\x4d\x78\xfb\xac\x54\x70\xf2\x17\x24\x82\xee\x13\x77\x2d\x5a\xe8\xaf\xe8\x4e\x9c\xb9\x73\x9f\xb1\x58\xc7\xa2\x31\xf0\x01\x9f\xeb\x85\x33\x6d\x1c\x8c\xf8\xa9\x71\xa4\x98\x5b\x2f\x31\xf2\xa0\x51\x48\xd7\xf4\xda\x51\xee\xce\xf6\x1a\x74\x37\x95\xf7\x75\x0a\x47\x00\x59\x5a\x3c\xd3\x4d\x5d\xe4\xb1\x4b\xc6\x74\xa3\x8c\xfe\x2f\xb2\xe0\xa2\xc3\x82\xfb\xf8\x69\x87\x65\xa1\xd4\xc6\x9c\x8a\xe5\x6a\x5b\x14\x6f\xcc\x83\xbb\xef\xa0\x74\xb6\x24\x9e\x43\x61\xa2\x9e\x9e\xe5\xd0\x53\x43\x08\xf6\xf0\xe2\x13\xaa\xfe\xba\x35\x67\x87\x02\xea\xba\xc0\x96\xce\x05\x36\xa0\xa0\x3e\xd3\x00\xf3\x93\x96\x8d\x99\xe5\x5a\xcd\x4e\xbc\xb5\x21\xdf\x1b\x3e\xd4\x86\x0c\x9b\x17\x0b\xc3\xdb\x97\xb3\xd4\x11\x5b\x49\x16\xef\x68\x0e\x25\x7b\x5f\xb2\x47\xd3\x4b\xa4\x1d\xe0\x7e\xfe\x3f\xbc\xbd\x69\x77\xdb\x46\xb6\x28\xfa\xfd\xfd\x0a\x8b\x37\x97\x17\x25\x6c\x42\xa4\x92\xee\xd3\x07\x54\x89\xcb\x71\x86\x76\x62\xa7\x33\x38\xe9\xa4\xf9\xb8\x74\x21\xb2\x28\x56\x1b\x44\xb1\x51\x45\x8b\x0c\x89\xff\xfe\x56\xed\x1a\x01\x52\xb6\x73\xfa\x9c\xf7\x45\x22\x6a\x1e\x77\xed\x79\xe7\x73\xf3\x80\xc5\x8a\x98\xab\x48\x11\x33\x5e\xea\x27\x55\x29\x9b\x66\x6d\xee\x5c\x5d\x2c\xf4\xcd\x5f\xff\x7b\x14\x4e\xe7\xd1\x89\xe8\x1d\x17\xea\x3c\x3f\xe8\x16\xf2\x83\x86\xd5\xb9\x79\xda\x34\xe1\xa2\x3b\x7e\xf2\x49\x7a\x3f\xb4\x0a\xd0\x64\x17\xae\xfa\x52\x1c\x9a\x9d\x99\x99\x9c\x6b\xd8\x57\xf7\x60\x17\xcf\x2d\x8c\x6d\x84\xef\x06\x02\xa9\xdd\x87\x94\xf2\xcd\x34\xff\x80\xa2\x62\x00\xd6\xbd\x44\x83\x62\xfc\x34\xea\xce\x5d\xb8\x6c\xf4\x9d\x03\x6c\xfe\x18\x8d\x49\xe3\xc5\xe5\xde\xc7\x2b\x5b\xd6\x8c\xfd\xce\x92\xc3\xdd\x1d\xfa\x7a\xb9\xbb\x33\xf6\x46\x9f\x17\x75\x88\x83\x91\xcf\x05\x7c\x8e\x8a\xa3\x51\xda\x4a\xc0\x17\x56\xfc\x14\xa5\x6e\x05\xe8\x35\x8a\x52\x96\x02\xbe\x77\x18\x52\x94\xfc\x20\xe0\x7b\x1e\x97\xdb\x08\xf8\x51\x9f\xa8\x28\x69\x2d\xe0\x27\xb3\x15\x51\xe2\x4e\x34\x24\xf8\x9d\xb9\x13\x71\x94\xef\xf3\x58\x70\x65\x2c\x29\x5f\x17\xf5\x03\xaf\x72\x01\xbb\x5c\xc2\x3e\x2f\x5a\x18\x74\xdd\xc2\xae\xcb\xc6\x3a\xe7\x9a\x53\x71\x55\x8f\x55\x86\xcf\xd8\xf7\x85\x5a\xa1\x9f\xf7\xa2\x9e\x27\x46\x02\xcd\x07\x73\xa8\xd2\x39\x81\xf2\x56\x4c\x12\x5d\xba\x8c\xf2\x4b\x9d\x87\x65\x2e\x86\x84\xe4\x21\x43\x40\x95\xbe\x56\xc0\x07\xaf\x15\x7a\x03\x2d\x85\x64\xbe\xf5\x79\xc9\x37\x49\x14\x21\x79\x7f\xc6\xb3\xc8\x2b\x16\xf9\xb8\xbc\x8f\x4c\xc3\x61\x6a\xd0\x3a\xe4\x3a\x3b\x1c\xef\xcb\x6a\xe1\x90\x3f\x97\x8e\x1f\x3a\x7d\x46\x3c\x47\x26\xe1\x03\x66\xf4\xc2\x3c\x3d\x2c\xa1\xba\x64\x57\xd7\x04\xea\x56\x5c\xe3\x84\x0f\xa2\x22\x8a\x90\xcb\xea\xea\xda\x61\x73\xdf\xa9\x44\xc1\x10\xa2\x02\x8c\x90\xc6\x47\xa5\xf3\xa3\xcb\xeb\xc4\x2a\xd9\xe0\x27\x01\x37\xd6\x90\xf1\x65\xb5\x20\x10\xc6\x9d\x7f\xa7\x12\xab\xab\x63\x8d\x31\xa1\xb0\xf9\xba\x5a\xc8\xfd\xb2\x5a\x60\x5e\x14\x22\xfb\xdd\x89\xd3\x9a\xc3\x2e\xe7\xa9\xba\xf4\xba\x7c\x8c\xc0\x3e\xaf\x5c\x8a\xe4\x55\xc2\xe2\x06\x1e\x5b\x27\x6d\x97\x73\x5d\x3a\x46\x52\x44\x38\x71\xb2\x75\xe2\x8a\x86\xb2\x58\xb3\xb2\xad\x27\x56\x18\x45\xca\x96\x4e\x59\x5a\x40\xbc\x50\xf3\xb0\x34\xab\x78\x39\x16\x61\xee\xdb\x86\xee\x05\x02\xe9\x1a\xe4\x40\x10\x58\xd2\x7a\x30\x87\x07\x5a\x0f\x56\xb0\xa1\x22\x9d\x5f\x2d\x61\x4d\xe5\x60\x75\xf5\x00\x3b\x5a\xa6\x0b\xb8\xa7\x65\xba\x85\x3b\x2a\xd2\xc5\xd5\x0e\xf6\x54\x0e\xb6\x57\xf7\x46\xd6\x73\x7a\xdc\x39\x54\x50\xc3\x06\xd6\x04\x56\xb7\xc3\xf0\xb0\xbd\x13\xc9\x03\xac\x8d\xa3\x11\x53\x92\x65\x3b\x60\xd9\x1e\x56\xb0\x06\x99\xbe\x56\xc4\x7a\x5d\x7b\xa7\xcb\xde\x83\x34\x65\xb1\x1b\x0d\x94\xde\x88\xe4\x5d\xb6\x83\x77\x68\x2a\xd0\x69\xf9\x1e\xf6\xe7\x5a\xde\x62\xbb\xb0\x4f\x71\x45\xbf\x7f\x49\x4c\x1c\x06\x37\xcc\x12\xf4\x4c\x4a\xd0\xf3\x32\x41\x28\x17\x9d\x76\x77\x70\x77\xae\xdd\x05\xdc\xb9\x26\x41\x0c\xc2\xc8\x1f\x75\x9d\x25\x88\xd3\x91\x3f\x66\x3b\x78\xd4\x23\x9f\x77\x7a\x58\xc2\xe6\x5c\x0f\x73\x6c\x17\x36\xa4\x69\x5d\xfa\x70\xc8\x5e\xb7\x0e\x59\x78\x8e\x29\x83\x8a\x5a\x7d\x10\xb4\xcb\x8d\xf4\x41\xc6\x2d\x0c\xab\xdf\x4f\xaa\x89\x1d\xa1\x41\xb9\xae\x2f\x5b\x05\xc0\xe4\x7d\x23\x78\x45\x7b\x48\xee\xf4\x30\xd0\x46\xa8\xf0\x74\xf1\x7b\xf6\x8e\x95\x3d\x02\x2c\xd3\x18\xdb\x0b\x5e\xcf\x4b\x26\xfb\xfd\xb3\xc2\xc4\xc3\x2e\xaf\x60\xef\xac\xd7\xdd\xbd\xf0\x57\xa4\x68\x5d\x91\x5a\xcf\xb0\x7c\xea\x8a\xd4\xfa\x8a\xcc\x3b\x57\xa4\x46\x00\xbd\x32\xca\x5b\xe8\x20\xd4\xb5\x4d\xad\x55\x2b\x7e\xa4\x77\x0a\xec\x23\x01\x51\x91\x22\xfe\xa0\xad\x1a\xad\xb6\x52\x54\x45\x8f\xa7\x3b\x18\xa0\x0b\xe1\xd3\x2b\x52\x81\x80\x39\x48\xdd\xa1\xc4\x63\xb7\xa2\xc3\xf1\xea\xa6\x55\x79\x9c\xa6\x2b\xa2\x32\x43\x5a\x26\x2e\x18\xc7\xf9\xb6\x4a\x90\xd8\xda\xc7\x34\xd4\x58\x45\x62\xa8\xfa\x7d\x37\x5b\x0b\xb0\x20\x94\x22\xd6\x71\xd3\xdb\x80\xf5\x7c\xc9\xbb\x5e\xed\x0c\xab\xd7\xb2\x5e\x9d\x64\xa2\x15\x1d\x3c\xa6\xa2\x5a\x39\x61\x0d\x5b\xc9\x7e\x9d\xe3\xc4\x3f\x6a\x39\x11\x9d\x16\x6a\x93\xa2\xe5\xd0\x49\xfd\x7e\x5b\xfc\x68\x3c\xbb\x92\x86\x57\x28\xf0\x3c\xeb\x76\x42\xe3\xda\xb5\xd8\xc8\xc4\xf1\x4e\xd0\x97\xe5\xa1\xb0\x00\x7d\x61\x59\x7c\xb9\x6c\xe8\x57\x9a\xdc\x38\xec\x72\x05\x7b\xf4\xd1\x1e\x23\x1b\x45\x38\xd7\x1d\x44\xa2\x85\x64\xcc\x3b\x14\xe8\xaa\x39\x19\xc5\x1f\xe7\xdc\x40\x47\xcb\x46\xcf\xc0\x3e\xb6\xc9\xea\x96\xde\xa9\xe3\xf1\xaf\x2a\x11\x80\x26\xdb\xfd\x7e\x22\x6f\x69\xd9\xef\xcb\x1b\x6a\xc4\x41\x86\x5c\x40\x82\x23\x12\x45\xe7\x0c\xf6\x39\x8f\xaf\x6e\x15\xa6\x28\x5a\x53\x94\xad\x29\x16\xa7\x53\xfa\x37\x98\x52\xc6\xf3\x6d\x52\xa5\x82\xa0\x65\x74\x22\xd3\x82\x78\x4c\x43\x0f\x33\x8d\xd4\xf4\x2f\x4b\x3d\xe8\x34\x52\xd5\xbf\x2c\x9b\xc6\xe2\xdb\x8e\x9a\xea\xfa\x2d\x39\x59\x02\x23\x17\x3a\x47\x60\x3b\x79\x01\x8a\xc2\x9c\x02\x9b\x71\x16\x10\x9f\xce\x27\xc0\xf4\x24\xfb\xf4\xd3\x7c\xd8\x86\x25\x06\xe0\x2d\x4b\x21\xea\x84\xb5\x2f\xd6\x95\xbe\xf8\x17\xc9\x10\x81\x53\x2b\xe7\x78\x6c\x01\xc2\x9b\xa1\x4e\x88\x96\xed\x66\x48\xd0\x5b\x8d\xca\x64\xf1\x0e\x9d\x8f\xf7\xfb\x9d\x26\x22\x93\x07\x4e\x93\x16\xb8\x0c\xa0\x4f\x2f\xb4\xca\x54\x5d\x54\xb2\x2c\x14\x4b\xfc\x4a\x73\x72\x59\x81\x5f\x65\xfd\xa5\xdf\x33\xcf\x4a\x43\x5b\xfb\x36\x2b\xcd\x81\x20\x9f\x1f\x31\xd3\xe2\xc7\x03\xc7\xdd\x5a\x21\x72\x78\x0f\x5c\xb7\x10\xae\xa3\x19\xd8\x85\x93\x9c\x98\xc1\x25\xa4\xb1\x0a\xbb\x1d\x4b\x24\x0c\x43\x78\xbe\x93\x4e\xd1\xff\xad\x37\x25\xc0\x55\xdb\xaa\xf9\x7c\xed\x93\x6b\x26\x95\xa8\x91\x35\x17\x5e\xf6\x9f\x2c\xfe\x49\x19\x39\x98\x27\xf5\x45\xb1\xa1\xdf\x7a\xf6\xc8\x8b\x62\x83\xab\x03\xac\x93\x80\x00\xdc\xb8\xd9\xf8\xa2\x90\xab\x24\x54\xd1\x9f\xbe\xb8\xfe\xc0\x87\xa9\xb4\x05\x8d\x3a\x21\x6d\x17\x37\x89\xad\x4a\x26\x89\xc4\xef\x7c\xa8\xa3\x3f\xdb\xc3\xf2\x29\xae\x86\xc1\x19\xbe\x6d\xf3\x79\x7c\x71\xfc\x22\x9d\x03\x10\xcd\x1a\x8f\x00\x8b\xbf\x22\x6c\xe8\x7b\xe1\x80\xb6\xc7\xb8\x78\xb6\x03\x9e\xed\xa3\x42\x5f\xb8\x85\x3d\x34\x11\x70\x77\x5c\x1f\xa7\x9e\x43\x87\xc6\xc1\x23\xad\x06\xa3\x86\x72\x97\x8e\x80\xfb\x04\xfb\x10\xc6\x7d\x72\x44\xc1\xa0\x0d\x90\xb8\x29\x34\xe0\x2c\x8e\x47\x71\x5b\xf7\xfb\xf2\xb6\xf6\xde\x2f\x50\xf7\xc7\x52\x03\x79\x09\xc8\xd8\x62\x99\xfe\x07\xbc\x64\x55\x3e\xbf\x29\xfb\xfd\x8b\xd5\xa4\x4a\xe7\x83\x32\x9f\x0f\xca\xe8\x64\xbc\xe8\xd2\x77\x07\xc3\x88\xcb\x85\xe7\xc7\x48\x3d\x40\xdb\x8b\xf3\x4d\x51\x9b\x5e\x4a\xdb\x41\x43\xbf\x10\x89\x41\x51\x61\xd5\x72\xc0\xea\xb5\x7f\xa4\x62\x9b\x0d\x5b\x4c\xbe\x51\xb9\xca\x14\xab\x24\xc6\x13\xec\xad\x45\x25\x94\x55\xcf\x50\xd9\x7c\x7b\xcf\xe7\x2f\x35\x40\xdc\x88\x12\x19\xa7\xaf\xc5\x82\x4d\x14\xcb\xbf\x17\x4d\x62\x3d\x71\x1a\x07\x88\x87\xb5\x78\xc7\x72\x54\x6f\xab\xd9\x3b\x56\x4b\x96\x6f\x1a\x5a\x1d\x8f\x87\xc6\xba\x46\x1c\x8e\x17\x37\x74\x8e\x5e\x11\xb7\x54\x4c\x93\x3a\x4d\x36\x93\xf9\x60\x91\x2f\x08\xf9\xdf\xc5\x0c\x8c\xf2\xc4\xf1\x98\x3c\x68\x94\x55\x37\xf7\x46\x24\xdb\x6c\x07\x5b\x8d\x54\x3f\xd0\x8b\x11\xc9\x57\x89\x82\x25\x6c\x61\x03\xd2\xcd\x40\x53\x37\xdb\x60\x5a\x8f\x7e\x77\x7c\xeb\xf9\xd0\xb4\x7d\xae\x1e\x81\x8b\x8b\xc8\xfb\xe5\xdf\xce\x50\xd6\xcc\xb2\x41\xdd\x72\x4b\x70\x27\x05\xd7\xb9\x8e\xd7\xd9\x2c\x40\x19\x2f\xc0\xdc\x2d\x00\x22\xa7\x60\x3d\x45\x6a\xc2\x89\x0e\x61\xe7\xf5\xd9\xef\x35\x39\x9d\x14\x69\x32\x9f\xd4\x03\x95\x2b\x42\xfe\xb7\x84\x3b\xe3\x35\x76\x79\x41\xe9\x03\x3a\x61\xb4\x67\x7e\x0d\x0f\xee\xb2\xe1\xd7\xb2\xf5\xb5\x21\xd6\x47\xac\x71\x60\x24\xa6\xf7\xc9\x90\xcc\xc0\x2f\xe7\x22\xdb\xc1\x22\xdb\x13\x87\x46\xd2\x1a\x71\x47\x0d\x69\x4d\xe9\x15\x99\xc1\x02\x37\xc2\xfb\x1c\xf3\x41\x0f\x74\x65\x4e\x17\xd9\x1e\x2a\x3a\x3c\xb2\x71\x45\x29\xdd\x4e\x12\x7e\xb3\x9c\x2c\x29\xcf\xf9\xad\x1e\xe8\x03\xe5\x68\x0b\xb6\xbb\x5c\xa7\x8c\x5c\xa5\xe9\x8e\xe4\xc9\x5d\x12\x8d\x12\x43\xa2\x6c\x69\xa5\x57\x00\x96\x14\x2b\x6c\x28\x6f\xee\x62\xda\xe7\xb9\x68\x4b\x88\xe2\x80\xfb\x01\x5c\xe9\xb7\x2c\x7c\x39\x6d\x45\x1b\x01\xc8\xc4\x91\xb6\x6a\x64\xc7\xa3\xca\x90\xc5\xac\xdf\xc7\xf3\xc7\x9d\x3d\x71\xdc\x75\x0d\x7b\x66\x8e\x47\x4e\x26\x7f\x13\xf9\x0b\xd1\xbc\x35\xdc\x41\x14\xe3\xbd\x8d\x39\x83\xd1\x2b\x9f\xf7\x8c\xd3\x94\x1e\x44\x20\x2d\xef\xfd\xaf\xe5\x72\xe9\x92\xbc\x04\x37\x82\x90\xf9\xb5\x73\xca\x31\xb4\xac\x5a\xab\x3d\x11\x75\xf4\xa3\x7e\xe3\x75\x6f\xed\xc7\x35\xef\x75\x12\x7a\x2e\x44\xc9\x1b\x71\x2e\x06\xa7\xa6\x33\xae\xbf\x08\x1c\xb4\x1f\xa3\x4b\xf0\x46\xf4\xfb\x26\x42\xaa\xd5\x89\xf3\xf2\xb7\x53\xe7\x3c\x46\x41\x14\xcd\x40\xd4\x6a\x2c\x8e\xc7\xc4\x7f\x61\xf0\x5f\xd3\x0f\xb0\x4c\xa7\xd8\x1b\xd3\xef\x8b\x98\xee\x25\x60\x5e\xc5\x10\xa5\xdb\xd3\x2a\x82\x44\xde\x77\x9f\xf0\x0c\x74\x70\x83\xec\x42\xca\x82\x3e\x17\x89\xc5\x0b\xac\x61\xe7\x33\xb1\x7c\x26\x08\x76\x27\xa1\xce\xa4\x7b\xc1\x62\xd2\xcb\xf8\x1c\xa9\xdd\xdb\x80\x1c\xc4\x9c\xa7\xfa\xc5\x20\x18\x69\xb5\xc5\xa6\x6b\x93\x5e\xe8\xa8\xd6\x50\x57\xaf\x3e\x9a\xba\x72\x6a\x85\xde\x9c\xfc\x1c\xb9\x85\x47\xb8\x9d\xe2\xc4\x25\xed\x54\x5c\xf9\x76\x8a\x11\xe8\xb4\xd2\xdc\x9a\xb5\x53\x23\x55\xcc\x51\xab\xb2\x89\x04\x6a\x92\x9f\x22\xb0\xce\x2a\x4a\x3d\x8d\x3f\x6b\x8c\x39\xe1\x4f\xdc\x48\xfe\xc4\x8d\x24\xfd\xfe\x05\x77\x77\xb2\xdf\xbf\x60\x9d\x01\x46\x31\x65\xbc\xea\xe2\x84\x99\xc5\xcb\x59\x58\xb2\xf1\xb2\x4a\x7c\x5d\xe0\x60\x23\x94\x77\x67\x3b\x6c\x1a\xc9\xd4\xb3\xcd\xd9\xc9\x8c\x7d\x79\xaa\xa2\xd8\x55\x6e\x65\xa3\x24\xbd\x25\x67\x5a\x1f\x69\xc2\xcb\x35\xde\x0d\x4f\x82\xa9\x58\xc0\x35\xd8\x2d\xe2\xd2\x5d\x64\xba\xb0\xa7\x6f\xdd\xa6\xc4\x66\xf7\x36\x97\x90\x66\xc9\x6b\xa9\xba\x9a\x1b\x7e\xd8\x56\x9c\x69\x06\x30\xf6\x58\x83\x97\xc9\x4f\x31\xcc\x0e\xde\x8d\x59\x53\x16\x1f\xdb\x12\xba\x85\x6a\x81\xe9\x67\xdc\xb4\xc6\x07\xa3\x99\xc6\xbb\x67\x0d\xf7\xdb\xfd\x61\x03\x58\x35\x65\x46\x8c\x69\x9b\x2f\xe8\xeb\x2a\xe1\x70\xb0\x8a\x10\xfb\x9c\xb5\x5c\x7a\x8b\xc6\x84\x14\x29\xda\x8a\x88\xde\x0f\x23\x06\xdf\x78\x2f\xba\xb4\xa9\xfe\x38\xba\xb4\xae\xf2\x87\xaa\x49\x2a\xef\x9b\xd0\x7a\x1b\x1a\xc2\x8a\x7a\x3f\x92\xce\xe5\x50\x2c\xbc\xb0\x50\x67\xd5\xd0\xc2\xf8\xf9\x96\x53\x3e\x83\x2d\x95\xd3\x15\x2a\x54\x2e\xf4\x03\x4c\x0e\xb5\x71\x4f\x64\xdc\x0c\x1a\x37\xa1\x66\x42\x4b\x5a\x26\x1a\xe9\xf0\x26\x80\x89\x18\x2c\xa6\x6c\x46\xae\x92\xed\x94\xcd\xcc\x6f\x02\x95\x47\x89\xc6\xcb\x29\x9b\x99\x45\xb5\x8d\x2e\xbd\x4d\x96\x7e\x0a\x5c\x04\x99\x49\x3d\x1d\xce\xf2\xba\xd1\x47\xfa\x27\xb3\xd1\x1d\x15\x9b\xe7\x26\xe4\x24\x49\x14\x18\xd5\x3b\xe0\x04\x8b\x3f\x19\x44\xc7\x1f\x18\xa9\x01\xb6\x5d\xac\x82\x56\xe6\xda\x8e\x19\x65\x18\xce\x91\xf2\xe3\xd1\x49\xa7\x9d\x66\x27\x3b\x05\xee\x45\x9f\x4a\x8c\x2a\xe6\x21\x38\xc3\xb5\x64\x29\xd7\x10\xdc\xe1\x08\x17\x85\xa5\xf0\x9f\x94\xfe\xda\xb3\x86\x68\x5c\x22\x6c\xc7\xc7\xe3\x74\x46\xfc\x65\x90\x1d\x96\xab\xa7\xb5\xf1\x35\xb5\xe8\x61\x44\x09\x82\xf0\xc0\xbe\xdf\x47\x3b\xe9\x2e\x74\x15\x2d\x00\x4e\x62\xc9\xc3\x97\x67\x5d\xcb\xbb\x1b\x71\x98\xf2\x19\x7a\xc3\x8a\x78\x2e\x7c\x06\x55\x5b\xf3\x15\xcd\x4e\x07\x92\xdc\x08\xe7\x26\x46\x64\x2b\xae\x0c\x2e\xd2\xbc\x8a\x55\x56\x5f\x9d\xa2\x36\x8e\x16\xcd\x7b\xf7\x5b\xa5\x1c\x22\xa3\x11\xb0\x7c\x3a\x83\x2e\x2d\xe9\x51\x1b\x4f\x2b\xe6\xbd\x35\x8f\x90\x22\x83\xf2\x7c\x0a\xf3\x62\xf3\x39\xfb\x9d\x5b\xde\x8b\xcc\x2f\x86\x70\xfe\x3e\xe5\x3d\x3b\xa2\x9e\x93\xbc\xc6\xda\xb0\x60\xcf\xb2\xfe\x69\xef\x69\x3e\x6c\xa2\x79\x7c\x34\xe6\xd4\x46\xda\xa2\x8f\x9e\x6d\x4e\xce\x6b\xbe\x51\xa2\x96\xf4\x70\x67\x7e\xdb\xa8\x47\x60\x54\x6f\xf1\x4b\xd1\xdb\x5e\x58\x13\xd4\xa2\xe8\xf7\x7b\x7a\xe0\xf8\xdb\xc9\x9e\x5f\xfe\x5b\x5c\x58\xab\x42\xde\x62\xbf\xbe\xe5\x9b\x0e\x3f\x36\xc2\x11\xfe\x2b\xec\x51\x7f\xc6\x76\xb9\x80\x3d\x9e\xb2\x27\xb9\xa6\xad\xe3\xb6\x11\x8f\x89\x1a\x08\xb8\x26\xa9\xff\x66\x03\x09\xd7\xe4\xc6\x7f\x57\xe1\x00\xa6\xce\x79\x11\x5c\xeb\x01\xfd\xea\x47\x14\x7c\xc9\xf8\x78\xb6\xba\x4b\xa6\x4b\xfd\xf6\xde\x52\x7b\x2c\xf5\x01\x06\xe7\xd3\xf3\x09\x0a\x3b\xae\x68\x63\xd4\xce\x9d\x85\x59\xa2\xa8\x6a\x87\xb4\x42\x8f\xde\x76\x1e\xc7\xe3\xb0\x6d\x03\x8b\xa1\xfa\xd1\xf4\xf5\x47\x57\xc0\xaf\xd8\xf5\x65\xc2\xd2\x04\x4b\xdc\x77\x6c\x76\x3f\xc8\x8c\x1c\x33\x4b\x42\x73\xdb\xf3\x4d\x36\xd2\x78\xc1\x7b\x18\x6e\xef\x13\xf5\xbc\x8f\x89\xf7\xad\x32\xa1\xfd\x8c\x2c\xcb\x38\xfb\x37\x5b\xd0\xc1\x03\x62\xf8\xe9\x5f\x53\x0b\x75\x54\x04\x75\x02\x84\xfb\xfd\xac\x6c\xd5\x3a\x07\x36\x4e\xc7\xa5\xf3\x49\x5e\xb4\x41\xdd\x87\x3c\x27\x02\xf3\x7e\x5d\xc1\xf8\xfd\xf3\x43\x0a\x1e\xd7\x27\xc9\x82\x16\x57\xd7\x5e\x48\xcb\x35\x46\x21\x48\xcc\x13\xc2\xef\x39\xad\x06\x0b\x58\xd1\x2a\x5d\x90\x3c\x59\x50\x89\x75\xf8\x60\x01\x25\xe5\xe9\x22\xe6\x19\xa1\xf1\xd3\x8a\x46\x66\x07\x82\x10\x1b\xd4\xba\xc6\x78\xd4\x73\x1b\xc0\xba\x74\x01\xa8\x57\xd1\x8a\x7c\x25\x62\x63\xc6\xb6\xa4\xff\xa7\xb7\x5c\x83\x3b\x6f\xdc\x18\x96\x99\x4d\x12\x5d\x3c\x9a\xd8\x2f\x9a\xf8\xee\xe9\x5e\x7b\xd0\xc3\xfe\x7a\x9a\xea\x29\x24\xbb\x55\xd9\x8e\xe4\x26\xdf\x0c\xa0\x07\x3d\x25\x36\x2e\xff\x46\x65\x7b\x02\x5c\x63\x07\x17\x43\xe0\x24\xe7\x61\x74\xbf\x44\x2f\x12\x06\x05\x82\xc8\x1f\x6b\x35\x49\x0a\xca\x41\xd1\xcf\x45\xa2\x68\x22\xa8\x22\x94\xd2\x44\x52\x46\x26\x45\x2e\x28\xa5\xc5\x44\x93\x6c\x1c\x18\x21\xb9\x29\x06\x26\x68\x6a\xe8\xc1\x27\xda\xab\x6d\xf5\x7e\x30\xfa\x2d\xcb\x7b\xac\x5a\x98\xdf\x3c\x8f\x2a\xfd\xfd\x34\x30\x8d\x9a\x0c\xf3\x53\x1f\x34\x28\x2a\xe3\x11\xef\xe1\xaf\x2d\xde\x83\x3e\x8e\x04\x6f\x99\xb1\x06\x60\xc6\x1a\xa0\x42\x46\x04\xda\x03\x30\x0c\x1c\x2e\x9e\x34\xa3\xec\x6e\x99\xb9\x5f\x82\xe2\xb6\x82\xa4\x5f\xb2\xa4\x0a\xba\xa8\xf9\xdf\x45\x82\x01\xc9\x41\xe2\x5f\xbd\xdc\x50\x9b\x54\x13\xbf\x5c\xda\xff\x43\x60\x04\xee\x4d\x8e\x75\xe9\x2f\xdd\x0f\xac\x55\x9a\x3c\x1c\xaf\x34\xff\x74\x1d\xf4\x5c\xcb\xaf\xae\xa1\xba\xba\xd6\xfd\x9f\x97\xd8\x9e\x89\x34\x50\x75\x6e\xdb\x69\x91\xde\x8c\x80\x38\x99\xb0\xd5\x46\x91\xf4\xa5\xa6\xe5\x63\x95\x12\xdc\xe9\xda\xae\x44\x49\xab\xe3\xf1\xe7\x24\x38\xa2\x55\x62\xf3\x4a\x5f\x91\xbf\x8b\xe4\xa2\x3c\x1e\xd1\x8b\x8b\xfe\x67\x27\x64\xb3\x8d\xe2\x87\x12\x9b\x1f\xf1\x06\x75\x0b\xbb\x35\x73\x05\x4c\x71\xb3\x4c\xed\xd6\x4d\x5a\xd4\x41\x28\x14\x57\xea\x74\x13\x6a\xb9\x9e\xa2\x62\x56\xf1\x24\x5a\xef\x96\xea\x4b\xae\x1f\x14\xd3\xdb\x3e\x37\xc7\xe8\x31\xe7\xb0\x42\xa7\x4b\x46\xa0\xd6\x18\xf9\x5a\x28\x99\x8a\xac\x74\xa5\x53\x91\x29\x5d\x63\x20\xb2\x72\x20\xb2\x5a\xd7\x1c\x88\x4c\x0d\x44\x76\xef\x5a\xf0\xab\xe8\x4f\xfe\x30\xac\x5d\xb0\x56\xd1\x2d\x89\xac\x24\xd1\x4a\x76\x2b\x60\x6a\xb7\x46\x4d\x5a\x8b\xd9\xaa\x13\xd2\xe3\x5a\xf7\xb6\x9f\x78\x35\xcf\x54\x3b\xe9\xed\xde\xf4\xd6\xc4\x82\x94\xef\xce\x60\xc3\xd6\x4f\x11\x03\xe9\x7e\x72\x28\x34\xd6\x75\x91\x88\x7e\x5f\x92\x7e\x1f\x5f\x98\x80\x13\x17\x1a\x0b\x3f\x1e\xd9\x2d\x52\x63\x4b\xd5\xef\xb3\x1b\x5a\x58\x07\x42\xfd\x7e\x22\x8f\x47\xae\xf3\x94\xd8\xf4\xfb\x5c\x67\x59\x3f\x42\x61\x1c\xff\xb4\x6f\x96\xc6\xf2\xe7\xca\xab\x78\xb0\xec\x11\x58\xb6\x22\xcd\x4b\x67\x1d\x80\x6a\x8e\x2f\x4f\x91\x6a\x83\x05\x8f\xc0\x3f\x88\xfa\x77\xc7\x71\x87\x4b\xb2\x05\x3e\x33\xda\xd2\x16\xa7\x9e\xa3\x88\xab\xe7\x76\xfd\xd3\x48\xd5\xb9\x89\x3a\xfc\xef\xc0\x7e\x2d\xca\xfa\xc9\xbf\x85\xb2\x86\x67\xa9\x95\xac\x1f\x9b\x56\x02\x3e\xe1\xed\x9a\xf8\x98\x7f\x10\x95\x3d\x87\x2c\x05\x1c\xd6\x5c\x2a\x6e\xc4\xd5\x1a\xb0\xfd\xd5\x12\xac\x20\xf4\xeb\xe4\x50\x50\xe2\x2e\xca\xf1\x18\xae\x80\xfe\x1d\x8e\x76\xf8\xc2\xcc\x09\x67\xf9\x3f\x05\xea\x55\xca\x71\x90\xba\x66\x8f\xc8\xcf\x7a\xec\xf7\xab\x6c\x85\x3f\x57\x88\x99\xc5\x2c\x47\x73\x2a\xbd\xd2\x1f\x7e\x73\xd2\x42\xc4\x58\x07\x79\x43\xa1\x63\x8f\xbd\x63\x95\x58\x2c\x7a\x27\xba\x28\xe7\x5b\x38\x91\xc7\x1a\xd1\x65\x4b\x58\xd9\x21\x04\x9c\x36\x9f\x68\x85\xc8\x3d\x8b\x9c\x87\x32\xa8\x3b\xfa\x14\x76\xee\x8a\x99\xa8\xe7\x1f\x81\x9e\x1b\x0c\xb0\x82\x28\x34\x8e\x78\x5a\xbf\xc0\x22\x80\xa1\x70\x07\x8d\x17\x93\x84\xa5\x15\xb9\xba\xc6\xc6\xc5\x84\xe7\x09\xc7\xef\x26\x60\xb2\x9e\xff\x63\x82\x7f\xa9\x49\x38\x90\x57\xd7\x79\x74\x16\x75\xad\x4f\x22\xd7\xe2\x9f\x9c\xde\x6f\x8b\xa6\x39\x95\xe5\x16\xed\x3b\xec\xca\x02\xce\x05\xf9\x19\xc6\xb7\xdd\xc9\x03\x3e\xf9\xef\xbd\xd7\xfa\xd0\xfe\xf6\x21\x65\xe0\xe7\xf5\xdc\xaa\x6e\xe7\x6f\x8d\x7e\xaf\xfb\x7c\x25\x00\xb7\xce\x7d\xbf\x14\xf0\x79\x51\xbb\xaf\x4f\x5a\xaa\xba\x3f\x0b\x1b\x0e\x32\x16\xd2\xb4\x9c\x6c\xa1\x4d\x90\xe5\x9e\xc6\x85\x20\x4a\x2b\x54\x01\xe7\x62\x9f\xee\x13\x05\x18\x2d\xbc\x07\x07\x63\x4c\xc1\x9a\x98\x89\xf2\x2b\xf6\xde\xf5\xa9\xe3\x0d\xd0\x14\xbd\x3d\xe0\x00\x1b\x42\x1a\xbd\x28\xff\x12\xf4\xc0\x17\x79\xcf\x0e\x82\x8b\xaa\x07\x21\xae\x6a\x51\x3e\x88\x9a\xab\xd5\x3a\xef\xad\x79\x35\x58\x17\x9a\x28\xc5\x2d\x5c\x58\xb3\x17\x8c\x55\x6c\x35\xd8\x0d\x9b\x27\xb7\x37\x8b\xde\x62\x4c\x4c\x6e\x5d\x85\x2c\x9c\x69\x34\xee\x30\x0e\x73\x1c\xd0\x48\x3c\x7a\xe3\x27\x87\x9d\x30\x13\x69\xdf\x5c\x1b\x5c\x9d\x5c\x46\x3a\xf5\x56\xf5\xf4\xc4\x3e\x0a\x69\x1b\x79\x3c\x1a\x43\xab\x31\x5f\x26\xbd\xbd\x3e\xf0\xbf\xb0\x64\x5a\x44\x01\xf2\x7d\x4b\x33\x1f\x6d\x59\x97\x45\x46\xd1\x05\xa5\xb5\x89\xd9\xdc\x62\xa9\xce\xa9\x32\x21\x38\xe4\xb4\xce\xb0\xee\xcb\x2f\x66\xbe\x56\x81\xfe\xac\xe6\x2e\x1c\xb0\xe2\x6b\x16\x12\xa2\x2e\xc2\x10\xac\xf7\x76\x97\x67\xe4\xaa\x96\xc1\xb7\xb0\x5e\x37\xb6\x6d\x87\x26\xb1\xcd\x4a\xe4\xce\xa4\x02\xe1\x04\xb0\xce\x7d\x89\xf1\x22\x1f\x05\x7d\x8c\x7d\x95\x94\xb1\xaf\x92\x79\x43\xe5\x89\xaf\x92\x48\x02\x8d\x2e\x4b\xd0\x83\x88\x89\x18\x08\x05\x7a\x2a\x19\x02\x47\x1f\x24\x15\x9d\x4f\x3a\x05\x6a\xeb\x7a\x44\x00\x27\x03\xa1\x31\x3a\xe8\x38\x13\xa9\x9a\x26\xa9\xa1\x44\x06\xf6\xf6\x86\x7e\x76\x59\x91\x9f\x51\xb0\xc5\x4a\xc9\x0e\xf2\x91\xab\xf9\x2a\xf9\xc4\xc4\x12\x65\xe6\x6e\xd0\x32\x88\x1f\xde\x73\x57\x98\xbf\x2b\xce\x83\x99\xe3\x63\x45\x21\x72\x2f\x86\xf0\xc0\x54\x90\xbe\x75\xc4\x10\xfe\x7a\x36\x20\xe3\x62\x2e\x32\xae\x19\x8f\x6a\xd0\x38\x33\xf3\x37\x86\x1c\xe6\x1a\x50\x97\x4a\xdd\xf7\xf2\x15\xed\xca\xf6\x40\xb8\xdd\xc3\xa8\x2d\xc5\x7a\x53\x32\x79\x3c\xe2\xa1\x90\xb7\x94\x07\x67\x26\xc6\x59\x0f\x03\x96\xf2\x60\x54\x34\x9d\x41\x4d\x13\x3e\xb8\x26\x57\x89\x1c\x5c\xbb\xc0\xa1\xc3\xe0\x48\x24\xe5\x83\x51\x57\x3a\x4f\x0d\x3b\xb9\x98\x96\x69\x3a\xa3\x6a\xba\x99\x59\x61\xb9\x1c\x5c\x9b\x98\x71\xfe\xfc\x80\x8c\x1a\x8b\xd4\xb7\x92\x55\x3a\x22\x97\x35\x49\x47\x29\x83\x75\x20\x77\xda\x45\xae\x4d\x11\xe0\x24\x65\xb0\xa3\xeb\xc1\x1c\x3b\xae\xe8\x7c\x5c\xdd\xac\x31\x96\xad\x48\x29\x7a\xef\xdf\x81\xb4\xbf\xf6\x63\x71\x45\x77\x20\xaf\xe8\xce\xab\x0f\x44\xcd\xae\x5c\xaf\x77\x4f\x8e\xe7\xb0\xcb\xf7\xb0\xcf\xdf\x35\x38\x37\xec\x72\x4b\x97\x74\x30\x82\x8a\xde\x8f\xab\x9b\x3b\xec\x79\x49\xb3\x3f\x5d\x06\xc1\xc1\x7e\x20\xc8\x65\x62\x46\x30\x78\x47\x06\xc9\x7e\x60\x06\x46\x2e\x13\x39\x78\x47\x08\x2c\x6f\xb7\x26\x86\x12\x2c\x70\xa4\xf0\x40\x2b\x32\xb6\xab\xb8\x80\x0d\x7d\xf0\x61\xc5\xdc\xca\xce\x67\x50\x34\x49\x89\x4b\x5f\x01\xb7\x5e\xf3\xc6\x78\x24\x1c\x24\x3d\x73\x2a\xac\xb8\xd9\xf9\xfd\x03\x1b\x24\x55\xef\x1e\x1d\xc2\xc6\x6f\xc9\x5a\x1f\x80\x9d\xd9\x64\xb8\x47\xb1\x46\xb6\x83\x3b\xf4\x7b\x99\xed\x06\xf7\xd6\x1f\x1f\x1b\x0b\xeb\x5d\x44\x90\x83\xa4\x6a\x2a\x66\x68\xc9\xaf\x8b\x90\xab\xbb\xcb\x0a\x6a\x2a\xb3\xbd\x57\x83\x18\x1e\x11\x46\x32\x4a\x69\x49\xea\x9b\xed\x24\xd9\x62\xa4\x59\x41\xf2\xfa\x76\xd9\xef\x27\x4b\x5a\xc3\x8a\x0a\x74\xe9\xbb\xb9\x7c\x48\x65\xb6\x23\x57\x69\xba\x31\x37\xd5\x41\x23\x31\x18\xa1\x2c\xea\x93\x64\x4e\xfa\xfd\x8b\x4f\x92\x15\x09\xef\x9f\x3f\x31\x73\x58\x69\x78\xe1\xc9\x20\xfd\x3d\x66\x26\xec\x94\xfe\xc7\xfb\xfd\xb5\x8d\x4e\x91\x65\x19\x4a\x6e\x76\xf9\x43\x43\xa0\x32\x65\xaa\x33\x65\x2a\x5b\xa6\x11\xe8\x8a\xc4\x14\xb4\x25\x14\xc6\x0b\xb6\x1f\x12\x6d\x11\xf4\x8a\x82\x3e\x21\x7a\x92\x2b\xba\xa0\xa2\x71\x3b\xb9\xf6\xbb\xe7\xf6\xce\xbe\x8a\x79\x37\x1c\xfa\xff\xfd\xb9\x92\xdb\xcd\x06\xbd\x46\x3d\x0b\xcf\xe8\x33\x0f\x09\x9e\xfd\x9f\x4f\x0e\x11\x60\x68\xfe\xcf\xff\x25\x0d\x8b\x65\xd1\x2b\x0d\x3b\x1a\x58\x30\xa9\x6a\xb1\xd7\x80\x05\x9f\xc7\x26\x8a\x3b\xfd\xad\xe8\xb2\x5e\x4e\x1c\x2b\x9d\x28\x93\x68\xdc\xd7\xfa\xee\xb7\xae\xf2\x55\x51\x3f\x30\x15\x31\xb1\x7d\x08\xbd\x0a\xfd\xf5\x5f\x5c\x9c\xe0\xd0\x04\x2e\x46\x17\x98\x6f\x1d\x82\xea\x92\x17\x58\x65\xd2\x13\x35\x7f\xe0\x55\x2f\xaf\x08\x06\x8b\xe6\xcb\xe4\xe7\xa4\x72\x2f\xa8\xb5\x71\xaf\x32\x44\x53\x48\xbf\x5f\x59\x67\x5b\xc8\xd2\xff\xaa\x14\x85\x0a\xcc\xa1\x67\xbf\x26\x82\xd8\x70\x5e\xe6\x62\x0b\x82\x61\xef\x92\xde\x40\x3f\x9c\xd5\x74\x38\xeb\xf7\x7b\xa9\xfb\x6d\xd4\x30\x52\x41\xe0\x22\x11\x9a\x24\x3e\x1e\xc5\xcd\xf0\x78\x14\x1a\x74\xf6\xfb\x82\xe4\x53\x37\x3a\x70\x88\x29\x72\xd3\xf0\x6b\xfe\xb6\x37\xf3\xb1\xf6\x2a\x72\x4b\x87\xfd\x7e\x65\xd5\x1a\xbe\x3e\x1f\xff\x7c\x47\x55\xb6\x33\x54\xda\x9e\xaa\x6c\x6f\x7e\xd6\xce\x35\x85\xf9\x71\x4e\x6a\xd8\x36\x12\xf0\xbc\x0f\x23\x61\x77\xfc\x4c\x3d\x7e\xfb\x28\x1a\x05\xbe\x3b\xd5\x44\x2a\xf2\xd2\x68\xf1\x83\xd5\xd9\x44\xad\xfb\x0b\x9e\xdd\xe3\xfb\xdc\x96\x2a\x77\x49\x8b\x3a\xf0\xb7\x8c\x38\x52\x19\xdb\xc8\xb3\xba\xc5\x82\x5c\x56\x6d\xdd\x62\x4c\xb1\x6a\xe2\x31\x77\xe2\x1f\x51\x40\xe5\xc4\x22\x42\x46\x30\xf0\x94\x59\xe7\xe4\xd4\x13\x98\xb4\x8e\xc0\x50\xd6\xc5\x35\x8a\xd2\x76\x57\xd2\xb2\xdd\x75\x9a\x8e\x52\x83\xbe\x42\x93\xb1\x46\x15\x6d\x82\x9e\xbb\xac\xa7\xb0\xba\x9d\x6e\x3c\x88\x15\x3b\xf3\x3a\x6a\x68\xaa\xcf\xe8\x8a\x06\x2e\x2b\x9f\x14\x9e\xcb\xca\x27\x75\xfe\x73\xc2\xc9\x84\x67\x16\xb3\x76\x4e\x93\x8c\x5d\xaa\xa6\x75\x1f\x6a\xbe\xc8\x9c\x5d\xb7\x7b\xa3\xe7\x36\x78\xdf\x59\x6b\x56\x64\xaf\x69\x68\xf1\xb5\x48\x0e\x3b\xb4\x60\xdd\xa3\xd5\xaa\xdd\x19\xf6\x01\x1f\x1b\x2b\xd2\x58\xcd\x5f\x3a\x1c\x97\x37\x62\x9c\xa6\x25\x91\x06\x8a\xbd\xa7\xdb\x12\x56\xc1\x29\x90\xd4\xd7\x33\x7f\x72\x03\x30\x82\xb3\xdb\x03\x8f\x42\x62\xd0\xb5\x2e\x57\x9a\x4f\x84\xe7\x0e\x47\x0b\xa7\x13\x95\xd8\x98\xe5\xb3\x1b\xd7\x75\x49\x65\xc0\x40\x58\x54\xcc\x47\x8c\x92\x75\x9c\x53\x11\xf8\x15\x63\x9d\xe9\xd3\xd0\x09\xb5\xab\x2f\xd2\x44\x18\x72\x6d\x9f\x57\x13\xfd\x23\x17\x0d\xc1\x14\x3d\xcb\x70\x44\x7f\x08\xbc\x6e\x13\x41\x20\x67\x36\x3e\x24\xb7\x2e\x0a\x2a\xf4\x70\x80\xb4\xb6\x3b\x56\x22\x08\xeb\x6b\xea\x64\xe2\x2d\xcd\x89\x18\xed\x9e\xce\xc0\x3a\x65\xf8\x09\xc1\x7f\xdb\xc1\x8d\x09\xcc\x1a\xd4\xb6\x15\x1d\x8e\xd5\x8d\x8b\xe3\x39\x56\xc1\x70\x5a\xd0\x6a\xaa\x90\x78\x08\xc1\x6c\x99\x09\x58\x3a\xfe\x46\x20\x64\xe4\xd9\xb6\x92\x2b\xbe\x54\x89\x70\xf4\x91\xd7\x5f\xe0\x0d\x72\xfa\xc7\x36\x98\x13\x97\xfa\xa0\xd9\x25\x72\xae\x7d\x1a\x10\xa4\x3b\x94\xe2\xcc\x50\x18\x2d\xf4\x50\x42\x41\x0b\x73\xc6\xea\x86\x22\x10\xc2\xc2\xe8\xdf\xbd\x9e\xaa\x99\x89\x2b\x63\xe4\x21\xec\xf1\xd9\x2b\x91\x38\xad\x5e\xe9\x75\xd5\x0e\x4d\xe3\x4c\xcc\xbe\x11\x54\xd1\x5b\x43\x57\xa1\x5e\x89\xa1\x8f\x2e\x54\x66\x7c\x4a\x84\x07\xcf\xd9\xad\x87\x07\x6f\x1a\x46\xa5\xe9\x1b\x71\xc3\xbd\xa7\xe1\x30\x7c\x49\xb9\x46\x72\x0e\xa8\x02\x94\x17\x50\x16\x52\xe5\xb5\x61\x30\xa0\xb9\xab\x1e\x38\x83\xde\xae\x67\xd4\x65\x90\xd3\x5d\xf4\xfb\x35\x21\x7c\x99\x14\xa4\xf2\xcb\x5c\x1a\xf2\xe3\x19\x12\x69\x26\xaa\x2c\x81\x8b\xda\x86\x91\xb5\x49\x59\x96\x55\xd1\x91\x63\x27\x83\x56\x59\x0c\x9d\x75\x56\xcb\x57\xe1\xa1\x09\x11\x70\xa6\x7c\x86\xee\x93\xfd\x01\x2c\xa8\x72\x5a\x4a\x28\xd9\xa3\x17\x23\x28\xe9\xc5\xa8\xb3\x8b\xf2\xec\x2e\x4a\xbd\x39\x15\x2d\xa6\x76\xff\x66\xba\xf9\x39\x7e\xb3\x6a\xa1\xbf\xf0\xb8\xdd\xea\xf7\x5c\xdc\xd0\x39\x39\x98\x08\xfd\x15\x94\xf8\x7f\x6e\xfd\x3c\x3b\xf7\x8f\x66\x41\x6b\xb3\xa0\xa5\x5d\xd0\x2a\x7a\x11\xb8\x0d\x23\x64\x0c\x14\xf0\x66\x5c\x8c\x82\xeb\x51\x85\xf7\xf9\x62\x08\x9c\x2a\x92\xf3\x73\x17\xea\xb0\xcb\x39\x75\x37\x1b\x7f\x34\x54\xe9\x47\x05\x22\x75\x65\x7d\x4f\x83\x3f\x15\xaf\xbe\xd9\x62\x70\x78\xef\xf0\x53\x65\x27\x8f\xbe\xd5\x14\xce\xdc\x39\x36\xaf\x26\x89\xf4\xc1\xcf\x18\x42\xe5\xaa\x21\x10\xd2\x0a\x97\x66\x80\x8b\xc1\x36\xa3\x3a\x1c\x45\x15\xfb\x56\x1d\x9d\x56\xe8\x34\xa2\xa9\x41\x69\x4d\x26\xdc\x41\x9d\x74\xae\x08\x0f\x57\x24\xd2\xe7\x30\xba\x7c\x55\xe4\x2d\xa2\x72\xf0\xcd\x2f\x76\x25\xdb\xd1\x3e\x90\x00\x40\x7c\xcf\x1d\xa7\x29\xb3\x01\x7e\xf1\xbc\xf1\xe0\x97\x4e\x1f\x9e\xb1\xc3\xe9\x4c\x6c\xe1\x08\x15\x1a\x23\xe7\xea\xe2\xd7\x80\xc6\x3d\x33\x24\xa9\x21\x7c\x2e\xa4\x43\xee\x10\xc3\x97\xd9\x3b\x03\xf1\x42\x59\x17\x2c\x58\xa3\xf6\x12\x87\xd4\xb8\x1a\x61\xf8\x42\x06\x83\x87\x98\xa9\x6b\x95\x68\x55\xac\x52\x9d\x19\x15\xbc\x6c\x67\xd8\xbd\x3e\xd9\x2a\xf9\xb9\xf4\xf7\xdb\x96\xcb\xc8\x0b\x06\xd7\xf3\x8c\xb8\x2c\x82\x32\x7d\x57\x34\xe4\x50\x33\x1f\x7f\x0a\x8d\xb6\x28\xaa\xb4\x24\x82\xfe\x5d\x25\x82\x80\xd4\xff\x25\x21\x91\x12\x9e\x6a\x29\xe1\xc5\xb2\xfe\x42\x9e\x0a\x69\xfb\x7d\x36\xa9\x90\x10\x01\xa6\xa9\x91\x5c\x4d\xf4\x47\xce\x26\xfa\x33\x1f\x86\xda\x75\x1b\x92\x1c\x14\x1e\x09\xfb\xee\x8a\xc6\x3b\xc2\x0d\x9e\xde\xc2\x98\x82\x2a\xbf\x35\xfa\xe0\xa8\xa2\x60\x58\xbd\x12\xb5\xb8\xda\x96\x98\x28\xd8\x29\xa0\x82\x7a\x50\x80\x18\x44\x8c\xfa\x68\x09\xcb\x33\x8e\x44\x58\x0b\xba\xa1\x21\xb0\xe8\xf7\xfd\x26\x89\x6c\x07\xa2\x65\xc4\x32\x8f\x63\x8d\x19\x7f\x17\x1c\x0c\x55\x92\x57\xe0\x67\x20\x60\x8e\x4c\x5c\x69\x1f\x6c\xcb\xde\x7b\x5a\x0a\xed\x61\xa6\xf0\x30\x13\x64\x00\x1a\x85\x7b\x3c\xac\xfe\xc6\x33\xb1\x7c\x56\x45\x11\x6f\x65\xc2\x21\x02\x16\x0e\x54\xe8\xe3\x26\xc4\xc6\x80\xec\x00\x6c\xc8\xc1\xc6\x0c\x3f\x48\xb1\xad\xe7\x2c\x57\x61\x0a\xf6\x34\x84\xb6\x50\x37\xd3\xb6\xd7\x9c\xa8\x31\xd6\xf4\xb5\x91\xd2\x47\xa3\x63\x7a\x74\x75\x08\xd5\x83\xa3\x93\x1e\x8e\xe3\x4f\x1c\x9d\x31\xbc\xd1\x84\xec\x63\x85\xda\x78\x35\xe9\x4e\xb2\x24\x4f\x0d\xd5\x69\x8f\xa2\x5a\x5d\x21\x93\x0a\x6a\x4f\x28\x39\x92\x9c\x34\x38\xfc\x56\x11\xa4\xa1\x1c\x0d\x4f\xf4\xcb\xee\x79\x1f\x4d\x62\xf8\x5a\x61\x10\xae\x57\xe6\x7a\x2d\x5d\x40\x5c\xab\xfd\x19\xcd\xf4\x80\xba\xea\xf9\x09\x9b\xbf\xa6\xb2\xa1\x87\xa6\xa1\x2c\xc8\x9c\x62\xa9\x4f\x0d\x78\x57\x0a\x90\x32\x11\x1a\xc5\xef\x8a\x8a\x2c\x48\x5c\xd0\x8b\x0b\x9e\x75\x08\x34\x32\x5e\x4c\x5a\xb0\x23\x2f\x8d\x6e\xe5\x4a\xcf\xc3\x54\xdc\xd2\x8b\x8b\xaa\x53\xb1\xb4\x36\x31\x0b\x6f\x10\x73\x31\x6c\x08\x2c\xe9\xa2\xdf\xdf\x8e\x97\xc7\xa3\x6d\x66\x0e\xe2\x14\x38\xa1\x4c\x6a\x39\xf1\xb2\xad\xbc\x57\x89\xea\x77\x56\x8b\x5e\xc7\xaa\xce\x5f\x9b\xd5\x09\x5e\x71\x8a\xcb\x3b\x14\xd7\x20\xf2\x06\xb3\xd5\x54\x9f\x3e\xbc\xbf\x26\xdc\x83\xf3\xf3\x98\xec\x09\xe7\x9c\x91\x48\x8b\xf9\x4c\xd4\x01\xa6\xc9\x24\xef\xb2\x1b\x91\x6f\x87\xdd\x58\x0a\x5b\x13\x06\xae\xd3\x1f\x22\x76\xbf\xa0\x48\x3c\xba\xe6\xc5\x33\x5e\x19\xe2\x47\x2c\x9f\x7d\x2d\x26\x22\xe7\x7a\x23\x2b\xd2\x24\x8c\x80\x81\x11\xc2\xc2\x01\x09\x45\xc4\xed\xf7\x1a\xac\x50\xd2\x1a\x57\x15\xe6\x18\xcb\xbc\x2d\x04\x3c\x14\xf7\x7a\xab\x56\x74\x0e\xf7\xac\x14\x8f\xf9\x82\xce\x1b\x5a\x22\x4c\xd4\xc8\x4f\x5b\xe3\xb6\xdf\x4f\xfe\xa1\x8c\x6c\xf1\x1c\x8a\xd2\x05\x59\xa6\x6d\x61\x5b\x96\x50\xd4\xac\xc8\x0b\x3b\x5c\x6b\x6f\xc7\x8d\x9e\xef\xc4\x3e\x2a\xb9\xf1\x72\x15\x4e\xb3\x01\xcc\x65\xbf\x2f\x2f\x28\x15\xfa\xbd\x31\x87\xa7\x30\xce\x38\x11\x66\x9e\x74\x6c\x00\xa4\x5b\x98\x3a\xc0\xce\xb2\x69\x6b\xe4\xfa\x6e\x7c\xab\x56\xc4\xff\xfe\x96\xe5\x07\x5b\x6e\x7c\x65\xd1\x5d\x8f\x95\x5b\x69\xb3\x1e\xbc\xbb\x7d\x04\x7e\x50\x89\xb2\x12\xa8\x85\x34\x12\x28\xbd\x81\xac\xee\x41\xb1\x54\xac\xb6\xa7\xcd\x8a\x94\xba\xa7\x3f\xe9\x08\x8a\x62\xa5\x65\x10\x2e\xfc\xad\x0b\x9e\x82\x2c\x6f\x3a\x1c\x17\x18\xdf\xa3\x20\xf2\xf4\xb4\x17\x04\x39\xa1\xce\x95\x58\x69\xd0\xd0\xba\xdf\xaf\x83\x33\xe0\x3a\x3e\xa8\xaf\xf4\x3e\x95\xf4\x60\xf1\x9f\xfc\xcc\x0d\x29\x9c\x27\xbc\xc2\xdc\xc9\x6f\x45\x52\x63\x84\x1f\x30\x57\x55\x99\xd5\x90\xb1\x07\xbf\x13\x79\x94\x5b\x39\xe7\x71\x0d\xd7\xbb\x46\x9c\xf3\x13\xb3\x60\xb4\x04\xe1\xe8\x93\x93\xa9\x96\x54\x4c\x8b\x19\x94\xfd\x3e\x62\x7c\x25\xde\x12\xf4\xd1\xa9\x7f\xd0\x4a\xa2\xc1\x3c\xcf\xf4\x1e\x17\x0f\x85\x62\x84\x38\xa1\xde\x17\x5e\x79\x3c\xac\x7b\x2f\x64\x19\x23\x96\x45\x5d\x3c\xbe\xe1\x6b\x8c\x8d\xfb\x01\x32\x18\x69\x1b\x8f\xae\x78\x1a\x86\xd1\xe0\xc5\x78\xcc\x4c\x90\xdf\x08\x2e\x09\x8d\xd8\xda\x99\x8e\x35\xfe\xcd\x11\xb9\x38\xeb\xb4\x58\xa2\x09\xb8\x86\x95\x18\x62\x9b\x83\x24\xa4\xf1\xd3\xb1\x47\x25\x9e\x96\x86\x55\xa7\xb9\xbd\x8b\x78\x66\x6d\xa1\xdf\x1f\xa0\xf6\x19\xad\xde\x37\xb1\xaa\x33\xb1\x68\xd8\xb1\xcf\xe5\xee\xf8\xcf\xed\x0a\xcb\xd6\x4c\x15\xbe\xb1\xca\x6e\x76\x65\x37\xbb\x77\xd2\x40\x7b\xef\xa2\xbe\xab\x76\xdf\x91\x20\xd8\x1f\x90\xfc\x62\x08\xae\x66\x7e\xa6\xe9\xc6\x51\xb4\x5b\x89\x51\xff\x08\xbd\xd5\x34\xca\xe1\x5e\xec\xfe\x6a\x14\x5b\x39\x65\x70\x2f\x76\xd6\xb1\x24\x65\xfa\x8d\xf2\xc2\xae\xad\x64\xdf\x7b\x65\x80\x28\x02\x10\x6a\xaa\xb2\x20\x2f\x40\xcd\x53\xa6\x51\xf1\xd0\x14\x44\x7d\x00\x57\x6c\x6d\x3f\x22\xf5\x64\x4e\x42\x80\x0b\xf9\xb1\x3a\x3e\x77\xc5\x62\x11\x59\x8c\x19\xef\x9f\x7f\xe5\xea\x73\xb1\x63\xc8\x36\x32\xa5\x50\x81\x89\x2d\x5e\x2a\xb6\x36\xe0\x03\x93\x5d\xe8\x9a\xd7\x62\xc1\x7c\x13\xb8\xc6\xde\x63\x73\x4b\x91\x28\xb0\xf0\x4d\x49\xb5\xa3\x66\x6f\xa2\xbe\x75\x17\x1d\x5f\x25\xa2\xdc\xae\xab\x9f\xf8\xef\xac\x9d\xee\x35\xa0\xdb\xc9\xeb\xc2\x2e\x54\x37\xf5\xef\x27\x2a\x49\xaa\x63\x7e\x67\x1e\x8f\x76\x27\x6c\xd9\x6e\xa8\x3e\x69\x7a\x75\xda\xdb\xa9\xf6\xd3\xdd\x1a\x1d\x4b\x74\xf4\xff\x2d\x63\xb3\x5d\xf7\xb4\x39\x4d\x2c\xeb\xf9\x77\xdd\x71\x9f\x6a\xfb\x8f\xab\x30\x53\x05\x55\xb4\x18\x0c\xaa\x30\x08\x0e\x55\xa6\x0f\x35\x5f\x1b\xd2\x5c\x22\xff\xf7\x7e\xcb\xcb\x85\x63\x49\x83\xbe\x62\x2a\x21\x4d\xa7\x5c\x4b\x4d\x7c\xac\x3a\x3c\xcc\x49\x62\xd5\x1d\xa8\xf2\x03\xd1\x94\x86\x5e\xc5\xa1\x7e\x60\x71\x2c\xb6\x0c\xba\x2c\xb2\xab\xa7\xc2\x50\x41\xe1\xc6\xe8\xe2\x76\x43\x5c\x29\xd2\xb4\x86\x78\xea\x25\xdc\x47\x30\xb3\x81\xce\xac\x0d\x37\xa7\x3f\x20\x3b\x39\xf6\x64\x0b\x53\x7b\x44\x67\xa0\x08\xba\xba\x47\xa1\x92\x62\x35\xde\x4c\x6e\x3f\x92\x84\xd3\x5b\x97\x93\x78\xf8\x85\xaf\x29\x21\x44\x93\xf5\x52\xd4\xca\xd6\xd1\x3f\x93\x04\x89\x45\x5d\x0b\x3f\x79\x80\x3c\xa1\x56\x18\xaa\xc5\xb1\xfb\x7d\xee\x7e\x1a\xa3\xeb\xe8\x32\xf0\x06\x77\xa2\x3d\x5d\xef\x58\x8a\xc1\x5c\xed\x0c\x77\xdb\x90\x72\xd6\xff\x6a\xac\x92\x12\xed\x8a\x5d\xef\x21\x89\xa2\xb2\x99\xe5\x02\x41\xbf\x62\x49\x95\x2d\x45\x85\xfa\xcd\x02\x9d\xf4\x23\xa7\xce\x79\x65\x7e\xc3\x55\xc9\xcc\x2e\x25\x31\x78\xaa\x63\x90\x54\x36\x74\xab\x09\x2a\x19\x0c\xe7\x38\x36\xaa\x5b\x54\x35\xaf\x1e\xe0\xf4\xd8\xcc\xe3\x03\xa3\xc7\x79\xb7\xe4\xea\x47\xf1\x28\x93\x02\x24\x06\x55\x4d\x47\x43\x92\x27\xab\xd6\x49\x99\xdb\x82\x2f\x44\xd9\x2e\x08\x6e\xc2\x91\x44\x96\xf9\x0e\x8e\xc7\xd0\x99\x2e\x6a\xd7\xc4\x97\x5d\x99\xb2\xa6\x13\x5b\xf8\xaf\xf6\x04\xfa\x71\x9d\xb7\x3d\x3b\xe8\xcd\x90\xe0\x5a\xcf\x43\xac\x11\xef\x51\x79\x53\x2c\x16\xbc\x7a\xc8\xeb\xa6\x69\xa8\xb0\x01\x55\xba\x60\x77\xae\x53\x03\x80\x9b\x0e\x67\x68\xb2\x60\x1c\x66\x2d\xa8\x1a\xcb\x4c\xb1\x9d\x42\x7b\x75\x6a\x6d\x03\x4c\xd2\xe7\x85\x64\xba\x26\xed\xad\xf9\x62\x51\xb2\x1e\x56\xd9\xd2\xc1\x08\x96\x74\xe0\xed\x37\x45\x7c\xc4\x22\x65\x24\x15\x29\x23\x3d\x7b\xa0\x3c\x65\x57\xd7\xa9\xcc\xd6\xac\x90\xdb\x9a\xbd\x61\x3b\x95\x28\xec\x87\x58\xbd\x26\x74\x6f\x23\x8e\xc7\xf9\x74\x1e\xe2\x3b\xa4\x0f\xe9\xf5\x65\x7d\x5b\x90\x7e\x3f\x59\xa4\x74\x05\x51\x6e\x22\x6e\x87\x93\x61\x3e\x22\x33\x3a\x84\xa5\xce\xdc\xa6\x29\x81\x72\x2a\x66\xd4\xd8\x56\x0c\xd1\xb6\x62\x09\xb5\x78\xcc\xb7\xd6\x76\xe4\xc1\xd9\x8e\x54\x0d\xb4\xbb\xa2\x0f\x69\xdd\x10\x02\x8b\xc6\x1f\x85\x0f\xed\x8d\x3d\xa9\xff\xce\xe6\xc4\xaf\xd2\x54\x6f\x4e\x31\x50\x76\x73\x6a\xd8\xa2\x8b\x84\xa1\x53\x6c\x80\x75\xf0\x9a\xfe\x51\xeb\x5e\x7c\xc4\xba\xa3\x16\xc0\x32\x65\xb8\xd0\x2b\xb3\xce\xdb\xb4\x86\xb9\x65\x8a\x98\x65\xdb\xba\x65\x5b\x36\x04\x1e\x4c\x89\x75\x9a\x7a\xe5\x80\xa1\x0f\x7e\xac\x91\x88\x2d\x14\x44\x6f\x09\x4b\xeb\x78\x3f\x1e\x70\x3f\x36\x9a\x7a\xca\xd7\x76\x3f\x8a\x68\x3f\x36\xa9\x3e\x9a\xb8\x07\x29\xdd\xbe\x6f\x04\x8b\xa6\x58\xfc\x73\x2b\x95\x5b\xcd\xee\x7b\x82\x91\x17\x3d\x6c\x6c\x43\xb2\x71\xa4\x65\x78\x1e\x1e\xb5\x77\x2a\x66\x41\x17\xe8\xd7\xa1\x82\xee\x36\x4b\xbd\xcd\x08\x38\x8d\x43\xb3\x16\x54\x32\x0c\xe8\x82\x0e\x35\x3d\x9e\x54\xf6\x1d\x4b\xa5\x7b\xc7\x06\x91\x15\x96\x9c\x16\xb3\x98\x43\x55\x3e\x13\xcb\x67\x9c\x14\x48\x98\xd4\xe2\xb1\xdf\x4f\x0a\xf3\xeb\x63\x1b\x23\x50\xa2\xad\x00\xc5\xe7\x30\x65\xa9\x84\xd2\x3c\xa4\x35\xd4\x29\x2d\xcd\x31\x48\x65\x83\xea\x29\xdd\x91\xba\x2a\xee\x0d\x1d\xa8\xf8\xc4\x4e\x8b\x99\x7b\x52\x4f\xc7\x5c\xea\x92\x17\x94\x16\x76\xcc\x73\x51\xfe\xf1\x66\xed\xe8\x69\x6d\x07\x9d\x52\x3f\x61\x1c\xbc\x29\x96\xca\xa6\x69\xaf\xb9\x53\xdd\x55\x62\x83\x1c\xea\xd8\x08\xde\xa1\x4b\xc7\xa3\x33\x76\x7a\xaa\x84\x8b\x0b\xd3\x3d\x5b\xa7\x47\x2b\x52\x2f\x99\xab\xdd\xf8\x1f\x2a\x61\x80\x2c\xfa\x3b\xd3\x84\x26\xe6\x19\x69\x9a\xbb\x33\x2d\xb6\xde\xe0\xb0\x0a\x96\x41\x65\x76\x32\xaf\xf0\x79\x2e\x50\x47\xd1\x9c\xc2\xda\x9d\xc2\xb2\xa1\x0c\xe6\x74\x87\x6b\x28\x6a\x58\xd1\x5d\x95\xb0\xac\x56\xa5\x3d\x1d\xee\x15\x23\xb0\xd0\x4f\x73\x69\x9f\xe6\x83\xe1\x62\x6c\xc1\x9d\xe2\x65\x43\x4b\x78\xa0\x0b\xf3\x60\x6f\xe8\xc3\xd5\x35\x82\xa2\xf5\x58\x59\x4a\x48\x95\x1a\xad\x28\xa2\x37\x63\x15\x7e\x27\xe6\xfd\x70\xf9\x27\x0f\x08\x14\x91\xb5\x61\xf6\x27\x28\xcc\x6b\xbe\xb0\xaf\xb9\xd5\xc6\xf4\xc8\xc0\x2e\xa2\x55\xee\x63\xc4\xe0\x0e\x11\x83\x12\x1e\x08\xec\x69\x17\x05\x80\x77\xce\x13\xfb\x99\xab\x3d\x5e\xd3\xfd\xe4\xb0\xcb\x45\x52\xbb\x8b\xb3\xf4\x17\xa7\x9a\x0e\x67\x04\xf6\xb9\x39\x9d\xcb\xf4\x9d\x61\x24\x0c\x9b\xfc\xb0\xcb\x7d\xe9\xbd\xad\xac\xcb\xbc\xc3\xda\x2e\x2c\xcc\x74\xe8\x4f\xad\xab\x09\xf7\x95\xa5\x1a\x19\x2e\xc9\x17\xbc\x66\xc8\x2e\x73\x58\xd3\x23\xbd\x4b\x97\x63\xf5\x04\x2c\x67\xf0\x5a\xc3\xf2\xa2\x65\xc0\xc9\x70\xd5\x90\x6d\x77\x3c\x6e\xf5\x22\x46\xca\xfd\x71\x96\xed\xe2\x2d\x2d\x5a\xd0\x9f\xc5\xd0\x1f\x7e\x6a\x6d\x20\x0b\xbf\xd1\x11\x5a\xd8\xe6\x32\xfc\x26\x04\xbe\xa7\xbb\xf4\xe1\xea\x3a\x7d\x8b\xc7\xe3\x0b\xba\xce\x76\xf0\x82\xae\xb3\xfd\x78\xa5\xe9\x01\x1b\xc5\xd7\x1d\xba\xfd\xe4\xb5\x7e\x63\xbe\x48\xbf\x4f\x97\xb7\x76\xb5\xfb\xfd\x04\x2b\xa4\xf4\x11\xd6\x78\x2c\xd2\x14\xb0\x21\xfa\xc4\xe6\x98\x52\x33\x42\x72\x6c\xed\x45\xfa\x78\xeb\xd6\xbe\xdf\x4f\x4c\xd5\x2f\x52\xee\xca\x59\xb0\xb6\x0c\xad\x63\x7f\xf4\xc9\xdd\x73\xf5\x1c\xe0\x19\x5f\x74\x45\x29\x7c\x99\x84\xd0\x5e\xbb\x1b\x3a\x8c\x03\x7c\xdd\xdf\x0c\xdd\xfb\x52\x58\x6e\xa2\xc7\x8c\xbf\xb5\x1c\x19\x83\x95\x8e\x90\x01\x1c\xef\x9b\xce\xf7\x5f\x30\x27\xf6\xa2\x38\xa7\x70\xf6\x37\x18\x83\x7b\x97\xdb\xf1\xeb\xd6\x4e\xc2\x70\x44\x6d\x27\x6e\xee\x03\xac\xfd\x3d\x69\x5d\xc7\x0a\x8a\x13\xb7\x6c\xd1\xb7\x19\x54\xd7\xf5\x9c\xeb\x13\xa6\xe6\x99\x69\x31\x26\x02\xd2\x74\xb0\x5a\x3c\x3b\xa3\x50\xfa\xd3\x0f\x3f\xbe\xb9\xbe\xba\x8e\x0d\x1a\xac\x03\x0f\xd3\x95\xb7\x5c\xe2\x99\xfb\xd9\xb2\x97\xa8\x1a\x90\x74\x95\xed\xbe\x2f\xb7\x1a\x43\xdb\x5d\x5d\x93\xf1\xb7\x2a\x29\x8c\x0e\x58\xba\x21\x4d\xa4\x68\x29\xa8\x55\xdd\xd2\x68\x49\xf2\x30\xb8\x27\x26\x56\x93\x6e\x41\x1f\xb1\xaf\x44\xfd\x4a\xd5\xba\x19\x02\x35\x7d\xc9\xbc\x37\x3a\x63\x78\x41\xc6\x45\x4b\x0e\x68\x35\xa8\x51\x4d\x47\x26\x35\xc9\xa4\x58\x33\x14\xa8\x0f\x31\x40\x02\x99\x70\x96\x14\x70\x30\x6e\xc5\x05\x3c\xe6\x3b\x58\xe5\xde\x18\xaf\x6e\x48\x5e\x18\x51\xa2\x04\x01\x3b\xb8\x27\xf6\x02\x27\x04\x86\x46\xdc\x5c\x04\x6f\x42\x45\xcc\x48\x5e\x65\xbb\xe4\x0b\x02\x2f\x80\x11\xf8\x82\xca\xe4\x27\xf8\x22\xdd\xa5\x1b\x77\x43\xda\xac\x78\x7d\x5c\x99\x1e\x09\xc7\x7b\x0b\x0a\x58\x7a\x77\x75\x0d\x0b\x38\x68\x60\xfb\x96\xa9\x55\x2d\xb6\x0f\xab\x9c\x5b\xa5\x12\xf0\xd7\x3b\xe7\xe1\xaa\x37\x9d\x7e\xf7\x93\x75\xb6\x4b\xe9\xf7\xe9\x32\x37\x77\x57\xe3\x6a\x77\x4f\xc1\xb8\x26\x7a\x33\x9e\xa4\xb1\x51\x0b\x13\x7d\xde\x83\xd4\x8f\x13\xb7\x8f\x53\x41\x7f\xd7\x1f\xf6\x69\x32\xe2\x45\x7e\x1e\x93\xab\x9f\x7e\xef\x4a\xcb\x18\x9a\xa3\x8f\x18\xf3\xa8\xc3\x8a\x4a\x7c\xe1\xf4\x7a\x18\xbb\xbe\xd4\x18\x05\x6c\x61\x69\xd1\x0b\x78\xf0\xf6\x16\x4f\xe0\x74\x0f\x01\xdb\xcd\xb2\x2c\x46\xba\x34\x26\x6c\x20\xcc\x02\x96\x54\x24\x2c\xc3\xf7\x1a\x02\x30\x7b\x20\x6d\x5d\xe0\x16\xf2\x93\xd5\x6c\xb1\x9d\x33\x44\xe5\x19\xa1\xb7\xbe\x1b\x05\x2c\x60\x45\x43\x32\xde\xd2\x45\x1a\x5a\xc7\x1e\x23\x78\x36\xf0\x51\x72\xec\x12\x0e\x9e\x40\x77\x9d\xda\xd1\x86\x8a\x64\x0e\x4b\x58\xa6\x0f\x64\x1c\x81\x7b\x5a\x47\x0f\x44\x95\xcc\x0d\x4a\x76\xf6\x7d\x2f\x3b\x9e\x06\x0c\x3a\x52\xb6\x3c\x09\xf8\x34\xfd\xf4\x4b\x47\xc8\x33\x96\x94\xee\xac\x6e\x60\x0b\x92\x34\x67\x07\x7b\xd6\xb9\x80\x3d\x3e\x4c\x1f\x1f\x65\x8f\x0f\xa7\x18\x17\xd0\x1f\x1f\xcf\x3c\xb5\x27\x68\xc2\x70\xc7\x4c\xbb\x29\xb7\x0b\x9b\x0f\x31\x66\xf7\x2b\xff\x1a\x3f\x57\xa7\x3e\x88\x9c\xf2\x1f\x18\x54\xf0\x96\x72\x6b\x36\xaa\x6e\x28\x77\xaf\x1b\xd3\xc9\x68\x31\xca\x6e\xa8\xd3\x2f\xc3\xe0\xf4\x12\xcb\xc7\x04\x06\x54\x74\x38\xae\x82\x8e\x52\x9a\x56\x84\x2f\x13\x41\xe5\xb4\x9a\x81\xba\xa5\x22\x74\x20\x9c\x11\xf0\xa3\xf1\x36\xc3\x74\xae\xeb\x47\x58\xa3\x60\x7b\x4a\x9c\x6c\x32\xc6\x2e\xa6\x95\xd7\x0c\x42\x81\xe4\xaa\xa8\x16\x25\xfb\xf2\x1d\x8b\x4c\xee\x9e\xf0\xd3\x75\x71\xe2\x9d\xb5\xb7\x16\x5b\xc9\xd6\xe2\x9d\xd7\x02\x61\x99\xa8\xfe\x2a\xde\xb1\x1a\xfd\xd0\x56\xaf\x58\xf1\x8e\x79\x5d\x67\xeb\x1f\xd7\x46\x3a\xea\xf7\x93\xde\x5c\xff\xc0\xba\xe8\x4c\x69\x2b\xd9\xd6\xa0\xeb\x51\x1d\xaf\x19\x93\x18\x4d\x38\xf0\x62\xda\x88\xf3\x74\xba\x6b\xd9\x0e\x54\xb6\x37\xb2\xd6\xf6\x30\x8d\x79\x91\xa7\x90\x59\x8b\x2b\x0d\x35\xda\x7f\x82\xd5\x66\x4a\x04\x2d\x88\x57\xeb\x96\xfd\xbe\x57\x2c\x7c\x69\x55\x10\x65\x2b\x41\x17\xe0\x3e\xc7\x44\x69\x1a\x17\xfd\xfe\x45\xdd\xef\xff\x90\x70\xb7\x24\x30\x55\x50\x00\x9b\x19\x47\xe4\x6d\xae\x38\x54\x71\x71\x5c\x4c\x5d\xbc\x32\xc5\xf1\x6d\x7b\x56\xb9\x6c\x5c\xc9\x28\x7b\x6c\x3d\x30\x34\x28\x35\x7c\xb0\x52\x43\xb3\xff\x3d\xb8\xb3\x61\x54\xf2\xa5\x55\x7f\x39\x55\x12\x31\x45\xd1\x69\xdf\x52\x26\xc8\xe9\x30\x10\xd4\xfb\x9f\x77\x92\xb9\x86\x8c\xbf\x66\x99\x33\x19\x62\x28\x37\xe5\x04\xbe\x66\x59\xb1\x58\x7c\x2e\x76\x68\xcd\xda\x80\x54\x62\xa3\x4f\xd6\xd7\x2c\xab\x71\x0f\x4c\x96\xeb\x89\x04\x7b\x3e\x93\xe0\x64\x39\xe7\x85\x9a\xae\xd4\xd9\xae\x2b\x2f\x20\xe0\x8d\x91\x90\xfe\x7c\x1a\x21\xc9\x35\xc0\x3a\x6c\x6a\x3d\xec\x36\x47\xc1\xb6\x61\xef\x86\x3e\xf2\x7a\x0a\x1a\x78\x1c\x8f\xae\x99\x2c\xbe\x3f\x2c\x63\xfa\x7f\x4b\x26\xe4\x83\x58\x0d\xc1\xbd\x3f\xb9\xf1\xac\x51\xb4\x5d\x44\x3a\xde\x7c\x1e\x39\x10\xbd\x18\x81\xe1\xe2\xe7\x23\xf6\x69\x37\x42\x58\x38\xfc\xf1\x01\xc4\x08\x4f\xb8\x43\x63\x71\x2a\x6e\xad\xc8\x24\x11\xfa\xc5\xd7\x3f\xf5\x73\x82\x6f\x3f\xbd\x18\x92\x3c\x11\x18\xa8\xa9\x9d\x3e\x22\x0d\xd8\x33\x68\x74\x65\xed\xf9\x35\x1f\x8e\x09\x62\xc8\xc8\x28\xa2\x98\x83\xcb\x06\xd6\x7b\x82\xee\xb3\xa1\xa7\x34\x47\x43\xf8\x50\x40\x38\x2f\xb8\x06\xcf\x54\x6b\xe1\x97\x39\x8f\x31\xc8\x18\x81\xf1\x9a\x51\x4d\xe3\xf7\xdb\x03\xb2\x10\xff\xda\xcb\x28\xdb\xc2\x49\x13\x55\x4e\x45\x3c\x34\x75\x3e\x7e\xdc\x64\x68\x0d\x71\x35\xe6\xf8\x3b\x4b\x8a\x96\x9b\xe3\x76\x70\xb9\xa9\x0d\xd7\x39\x33\x8f\x72\x14\x6b\xae\x38\xd1\xc5\xf0\x34\x5c\x2e\xa3\x28\x72\x56\x88\x0e\x96\x18\xc8\x8b\xae\xaf\x68\x87\x8c\xfb\x1c\xc4\xcc\xdb\x64\x41\x2b\xcf\x52\x0a\x8e\x2e\xf0\x79\xc1\xcf\x73\x88\x6d\x97\xd4\x96\x9e\xaa\xdd\xe3\x72\xf5\x59\x2b\x28\x5e\xd1\xb2\x4c\x8f\x37\xe6\x78\x2c\xce\x62\xf7\x45\xc0\xee\xa3\xad\xd3\xa5\xfd\x67\xd7\x30\x3a\x3e\xe8\xb9\x5d\xd1\xa6\x31\x12\x48\x8c\x7d\x87\xa1\x93\x3e\x74\x1e\x43\x5c\xb9\xe8\x4a\xba\x6b\x88\xdb\xd5\xeb\x35\x68\x69\xe4\x1c\x7c\xe5\x2d\x07\x5f\x8a\xde\x5e\x58\xd5\x35\xf9\x77\xae\x56\x49\x4f\x54\x3d\xe2\x6f\x43\xb7\xe8\xb4\xd7\x3e\xe9\x3d\xe8\x19\x29\x50\x0f\x7a\x52\xd4\x0a\xad\x6c\x30\xfe\xb6\x44\x7b\x26\x1f\xdc\xee\xa3\x65\xaf\xff\x65\x49\xe9\x9d\xbd\x8e\xff\x03\xc2\xcc\x0f\xfa\x6d\xf8\xef\x91\x5b\x3e\xed\x1d\x52\x3f\xfc\xdc\x09\x0c\xb9\x95\x04\x5e\x54\x67\xa5\x5a\xdc\x0e\xd7\xa1\x81\x0e\x8d\xf3\x88\x1b\x1d\x92\x71\x28\x64\x85\x8f\x10\x15\xb7\xc5\x98\x57\xdf\xfa\x2d\xa9\x0c\x9f\x65\x62\xfe\x5b\xdc\x2e\x1f\x8d\x79\x58\xf6\xdf\x59\x52\x05\x14\xd5\x5b\xba\x5e\x06\xf1\x59\x1b\x49\x75\x15\x6d\xbf\x63\xde\x15\x7f\xf9\x11\xc9\xdc\x0d\x57\x76\x19\xa3\x67\x31\x68\xb7\x13\xe3\x0e\xdb\xb4\xcd\x22\x35\xdc\xcb\xe7\xf5\x43\x00\xd7\xa8\x74\xcb\x00\xd9\xfb\xdc\xe9\xde\x56\xd6\x9b\x55\x30\x6f\xb0\xa1\x20\xa0\xa6\x85\xa1\x57\x82\xb5\x11\x2c\x82\x50\xe3\x0c\xa1\x85\x91\xb4\x30\xce\xba\x24\xb0\xa2\x2c\x55\x50\x52\x39\xe0\x24\xb7\xec\x46\x4a\x69\xe1\xc7\xaf\x4b\xf3\x54\xc1\x0a\xeb\x54\x1a\xbf\x5a\x50\x13\x5d\x98\xe4\xc9\x9c\xca\x81\xcb\x43\xb7\x4f\x0b\x6a\xb2\xa0\xa4\xd5\x80\x11\x30\xc1\xd7\x7e\xcd\xe7\x06\x94\xfc\x96\xaf\x82\x04\xae\x0c\xa0\x6b\xd1\x9c\x63\x0c\x83\x65\xfe\xa2\x93\xd3\x18\x6f\x7e\x82\x6c\x15\x31\xb9\x2b\xad\x9c\xee\xaf\xd6\xa3\x44\xaa\xc2\x6e\x6b\xc2\xce\x8d\xac\x70\x23\xab\xcf\x8e\x6c\xde\x50\xcb\x72\xc6\x5d\x92\x64\xcc\xd0\xa2\xc2\x50\x56\x43\x18\x82\x70\x6c\x5f\x47\x8a\x9d\x6d\x26\x02\xc9\x55\xc2\xcd\x96\x11\x88\xa9\xbe\xdc\x53\x7d\x2e\x2a\x84\xae\x38\x2d\xa0\x9e\x35\xc4\xa0\x9f\x6b\x8b\x7e\xe2\x88\x23\xec\x73\xd3\xc1\x3e\x2f\xce\xab\x5b\x6a\x1c\x74\x73\x16\x07\x65\x4f\xe3\xa0\xa8\x00\x13\xe3\xa0\xa8\xf8\x8e\x23\xf8\xbc\x14\xf3\xb7\x94\xa3\x37\xa6\x08\x31\x0d\x58\x47\x28\x35\xee\x60\xab\x2c\x42\x53\x43\xa9\x0f\xa1\xaa\xed\xf6\xde\x8f\xae\xc6\xee\x24\x5a\x78\x61\xf4\x5a\xe9\x93\x92\x1f\x2c\x46\xd8\xbb\x17\xe5\xa2\xd7\xb4\xf0\xc6\x08\xbb\xea\x20\x9b\xf6\x59\x73\xe8\xe4\x35\xfb\xd4\x77\x69\x5c\x87\xb8\x57\xb3\x37\xb7\x2e\x2e\x9f\x7c\xfe\xda\xfe\x2d\x2f\x46\x5e\x99\x69\x27\xe9\xa1\x78\xc7\xea\xc2\xf8\x4e\x31\x22\xb8\x96\xa3\xdd\x0b\x63\x6c\x8f\x32\x55\x3a\xf4\x16\xf4\x9a\x2a\x66\x74\x18\x3b\x07\x66\x37\x7c\x9c\xa6\x31\x78\x9f\xb2\x59\x66\x0f\x10\x82\xf6\x7e\x9f\x67\xab\x42\x5a\xab\xc3\x70\x13\x35\xa8\x6f\x07\x79\x21\xe3\x2a\x45\xc3\x54\x91\xa2\x51\x6a\x9a\x4a\x6f\xb1\xb3\xcb\xab\x2b\xe4\xd4\x5d\xc9\xa6\x81\x8a\x15\x35\x93\xca\xd3\xb7\x4f\x8c\x1f\x35\xb8\x51\x75\x7e\x07\x9a\x7e\xdc\x43\x4d\xbf\xc3\x10\xcc\xd9\xf7\x7f\xfb\xe9\xe5\x9b\x97\xbf\x7c\x79\xf7\xf2\xbb\xaf\x5e\x7e\xf7\xf2\xcd\x6f\x26\x24\x15\x1d\x42\x88\x43\x31\xe6\xa8\x78\x18\x1f\x95\x29\x6f\x4d\xae\x42\x37\x41\x67\x26\xf7\x8b\x4a\x18\x54\xdd\x38\x35\x84\x8c\xd5\x4d\xdd\xef\x27\x35\x55\x20\x68\x45\x9a\x86\x2f\x13\x11\xaa\x89\x33\x6b\x22\x71\x49\x34\x72\xbb\x0f\x8b\x81\xb1\x10\x9b\xd8\xa6\xfa\x5e\xb6\xdc\xf6\xb0\x7e\x3f\xf9\x2d\x61\x64\xf2\xbc\xae\x8b\x7d\x86\x9e\x61\x34\x39\x8d\x92\xda\xac\xd8\x6c\xca\x3d\x96\xcf\xad\xed\x17\x23\x2d\x4f\x7e\x77\x32\xb2\x88\xed\x19\xde\x4f\xf0\x46\xaf\x8e\x47\x15\xeb\x8f\xfe\x84\xf9\xe8\x6e\xdd\x19\xdf\xf4\xfe\xdf\xaa\x47\x6e\x07\xa3\x89\xca\xe4\xa6\xe4\xca\x24\xc4\x7e\xff\xf6\x2d\xeb\x09\x07\x72\x78\x1b\x77\xac\xac\xd6\xa9\x68\xd0\x4f\xd8\x89\xaa\x6b\x15\x87\x8c\xb6\xf4\x47\x5e\xd8\xc0\xbc\xb5\xf5\xfe\xd1\x8e\x04\x1c\xdc\xd6\x39\xcd\x55\x57\xcb\x78\x67\xcd\xe3\x10\xc0\x82\x40\x5d\x3c\xe6\x1d\x42\x67\x5a\xcd\x4c\x4c\x57\x31\x83\x76\x70\xcf\xbc\x76\xe3\xcf\x3b\xe1\xd5\x7d\xb8\xe6\x5c\x74\xa7\xe8\xe7\x1e\x47\x3e\x94\x5d\x95\xf6\x3b\x6b\x23\xa3\x76\x70\xb8\x17\x8b\x7d\x5e\xc1\x52\x08\xc5\xea\x5c\x58\x7c\xda\xf8\x45\xf1\x54\x5c\x11\x89\xe5\xac\xf2\xf6\x57\x2c\x61\x99\xae\xfc\x15\xbe\x65\x73\x93\x80\xb5\x4d\xca\xca\xa4\x98\x86\x4d\xd2\x82\x3a\x7e\x17\x6c\x43\x7c\xdf\xa5\x57\x08\x05\x44\x8f\x58\x40\x8f\xf4\xcd\xdb\x50\x87\xfb\xd8\x18\x1a\x55\x97\x5b\xaa\x52\x96\x19\xa8\x6c\xdb\x49\x0d\xa3\x4f\x86\x4f\xa4\xea\xdd\xc5\x86\x21\xb2\x88\x76\x1a\x34\x98\x7a\x9f\x8b\xc5\xde\x15\x56\xa6\x70\x94\x04\x8b\x7e\x3f\xd9\xa4\x74\x71\x39\x8f\x71\xb3\x64\x31\x18\x91\x4b\x3b\xe7\x9f\x36\xc5\x9c\x57\x0f\xa9\xfd\x34\xa1\xa0\x3e\x37\x1c\x40\xd8\x91\xc3\x26\xa5\xcb\xcb\xc4\x2b\x58\x21\xc9\x24\x27\x9e\xcf\x8b\xa2\x6e\xdf\x34\xc9\x5b\x5f\x69\xb2\x1b\x2c\xc9\x65\xd9\xea\x7c\x67\x3a\xd7\x3b\x60\xfb\x6e\xb6\x66\x98\x6e\xcd\xcd\x18\xde\x88\x4d\xba\xbd\x5c\xb5\xea\x6e\x4d\x5d\x53\xcc\xd6\x36\x8b\x7d\xef\x3d\x69\xdc\xb5\x4c\x29\xd6\x81\xf3\xbd\x06\xde\xd6\x2c\xb1\x62\xc5\xf4\xde\x07\xf9\x7c\xc6\x9d\x6e\xbd\x55\xde\x9a\x3b\x9e\xef\x37\x89\x7d\x22\xe1\xce\x67\x96\x71\x66\xb4\x1f\x73\x51\xcd\x0b\x95\x44\xfb\x41\x74\xad\x7b\xda\x5d\xc5\x22\xbd\xce\x87\xf0\x4d\x52\x01\x92\xf0\xa1\x19\x5d\xfc\x1b\x1b\x47\x45\xba\x0f\x6c\x0d\xee\xd0\x10\xf1\x1e\xe9\x04\x1c\xc5\x2a\x1e\x85\x59\x19\x33\xc6\x60\x31\xb0\x4e\xe9\x83\x15\xa1\x5a\xfd\x94\xb5\xd3\x4f\xd9\xc4\x81\x42\xbb\x3a\x44\xe8\x3d\xd9\x7a\xb1\xc5\xd8\x43\x4e\x0b\xc6\xab\x14\xe7\xce\x2f\xac\xf5\x08\xdb\x38\x7b\xf3\x39\x75\x48\x81\xc3\xd2\xed\x27\xfa\x99\x98\x53\x71\x43\x93\x3a\x2d\xc9\xd5\xf5\xc4\x60\xc6\xb9\x75\xf2\x9a\x8b\x1b\x2a\xaf\xae\x27\x73\xab\xe0\x95\x8b\x5b\x5a\x0c\xe4\xd5\x75\xbf\x9f\xcc\xa9\x2d\xd4\x95\x1f\x3d\x31\xe2\x0a\x0a\xca\xb3\x79\x51\x33\xa5\xb1\x8e\xd4\xfe\xfe\xde\xdc\x52\x37\x30\x87\x98\xab\x7e\x5f\xa4\x32\x2d\x6e\x99\x59\xab\xe3\xd1\xf6\x66\xf3\x06\x72\x50\xdc\x0c\x8f\x47\x4b\xd7\x25\x73\xeb\x5a\xce\x0c\xcc\x4e\x8f\xc0\x3c\x0a\x8a\x79\x62\xe5\xc3\xb2\xbd\x15\x58\x9f\xb3\x45\xd9\xe7\x3c\x28\x18\x51\xe6\x0f\xe5\x4d\xa5\x97\x49\xe3\x46\x39\xbf\x75\x9a\x7b\x03\x4c\xb4\x04\x8f\x47\xc1\x0c\xc2\xe8\x7d\x41\x18\xac\x98\x65\x3b\xdb\x6b\xb4\xc5\xb0\xb7\x28\x73\x74\x02\xde\x9e\x9c\x00\xbf\x78\xb9\x80\x78\xf1\x72\x09\x73\x51\x57\xad\xf0\x79\xe0\xfa\xab\x5d\xdb\xa5\x3e\x35\x73\x2a\x52\x09\x2b\x5a\xa4\xd2\xea\x8a\xb5\xe7\x5e\x32\xe3\x39\xf9\xd1\x0a\x4c\xbd\xf6\x78\x58\x7e\x36\xe1\x03\x1a\xf0\x4c\x9d\xd2\xef\x27\x3a\xed\xea\x9a\x00\x5a\xcb\xd7\xc1\xba\xab\x2b\x5b\xd4\x1d\xe8\xa7\xc2\x2e\xad\x88\x7a\xb0\xa4\x23\x9b\x54\x29\xe5\x79\x35\xa0\x11\x05\xc9\x26\x22\xe5\xb9\xb8\xba\x86\xaa\xc1\x00\xb5\x73\x72\x7a\x96\xcb\x89\x3f\x3f\xf5\x64\x91\xd2\x79\x1e\x46\xad\xb1\x9c\xc5\x80\xce\x49\x1e\x97\x19\xd0\x55\xb7\x4c\x4a\x57\xe8\x08\xe1\x3b\x95\x2c\x60\x08\x95\x39\x7f\x03\xe6\x75\x12\x74\xce\x16\x73\xec\xde\x7b\xe1\x5a\x1c\xa8\xed\xe4\xb4\xb5\x85\x92\x27\x63\x67\x13\x95\xed\x52\xe5\xbd\x04\xc6\xeb\x1d\xe5\x0c\x2a\xc3\x44\xc8\x75\x5a\x85\x5c\x8a\x28\xd2\x59\x84\x24\x69\xfc\x6b\x3a\x03\xc4\x9b\xe2\x38\x67\x9d\x67\x9c\xf5\xfb\x9e\x0d\x1c\xfd\x74\x68\xdf\x99\xa4\xcc\x47\x1c\xf7\x57\x62\xa2\x7c\xf8\xf2\x84\x6b\x9c\xca\xf0\xa1\x5e\x7c\x34\x1f\x4a\xe8\xd7\x43\xed\x5d\x48\xce\xbb\x62\xae\xf8\x3b\x16\x94\xff\x1d\x9f\xea\x2e\x62\x54\xdd\x21\xcb\xfc\xfb\x73\x8c\xa0\x3b\x19\x58\x3e\xae\x05\x8c\xbc\xff\xbc\xb2\xee\x83\x3a\x81\x6b\xec\xd4\x8c\xb2\xb3\xeb\xf5\x93\xe2\x7c\xe9\x4f\x34\x82\xc7\x76\x6d\x46\xd3\x13\x6c\x33\xbd\x76\xdf\x9f\xc6\xcf\xc1\xc7\xab\xcd\x2b\xf3\x2f\x56\x87\x85\xd6\x49\xf0\xaf\x58\x9b\xcd\x85\x2f\x4d\x2b\xc9\xdc\xfe\x56\xd2\xfe\x34\x69\xd7\x2e\xf0\xc7\xad\x0a\x10\x0c\xfd\x7a\x9a\xf4\x5b\x9b\xed\xa7\x11\x5a\xf3\xce\x9e\xa6\x07\xc6\xfc\x99\x4c\x8d\x1c\xb4\x2a\x36\xbc\xe2\x8a\x17\xa5\x75\xa3\xdf\x5e\xfc\x8f\xd9\xec\xce\xf6\x35\x77\x35\x93\xa2\x7c\xc7\x42\xf1\x73\xdc\x99\x93\x36\x51\x22\xe9\x78\x81\x6c\xdc\x45\x8b\x21\xf6\xde\x2d\x19\x06\xb7\x37\x1a\xb4\x0f\xe1\x83\x10\x0c\x60\x62\x3d\x38\x6a\xba\xd4\xd5\xf0\x47\x4f\xd3\x73\xe1\x1c\x82\x44\xde\xc6\x3b\x9e\xf8\x7e\x44\x30\xf5\xb4\x83\xd4\x8d\xa1\x19\xfa\xe9\x3a\xb4\x1d\x74\x4a\x74\xa2\x10\x8f\xa7\xad\xae\xe8\x05\x1e\x6e\xc9\xd0\xf1\xac\x5f\xbf\x84\x05\x22\x20\x6e\x44\x53\xe3\x38\xfd\xd6\xb5\x82\xb6\xb3\x5d\xfb\x35\xaf\x19\x7a\xee\x20\x70\xb0\x85\x73\x0e\x71\xb5\xbc\x02\x4d\xe3\xe5\x3d\x9b\xd8\x6b\x08\x31\xb2\x4a\x7c\x19\xf5\xe8\x8d\x9e\xc8\x29\x4b\xf7\xe0\x01\x15\x3e\xe0\xb8\xd4\xe6\x9a\x61\x0d\x4b\x73\x72\x98\xaa\x19\xd1\x0b\x6b\x6e\x65\x3b\xb9\xa0\x95\xb9\x72\xa7\x55\xac\xd7\x90\xe0\x2f\xa3\xa6\xf7\x32\xa9\x35\xc4\x15\x84\x40\xf8\x92\xad\xaf\x42\x7f\xe9\x61\x7f\xee\x6f\x7c\x8b\x4e\xfe\x5e\x26\x2c\x80\xd8\x18\x93\xb5\x34\xb2\x9e\x9a\xee\x1f\xfd\xde\x86\xea\x1f\x98\x7a\x18\xe6\x37\x89\x82\x96\x1f\x8f\x83\xe9\x23\x9f\xce\x50\x6c\x23\xf5\x0f\x9c\x73\x3e\x9d\x35\x20\xe9\x17\x32\xa9\x40\x91\xf1\xbd\x1e\x99\x43\x89\x65\xe2\xc6\x86\xc4\x2c\x8e\x38\xe1\xa0\x88\xc6\x87\x75\x41\x83\x2d\xdb\x5b\x1c\x65\x9b\x5c\x8b\x3e\xeb\x56\xf0\xe7\x69\x23\xc2\xb1\x01\x34\x86\x2d\xf4\x5c\x9f\x3b\xd0\xf7\xbe\xf5\x0a\x54\xd7\xb9\xe5\xfa\x0a\xe1\xe4\x1f\x3a\x2b\xa6\xca\xe9\x61\x59\x9e\x49\xf7\xa7\xe5\x4c\xa5\x7f\xeb\xb8\xdc\x99\x7b\x82\x37\xe2\xac\xb2\x85\x7d\x31\xd1\xc3\xd7\x5d\xb0\xf4\xc1\x8d\x77\xce\x97\xac\xdd\x2e\x3a\x3e\x74\x1e\x1b\x6a\x3a\x44\x13\x6a\x17\x59\xeb\xa6\x1c\xa7\x69\x4d\xac\xfe\xfc\x5e\xaf\xad\x85\x33\x7c\x5a\xcf\x48\xa4\x0d\xe3\x2d\x95\xe6\x74\xee\x2d\x95\x12\x7d\x29\x85\x26\xa6\x5d\x12\x26\x40\x65\x4d\x8e\xb8\x62\xeb\x9f\x8c\xb1\x92\xae\x66\x8d\x95\x8c\x3b\xdb\x90\x9b\x18\xa4\x57\x57\xf9\x26\x99\x43\xc2\xfd\x61\xad\xf4\x61\x54\x61\xbb\x35\x76\xed\x5c\xa2\x44\x8f\x8c\x39\x48\xa8\xef\xe1\xbc\xc7\x54\xdd\xb7\x26\x2e\x53\xb4\xca\xf8\x27\x27\x2a\xd2\xa0\x9d\x55\xfc\x8c\x09\xf7\x1d\x3f\x5f\xd2\x25\x46\xcf\x56\x01\x2c\x46\x03\xe6\x30\xff\x28\x29\x54\xfc\x68\xf0\x93\x47\x83\xbb\x1d\x77\xa6\xd8\x7a\x43\xd1\xc1\x95\xe5\x4e\x78\x48\xbe\x93\xd3\xca\x0b\x39\x66\xee\x8a\x09\xe0\x1d\x04\x8a\x8c\x35\x79\xd6\x3a\x68\x95\x26\x5c\x0d\xaa\x82\x23\x30\x80\x16\x6d\xac\x79\x8c\xb0\x60\x66\x04\xce\x5c\x89\x90\x17\xa5\x06\x04\x06\xb3\xc2\xa5\xb6\xf9\x16\x95\xc1\x4c\x7b\x5d\x75\x8e\x37\xbd\xe0\x0e\xbb\x93\x68\xe4\x06\x35\x6d\x3f\x2c\x87\x06\x9d\x82\x43\x49\x5f\xcb\x84\xfb\xd7\x18\x6a\x02\x73\xfa\xd6\xb8\xd9\x28\xc1\x65\x90\x31\x77\x98\x52\x69\x7f\x00\x77\x88\x52\x69\x7f\x80\xa4\x07\x8b\xa1\xe6\x23\x88\x9d\xcc\x19\x2a\xc9\x92\x06\x8e\xa4\x71\xe4\x80\x21\xd1\x7e\xd5\x98\xba\xf9\xf9\x5b\xae\xb2\x7d\x63\xf4\x70\x86\x68\x06\x6d\x5b\xed\xf7\x93\xa8\x8b\x61\xa3\x47\xd5\xc6\x49\x0b\xe0\x27\x78\xa7\xd4\x08\xc3\x39\xec\xc5\x9a\x6f\x27\x28\xf8\x52\x1a\x83\xd0\x68\x78\x5d\x15\x65\xfc\xdb\x1d\x05\xcb\x75\xf4\x4b\x15\xde\x61\xa3\xb2\x82\x1e\xb0\x17\x75\xf1\xf8\x42\xcf\xe1\xbc\x61\x13\x9e\x4f\x24\x48\x7d\x7c\x74\x2c\x34\x66\x91\xb3\x9a\x11\x88\x6c\x3f\xc2\x7b\xe4\xd3\xae\x75\xda\x75\x3b\xed\x53\x9d\xf6\xa9\x71\xeb\xde\x69\x33\x76\xf9\x68\x09\x66\x47\xdd\x5a\x97\xee\x70\x68\x51\xc2\x12\x02\xcd\x5c\x20\xd7\x64\xa7\x09\x62\x4d\x0b\x2b\xc7\x41\x99\xbb\x8d\x5b\x69\x32\x3f\x04\x26\xc6\x78\xbb\xa7\x84\x9a\x98\x24\x1b\x5a\xa6\xab\xab\x6b\xf0\x94\x64\x35\x49\x8c\xd1\xd5\x62\x50\xc0\x03\xdd\xa4\x05\xac\xe9\x66\x50\x60\x78\x9f\x3a\x9d\xeb\x9c\x14\x73\x06\x98\x93\x16\xe8\xcd\x84\xe4\xc9\x96\x46\x8d\xd4\xa9\x4c\x8b\x88\xf2\xd3\x29\xf3\x81\x1c\x14\x79\x84\x6b\x83\xa3\x93\xc5\x24\x79\xa0\x25\x6c\xe8\xc3\xa0\x80\x05\xdd\x0e\x0a\x58\xd2\x6d\xaa\x3b\x7d\xd0\x03\xd4\x39\x29\xe6\xa4\x98\x33\x28\x08\xac\xe9\x83\x26\x6e\x47\xf9\x02\x76\xd7\xf9\x16\x76\x9f\xe6\x4b\xd8\x8f\xf2\x07\xd8\x5f\xe7\x1b\xd8\x7f\x9a\xaf\x9b\x48\xf9\xf6\xa9\x90\x7b\x4e\xeb\x56\xc4\x8e\xb1\x8d\x3b\x08\xbe\x4c\xa4\xab\x31\xa7\xbb\x2a\xe1\xa8\x5e\x5b\x65\x3b\x47\x4a\x1b\x83\x1f\x95\xed\xe8\x4f\xfa\x3a\x5a\x10\x63\xef\x1e\x81\xd8\x76\x60\x1e\x29\x90\xc6\xe5\x5c\xa9\x33\x86\x22\x46\x34\x1a\x71\x90\x35\x2c\x89\x99\xab\xc0\x5a\x5a\xa5\x98\xe5\x02\x88\x23\x0f\xaf\x70\x3c\x3c\xe3\x12\x52\xa2\x4b\x48\x53\x09\x59\x95\x62\x5a\xce\x60\x9e\xed\xf4\x14\xf4\xa3\xb6\x4f\x8b\x96\x00\xd6\xa4\xd1\x38\x31\xad\xa1\x4c\x47\xde\x3f\xd4\x3e\x75\x1d\xc7\x1c\xde\x41\xed\xac\x7c\x70\x38\x56\x7e\xd8\xf5\x66\x8d\x7b\x50\xd0\x16\x4d\x35\xe5\x33\x74\xb0\xd1\x7d\x8f\x74\x7a\xe4\x1a\xa0\x0c\x0a\x55\xf3\x86\x0a\xc3\x5b\x17\x11\xfb\x7d\xa1\x77\x44\xba\x40\x4f\x02\x83\x2d\x67\xbb\x04\x23\x65\x97\x37\x31\xf7\x77\x92\xc4\x5f\x83\x92\x5c\x5d\xe7\x43\x78\xa0\x2c\xdb\xa7\x4b\xf3\x10\x9d\x55\xe9\x67\x5e\xa5\x3f\x32\x8b\xd5\xb5\x63\xc5\x9f\xfa\xac\xd6\x4f\x7d\x5e\xa7\x7f\xd4\x00\xa7\x55\xac\x91\xbf\x85\x39\x49\xe7\x57\xd7\x20\xe9\x43\x5a\x5e\x5d\x8f\xdb\x61\xcc\x44\xb6\xde\x96\x8a\x7f\xcb\xf6\x9f\x7b\xf5\xa9\x96\xcb\xa3\xb3\x05\xbe\x75\x90\x4f\x76\xc3\xd0\x17\x67\x22\x6b\xf8\x9c\x73\xc1\xcf\x4c\x2b\xc6\xd4\x20\x8e\xa2\x56\xb4\xe3\xb6\x8d\x3e\xd0\x4f\x6c\x52\x11\x2b\x67\xa1\xb7\x96\xd3\x08\xfe\xa7\xfa\x5b\xc7\xe3\xd0\xbf\xaa\x27\x0b\xd8\x5d\xd4\xca\x5a\x4d\x6c\x61\x44\x60\x3e\xc0\xf0\x4f\x2f\x83\xe6\x9a\xb3\x79\x68\x5b\x39\xc8\x33\x56\x0e\x27\xee\xd1\x3e\xb0\xf0\x5c\x43\x21\xeb\x6f\xf7\x01\x1e\x35\xb4\xce\xcb\xe0\xe8\x97\xc4\x51\x48\x9c\xf9\xc3\x07\x76\xa1\x3d\x02\xd7\x01\xd7\x1d\xa4\x23\xdd\xc5\xe0\x5a\x77\x32\xb8\x3e\xd7\x0d\xba\x0c\xf8\xc0\x98\x4d\x81\x1f\x31\xa0\x0f\x3c\x80\x3e\xe1\x7e\x74\xdd\xd4\xf7\x0f\xd4\xb7\xc3\x41\x8f\x4d\x8f\xac\x1c\x5c\x13\xd2\xc4\x15\x4f\x58\x25\x53\x3e\x43\x20\xee\x88\xa5\x13\x18\x6e\xe4\x75\xa2\xa1\x95\xf9\x69\x41\x63\x2e\x41\x7f\x99\x07\xb5\x80\x96\x7c\x24\xaf\xe1\x29\x48\xc2\x0d\x24\xe1\x01\x92\x58\xd6\x72\x0c\x23\x60\xeb\x85\x42\xcb\xf3\xcf\x02\x3c\x04\x66\x31\x27\x87\x08\xe2\x72\x58\x1a\x70\x9b\x6e\x0d\x70\x5d\x78\x28\xbb\x48\x65\x03\x1b\xba\x8c\x1e\x8a\xc2\x74\xbf\x86\x1d\xdc\xc3\x1d\xec\xe1\x1d\x3c\x1a\x4d\x81\xe8\x65\x29\x9e\x7c\x41\x58\x47\x92\xe3\x1f\xaa\x8d\x79\x9d\x5a\xc1\x0d\xc5\xc2\x2c\x0f\x7c\x93\x54\x11\x4a\x0c\x0f\x1a\x76\xd6\xfd\xbe\x7d\xcb\x2f\x28\xdd\x4c\x22\x1c\xa2\x98\xcc\xaf\xae\xd3\x51\x3e\x47\x99\xd3\x1d\x1d\xc2\xbb\xf0\x96\xde\xdd\xbc\x1b\xa7\xe9\x1d\x39\xe8\x31\xaf\xa9\x98\xde\xcd\x50\x5e\xd9\xdd\xe4\xbb\x59\x6b\x34\x3b\xf8\x26\x59\x3b\xfa\xfc\x81\xc0\x3d\x5d\x5b\x22\xbc\xee\xf7\xef\x83\xff\xad\x2a\x6b\xbf\x31\x0c\x14\xdc\xc1\x52\x4f\x6e\x11\xe4\x73\xad\xad\x2b\x09\x81\x3d\x1d\xc2\x23\x75\xed\x8c\xf7\x37\x8f\xe3\x34\xdd\x93\x87\xe4\x7e\xba\x9f\xe9\xaa\x71\x8d\xb1\x1e\x8a\xa1\xf1\x1f\x48\xb3\xa5\xc3\x4e\x3e\x2e\x97\xa7\x04\xf4\x68\x55\xb6\x1f\x50\x89\xa7\x36\x10\xe9\x67\x71\x0f\x2b\x55\x3b\x45\x3e\x5a\xa8\x47\xf9\x71\xa8\x87\x69\xcc\xe3\x1e\xf6\x69\xee\x48\x3e\xe1\x09\x73\xc6\xa4\x55\xff\x83\x38\x49\x2c\xc3\x6e\x1f\x23\x93\x73\x1e\x09\xa9\xe9\x70\x5c\x23\x12\x52\xb7\x91\x90\x7a\x06\xe5\x1f\x43\x42\x78\x5b\x56\x6b\x10\xbd\x00\xb6\x4e\xa4\x77\x4e\x27\xda\x02\x04\xe9\x30\xec\x5d\x5e\xc0\x3e\xaf\x23\x14\xba\x74\x28\xb4\x85\x06\x55\x16\x63\xe1\xe3\x78\xb6\xd5\x09\x94\x63\xad\x67\xae\x6a\x3d\x73\x2c\x36\x34\x6c\x45\x41\x64\x1d\xd7\xa6\x6b\xf1\x4e\xd3\x0f\x45\xba\xd2\xa4\x9e\xc3\x91\x65\xbf\x6f\xf8\xf0\x27\xf4\x4b\x20\x39\x8a\xb4\x1c\x60\x25\x96\xfd\x6b\x5b\x2c\xea\x42\xf1\xf9\x8b\x6d\x6d\x9b\x2b\xa1\x06\xfc\x9b\xae\x08\x44\x57\x58\xfa\xcb\x4d\xd1\xad\xdc\xc7\x74\x03\x1a\x9d\x5f\x3d\xdd\x51\x3a\x07\x3b\x98\x74\x4e\x20\x92\x7e\x7d\xdc\x34\x6c\xbd\x73\xad\x9b\xb6\x5d\xff\x9d\x69\x38\x02\xe4\xa3\x66\x61\x16\xe2\x7c\x1f\x60\x57\x9f\xb5\x5c\x32\x32\xf7\x40\xb7\x36\xf0\x76\xd8\xef\xb3\x60\xb0\x78\x67\x68\x56\x4f\xc6\xbe\x41\x97\x77\xe7\x79\x5d\x8e\xc1\xce\x62\x11\x8d\x86\x0d\x9a\xbc\xdd\x81\x34\x3f\xf6\x88\x86\x1e\x8f\x32\xc0\x90\x9d\x9c\xaa\x2e\x2f\x84\x41\xe0\x9e\xb1\x13\x9e\x48\xec\x4d\x7a\x1c\xd9\xfd\x38\x16\x04\x9a\xea\x9f\x61\x41\x54\x60\x0b\x39\x46\x04\x28\xcf\x81\x50\x86\x03\x41\xc6\x42\x13\xf9\x94\xd2\x79\xb6\xeb\xf7\xa5\xff\xd8\xa3\x01\x75\x97\x2b\xc1\x4e\xb8\x12\x96\xed\x40\x0b\xcb\x7e\x70\x7c\x07\x5a\x38\x06\x04\x73\xe2\x99\x0a\xc3\x0a\x5a\xc1\x4c\x85\xf1\x05\xdf\xc7\x38\x60\x30\x27\xa4\xf9\x60\xd4\xe0\x98\x45\xc5\xda\x2c\x2a\x1b\x18\x83\x39\x0e\x47\x7b\x21\x59\xf6\xc4\x76\xf3\xe0\xc5\xf2\xf0\x5e\xde\x4a\x03\x92\x7a\xc7\xd2\x2c\xdb\x37\x63\xeb\xba\xac\xb8\x97\x49\x45\x6e\xb2\xe1\x70\x34\x19\xe6\x61\xcf\x5a\xd2\x57\xa8\x9d\xe5\xa8\x7d\x42\x8e\x47\x76\xaa\xc3\x83\x89\xed\xcf\xae\x4e\x8f\x4e\xb3\x8c\x60\xa7\xa1\x17\xa4\x39\x75\x1c\xd1\x5d\x65\x0f\xa5\xb8\x2f\xca\xe7\xe5\x66\x55\x50\xbd\x79\x1d\xe0\x2b\x01\x23\xbe\x13\x34\xfc\xb7\x6a\xb7\xc1\x20\x16\xa4\x81\xe6\x0a\x5f\xa3\x40\xa0\xeb\x5a\x88\x95\x78\x74\xaf\x95\x62\x9f\x52\x9b\x76\x77\xb6\xe5\xc8\xe7\x24\xf2\x5c\x9e\xe3\x5d\x70\x41\xc7\xba\xe1\x9a\xcc\x4d\xd1\x34\x46\x23\x4f\xca\x9e\x67\x68\xba\xdb\x25\xd0\x71\xd2\x26\x49\x92\x43\xdb\x1c\xc3\xaa\xd4\xb1\x86\x44\x8c\x5e\x1e\x89\x96\x62\x05\x3b\xe5\x2e\x65\x37\x50\x4c\xef\x45\x51\x55\x42\x3d\x5b\xf2\x6a\xf1\xac\x78\x66\xbb\x78\x56\xa8\x67\xd8\xfc\xb3\x5e\x1a\xc2\xf8\x75\xfa\x77\xfa\x6e\x95\x51\xa2\x63\x33\x3f\x22\xf4\x33\x4e\x2f\x94\x32\x91\x98\x91\x45\xea\x00\xc8\x8b\x55\x51\x3d\xb0\x45\x22\x80\x91\x71\x22\x8f\x47\xf4\x35\xe4\xe7\x4b\x4f\x79\xac\x94\x01\x77\x77\xec\x62\x48\x48\xdb\x86\xf2\x7d\xdc\xe0\x98\xe5\x8b\xae\xc2\x90\xed\x4b\x2f\x46\x86\xf3\x6b\xec\x14\xc5\x16\x31\x4d\xe7\xf6\x3f\x29\x5a\x8b\xe8\x76\xe9\xb9\xc2\xfe\xbe\x12\xf5\x6b\xb1\x40\x95\xe2\x6c\x2d\x16\xcc\xa8\xbc\x57\xc1\x1b\x58\x11\xbc\x81\x11\x6f\x2e\x7d\x66\xfa\x45\x08\x8f\xf8\x4c\x52\x76\x3c\xea\xd5\x2a\x40\x90\xe3\xb1\x06\xd9\x5a\x91\x02\x12\x2f\xed\x3c\x1e\x03\x2b\xd2\xae\x5b\x7b\xad\xd0\x75\xc6\x0e\xbd\x6a\xec\x9b\x78\xdd\x80\x11\x14\x5c\x9e\x8c\x24\x52\xde\xb1\xac\x57\xee\x18\xaf\x95\xd7\x00\x77\x7c\x42\xa9\x5f\x03\xd1\x7d\x0d\x6c\x00\x4a\xef\x9e\x17\x5d\x3d\xe2\x24\xf4\xff\x6c\x77\x3c\x56\xf8\x63\x4f\x9a\xe6\x45\x30\x7e\x60\xb5\x6e\x0e\xc5\x92\x7f\x73\xaa\xeb\x56\x5e\x19\x94\xd7\x5f\x48\x88\xca\xe7\x3b\x69\xa4\x6c\x2f\x2b\xee\xf5\xd9\x39\x82\x0c\x5b\x15\x45\xbd\x2f\x64\x72\xb8\x73\x7a\xa1\xde\x92\xb2\x09\x8e\x44\xdb\x2a\xe4\x91\xe2\x46\x50\xd8\x88\x24\xe6\x9c\x34\x50\x33\xc9\xd4\x1f\xa9\x60\x5c\xc6\x76\x1f\x03\x57\x1a\x38\xf5\xb2\x5b\xd6\x18\xdf\xf7\x2a\xab\x84\xe2\xcb\xfd\xf7\xe5\xf6\x81\x57\xd2\xf9\x01\x7d\x63\x8a\xa1\x27\x4b\xa3\xab\x65\xd4\x4f\xb0\xe9\x6c\xae\x10\x93\xed\xd4\x34\xd2\xd7\x76\xc5\x33\x06\x96\xe8\x5a\xc7\x0e\x23\x0e\xdc\x67\x78\xd8\xe3\x30\xb7\x33\x66\x97\x76\x28\xd9\xdc\x9c\x23\x7a\x31\x24\x4d\xac\x57\xef\x43\x32\x0e\xc1\x9d\x58\x63\xc6\x18\x54\xe5\xad\xf6\x7a\x0f\x4e\xc2\x68\xd6\x0f\xf7\x45\x32\x44\x03\x8a\x61\xf6\x17\xd2\x83\xc0\x70\xcc\x7b\xff\x6b\xb9\x5c\xda\x94\xaf\xce\xa9\xe8\xc7\x7c\xcb\xfc\x1a\x4e\x58\x86\xf9\x9f\x21\x30\x45\xad\x62\x13\x78\xa2\xd4\xb5\x1f\x53\xf8\xd7\xe0\x88\xf4\xfc\xd0\x44\xd4\xbe\xad\x1b\x51\x22\xae\x76\x8b\x66\xc8\xaf\xa1\x43\x1c\xe5\x7f\x86\x40\xd8\x9c\xda\x18\x04\xfa\xc8\x75\xe1\x4c\x0d\xfe\xdc\x56\x61\xbb\x8e\x38\xf5\x7f\x6a\xab\xb3\xfd\x39\xe2\x3c\x58\x65\xdd\xa0\x34\x6c\x3c\x0e\x79\x76\xc4\x13\xf9\xa7\x4c\x1a\x37\xbd\x36\x93\xe3\x62\xd8\x0e\x73\x1a\xef\x1e\xe9\x06\x5f\xf5\xc8\x67\x7e\x58\x6c\x6b\xf3\xeb\xb3\xe1\x10\x58\x21\xf5\x8c\x7a\xac\x90\xec\x6f\x5b\xf5\xc3\xb6\xa8\x55\xaf\x09\xc5\x65\x7e\xa8\x50\xe9\x5f\xe6\x07\xa3\xdc\x60\x3e\x7b\xce\x19\x34\x67\x32\x0f\x11\x69\x11\x01\xea\x41\xcf\x60\x3e\x3d\xe8\x19\xe0\xe6\x7e\xfc\xd6\x9b\x35\xe0\x64\x47\x07\xd7\xb7\x8d\x92\x09\x7e\x60\xd7\xc3\x61\xd3\x40\x10\x73\x1f\x22\x55\x88\xfc\x3b\x73\x8c\x7c\x64\x55\x83\xcc\xdc\x0e\xa3\xeb\x3e\x1d\xce\x10\xf7\x0b\xc2\x65\xe7\xb4\xb1\xa2\x7c\xe2\x24\xc8\xf9\xd0\x79\xbd\xb0\xb4\x84\xf7\xef\xdc\xb3\x6f\xee\x89\xc7\x2c\xfd\xf8\x78\x3d\x1a\xaf\x6c\x86\x6d\x1f\x8f\xbd\x9e\xb1\xfc\xc7\xcf\x50\x0a\x3f\xd1\xde\xc1\x90\x11\x5e\x97\xfd\xa6\xf2\xbe\x0b\xa6\x51\xf2\xcc\x1a\x2a\xf4\x7a\x16\x72\xb8\x69\x07\xa4\xcf\x7f\xa0\x2a\x42\xfe\x9d\x51\xc2\x77\x2b\xf2\x5f\x9d\x90\x9d\x48\xda\xcb\x35\xfe\x91\xb5\x75\xf3\x8f\xc7\x6e\x8a\x31\x72\xb1\x66\xcc\xed\x65\xd0\x0f\x3a\x4b\xa9\x6e\x88\x44\xda\x46\x9d\xfa\xb6\xdb\x4f\x12\x4e\x34\x15\x91\x52\x8d\x0a\x36\x10\x64\x05\x6d\x10\x7e\x1e\xc3\x6a\x99\x85\x93\xb3\x26\xcc\x2a\xac\xad\x47\xaa\xe2\x8b\xd3\x0e\x37\xdd\x05\x8a\xa7\xa1\xa4\xe3\x8b\xc5\x5a\x74\x7e\xe0\x5a\xfb\x0c\x34\x4f\xee\x72\xb3\x5b\xb9\xd6\x40\xb9\x6d\x04\xdc\xd8\x75\xf0\x2c\xb4\x0e\x6e\xeb\xf6\xcf\xc3\x4f\x5b\x3e\x48\x31\xfe\x07\x17\x2f\x12\x7f\xb0\xb3\xe2\x0f\xe6\xc5\x1f\x8d\x3d\xc3\xee\xa0\x7a\xa2\xc4\x1f\x61\x83\xf6\xe7\xdf\x39\x7b\x0c\x5b\xc6\x25\x37\x27\x16\x5c\xfe\x4d\xe8\x2d\x45\xe5\x9f\x81\x38\x25\xbc\x51\x26\xe1\xfd\x56\xce\xce\x4e\xf9\x02\x95\xb5\x7b\x4e\xb1\xc3\x7d\xbb\x57\x14\xbf\xdb\x36\x61\x31\x84\x6a\xd9\x8e\x8d\x3a\xb6\x63\x31\xf4\xbd\x5b\xda\x4a\xed\x0c\x19\xe7\xf4\x7c\x72\x4f\x2f\xe0\x62\x81\x2f\x77\x51\xfe\x0d\x77\xfd\xa7\xb9\xd8\x20\xd0\xc5\x88\x2b\x05\x92\x46\x1a\xae\x3e\xef\xea\xcc\x75\x83\x5a\x7f\xe1\x23\x52\xe6\xff\x12\xf0\x15\xfa\x08\xcf\x17\x12\x8c\x4b\x91\xfc\x41\x82\x01\x35\x6b\x09\x16\x89\xc9\xff\x26\xe3\x78\xd6\x6f\xce\x06\xb5\x32\x36\x4b\x0c\x69\x1d\x8c\x22\xe4\xe0\x5a\xe2\xc3\x3f\x9f\x18\x41\xb1\x89\x37\x9d\x1a\x8c\x72\xe3\x5f\x8c\x11\x13\xc3\x8d\x13\x5b\xcf\xbb\x70\x41\x2c\xad\x2c\xa4\x39\xa8\xd8\xd9\x84\xe7\x2e\x4c\xe3\x8f\x41\x75\xf7\xd7\x27\x54\x77\x95\xf3\xdf\x8d\x16\x99\x08\x7e\xda\x4a\xb5\x28\x04\xc2\x80\xe8\x74\xd8\xa0\x29\x93\x47\xd5\x3e\x49\x54\x08\x80\xb4\xf5\x71\x95\xb8\x57\x26\x70\xce\x35\xc6\xd1\xac\x09\xbd\xd5\x65\x31\xa0\x3a\x4e\xea\x3b\x65\xe2\xe2\x5a\xee\x25\x01\x24\x0d\x12\x46\xb9\xfc\x4a\xa3\xb0\x2c\x61\xa4\xdf\xe7\x53\x36\xc3\x3a\x2c\x7f\x63\x18\x31\xdf\x22\xdb\x26\x04\x8e\x1a\x8c\x48\xb3\x60\x8a\xd5\x6b\x14\x99\xa9\xe2\x15\x5f\x73\x75\xa2\x06\x7a\x88\x82\x3a\xb3\x38\xa8\x33\x6f\x8c\x1d\x58\x2b\xa8\x73\xc9\x14\x46\x84\xae\x30\x22\xb4\xb0\x45\x5e\xf3\xea\x75\xb1\xd3\xc4\xdf\xb8\xa7\xf8\xfc\xad\x34\x7e\x65\x02\xe8\xd1\xb5\x35\xa4\x3f\x1e\x93\x8a\x0e\x09\x70\x0c\xc5\xa9\xce\x84\x6a\xc4\x80\xd0\x2a\x5b\xf3\x8a\x56\x80\x0e\x82\xa9\x30\xde\xa9\xdf\xe8\x86\xcf\x29\xb1\xae\x79\x85\xa6\x92\xeb\x62\xd7\xd2\x4f\x15\x06\x5c\x86\xd0\x0e\xed\x0e\xc7\x92\x0e\x8d\x96\x3f\x47\xe7\x34\xae\xff\x89\xcc\xa5\x8f\x9f\xcc\xd3\x11\x3a\xad\x8c\x76\xdd\x0b\x13\x7c\x95\xa4\x42\xb7\xbb\x60\x8a\x46\x07\x07\xc7\xa6\xb3\xb3\x3f\xe5\xc3\x38\x90\x1e\x1b\xab\x1b\xca\x31\xf8\x9a\x55\xf4\xb2\x71\xd9\x55\x13\x14\x5f\x1b\x37\x58\x1f\x0f\xb1\xc3\xb5\x3a\x73\xa4\x9e\x29\x8c\x4b\xaa\x6e\x1c\x0f\x68\xc2\xa6\x6a\x96\xab\x26\x58\xdb\x76\xd4\x61\xf1\xd8\x47\xc6\xb8\xe4\xc4\x89\x34\xea\xc7\xde\x59\xb2\x19\xa3\x2d\x4a\x7a\xd1\x4d\x41\x26\x4b\x3b\x7a\x63\x67\xb4\x4e\xe7\xc4\x62\x85\x17\xde\xca\x51\x53\x87\x94\x65\xf6\x2e\x11\x02\xfe\x3e\x7c\x57\x7c\x97\xb7\xc2\x42\x1a\xb8\x54\x26\x89\x1a\xb0\x78\xa5\xc9\x15\x8b\xf7\xa8\x35\x98\x37\xe8\x23\xa6\xb3\x72\x78\x4a\xfd\x9a\xdd\x0c\x8f\x47\x75\xcb\xc2\x11\xc0\x8b\xe8\x96\xb8\x3d\x2b\xbd\x9e\x36\x2c\xa5\xee\x05\x13\xbf\x12\xb5\x89\x42\x79\x7e\xca\xcf\xa2\xfb\xdc\x1a\x76\x6a\xe2\x78\x9a\x49\x45\x8d\x5c\x9e\xce\x26\x8a\x74\xd9\x7a\xde\x6d\xa0\xc6\xe6\x47\x99\xf1\x05\xed\xcd\x0b\xc5\x1e\x44\xbd\xef\xc1\x8f\x32\x73\xb4\x1e\x3d\xe0\x74\x73\xaf\x0e\x9a\xff\x28\x23\x53\xd5\xee\x31\xf3\x1e\x37\x5e\x7d\x3c\xb8\xc4\x39\xb5\x00\x25\xab\x16\x1d\xeb\x85\x27\x00\x2a\xb3\x16\xa3\x1f\x07\x66\x3d\x2a\xa8\xf4\xb9\x74\x87\xe9\x49\x93\x59\x63\x86\x4c\xfa\xfd\x0b\x0f\x3d\x53\x65\x5f\x8f\x54\x59\x4e\x95\x3e\x21\xd8\x95\x79\x35\x4f\x41\x24\xca\x64\x9e\xab\x7f\xb0\x5a\x98\x18\x58\xf3\xb7\x0e\x40\x3a\x4e\x56\x0c\x46\xab\x18\x8c\x8a\xf7\x81\x51\x74\x9a\x8d\x86\x4d\x9e\x17\xa5\xe8\xad\xa4\xd5\x44\xe6\x0a\x4a\xfd\x51\x50\x31\x29\x72\x34\x83\x66\xc7\x23\x0f\x43\xfb\x42\x25\x92\x00\xd3\xff\x0b\x32\x56\x37\x9a\x64\xb8\x19\x4e\xca\x64\x48\x72\x85\x04\x84\xfe\x53\x27\x43\xd2\x48\x6a\xbc\x0e\x97\x49\xa1\xe1\x19\x3b\x1e\xeb\x44\x46\x90\x56\x5a\x48\x5b\x18\xc5\xf3\xf9\x5b\x7c\x2a\xde\x17\x08\xc0\xdc\x1f\x63\xfc\x7d\x58\x17\x3b\x04\xce\x58\x0b\xe3\x99\xb1\x8d\xb1\xe7\x8a\x2c\xcc\xc4\xc4\x86\xe5\x98\x33\x5e\x26\xd8\xdf\x95\x20\x83\x28\x78\x33\x8e\xe5\x4a\x90\x74\x94\x27\xc6\x07\xa0\xf5\x77\xe7\xc7\x03\x15\xad\x8e\xc7\xd1\x08\x63\xb6\xc4\x61\x3e\x2a\x54\x78\xe5\xcd\x69\x15\x77\x60\x9e\xb2\x47\xff\xc0\xdb\xd2\x76\xca\xe8\xe6\x6c\x23\xba\x44\xdd\x8c\xa3\x98\xe4\xd7\x41\xb1\x53\x3c\x1d\x03\xf6\xa0\x57\x49\x1f\x15\x5e\xe5\x02\x8f\x81\x84\x4d\xcd\xe6\x1c\x43\x3a\x16\x30\x17\xdb\x4a\x19\xaf\x16\x38\xba\xbc\xc4\x53\xc5\x1f\xb8\x92\xf9\x1c\x56\x1e\x40\xe7\xab\x86\x2a\x58\xe0\xca\xc0\x96\x96\x83\x11\x1e\xc6\x7c\x89\x8d\x3e\x34\x18\xb1\xfc\xe2\x93\x44\x10\x58\xeb\xff\x92\xc0\x4e\xff\xaf\x09\xdc\xd3\xe4\x61\xb0\x24\x57\x73\x9c\x95\x55\x2a\x80\xd7\xf4\x85\x4a\x4c\xc6\xf6\x6a\x41\x2e\x17\xfa\xec\xbd\xbe\x19\xb1\xc1\xe8\xb3\x7e\xff\x62\xd3\xef\x5f\xac\x2d\x9a\x33\xb5\xcf\xd6\xb2\x01\xfb\xeb\xa1\x99\x8d\x1f\xa3\x8d\x7e\xb8\x7a\xdd\xda\xe4\xe5\xd5\x6b\x02\x8f\x18\x1b\x1f\xfb\x79\xbc\x7c\x6d\x7b\x21\xf0\x49\x52\xe8\x4b\x6d\x43\xf5\x6f\xc4\x63\x32\xc2\x40\xc8\xaf\xa3\xf6\x5e\x5f\xde\x91\xab\x3b\x02\x7b\xda\x69\xf4\xf2\x35\xbc\xeb\xf4\x7b\xf9\x1a\x36\xfd\xfe\xba\xdf\xaf\xfa\xfd\x1f\x55\x92\xc8\x81\x20\x57\x15\xbc\xbe\x1a\xb1\x4f\xc9\x24\x79\x0c\xe7\xc7\x64\xbd\x86\x52\x77\x66\x3e\x1e\x61\x4f\x05\xbc\xa3\x92\xe4\xbb\x49\xb2\xa7\x9b\x89\xc8\xf7\xf0\x8e\xae\x27\x32\x7f\x07\x8f\xb4\x1e\x8c\x74\xd9\x77\x83\x3d\xb9\x7a\x24\x79\xf2\x68\x7f\xbf\x86\x47\xfa\x46\x25\x8f\x10\x01\xfd\x47\xe2\x3a\x6d\x25\xe6\x61\xb8\x8f\x84\x40\x7b\xde\x7a\x31\x26\xbf\xab\xe4\x35\xc9\x0b\x3f\x5d\x53\x73\x8f\x6b\xe0\xa6\x6b\xd2\xde\x61\x1a\xee\xe3\x5b\xeb\x42\x62\x83\xfc\xe7\x18\xbb\x10\x0d\x81\xfd\x0d\x15\xfd\xfe\xdb\x34\x85\x37\x2d\x44\x33\xd9\xa7\x6f\x2f\x5f\x13\xd3\xb4\x80\xfb\xcb\x64\x35\x49\x7a\xbd\x54\x10\xef\xaa\x87\x10\xac\x48\xc6\x6f\x51\x4d\xe2\x2d\x69\xb7\xfe\x44\x63\x01\xa3\x59\x4f\xde\xa8\x84\x4f\x03\x82\x6a\x1f\x52\x90\xa1\x3b\x19\x77\x37\x39\x53\x18\x5d\xf9\xc4\xdd\xca\x86\x74\x52\xde\x35\x68\xb0\xe9\xe1\x92\xbd\x65\x26\xda\xb7\x8d\xfb\x5d\xec\xa2\xdb\xc6\x33\xff\x1b\x81\x57\xce\x33\x07\xc3\xec\x3d\xe4\x19\xfe\x8f\xae\xa0\xca\xee\xfc\x47\x42\xe2\xfb\xd8\xc5\x9f\x1a\x8d\x15\xd6\xfa\x7d\x39\x1e\xbd\x50\x21\xe0\xc9\xcc\xe3\xc7\xaf\x54\x22\x40\x41\x0f\x67\xd1\x23\xc0\x7c\x58\xf2\x44\xb4\x82\x98\x98\xd7\xd6\x60\xbc\x18\x25\xd2\x60\x9a\xa8\xc4\xe5\xf3\x78\x15\xf2\x8a\x1d\x01\xf1\x24\x0e\x08\xc6\xd9\x8b\x87\xe8\xb6\x76\x65\x6a\xa2\x02\xca\x19\x24\xb1\x8d\x66\xf7\xfb\xec\x44\x49\x3f\xa9\x06\x9c\x5c\x85\x48\x4a\x7e\x2b\x61\x44\xae\xae\xc7\x7c\x40\x15\x54\x29\x55\x4d\x1b\x6b\xe6\x7a\xbd\x3c\x56\x50\x75\xd0\xef\x6a\xc0\xcf\x22\xc6\xf6\x8c\xfd\xce\x13\x15\x79\x01\x0b\x91\x6b\xc4\xbc\x28\x19\x69\x2c\x25\xf8\x65\x40\x6d\x5e\xc9\xc3\x47\x92\x49\x86\x3e\xf2\x84\x51\x44\xf5\x98\x67\xf4\x57\x4d\x6d\xb2\x7c\x68\x5f\xd3\x5f\x31\x2c\x7c\x3e\x02\x95\x3d\x85\x67\x9c\x7b\xb0\x4e\x7d\xeb\x77\x3c\xed\xc6\x48\xa5\x7d\x4c\x8d\x79\xed\x67\x43\x12\xc7\x72\xb0\xa2\x70\xdd\xf6\x57\xa2\x52\xae\xd3\x21\x19\x9f\x69\xc1\xb0\x61\xaf\x62\x2f\xb0\xe7\x51\xfa\x88\xbe\xf5\x38\x7a\x17\x53\x8e\xd0\xf4\x2e\xee\x47\xae\xba\xf8\xdd\x79\x34\xba\x25\x9e\x8d\x30\x66\xd7\xd5\x19\xa4\xb9\xdb\x70\x64\xb7\xfc\x32\x36\x21\x1e\xe9\x71\x5f\xc5\xb0\x36\x7a\x4a\xbe\xc7\x18\x83\xa4\xf9\xd2\xe0\xd3\x8e\xe1\xfc\xe5\xfb\xb0\xe9\x5f\xb8\x67\x58\xd6\x32\xab\xb6\x6b\x56\xf3\xb9\xc7\xa2\x7f\xff\xff\x05\x8b\x7e\x0a\x5f\x76\x18\xc7\xab\x18\xe3\xc7\xfc\xb6\x29\x19\xb0\x19\xb2\x65\xd0\x82\xc3\x1d\x31\x7d\x82\xfb\x7d\x7e\x3b\x9c\x70\xe4\x0b\x8d\x4d\x5f\xbf\xb3\x5a\xd0\x8b\xe1\xc7\x72\x17\x3e\xea\xda\x78\x28\x31\x04\x66\x02\x57\xc7\xb7\x28\xca\xe5\x3e\xd7\xb3\x17\x02\x76\x6e\x0c\x44\xed\xf8\xc8\xfb\x2e\xde\x47\x62\xfe\x7f\x94\x39\x82\xa8\xa1\x06\x9e\xc2\x02\x4f\xaf\xe0\x4e\x6f\x2b\xca\x26\x55\xae\xa0\xd0\x1f\x82\xf2\x89\xc8\x15\xd4\x34\x76\x6b\xfd\xd4\x79\x4c\x99\xc6\x30\x4d\xa0\xcf\xea\x86\x0e\x27\x89\x4c\x46\x04\x8a\x64\x34\x24\x24\x4f\x64\x52\x27\x15\x20\x42\x5f\x24\x75\x22\x60\x84\x66\x66\xba\x64\xbf\x2f\x31\x05\x33\x05\x26\x14\x58\xda\x60\xff\xb8\x56\xfd\x3e\x8e\x19\x79\x67\x77\x72\xfb\xf0\xc0\xa4\x62\x8b\xd7\xbc\xea\xf7\x75\xa7\x16\x33\x87\x21\x31\x8d\xd9\x9e\xfe\x18\x93\x26\x20\xd2\xe7\x31\xe2\xf6\x94\xf1\x81\x26\x3e\x72\x1f\xc2\x28\x4c\x6b\x5d\x5b\x8e\x46\x63\x9e\xbb\xf3\x2f\x3b\xce\xa7\x57\x12\x31\x00\x5c\x9a\xa2\xd3\xa1\x31\x4f\x8c\xd2\xe4\x55\x1b\x09\x25\x50\xd2\xe2\x66\x38\x39\x69\xbc\xb8\x47\x73\xc6\x7c\x34\x5e\x88\x43\x9b\x99\xa3\xa9\xbb\x7f\x8a\x3a\x7f\x29\x13\x49\x1a\x02\x69\x5a\xc3\x68\x68\x3d\x32\xd4\x74\x04\x69\x5a\xe8\x66\x6f\xe9\x70\x32\xca\x4b\x02\x32\xc6\xe8\xea\xcb\xf6\x08\x2e\x4b\x72\x55\x36\x8f\x2b\x5e\xb2\xa4\xb8\xe1\xc7\x63\x41\x31\xba\x7c\x7d\xe3\xc9\x8d\xb9\x59\x83\x62\x07\x32\xb2\x9f\x8e\x87\x34\xef\x0c\x49\x68\x34\x89\x57\x1a\x9b\xd9\x4a\x56\xbf\xb6\x08\x92\xfb\x2c\x76\x0d\x7c\x08\x65\xe1\x4f\xa0\x2c\xfc\xdf\x47\x59\xde\xfb\xd2\x1b\xf0\x87\x6f\x50\x6f\xd8\xcb\x3f\xf4\xf0\xbf\x17\xf9\x59\xf3\xea\x2c\x23\x2c\x06\xb7\xfa\xfc\x74\x79\x81\xfa\x76\xe2\x50\x07\x98\xfb\xb1\x3c\x30\x3b\x76\x23\x37\xc0\x7f\xc7\x23\xf2\xc0\xf4\x8a\x78\xf6\x97\x8b\xa6\xa1\xc8\xd3\x8c\x30\x85\xbb\xb1\xe6\xd5\x64\x98\x1b\x58\xf1\x61\xc6\xd8\x7b\x59\x56\x48\xe9\x9e\x7d\x5f\x5b\x58\x83\x3d\x95\x6d\x6e\x16\xef\xf2\xad\xc2\x03\xfc\x95\xec\xba\x16\xd4\xd8\x26\x0a\x41\xad\xa8\x5a\x03\xa1\x4e\xf0\x20\x65\x3c\x5e\xe9\x37\x76\x51\x8b\xcd\xf7\x1d\xdf\xf5\xdf\x26\x46\xab\x58\xa3\x9e\x4b\x2f\x13\xdf\xa9\xf0\x41\x52\x87\xd8\xb8\x78\xe3\x51\xb4\xfc\x5f\x64\x6c\x88\xe4\xf0\x0d\x4a\x35\x21\xad\xd0\x10\xed\x60\xe2\x8e\xb3\x01\xbf\xba\xc6\xd8\xe3\x2c\xe5\x57\xd7\x4d\xae\x6e\x74\x91\xdb\xb8\x80\xc9\x6e\x72\x97\xe2\x8a\x47\x4b\xf0\x79\x8c\x83\x0c\xcd\x06\x8f\xfe\x62\x0f\xb0\x55\x5d\xcd\xd5\xcd\xe8\x2f\xc3\x8e\xbb\xa2\xd0\xc4\xdf\xbd\x54\xe5\x3f\x6d\x03\xd7\xff\x61\x1a\xe0\xd9\x7e\x40\x59\xb6\xba\xba\xce\x13\x75\x7b\xfd\x1f\xc3\xe3\x51\xdd\xfc\xe7\xd0\xa8\x20\x99\xac\xc8\x5d\xca\x5f\x4f\x7d\xf0\x28\xc3\xcd\x47\x57\x82\x44\x64\x45\x3d\x4f\x54\xb6\x33\x5e\xf5\x40\x65\x7b\xfb\x8b\xc1\x10\xee\x94\x0d\xd7\xe0\x88\x05\x7d\x2e\x05\x0f\x4a\x4e\xf8\x86\x8f\x85\x53\x5e\xe6\xd9\x0e\x78\xb6\x0f\xfc\x6f\x49\x47\x63\x79\x53\x8d\x65\x9a\x92\xb3\xf5\x25\x30\x02\xc2\x29\xe7\xba\xfa\xd1\x5a\x7e\x17\xaf\xe5\x73\x7d\xec\x27\x2a\x1f\x36\xbf\x5b\xa4\x4d\x3c\x14\x35\x57\xab\x35\x9f\xf7\xe0\xf7\x8f\xc7\xdc\xa2\x7a\x16\x4c\x46\x4a\x32\xc1\x11\xf1\x3f\x5b\xb4\xc3\x7b\x11\x3a\xbb\x80\x6d\x77\x24\x67\xd2\x16\x75\xf1\xc8\xab\x87\xe7\x35\x2b\xda\x68\x1d\xca\x4c\x0d\x8f\x3f\xf8\x8d\x09\x89\xce\xb5\xcb\x87\x82\x89\x9e\x09\x1d\x7a\x36\x3e\xa8\xd5\x62\x79\x23\x36\x54\xdf\x58\x07\x44\xc9\xd5\x35\xf8\xd3\x40\x5b\x2c\x3b\xeb\xd8\x87\x84\x33\x12\xe7\x7b\xc2\x62\x10\xb7\x4d\x4c\xf9\x78\xd2\x9e\x13\x73\xb6\x82\x8f\x5f\x72\x75\xfd\x6f\x22\x9d\xa3\x18\xe9\x44\xae\xb0\x95\x27\xb6\xc9\x36\x9f\x83\x14\xdc\xf0\x0f\x52\x70\xa7\xe4\x55\x67\x8f\xaf\xf4\xe2\x46\xc2\x79\x54\x51\x35\x3e\xb1\xb1\x9d\x53\x0f\xf0\x7a\x1b\x5f\xb5\x99\xf6\xdd\xf2\x4e\xf1\x1b\xed\x30\x5a\x07\x87\xb5\xe4\x6c\x46\x59\x55\xa1\xb4\xd5\x4b\x67\x7f\x48\x58\xe4\xfb\xd8\x57\xf5\x3e\x09\x34\x85\xc0\x67\x41\x83\xf0\x59\x75\x3c\x0e\xd1\x96\xb7\xca\x7b\xbd\x86\x90\x73\xa1\x54\x23\xbc\x6f\x1c\xc1\x79\xd6\xea\xc1\xc5\x1f\x89\x3d\xea\x79\xab\xca\x32\x1f\x42\x9d\xdb\xdd\x07\x95\x0f\xe1\x3e\x3f\x7b\x42\x1a\xe0\xd4\x06\xa5\x35\x91\x48\x9c\x86\xf4\x74\x06\xb5\xfe\x53\x9e\x95\x36\x22\x48\x32\xd1\x46\xca\x71\x95\xa6\xc1\xce\x46\x9d\x5d\x8e\xa7\x5c\xde\x54\x84\x8c\xeb\x69\x35\xa3\xa5\x1b\x93\xf3\xa2\xd9\x06\x6c\x55\xfb\xd8\xa7\xba\x4e\x70\x2a\x16\x42\xd1\x8d\x51\x6f\xd0\xd8\xcc\x6c\x9d\xcd\xcc\xdc\xba\x53\x5e\xd1\x6d\x6c\x74\x24\xe8\x6f\x89\xc6\x98\xe2\x2d\xd7\xcd\x4e\x0e\x8f\xf9\xcf\x2a\x99\xc3\x1c\xdb\x81\x05\x81\x55\xbe\xb0\x13\xbf\x5c\x35\xf9\xe1\x31\x9f\xb7\xbc\x15\x2e\x5c\x10\xb4\x55\xbe\x6a\xa0\xd0\xf3\x11\xde\xb8\x0d\x67\x83\x52\xf5\xe7\xd5\x03\x86\x4e\x80\x07\xfa\x52\x25\x4b\x02\x1b\xfa\x8b\x4c\x1e\x40\x66\x3b\x10\xd9\x23\x0c\x61\xf4\x97\x21\x81\xb5\x4b\xdd\x83\xc8\x56\xf0\x9f\x43\xb8\xfe\x8f\x21\x19\x6f\x0c\xba\x77\xc3\xb2\x12\xd5\x13\x4b\x6a\x53\x80\x67\x25\xd5\xad\x69\x0c\xf0\x96\x65\x35\x66\xd7\x14\xbf\x81\x67\xb5\xce\x5c\xfb\xda\x26\xba\x8a\xa2\x6b\x5f\x5b\x99\x02\xa6\xf6\x3d\x66\xdf\xd3\xb5\xad\x7d\x4f\x97\x04\x9d\x30\xa3\x87\xed\xb1\x46\xed\x98\xfa\x91\x2d\xb6\x73\x73\x91\x5b\xfb\x82\x6f\x2c\xa8\x73\x90\xd6\x6f\x56\x20\x69\x96\x1a\x56\x6e\x09\x86\x48\xd2\x98\x13\x37\xd2\xa7\xaf\x6a\xb1\x36\x10\xd1\x63\x83\x5b\x83\xf7\x78\x1c\x19\x41\x51\x6e\x30\xc8\xa7\x8e\x22\xa3\xe6\x9e\x2d\xd1\x16\xf9\xec\x73\x59\xc1\x43\xca\xcc\x59\x02\xa1\xf7\xe4\x74\xaf\x34\x6d\xa1\x37\x74\xfc\x77\x99\x08\x40\x0f\x23\xee\xa4\x7f\x2e\x13\x61\x23\x0a\x8f\xe7\xc1\x6e\xbf\x9c\xf0\x6c\x97\xb7\xdc\xd0\xf1\x6c\x37\x90\xd9\xe3\xd5\x75\x6e\x7f\xd9\x36\x56\x74\x9e\xea\xaf\xd3\x05\xd3\x47\xe8\xb0\xd3\xc5\x61\x9f\xf3\x6c\x1f\xb9\xd1\x2e\x8d\x8f\xf4\x39\x86\x40\xd5\x59\xc6\x01\xdc\xca\xf9\x4c\xe7\xd9\x3e\x95\xd9\xaa\x69\x9a\x44\x91\x1c\x0d\x83\x63\x1f\xbf\x4e\x7b\xb1\xe9\xee\xe3\x99\xd8\xdd\x7a\x6e\x82\xb2\xac\x34\x34\x9d\xe4\x55\xc2\xb3\x40\x6e\x19\xde\x64\x3d\xb0\xd6\x74\x30\x24\x71\xb9\x5a\x13\x8b\x03\x96\x59\x8e\xd1\x5c\xc8\x84\x67\x68\x1e\x33\x88\x6a\xdf\x0f\x12\xef\x38\xaf\x8a\x9f\x3a\xdf\x9a\xa9\x78\x4f\xc6\x82\x7e\xa7\x57\x1c\xa4\xfe\x2f\x75\xeb\xdf\x69\x0a\x12\x6a\xfd\xbf\x26\x50\x9d\x79\x18\x8b\x5d\xa2\xae\xae\xc1\xbf\x92\xf1\x13\x3c\x48\x44\x2a\xf1\x49\x6d\xa7\x16\x69\xad\x53\x35\x15\xdd\x5d\x3c\x7d\x02\x0a\xa8\x31\x06\x79\x9c\x7e\x3e\xbc\xaf\xa4\xc2\x79\x0b\x1c\x88\xd6\x35\x29\xa8\x4a\xdb\x29\x35\xe5\x9d\x94\x92\xba\xf8\x4b\x03\x11\x2d\xcc\xa0\x6a\xb7\x35\x16\xe7\xf0\x8b\xa4\xc0\xa9\xa5\x26\xca\x93\xc6\x09\xcf\x21\x19\xc6\xc9\x67\xea\xa2\x3d\x45\xab\xdf\xb4\xef\x41\xc0\x19\xff\xae\x12\x75\x99\xdc\xa9\xab\xae\x1e\x85\x63\x62\xa7\x5f\xaa\xd6\x13\x6d\xa0\x0c\x36\x73\x3c\x0e\x8d\x4d\xc9\x7b\x6e\x7a\xf7\xed\xee\x68\x07\x7d\x57\x7c\x37\x0e\xda\xdc\x31\x66\x60\xd8\x1c\x03\x43\x0a\x8e\xbd\x6a\x68\x27\xaa\xf9\xc4\x16\x53\xe4\x92\xe7\xa8\x0c\xa1\x8b\x5f\xf2\x98\xbc\x3b\x1d\x9d\x55\xfb\x3c\x3f\x10\x4f\xfe\x29\x3d\x86\x27\x87\xf4\x9e\x31\x99\x62\xdc\xc8\x59\x52\x1c\x4b\x1b\x4e\x9d\xb7\x05\xe9\x6e\xd1\xe0\xb5\xf2\xbe\x45\x73\x7f\x75\x2a\x72\xc9\x52\xee\x29\x92\x7d\xee\xaf\xa8\xcd\x71\x14\x4a\xa1\x9b\xc9\xab\xe6\xa4\xfb\xb0\x37\x91\x1e\x81\xe7\x5c\x77\x06\xea\xd9\xcc\x4f\x6f\x31\x23\x41\x31\xc3\x57\x7c\x7f\xc3\x61\x08\xc7\xe3\xd0\xf7\xa1\x5b\x70\x9e\xcd\xfd\xa8\x5f\x19\x1d\xcd\xd0\xae\xa1\xd3\x10\x66\x32\x03\x33\x2d\xc4\xac\x1c\xc4\xb4\x36\x20\xa7\x40\x58\x39\xef\x5c\x1f\xa8\xde\xb5\x9c\x3d\x51\x83\xe8\x2a\xbc\xc2\x43\xcd\x17\xf9\x61\xce\xeb\xf9\xb6\x2c\xea\x9c\x37\x4d\x3b\xd4\x03\x8b\xf5\xff\xe6\x6a\x37\xae\x9c\xe5\x58\xd5\x32\x74\x45\x82\xf4\x43\xaf\x67\x24\x15\x22\xc0\xe1\x1c\x3e\xa7\xdb\x8d\x8d\x34\xab\x38\x18\xac\xfd\x4a\x8c\x3d\x90\x8b\x23\x89\x93\xfe\xba\xe6\x27\xd3\x3d\x13\xbd\x02\x0e\x78\xba\x5e\xa1\x3f\xb9\xca\xcc\x5e\x34\x94\x83\x3c\x8f\x5d\xb6\xfc\xc7\xf0\x73\x68\x6f\xbf\x7f\xce\x49\xaf\xa6\xc6\xa3\x20\xdb\x51\x3d\x7d\xb0\xa9\xf2\x94\xb4\xa0\x6c\x30\x1a\x8b\x5b\x3a\x1c\x8b\xc1\x20\xc0\x9c\xea\x49\x4c\x55\x20\x2a\x60\xbd\x8f\x63\xd0\x63\x6b\xf7\xfc\xd4\xd3\xbc\xb2\xe7\x64\xe1\xce\xc9\xb6\xa1\x67\x1e\x7a\x31\x33\xe7\x63\x51\x8b\x8d\x39\x1d\xcb\x86\x32\x34\x6a\xfb\x24\x59\x92\x0f\xb1\x74\xa2\x78\xaf\x74\x09\x3c\x78\x88\x98\x0f\x6c\x00\xca\xd5\xc0\x44\x74\x5c\x0c\xe6\xce\x6b\x2c\x6c\x07\x2b\xcf\xe1\x21\x0d\x63\x09\x87\x0e\x1e\x2c\x66\x68\x1f\x2c\x5b\x56\xe4\x20\x5d\xcc\x0f\x66\x63\x7e\xc4\x73\x3f\x1b\xd4\xa3\x21\x1a\x0f\x01\xa9\x9f\xa0\x88\x61\x65\xd0\xb9\x38\x40\x31\x52\x55\x5e\x8e\x72\xa8\x3f\x88\x13\x32\xab\x4c\xe6\x83\xf7\x89\x27\xf7\x8e\x0f\x46\xa7\x61\x78\x5b\xcf\x35\x1e\x58\x4d\xf0\xb9\x2b\xe9\x26\x5a\x44\xb1\xab\x6a\xbd\x31\x17\xb2\xdf\xbf\xa8\x8e\xc7\x8b\xe2\x78\xbc\xa8\x8f\x47\x7e\x33\x3c\x1e\x13\xe1\xae\xa7\x68\x3b\x69\xb1\xcc\x18\x63\xb1\x5e\x83\x68\xb9\x69\x89\x55\xd4\x1d\xdb\x26\x72\xd1\x72\x46\x83\x5d\x9c\x5e\x7e\x0e\x12\x2a\x5d\x3b\xbe\xbe\x22\xf8\x3e\x11\xb1\x3d\x27\x46\x0c\xa9\x41\x12\xb4\x64\x0c\x31\x8c\x0e\xc6\x1f\x86\x9d\x43\xf1\x84\x82\xe9\xb8\xd0\xf7\xa5\x08\xf7\x45\xbc\xe7\xbe\x14\xc4\xc7\x05\x97\xd1\x1a\xce\x1b\x4d\x1a\xf5\xfb\xd2\xd0\x30\x7e\x6d\xe6\x1d\xbb\x7f\xa9\xbf\xa3\xb5\x12\xad\xb5\x62\xdd\xb5\x12\xa7\x6b\xf5\xe1\x13\xc4\xdf\x43\x55\x38\xba\xb7\xfd\xbe\x15\xc6\x9c\xfd\xac\xab\x81\x33\x5c\xbf\xc8\x50\xbe\xcc\x76\x50\x66\x7b\x02\xc1\xc8\x9d\x34\xac\x0b\x4e\x3f\xc7\x49\x24\xe4\x80\x5f\x6e\x03\x3e\x0c\x5e\x2b\xca\x03\x67\xf8\x24\x36\xd5\x38\x1c\xf3\x36\xce\x30\x24\xce\x5f\xe0\xd8\x6f\x3e\xcb\x5c\x18\x1e\xf6\xd4\x94\xd0\xf2\x80\x69\x54\x3c\xf6\x84\xe1\x03\xcd\x3c\xe5\xf7\xe2\xf4\xd6\x0b\xa8\xdd\xad\x37\xc2\x9d\x0b\x2f\xfb\x68\x0f\xbd\x7c\xcf\x41\xab\x89\x0d\x14\xe1\x58\x00\x7c\x99\xc8\x0f\xee\xbd\x1d\xcc\xb4\x76\x3a\xa9\x50\x62\xd8\x42\x5c\xf3\xcf\x2d\x94\x25\x87\x82\xb2\x16\xa5\x2f\xac\xe9\x91\xb7\xb1\x0f\xd0\xb7\xcc\x5a\x60\x7c\x1c\xc1\xed\xf2\x14\x6e\xb3\x00\xa9\x07\xc5\xd5\xb5\x03\xd6\x03\x39\x98\xdb\x90\xc2\x16\x6c\x17\x1e\x68\x9b\x8c\x36\xdc\x66\x60\x47\x04\x43\x18\x48\x98\xbb\x2b\x57\x1a\xf8\xdc\x58\x4f\x95\xe1\x98\xc5\x91\x94\x9b\xe6\x9f\x86\xef\x5b\x17\x0b\x5e\x94\xaf\xac\xc8\xfe\x9f\x31\xe3\x37\x0a\x3b\x69\x2c\x26\x58\x3b\x02\xa5\x8f\x36\xd0\x83\xe8\x89\x8f\xab\x85\xbb\x3f\x8a\xad\x77\xa6\xb3\x53\x9b\x9d\x61\xd3\x45\x8c\x2e\x46\x0d\x04\x02\x22\x1f\x82\x65\x44\x9f\x6c\x95\xee\xe9\x03\x7a\x05\x10\xa3\x03\x9d\x37\xd7\xf2\x8e\x3b\xdb\x94\x5f\x43\x34\x11\x13\x35\x49\xef\x41\x3e\x1a\x06\xdb\x39\x8c\x0f\xe8\xcd\x18\xff\xd4\x34\xd1\x02\x1a\x83\x1a\x7a\xe8\x85\xb5\x31\x1b\xd3\xcb\x7b\x91\x45\x54\x0f\x7a\x2d\xde\xa1\x2d\x31\xb7\x79\xe6\xda\xb4\x53\x6d\x2f\xde\xe6\x86\xc6\x18\x56\x6c\xe7\xa2\x17\xb4\xe7\x43\x2b\x7d\x22\xe9\x61\xcd\xcb\x92\x4b\x36\x17\x95\x5e\x69\xb1\x5e\x8b\x4a\x4f\xcf\x4c\x0c\xd5\xb8\x64\x3e\x62\x9f\x36\xf0\x54\x19\xf6\xa9\x2d\xf5\xe7\x61\x03\x6b\x5e\x6d\x15\x3b\x29\xf4\x67\xf6\x59\x54\x68\x25\xb6\xf5\x49\x91\x4f\xff\xcc\xfe\x64\xcb\x5c\x7f\xd6\xc0\xa2\xd8\x9f\x14\xf9\xcb\x9f\x3f\xf3\x65\x3e\x1d\x36\xf0\xc8\xd8\xdb\x50\x68\x64\xbb\x1a\x7e\xf6\x17\x5f\xea\xb3\x06\xd6\xa2\x52\xab\x93\xa6\xae\xff\x7c\xfd\x17\xf6\x67\x37\xbd\xeb\x06\xfe\xb5\x2d\x6a\xc5\xea\x93\xe6\xfe\xe3\x2f\x7f\xf9\xcc\x17\xfc\xac\x81\x3d\x2b\xce\x8c\x7d\xf4\xa7\xcf\xd8\x7f\x34\x0d\xfc\xe6\x2d\x82\xde\xb2\xbd\x4c\x3e\x91\x91\x2d\xcf\xcf\xed\x90\x47\x6a\xc0\x82\x20\xe6\x57\x19\x59\xbf\xb0\x27\xac\x5f\xb2\xbb\x62\x51\x6c\x34\xfc\x3d\xa0\xe6\x49\x9d\x57\x60\xac\x55\x05\x70\x29\xfe\xce\xd8\x5b\xbd\x6a\xd2\x20\x96\xba\xc4\xdf\x36\xca\xb0\x6d\x0a\xaf\x40\xdc\x73\x7d\x06\x65\xef\x0a\xbd\x01\x54\xf8\x46\xff\x6a\x74\x47\x0b\x7a\x62\x40\x54\x4d\xb8\xb5\x2d\x28\xa0\x42\x55\x41\xf3\x11\x0c\x0d\x0a\xa3\x0f\x9e\x08\x6c\xaf\xa7\x77\xa7\x77\x41\xa9\x38\x1e\x2f\x9e\xab\x44\x92\x7e\xff\x42\xa3\x73\x72\xc2\x0d\x17\xe0\x6f\x4b\xf4\x04\x90\xc7\x9f\x3d\x3b\x91\x1e\x48\x42\x20\x2d\x22\x69\xdb\xbf\xba\xd2\xb6\x67\x82\xfe\x26\x63\x0e\xb4\x11\x8a\xfd\x26\xbd\x89\x94\x22\x63\x79\x23\x06\xa3\x71\x9a\xca\xf0\x6e\x7e\x22\xa7\xbf\xc9\xa9\x9c\xcd\x50\xbb\x04\x77\x76\x62\xff\xe7\x56\xbf\xf9\xf5\xf3\x5f\xef\x7e\x7a\xfe\xd5\x97\x77\x2f\xbf\x7b\xf3\xe5\xd7\x5f\xfe\x68\x14\xc8\xcc\xae\xf7\xfb\x41\x22\x91\xf0\x01\x23\x57\x89\xb8\xb4\x82\x52\x72\xe3\x6d\xb1\x9e\x61\x1f\x4d\xf8\x10\x83\xd1\x2c\xcc\xe6\x5b\xcf\x63\x43\x51\xe1\xc1\x86\x95\x8c\x34\xff\x0e\xa5\xc8\x2b\x58\x71\xf4\xc4\xa6\x71\x72\x46\xc6\x6a\xca\xa7\xd5\xec\x96\xb2\x89\xfe\x9f\xf3\xa9\x98\xcd\xe8\xc5\xd0\xba\x8d\x55\x53\x86\x5f\xbe\x93\xaf\x4f\x18\x79\x53\x3d\xe9\x43\x83\xc8\x6d\xc7\x41\x96\x5e\xc1\x42\x63\x74\xe8\x4f\xaa\x20\x35\x65\xd3\x62\x06\x62\x5a\xcf\x68\x01\x55\x4b\xff\xa1\xb6\x82\xbd\x8b\x51\x50\x4b\x1d\x1a\x67\x08\x7c\xf2\x3e\xc4\xda\x1f\x61\x49\x53\xe1\xf7\x9d\x4d\x87\x4e\x87\xb5\xd2\x08\x27\x9b\xb2\xae\xbe\xaa\xf3\x4e\x6d\x1d\x53\xcb\x71\x7d\x43\x8b\x71\xad\x5b\x29\x16\x8b\xa4\x86\x11\x54\x84\x94\x94\xa3\xeb\x2b\xb4\xde\x49\xd8\xb4\x9c\x65\x38\x50\x7a\x11\xd4\xf5\x98\xc1\x7b\x05\xaa\x40\x59\x3d\xc6\x7f\xfc\x01\x8b\x36\xf4\x9b\x4f\xd1\x4b\x08\x7a\x45\x37\x2f\xc8\x74\x06\x45\x59\xa2\x53\x74\x53\x6c\x5b\x71\x45\x7b\x8b\x62\xdf\xb3\x09\x38\x90\x9f\x75\x6a\x4b\x34\x69\xf4\x3e\xa5\xde\x14\x93\x50\xe9\xb7\xaa\xe4\xbf\xb3\x05\xbd\x18\xf9\x80\xaa\xf6\x36\xc7\x71\x0e\xba\x21\xb7\x14\x5f\x33\x34\x32\xd2\x3f\xe8\xa1\x21\x50\x59\x4e\x86\x5d\x74\xf4\x19\x21\x44\x76\x67\x9c\x42\x64\x36\x19\x03\x51\x30\x32\x96\x2a\xf1\x21\x25\xbf\xc2\x07\x53\x6a\x5a\xdf\xfc\x4a\x08\x39\x19\x8b\x03\x43\x16\x16\xd4\x16\x1a\xf1\xcc\x3a\x67\x0c\x30\x89\x67\xe1\xa3\x01\xa3\x22\x62\xa6\x40\x4e\x67\xcd\xb2\xf0\x71\xc6\x66\x25\x52\x58\x41\x78\xf3\xab\xb4\x8e\x39\x48\xe3\x6c\xb4\xf7\x62\xab\x12\xbb\x71\x59\x3b\xf1\x23\x37\xf1\x63\xe4\xa3\x6d\x7d\xac\xe8\x6c\x57\x68\xe5\xb0\x66\x99\x3e\x03\xc7\x23\x1e\x02\x6f\xab\xe2\x8c\x14\x22\x95\xb8\x22\x56\x89\xab\xcf\xa9\xc4\xf9\x1b\x8d\x8a\x26\x85\x57\x69\x41\x5e\x22\x1a\x01\x7a\x9e\xb6\x30\x1a\x65\x84\x40\x1d\x15\x2b\x76\xba\x58\xc4\xa9\xb7\xb6\x2a\x84\x34\x45\xbf\x5f\x1f\x8f\x49\x99\x98\xd8\xd5\x06\x8f\xb2\x1d\x13\x38\xa7\xad\xd4\x33\xcb\x65\x12\x0d\x3a\x22\xc5\xb6\x9e\xb3\xe3\xb1\x4c\x3a\x72\x62\xd4\x2d\xfb\x35\x11\x41\x16\x2c\xc8\x44\xe4\x69\x00\xfa\x5f\x14\x4a\xef\xf8\x63\x42\xf4\xe5\x97\xf4\x57\xf3\x54\x98\xc2\x92\x4c\xa4\x2e\xcc\xaa\x45\xb7\x68\x3a\xb2\xba\x73\xd1\xd4\xe5\x00\x8d\x07\xd7\xc5\x2e\xcc\x54\xa4\x23\x4d\xe2\x9e\xcc\xad\x1d\xb1\xd6\xe5\xbe\xe1\x6b\x26\x55\xb1\xde\x38\x4d\x44\xf6\x64\x0c\x46\xe0\x2e\xeb\xbb\x2f\xbf\x7e\xde\x0e\xcf\x18\x2c\xfc\x9d\x67\x45\xef\x25\x41\x4d\x55\x00\x6e\xa4\x2d\x65\xff\x43\x66\x34\x6b\x66\x4f\xda\xfc\xad\x04\x41\xa3\x5d\xa9\xec\x7e\x4c\xd4\xd9\x79\xe5\xb8\xd3\x46\xf0\x9d\xc4\xb6\xa6\x61\x8b\x45\x18\xb8\x59\xe4\xa0\xd9\x76\x3c\x0a\x3d\x11\xb3\xca\x41\xc3\x4d\x27\x8b\x68\x62\x41\x65\x13\x15\xd2\x0a\x5a\x30\x14\x98\x58\x31\x5d\x88\x97\x8e\x80\x92\xdb\xbb\x92\x54\x59\xb1\x55\xe2\xa7\xb7\x7c\x33\xf9\x97\x4c\xb8\xae\xab\x61\x26\x38\xb5\x36\xa3\xf8\xe6\x37\xf3\x45\x61\x7c\x5b\x24\x92\x90\xbc\xfb\xf0\x80\x30\xac\x0c\x8f\x17\x78\xd6\x85\xbc\x8d\xd1\x04\x4e\xc6\x32\xb0\x31\x38\xc5\x97\x1b\x65\x0d\x72\xca\x67\xfe\xd9\x0f\x37\x3c\x5b\xf0\xe5\x32\x11\x18\x6f\xf5\x96\xb2\xc1\xc8\xfb\x95\x88\xde\x7b\x3e\x69\x75\x91\x0f\x67\xfa\xe1\x29\x5c\xc0\xbf\xb3\x53\x33\xca\xa4\xe1\xa5\xa8\xcc\xf3\x15\xdc\x86\xf5\x34\xfe\x69\xfc\x38\xe1\xc2\xb5\xe4\xfd\x6e\xae\xac\x8d\x03\xa5\x23\xe0\x11\xa6\xe4\x62\xa0\x9a\xf9\xfd\x26\xa7\x6c\xe6\xe6\x18\xa1\x2e\x4c\x8f\xd6\xf4\x41\x1c\x3d\xa4\x10\x66\x1b\xea\x4c\x1a\x82\xff\x9c\x43\x28\x40\xb4\xa3\x68\xcd\x84\x34\x71\xd5\xae\x58\xc7\x47\x3f\xb5\x91\x5b\xd9\x89\x55\x44\x74\x91\x4e\x34\xeb\x2c\x09\x3f\x1d\xa2\xdc\x16\xd5\xd2\x9d\xd5\xee\x68\xc0\xf3\xe4\x89\xe2\xa3\x19\x19\x70\x72\x75\x8d\x97\xe8\x6c\x89\xd6\x3d\x95\xed\x96\xab\x3c\xa9\x06\x1f\xaa\x77\x3d\x23\xe4\xea\x9a\x78\x2d\x0a\x97\x71\xf3\xe9\x24\xfb\x53\x9e\x5d\xff\x69\x2c\xe8\x77\x2a\x11\x80\xf6\x59\x52\xff\x96\xe6\x37\x8b\x10\x03\xa3\x0b\x27\x50\x17\x4e\xc2\xb2\xd0\x78\x49\x3e\xba\xd2\x80\x2d\x95\xa4\x69\xa2\xbb\x7c\x26\x34\x91\x7b\x94\x3a\xe6\x28\x88\xfb\x3a\x78\x22\xa9\x30\xf0\xa4\xa0\xd2\x5e\xc4\x7f\xc9\x44\xfa\x13\xaa\xf7\xe6\xdc\xa5\xe3\xa8\xee\xfb\x6d\x22\x83\x9d\xcf\x88\x40\x69\x71\x7f\x63\x2d\x29\xa3\xa7\x1f\xe6\xf4\xb9\x4a\x4a\x72\x3c\x5e\xe8\x07\xbc\x84\x95\xd3\x36\x41\xa7\xfa\x94\xeb\x4b\x37\xef\xf7\x93\x25\x4d\x99\x7f\x20\x96\x11\x55\x50\x12\x02\x9d\xcc\xf9\x04\x1f\xd8\x1c\x57\x0d\x2f\x66\x05\x1c\x0a\x72\x3b\x62\x7f\xba\xac\x4f\x3c\xc1\xf1\xb4\xf7\xac\xa8\x16\xcf\x7a\x69\xa5\x7f\xd5\xec\x99\x12\xe2\xd9\xb2\xa8\x9f\x15\x9b\xa2\x56\xcf\x1e\xb9\x5a\x3d\x73\xd3\x79\x26\x96\xcf\x7a\x69\x9d\xf6\x9e\xf5\xd2\xc2\xed\xe3\x03\x45\xef\x2e\xe8\x14\xb3\xf5\xfc\xe9\x63\x6a\x3d\x7e\xb4\x9e\x11\x7d\x2f\x17\x74\x89\x4e\x8e\x17\x37\xd5\x78\xa1\x27\xa0\xb1\xd6\x05\xd4\x7a\xb3\xb7\x69\x4a\xbe\x95\xc9\x0a\x16\x10\xd4\x32\x17\x17\x94\x56\xfd\xbe\x05\xce\x9a\x8e\xf2\xc0\x79\x74\x41\xe9\xf6\x78\xf4\x55\x20\xa6\x39\x57\xc4\x45\x4e\xb1\x91\x4b\x07\x8c\x58\x6d\x25\x45\x6f\x53\x65\x84\x63\xef\x37\x88\x8f\x0f\x4d\x2c\xbc\xd5\x67\x24\xc4\xdf\xb4\x4e\xb3\x0c\xaa\x38\x61\x16\x53\x34\x5e\x04\xe3\x2c\x92\xb7\xf2\xda\x18\x26\xe2\x9e\xba\x5d\xd2\xdc\x29\x34\xb1\xd1\xc9\x5f\x3d\x4d\x42\x38\x51\xba\x3b\xbb\xfa\xc8\x22\xb2\xd5\xc1\x5c\x6b\x2a\x0c\xf8\x42\xd1\x79\x80\x44\x30\xa7\x75\xbf\x5f\x68\x32\x61\x45\x4b\xfd\xab\x9c\xc1\x82\xf2\x29\x9b\xc1\x56\x27\xac\xfa\xfd\x45\xbf\xbf\x30\x90\x17\x96\xba\xb2\x03\xfb\x7e\x16\xd5\xf1\x98\x6c\x27\xab\x7c\x4e\x08\x3c\x50\x6b\xc7\xeb\xb5\xbc\xdc\x12\x3d\x4c\x7e\x48\x1e\x60\xba\xd4\x73\x98\x69\x4a\x77\xf9\x84\x7e\x9a\x8f\x5e\xfd\xbe\x98\xd5\x15\x06\xab\x06\xeb\xea\xd9\x6e\xd4\x99\x25\xab\x2c\x25\xc5\xc0\x98\x1e\x9d\xc0\xa7\xf3\xba\xd4\x2d\x4b\x24\x2f\x0b\x6f\x4b\xad\x3f\xa8\x98\x6d\x5c\xb0\x5a\xc8\xf5\x24\x60\x8d\x84\xdf\xe7\xac\x9d\x2c\x6a\x98\x56\xe4\x92\x67\x06\xdc\x7d\xa4\xc2\xf5\xd3\x3d\xbb\x3a\x57\xae\xc5\x01\xe2\x94\x61\x20\x6b\x5e\xa5\xd5\x65\x7b\xb6\x1e\xe0\xfd\x64\xe3\xc9\x3d\xe9\xeb\xd4\xe0\x60\xba\xd7\xb9\xda\x9d\x0d\x5d\x0b\x82\x7e\xa9\x12\xd6\x31\x42\x9b\x70\xdd\xdf\x8f\xce\x8d\x0f\xe2\x04\xee\xcb\x2b\xd6\xcc\x05\x3e\xb6\x56\x89\x45\x6a\x44\xd7\x38\x29\x7d\xda\x34\x0d\xb9\x11\x4e\x5a\xfd\x98\x57\x97\x32\xad\x2f\x0b\x58\xe5\xd5\x65\x91\xd6\x97\xb2\x69\x4e\x81\xf9\xfb\xe7\x87\xc8\xe6\x09\x79\x28\x68\x35\x35\xa8\xdb\xec\x78\xac\xb2\x88\x97\x88\x1c\x86\xf3\x37\x7a\xa8\x11\x04\x06\x53\x35\xd3\xcf\x5c\x40\x11\x8c\x0f\x4d\x96\xb5\x97\x5d\x76\x2c\x4a\x4e\x96\xd0\x3a\x81\xbd\x2a\xb2\x47\xef\x01\xf6\xaa\xc8\x56\x64\x30\xf2\xd1\xb4\x6e\x87\x93\x3a\x1f\x35\x67\x80\x73\x5b\xc5\x37\x84\x91\x77\x01\xf2\xd0\x1b\x13\x3a\xd5\xe4\xcb\xa4\x6a\xc7\x6d\x7f\xd6\x91\xa5\xbc\x2e\xd4\x7c\xc5\xab\x87\x5f\xb8\xe4\xf7\x25\x7b\xcd\x54\xa1\xc1\x3f\xf2\x8e\x22\x02\x37\x60\xd7\xc1\x11\x58\xd4\x19\xd5\xe8\x75\xc7\x35\xd4\xf3\xb2\x34\x21\xbe\x7f\x31\xb1\x13\x14\x89\x20\x85\x38\x85\x14\x95\x8b\x6c\x2c\xa6\xec\xc3\x6d\xc5\xd8\x78\x34\x0e\x15\xe8\xf0\xa4\x0a\xaf\xc6\x93\xab\x17\x85\x42\xb4\xde\xdf\xbc\x33\x52\x0d\xda\x8c\xab\xb6\xd6\xbc\x59\x7b\xfd\xbc\x13\x96\x10\xdc\x5e\x74\x83\xdb\x9b\x90\xf0\x09\x32\x4c\xc5\x94\xcf\xce\x0c\xde\xf4\x4d\x5b\x6b\x3e\x61\x79\x3c\x1d\x46\x9a\xf0\x11\xb4\x4d\x56\x2c\x51\xe6\xf5\xfc\x59\x92\x58\x51\xfe\x07\x19\x45\xa8\x35\xaa\xb1\x50\x18\x25\xff\xaa\x75\x38\x35\x06\x1a\xd9\x5a\xe9\x3b\xac\xa6\xd5\x0c\x0a\xaa\xa6\x62\x66\xf4\xfd\x1d\x99\x51\x19\xbe\xc6\x58\x52\x9e\x95\x02\xdd\xc7\xae\xf0\xe8\x4d\x25\xb2\x26\xa7\xc5\xac\x71\xee\x2c\xc4\xa0\xf2\x87\x79\x22\xd3\xa4\x18\x48\x72\x99\xb0\x41\x45\xae\xea\x5c\x36\xff\x30\x92\x1b\x7d\x4d\x7b\xf0\x8f\x58\x62\x63\x70\x86\xdc\x60\x2c\xe0\x38\x3e\xf9\xa1\x01\x5d\x38\x77\x2c\x9c\x8b\x11\xe8\x5b\xac\xff\x1b\x26\xce\xc5\x28\xe6\xdf\x5c\x8c\xc0\xe2\x82\x79\x2f\xba\xe4\xde\x41\xa2\x85\x07\xf9\xa1\x69\xbc\x4c\x06\x51\xa2\xbc\xa7\xc9\xb9\xde\x89\x1d\xc0\x28\xd8\x01\x7c\x13\x78\x6f\xff\xf8\x80\x1d\xc0\x1d\xba\xfb\x0a\x1a\xfc\xeb\x62\x87\xf2\xcb\x98\x2b\xe6\x68\x8c\x73\x67\x13\x9d\x4d\xb8\xd3\xfb\x95\xa8\xdf\xe8\xe6\x12\x32\x56\xae\x65\x95\x21\x01\xfe\x4a\x88\xb7\xdb\x8d\xc9\x65\x96\x24\xb3\x3d\xb9\xa2\xc1\x08\x3b\x70\xb3\x5c\xd7\x8c\x34\x27\xcd\x78\xd5\xa3\xb6\x52\xbd\x55\x6a\xbb\x50\xed\x9b\x31\x3d\xe0\xee\x30\xd8\x08\x99\x0f\x1b\x30\x9f\x1c\x3f\x47\xcd\xcc\x2b\x39\x4c\x99\xb9\x5f\xe6\x3c\xea\x6b\x63\x48\x28\x8f\x3c\x08\x64\xe6\x0a\x62\xce\x1f\x14\xb7\x9a\x54\xbb\xe1\xfd\xbe\xe5\xe7\x16\x41\x13\xdd\x24\x70\x02\x55\xf3\xd4\x42\x9d\x01\x96\xe1\xca\x17\x65\xe9\xe0\xe4\x53\xf7\xdc\xaa\xdd\x76\x61\x30\x54\xf4\x3c\xa3\xc2\x3f\xcf\x3e\x08\xa1\x1e\xb8\xa5\xc0\xe2\xfb\xcc\x1d\xbc\xab\x08\xc9\x5d\xd9\x09\xcf\x2b\x68\x0f\x90\x32\x60\x67\x90\x98\xf3\x9e\xa9\x1d\x32\x81\xde\x95\x63\xf0\xcd\xc3\x79\xb8\x1d\xf6\xfb\x17\x9f\xa0\xe5\xc3\x55\x94\x9c\xf3\xf7\x23\x3e\xfc\x2c\xe2\x53\x59\xc4\x47\x90\xcb\x2a\x46\x7c\xce\x60\x70\xb6\x9d\x1f\xac\x01\x84\x39\x93\xa0\x9c\x59\xb8\x1b\xc7\xff\x30\xda\xf4\x03\x86\x80\x34\x7d\x57\x97\xed\xae\x01\x1d\xe5\x7e\x13\x00\x93\x64\x35\x67\xb2\x07\xdf\x44\xe0\x29\x02\x55\xe8\x1f\x59\x15\x1f\xf0\xa8\xf7\xc2\x3a\x66\xfa\x69\x5e\x94\x2c\xff\x51\x82\x11\x53\x9b\xcf\x2f\x25\xbc\x0a\xb6\x47\x26\xed\x77\x09\x3f\x46\xf2\x6c\x93\xf8\x4f\x09\xfa\x98\x99\x8f\x7f\xd8\x0f\x1c\x9e\x49\xfa\x46\x06\xb1\xc6\x37\x55\x56\xb3\x07\x2e\x15\xab\x93\x7b\x01\xaa\x80\xdf\x04\x3c\x97\x04\xbe\xa9\xb2\x15\x2b\x37\xac\x96\xf4\x90\x65\xd9\x8b\xaa\xd1\x49\x8e\x56\x90\x54\x08\xfd\xed\x9d\xd8\xd3\x3b\xde\xfa\x96\xf4\x1d\x26\x18\x39\xba\xa8\x69\xa1\xbf\xc2\x53\x2d\xe9\xf3\xd6\x27\x06\xc0\x94\xba\x8c\xf5\x28\xf9\xc2\xe7\xd1\x57\xd8\x92\xf5\xe1\x4d\xbf\xc4\x2f\xeb\x58\x5a\xd2\xdf\x70\x1c\x2f\x83\xeb\x42\xfa\x37\xa6\x53\x4a\xe4\x88\x4b\xfa\x35\x7e\x6d\xca\x42\x69\xf2\x46\xd2\x2d\x56\xc7\x85\xa0\xbf\xe2\x6f\xe4\x47\xd2\x5f\x78\x27\x4a\xef\x37\x15\x44\x0b\x02\x5b\x8e\x6b\xf2\x02\xa3\x71\x7f\x53\x41\x6f\x5b\x2d\x0c\x4f\x3b\x38\x29\x7b\xe4\xd5\x42\x3c\xf6\xfb\x89\xf9\xe1\x0b\xeb\x9a\x0d\x21\xe3\xff\xe7\xff\x0b\x00\x00\xff\xff\x3b\x38\xee\x9a\xb4\xc8\x02\x00") func assetsChartMinJsBytes() ([]byte, error) { return bindataRead( _assetsChartMinJs, "assets/chart.min.js", ) } func assetsChartMinJs() (*asset, error) { bytes, err := assetsChartMinJsBytes() if err != nil { return nil, err } info := bindataFileInfo{name: "assets/chart.min.js", size: 182452, mode: os.FileMode(420), modTime: time.Unix(1621756582, 0)} a := &asset{bytes: bytes, info: info} return a, nil } // Asset loads and returns the asset for the given name. // It returns an error if the asset could not be found or // could not be loaded. func Asset(name string) ([]byte, error) { cannonicalName := strings.Replace(name, "\\", "/", -1) if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) } return a.bytes, nil } return nil, fmt.Errorf("Asset %s not found", name) } // MustAsset is like Asset but panics when Asset would return an error. // It simplifies safe initialization of global variables. func MustAsset(name string) []byte { a, err := Asset(name) if err != nil { panic("asset: Asset(" + name + "): " + err.Error()) } return a } // AssetInfo loads and returns the asset info for the given name. // It returns an error if the asset could not be found or // could not be loaded. func AssetInfo(name string) (os.FileInfo, error) { cannonicalName := strings.Replace(name, "\\", "/", -1) if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) } return a.info, nil } return nil, fmt.Errorf("AssetInfo %s not found", name) } // AssetNames returns the names of the assets. func AssetNames() []string { names := make([]string, 0, len(_bindata)) for name := range _bindata { names = append(names, name) } return names } // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ "assets/chart.min.js": assetsChartMinJs, } // AssetDir returns the file names below a certain // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: // data/ // foo.txt // img/ // a.png // b.png // then AssetDir("data") would return []string{"foo.txt", "img"} // AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("foo.txt") and AssetDir("notexist") would return an error // AssetDir("") will return []string{"data"}. func AssetDir(name string) ([]string, error) { node := _bintree if len(name) != 0 { cannonicalName := strings.Replace(name, "\\", "/", -1) pathList := strings.Split(cannonicalName, "/") for _, p := range pathList { node = node.Children[p] if node == nil { return nil, fmt.Errorf("Asset %s not found", name) } } } if node.Func != nil { return nil, fmt.Errorf("Asset %s not found", name) } rv := make([]string, 0, len(node.Children)) for childName := range node.Children { rv = append(rv, childName) } return rv, nil } type bintree struct { Func func() (*asset, error) Children map[string]*bintree } var _bintree = &bintree{nil, map[string]*bintree{ "assets": &bintree{nil, map[string]*bintree{ "chart.min.js": &bintree{assetsChartMinJs, map[string]*bintree{}}, }}, }} // RestoreAsset restores an asset under the given directory func RestoreAsset(dir, name string) error { data, err := Asset(name) if err != nil { return err } info, err := AssetInfo(name) if err != nil { return err } err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) if err != nil { return err } err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) if err != nil { return err } err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) if err != nil { return err } return nil } // RestoreAssets restores an asset under the given directory recursively func RestoreAssets(dir, name string) error { children, err := AssetDir(name) // File if err != nil { return RestoreAsset(dir, name) } // Dir for _, child := range children { err = RestoreAssets(dir, filepath.Join(name, child)) if err != nil { return err } } return nil } func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } ================================================ FILE: template/chartjs/assets_list.go ================================================ package chartjs var AssetsList = []string{ "/chart.min.js", } ================================================ FILE: template/chartjs/bar.go ================================================ package chartjs import ( "bytes" "encoding/json" "fmt" "html/template" template2 "github.com/GoAdminGroup/go-admin/template" ) type BarChart struct { *Chart JsContent BarJsContent } type BarJsContent struct { JsContent Data BarAttributes `json:"data"` } type BarAttributes struct { Attributes DataSets BarDataSets `json:"datasets"` } type BarDataSets []*BarDataSet func (l BarDataSets) Add(ds *BarDataSet) BarDataSets { return append(l, ds) } type BarDataSet struct { Label string `json:"label"` Data []float64 `json:"data"` Type string `json:"type,omitempty"` BackgroundColor Color `json:"backgroundColor,omitempty"` BorderCapStyle string `json:"borderCapStyle,omitempty"` BorderColor Color `json:"borderColor,omitempty"` BorderSkipped string `json:"borderSkipped,omitempty"` BorderWidth float64 `json:"borderWidth,omitempty"` HoverBackgroundColor Color `json:"hoverBackgroundColor,omitempty"` HoverBorderColor Color `json:"hoverBorderColor,omitempty"` HoverBorderWidth float64 `json:"hoverBorderWidth,omitempty"` Order float64 `json:"order,omitempty"` XAxisID string `json:"xAxisID,omitempty"` YAxisID string `json:"yAxisID,omitempty"` } func (l *BarDataSet) SetLabel(label string) *BarDataSet { l.Label = label return l } func (l *BarDataSet) SetData(data []float64) *BarDataSet { l.Data = data return l } func (l *BarDataSet) SetType(t string) *BarDataSet { l.Type = t return l } func (l *BarDataSet) SetBackgroundColor(backgroundColor Color) *BarDataSet { l.BackgroundColor = backgroundColor return l } func (l *BarDataSet) SetBorderCapStyle(borderCapStyle string) *BarDataSet { l.BorderCapStyle = borderCapStyle return l } func (l *BarDataSet) SetBorderColor(borderColor Color) *BarDataSet { l.BorderColor = borderColor return l } func (l *BarDataSet) SetBorderWidth(borderWidth float64) *BarDataSet { l.BorderWidth = borderWidth return l } func (l *BarDataSet) SetBorderSkipped(skip string) *BarDataSet { l.BorderSkipped = skip return l } func (l *BarDataSet) SetHoverBackgroundColor(hoverBackgroundColor Color) *BarDataSet { l.HoverBackgroundColor = hoverBackgroundColor return l } func (l *BarDataSet) SetHoverBorderColor(hoverBorderColor Color) *BarDataSet { l.HoverBorderColor = hoverBorderColor return l } func (l *BarDataSet) SetHoverBorderWidth(hoverBorderWidth float64) *BarDataSet { l.HoverBorderWidth = hoverBorderWidth return l } func (l *BarDataSet) SetOrder(order float64) *BarDataSet { l.Order = order return l } func (l *BarDataSet) SetXAxisID(xAxisID string) *BarDataSet { l.XAxisID = xAxisID return l } func (l *BarDataSet) SetYAxisID(yAxisID string) *BarDataSet { l.YAxisID = yAxisID return l } func Bar() *BarChart { return &BarChart{ Chart: &Chart{ BaseComponent: &template2.BaseComponent{ Name: "chartjs", HTMLData: List["chartjs"], }, dataSetIndex: -1, }, JsContent: BarJsContent{ JsContent: JsContent{ Type: "bar", }, Data: BarAttributes{ Attributes: Attributes{ Labels: make([]string, 0), }, DataSets: make(BarDataSets, 0), }, }, } } func (l *BarChart) SetID(s string) *BarChart { l.ID = s return l } func (l *BarChart) SetTitle(s template.HTML) *BarChart { l.Title = s return l } func (l *BarChart) SetHeight(s int) *BarChart { l.Height = s return l } func (l *BarChart) SetLabels(s []string) *BarChart { l.JsContent.Data.Labels = s return l } func (l *BarChart) AddDataSet(s string) *BarChart { l.dataSetIndex++ l.JsContent.Data.DataSets = l.JsContent.Data.DataSets.Add(&BarDataSet{ Type: "bar", Label: s, }) return l } func (l *BarChart) DSLabel(s string) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetLabel(s) return l } func (l *BarChart) DSData(data []float64) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetData(data) return l } func (l *BarChart) DSType(t string) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetType(t) return l } func (l *BarChart) DSBackgroundColor(backgroundColor Color) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBackgroundColor(backgroundColor) return l } func (l *BarChart) DSBorderCapStyle(borderCapStyle string) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderCapStyle(borderCapStyle) return l } func (l *BarChart) DSBorderSkipped(skip string) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderSkipped(skip) return l } func (l *BarChart) DSBorderColor(borderColor Color) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderColor(borderColor) return l } func (l *BarChart) DSBorderWidth(borderWidth float64) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderWidth(borderWidth) return l } func (l *BarChart) DSHoverBackgroundColor(hoverBackgroundColor Color) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBackgroundColor(hoverBackgroundColor) return l } func (l *BarChart) DSHoverBorderColor(hoverBorderColor Color) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBorderColor(hoverBorderColor) return l } func (l *BarChart) DSHoverBorderWidth(hoverBorderWidth float64) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBorderWidth(hoverBorderWidth) return l } func (l *BarChart) DSOrder(order float64) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetOrder(order) return l } func (l *BarChart) DSXAxisID(xAxisID string) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetXAxisID(xAxisID) return l } func (l *BarChart) DSYAxisID(yAxisID string) *BarChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetYAxisID(yAxisID) return l } func (l *BarChart) GetContent() template.HTML { buffer := new(bytes.Buffer) tmpl, defineName := l.GetTemplate() if l.JsContentOptions != nil { l.JsContent.Options = l.JsContentOptions } jsonByte, _ := json.Marshal(l.JsContent) l.Js = template.JS(string(jsonByte)) err := tmpl.ExecuteTemplate(buffer, defineName, l) if err != nil { fmt.Println("ComposeHtml Error:", err) } return template.HTML(buffer.String()) } ================================================ FILE: template/chartjs/chart.go ================================================ package chartjs import ( "html/template" template2 "github.com/GoAdminGroup/go-admin/template" ) type Chart struct { *template2.BaseComponent ID string Title template.HTML Js template.JS Height int JsContentOptions *Options dataSetIndex int } func (c *Chart) SetID(id string) *Chart { c.ID = id return c } func (c *Chart) SetTitle(title template.HTML) *Chart { c.Title = title return c } func (c *Chart) SetHeight(height int) *Chart { c.Height = height return c } func (c *Chart) SetOptionAnimationDuration(duration int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Animation == nil { c.JsContentOptions.Animation = new(OptionAnimation) } c.JsContentOptions.Animation.Duration = duration } func (c *Chart) SetOptionAnimationEasing(easing string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Animation == nil { c.JsContentOptions.Animation = new(OptionAnimation) } c.JsContentOptions.Animation.Easing = easing } func (c *Chart) SetOptionLayoutPaddingLeft(left int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Layout == nil { c.JsContentOptions.Layout = new(OptionLayout) } c.JsContentOptions.Layout.Padding.Left = left } func (c *Chart) SetOptionLayoutPaddingRight(right int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Layout == nil { c.JsContentOptions.Layout = new(OptionLayout) } c.JsContentOptions.Layout.Padding.Right = right } func (c *Chart) SetOptionLayoutPaddingTop(top int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Layout == nil { c.JsContentOptions.Layout = new(OptionLayout) } c.JsContentOptions.Layout.Padding.Top = top } func (c *Chart) SetOptionLayoutPaddingBottom(bottom int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Layout == nil { c.JsContentOptions.Layout = new(OptionLayout) } c.JsContentOptions.Layout.Padding.Bottom = bottom } func (c *Chart) SetOptionLegendDisplay(display bool) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Legend == nil { c.JsContentOptions.Legend = new(OptionLegend) } c.JsContentOptions.Legend.Display = display } func (c *Chart) SetOptionLegendPosition(position string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Legend == nil { c.JsContentOptions.Legend = new(OptionLegend) } c.JsContentOptions.Legend.Position = position } func (c *Chart) SetOptionLegendAlign(align string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Legend == nil { c.JsContentOptions.Legend = new(OptionLegend) } c.JsContentOptions.Legend.Align = align } func (c *Chart) SetOptionLegendFullWidt(fullWidth bool) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Legend == nil { c.JsContentOptions.Legend = new(OptionLegend) } c.JsContentOptions.Legend.FullWidth = fullWidth } func (c *Chart) SetOptionLegendRevers(reverse bool) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Legend == nil { c.JsContentOptions.Legend = new(OptionLegend) } c.JsContentOptions.Legend.Reverse = reverse } func (c *Chart) SetOptionLegendRt(rtl bool) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Legend == nil { c.JsContentOptions.Legend = new(OptionLegend) } c.JsContentOptions.Legend.Rtl = rtl } func (c *Chart) SetOptionLegendTextDirection(textDirection string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Legend == nil { c.JsContentOptions.Legend = new(OptionLegend) } c.JsContentOptions.Legend.TextDirection = textDirection } func (c *Chart) SetOptionLegendLabels(labels *OptionLegendLabel) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Legend == nil { c.JsContentOptions.Legend = new(OptionLegend) } c.JsContentOptions.Legend.Labels = labels } func (c *Chart) SetOptionTitleDisplay(display bool) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Title == nil { c.JsContentOptions.Title = new(OptionTitle) } c.JsContentOptions.Title.Display = display } func (c *Chart) SetOptionTitleFontSize(fontSize int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Title == nil { c.JsContentOptions.Title = new(OptionTitle) } c.JsContentOptions.Title.FontSize = fontSize } func (c *Chart) SetOptionTitlePosition(position string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Title == nil { c.JsContentOptions.Title = new(OptionTitle) } c.JsContentOptions.Title.Position = position } func (c *Chart) SetOptionTitleFontFamily(fontFamily string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Title == nil { c.JsContentOptions.Title = new(OptionTitle) } c.JsContentOptions.Title.FontFamily = fontFamily } func (c *Chart) SetOptionTitleFontColor(fontColor Color) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Title == nil { c.JsContentOptions.Title = new(OptionTitle) } c.JsContentOptions.Title.FontColor = fontColor } func (c *Chart) SetOptionTitleFontStyle(fontStyle string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Title == nil { c.JsContentOptions.Title = new(OptionTitle) } c.JsContentOptions.Title.FontStyle = fontStyle } func (c *Chart) SetOptionTitlePadding(padding int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Title == nil { c.JsContentOptions.Title = new(OptionTitle) } c.JsContentOptions.Title.Padding = padding } func (c *Chart) SetOptionTitleLineHeight(lineHeight int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Title == nil { c.JsContentOptions.Title = new(OptionTitle) } c.JsContentOptions.Title.LineHeight = lineHeight } func (c *Chart) SetOptionTitleText(text string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Title == nil { c.JsContentOptions.Title = new(OptionTitle) } c.JsContentOptions.Title.Text = text } func (c *Chart) SetOptionTooltipsEnabled(enabled bool) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.Enabled = enabled } func (c *Chart) SetOptionTooltipsMode(mode string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.Mode = mode } func (c *Chart) SetOptionTooltipsIntersect(intersect bool) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.Intersect = intersect } func (c *Chart) SetOptionTooltipsPosition(position string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.Position = position } func (c *Chart) SetOptionTooltipsBackgroundColor(backgroundColor Color) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.BackgroundColor = backgroundColor } func (c *Chart) SetOptionTooltipsTitleFontFamily(titleFontFamily string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.TitleFontFamily = titleFontFamily } func (c *Chart) SetOptionTooltipsTitleFontSize(titleFontSize int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.TitleFontSize = titleFontSize } func (c *Chart) SetOptionTooltipsTitleFontStyle(titleFontStyle string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.TitleFontStyle = titleFontStyle } func (c *Chart) SetOptionTooltipsTitleFontColor(titleFontColor Color) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.TitleFontColor = titleFontColor } func (c *Chart) SetOptionTooltipsTitleAlign(titleAlign string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.TitleAlign = titleAlign } func (c *Chart) SetOptionTooltipsTitleSpacing(titleSpacing int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.TitleSpacing = titleSpacing } func (c *Chart) SetOptionTooltipsTitleMarginBottom(titleMarginBottom int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.TitleMarginBottom = titleMarginBottom } func (c *Chart) SetOptionTooltipsBodyFontFamily(bodyFontFamily string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.BodyFontFamily = bodyFontFamily } func (c *Chart) SetOptionTooltipsBodyFontSize(bodyFontSize int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.BodyFontSize = bodyFontSize } func (c *Chart) SetOptionTooltipsBodyFontStyle(bodyFontStyle string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.BodyFontStyle = bodyFontStyle } func (c *Chart) SetOptionTooltipsBodyFontColor(bodyFontColor Color) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.BodyFontColor = bodyFontColor } func (c *Chart) SetOptionTooltipsBodyAlign(bodyAlign string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.BodyAlign = bodyAlign } func (c *Chart) SetOptionTooltipsBodySpacing(bodySpacing int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.BodySpacing = bodySpacing } func (c *Chart) SetOptionTooltipsFooterFontFamily(footerFontFamily string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.FooterFontFamily = footerFontFamily } func (c *Chart) SetOptionTooltipsFooterFontSize(footerFontSize int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.FooterFontSize = footerFontSize } func (c *Chart) SetOptionTooltipsFooterFontStyle(footerFontStyle string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.FooterFontStyle = footerFontStyle } func (c *Chart) SetOptionTooltipsFooterFontColor(footerFontColor Color) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.FooterFontColor = footerFontColor } func (c *Chart) SetOptionTooltipsFooterAlign(footerAlign string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.FooterAlign = footerAlign } func (c *Chart) SetOptionTooltipsFooterSpacing(footerSpacing int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.FooterSpacing = footerSpacing } func (c *Chart) SetOptionTooltipsFooterMarginTop(footerMarginTop int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.FooterMarginTop = footerMarginTop } func (c *Chart) SetOptionTooltipsXPadding(xPadding int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.XPadding = xPadding } func (c *Chart) SetOptionTooltipsYPadding(yPadding int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.YPadding = yPadding } func (c *Chart) SetOptionTooltipsCaretPadding(caretPadding int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.CaretPadding = caretPadding } func (c *Chart) SetOptionTooltipsCaretSize(caretSize int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.CaretSize = caretSize } func (c *Chart) SetOptionTooltipsCornerRadius(cornerRadius int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.CornerRadius = cornerRadius } func (c *Chart) SetOptionTooltipsMultiKeyBackground(multiKeyBackground Color) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.MultiKeyBackground = multiKeyBackground } func (c *Chart) SetOptionTooltipsDisplayColors(displayColors bool) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.DisplayColors = displayColors } func (c *Chart) SetOptionTooltipsBorderColor(borderColor Color) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.BorderColor = borderColor } func (c *Chart) SetOptionTooltipsBorderWidth(borderWidth int) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.BorderWidth = borderWidth } func (c *Chart) SetOptionTooltipsRtl(rtl bool) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.Rtl = rtl } func (c *Chart) SetOptionTooltipsTextDirection(textDirection string) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Tooltips == nil { c.JsContentOptions.Tooltips = new(OptionTooltips) } c.JsContentOptions.Tooltips.TextDirection = textDirection } func (c *Chart) SetOptionElementPoint(point *OptionElementPoint) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Elements == nil { c.JsContentOptions.Elements = new(OptionElement) } c.JsContentOptions.Elements.Point = point } func (c *Chart) SetOptionElementLine(line *OptionElementLine) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Elements == nil { c.JsContentOptions.Elements = new(OptionElement) } c.JsContentOptions.Elements.Line = line } func (c *Chart) SetOptionElementArc(arc *OptionElementArc) { if c.JsContentOptions == nil { c.JsContentOptions = new(Options) } if c.JsContentOptions.Elements == nil { c.JsContentOptions.Elements = new(OptionElement) } c.JsContentOptions.Elements.Arc = arc } func (c *Chart) SetOptionElementRectangle(rectangle *OptionElementRectangle) { if c.JsContentOptions.Elements == nil { c.JsContentOptions.Elements = new(OptionElement) } c.JsContentOptions.Elements.Rectangle = rectangle } type JsContent struct { Type string `json:"type,omitempty"` Options *Options `json:"options,omitempty"` } type OptionAnimation struct { Duration int `json:"duration,omitempty"` Easing string `json:"easing,omitempty"` } type OptionLayout struct { Padding struct { Left int `json:"left,omitempty"` Right int `json:"right,omitempty"` Top int `json:"top,omitempty"` Bottom int `json:"bottom,omitempty"` } `json:"padding,omitempty"` } type OptionLegend struct { Display bool `json:"display,omitempty"` Position string `json:"position,omitempty"` Align string `json:"align,omitempty"` FullWidth bool `json:"full_width,omitempty"` Reverse bool `json:"reverse,omitempty"` Rtl bool `json:"rtl,omitempty"` TextDirection string `json:"text_direction,omitempty"` Labels *OptionLegendLabel `json:"labels,omitempty"` } type OptionLegendLabel struct { BoxWidth int `json:"box_width,omitempty"` FontSize int `json:"fontSize,omitempty"` FontStyle string `json:"fontStyle,omitempty"` FontColor Color `json:"fontColor,omitempty"` FontFamily string `json:"fontFamily,omitempty"` Padding int `json:"padding,omitempty"` UsePointStyle bool `json:"usePointStyle,omitempty"` } type OptionTitle struct { Display bool `json:"display,omitempty"` Position string `json:"position,omitempty"` FontSize int `json:"fontSize,omitempty"` FontFamily string `json:"fontFamily,omitempty"` FontColor Color `json:"fontColor,omitempty"` FontStyle string `json:"fontStyle,omitempty"` Padding int `json:"padding,omitempty"` LineHeight int `json:"lineHeight,omitempty"` Text string `json:"text,omitempty"` } type OptionTooltips struct { Enabled bool `json:"enabled,omitempty"` Mode string `json:"mode,omitempty"` Intersect bool `json:"intersect,omitempty"` Position string `json:"position,omitempty"` BackgroundColor Color `json:"backgroundColor,omitempty"` TitleFontFamily string `json:"titleFontFamily,omitempty"` TitleFontSize int `json:"titleFontSize,omitempty"` TitleFontStyle string `json:"titleFontStyle,omitempty"` TitleFontColor Color `json:"titleFontColor,omitempty"` TitleAlign string `json:"titleAlign,omitempty"` TitleSpacing int `json:"titleSpacing,omitempty"` TitleMarginBottom int `json:"titleMarginBottom,omitempty"` BodyFontFamily string `json:"bodyFontFamily,omitempty"` BodyFontSize int `json:"bodyFontSize,omitempty"` BodyFontStyle string `json:"bodyFontStyle,omitempty"` BodyFontColor Color `json:"bodyFontColor,omitempty"` BodyAlign string `json:"bodyAlign,omitempty"` BodySpacing int `json:"bodySpacing,omitempty"` FooterFontFamily string `json:"footerFontFamily,omitempty"` FooterFontSize int `json:"footerFontSize,omitempty"` FooterFontStyle string `json:"footerFontStyle,omitempty"` FooterFontColor Color `json:"footerFontColor,omitempty"` FooterAlign string `json:"footerAlign,omitempty"` FooterSpacing int `json:"footerSpacing,omitempty"` FooterMarginTop int `json:"footerMarginTop,omitempty"` XPadding int `json:"xPadding,omitempty"` YPadding int `json:"yPadding,omitempty"` CaretPadding int `json:"caretPadding,omitempty"` CaretSize int `json:"caretSize,omitempty"` CornerRadius int `json:"cornerRadius,omitempty"` MultiKeyBackground Color `json:"multiKeyBackground,omitempty"` DisplayColors bool `json:"displayColors,omitempty"` BorderColor Color `json:"borderColor,omitempty"` BorderWidth int `json:"borderWidth,omitempty"` Rtl bool `json:"rtl,omitempty"` TextDirection string `json:"textDirection,omitempty"` } type OptionElement struct { Point *OptionElementPoint `json:"point,omitempty"` Line *OptionElementLine `json:"line,omitempty"` Rectangle *OptionElementRectangle `json:"rectangle,omitempty"` Arc *OptionElementArc `json:"arc,omitempty"` } type OptionElementPoint struct { Radius int `json:"radius,omitempty"` PointStyle string `json:"pointStyle,omitempty"` Rotation int `json:"rotation,omitempty"` BackgroundColor Color `json:"backgroundColor,omitempty"` BorderWidth int `json:"borderWidth,omitempty"` BorderColor Color `json:"borderColor,omitempty"` HitRadius int `json:"hitRadius,omitempty"` HoverRadius int `json:"hoverRadius,omitempty"` HoverBorderWidth int `json:"hoverBorderWidth,omitempty"` } type OptionElementLine struct { Tension int `json:"tension,omitempty"` BackgroundColor Color `json:"background_color,omitempty"` BorderWidth int `json:"border_width,omitempty"` BorderColor Color `json:"border_color,omitempty"` BorderCapStyle string `json:"border_cap_style,omitempty"` BorderDash int `json:"border_dash,omitempty"` BorderDashOffset int `json:"border_dash_offset,omitempty"` BorderJoinStyle string `json:"border_join_style,omitempty"` CapBezierPoints bool `json:"cap_bezier_points,omitempty"` CubicInterpolationMode string `json:"cubic_interpolation_mode,omitempty"` Fill bool `json:"fill,omitempty"` Stepped bool `json:"stepped,omitempty"` } type OptionElementRectangle struct { BackgroundColor Color `json:"backgroundColor,omitempty"` BorderWidth int `json:"borderWidth,omitempty"` BorderColor Color `json:"borderColor,omitempty"` BorderSkipped string `json:"borderSkipped,omitempty"` } type OptionElementArc struct { Angle int `json:"angle,omitempty"` BackgroundColor Color `json:"backgroundColor,omitempty"` BorderAlign string `json:"borderAlign,omitempty"` BorderColor Color `json:"borderColor,omitempty"` BorderWidth int `json:"borderWidth,omitempty"` } type Options struct { Animation *OptionAnimation `json:"animation,omitempty"` Layout *OptionLayout `json:"layout,omitempty"` Legend *OptionLegend `json:"legend,omitempty"` Title *OptionTitle `json:"title,omitempty"` Tooltips *OptionTooltips `json:"tooltips,omitempty"` Elements *OptionElement `json:"elements,omitempty"` } type Attributes struct { Labels []string `json:"labels,omitempty"` } type DataSets []DataSet type DataSet struct { Label string `json:"label,omitempty"` Data []float64 `json:"data,omitempty"` Type string `json:"type,omitempty"` } type Color string func NewChart() *Chart { return &Chart{ BaseComponent: &template2.BaseComponent{ Name: "chartjs", HTMLData: List["chartjs"], }, } } func (c *Chart) GetAssetList() []string { return AssetsList } func (c *Chart) GetAsset(name string) ([]byte, error) { return Asset(name[1:]) } func (c *Chart) GetContent() template.HTML { return c.GetContentWithData(c) } ================================================ FILE: template/chartjs/chartjs.tmpl ================================================ {{define "chartjs"}} {{if ne .Title ""}}

    {{langHtml .Title}}

    {{end}}
    {{end}} ================================================ FILE: template/chartjs/line.go ================================================ package chartjs import ( "bytes" "encoding/json" "fmt" "html/template" template2 "github.com/GoAdminGroup/go-admin/template" ) type LineChart struct { *Chart JsContent LineJsContent } type LineJsContent struct { JsContent Data LineAttributes `json:"data"` } type LineAttributes struct { Attributes DataSets LineDataSets `json:"datasets"` } type LineDataSets []*LineDataSet func (l LineDataSets) Add(ds *LineDataSet) LineDataSets { return append(l, ds) } type LineDataSet struct { Label string `json:"label"` Data []float64 `json:"data"` Type string `json:"type,omitempty"` BackgroundColor Color `json:"backgroundColor,omitempty"` BorderCapStyle string `json:"borderCapStyle,omitempty"` BorderColor Color `json:"borderColor,omitempty"` BorderDash []int `json:"borderDash,omitempty"` BorderDashOffset float64 `json:"borderDashOffset,omitempty"` BorderJoinStyle string `json:"borderJoinStyle,omitempty"` BorderWidth float64 `json:"borderWidth,omitempty"` CubicInterpolationMode string `json:"cubicInterpolationMode,omitempty"` Fill bool `json:"fill"` HoverBackgroundColor Color `json:"hoverBackgroundColor,omitempty"` HoverBorderCapStyle string `json:"hoverBorderCapStyle,omitempty"` HoverBorderColor Color `json:"hoverBorderColor,omitempty"` HoverBorderDash float64 `json:"hoverBorderDash,omitempty"` HoverBorderDashOffset float64 `json:"hoverBorderDashOffset,omitempty"` HoverBorderJoinStyle string `json:"hoverBorderJoinStyle,omitempty"` HoverBorderWidth float64 `json:"hoverBorderWidth,omitempty"` LineTension float64 `json:"lineTension,omitempty"` Order float64 `json:"order,omitempty"` PointBackgroundColor Color `json:"pointBackgroundColor,omitempty"` PointBorderColor Color `json:"pointBorderColor,omitempty"` PointBorderWidth float64 `json:"pointBorderWidth,omitempty"` PointHitRadius float64 `json:"pointHitRadius,omitempty"` PointHoverBackgroundColor Color `json:"pointHoverBackgroundColor,omitempty"` PointHoverBorderColor Color `json:"pointHoverBorderColor,omitempty"` PointHoverBorderWidth float64 `json:"pointHoverBorderWidth,omitempty"` PointHoverRadius float64 `json:"pointHoverRadius,omitempty"` PointRadius float64 `json:"pointRadius,omitempty"` PointRotation float64 `json:"pointRotation,omitempty"` PointStyle string `json:"pointStyle,omitempty"` ShowLine bool `json:"showLine,omitempty"` SpanGaps bool `json:"spanGaps,omitempty"` SteppedLine bool `json:"steppedLine,omitempty"` XAxisID string `json:"xAxisID,omitempty"` YAxisID string `json:"yAxisID,omitempty"` } func (l *LineDataSet) SetLabel(label string) *LineDataSet { l.Label = label return l } func (l *LineDataSet) SetData(data []float64) *LineDataSet { l.Data = data return l } func (l *LineDataSet) SetType(t string) *LineDataSet { l.Type = t return l } func (l *LineDataSet) SetBackgroundColor(backgroundColor Color) *LineDataSet { l.BackgroundColor = backgroundColor return l } func (l *LineDataSet) SetBorderCapStyle(borderCapStyle string) *LineDataSet { l.BorderCapStyle = borderCapStyle return l } func (l *LineDataSet) SetBorderColor(borderColor Color) *LineDataSet { l.BorderColor = borderColor return l } func (l *LineDataSet) SetBorderDash(borderDash []int) *LineDataSet { l.BorderDash = borderDash return l } func (l *LineDataSet) SetBorderDashOffset(borderDashOffset float64) *LineDataSet { l.BorderDashOffset = borderDashOffset return l } func (l *LineDataSet) SetBorderJoinStyle(borderJoinStyle string) *LineDataSet { l.BorderJoinStyle = borderJoinStyle return l } func (l *LineDataSet) SetBorderWidth(borderWidth float64) *LineDataSet { l.BorderWidth = borderWidth return l } func (l *LineDataSet) SetCubicInterpolationMode(cubicInterpolationMode string) *LineDataSet { l.CubicInterpolationMode = cubicInterpolationMode return l } func (l *LineDataSet) SetFill(fill bool) *LineDataSet { l.Fill = fill return l } func (l *LineDataSet) SetHoverBackgroundColor(hoverBackgroundColor Color) *LineDataSet { l.HoverBackgroundColor = hoverBackgroundColor return l } func (l *LineDataSet) SetHoverBorderCapStyle(hoverBorderCapStyle string) *LineDataSet { l.HoverBorderCapStyle = hoverBorderCapStyle return l } func (l *LineDataSet) SetHoverBorderColor(hoverBorderColor Color) *LineDataSet { l.HoverBorderColor = hoverBorderColor return l } func (l *LineDataSet) SetHoverBorderDash(hoverBorderDash float64) *LineDataSet { l.HoverBorderDash = hoverBorderDash return l } func (l *LineDataSet) SetHoverBorderDashOffset(hoverBorderDashOffset float64) *LineDataSet { l.HoverBorderDashOffset = hoverBorderDashOffset return l } func (l *LineDataSet) SetHoverBorderJoinStyle(hoverBorderJoinStyle string) *LineDataSet { l.HoverBorderJoinStyle = hoverBorderJoinStyle return l } func (l *LineDataSet) SetHoverBorderWidth(hoverBorderWidth float64) *LineDataSet { l.HoverBorderWidth = hoverBorderWidth return l } func (l *LineDataSet) SetLineTension(lineTension float64) *LineDataSet { l.LineTension = lineTension return l } func (l *LineDataSet) SetOrder(order float64) *LineDataSet { l.Order = order return l } func (l *LineDataSet) SetPointBackgroundColor(pointBackgroundColor Color) *LineDataSet { l.PointBackgroundColor = pointBackgroundColor return l } func (l *LineDataSet) SetPointBorderColor(pointBorderColor Color) *LineDataSet { l.PointBorderColor = pointBorderColor return l } func (l *LineDataSet) SetPointBorderWidth(pointBorderWidth float64) *LineDataSet { l.PointBorderWidth = pointBorderWidth return l } func (l *LineDataSet) SetPointHitRadius(pointHitRadius float64) *LineDataSet { l.PointHitRadius = pointHitRadius return l } func (l *LineDataSet) SetPointHoverBackgroundColor(pointHoverBackgroundColor Color) *LineDataSet { l.PointHoverBackgroundColor = pointHoverBackgroundColor return l } func (l *LineDataSet) SetPointHoverBorderColor(pointHoverBorderColor Color) *LineDataSet { l.PointHoverBorderColor = pointHoverBorderColor return l } func (l *LineDataSet) SetPointHoverBorderWidth(pointHoverBorderWidth float64) *LineDataSet { l.PointHoverBorderWidth = pointHoverBorderWidth return l } func (l *LineDataSet) SetPointHoverRadius(pointHoverRadius float64) *LineDataSet { l.PointHoverRadius = pointHoverRadius return l } func (l *LineDataSet) SetPointRadius(pointRadius float64) *LineDataSet { l.PointRadius = pointRadius return l } func (l *LineDataSet) SetPointRotation(pointRotation float64) *LineDataSet { l.PointRotation = pointRotation return l } func (l *LineDataSet) SetPointStyle(pointStyle string) *LineDataSet { l.PointStyle = pointStyle return l } func (l *LineDataSet) SetShowLine(showLine bool) *LineDataSet { l.ShowLine = showLine return l } func (l *LineDataSet) SetSpanGaps(spanGaps bool) *LineDataSet { l.SpanGaps = spanGaps return l } func (l *LineDataSet) SetSteppedLine(steppedLine bool) *LineDataSet { l.SteppedLine = steppedLine return l } func (l *LineDataSet) SetXAxisID(xAxisID string) *LineDataSet { l.XAxisID = xAxisID return l } func (l *LineDataSet) SetYAxisID(yAxisID string) *LineDataSet { l.YAxisID = yAxisID return l } func Line() *LineChart { return &LineChart{ Chart: &Chart{ BaseComponent: &template2.BaseComponent{ Name: "chartjs", HTMLData: List["chartjs"], }, dataSetIndex: -1, }, JsContent: LineJsContent{ JsContent: JsContent{ Type: "line", }, Data: LineAttributes{ Attributes: Attributes{ Labels: make([]string, 0), }, DataSets: make(LineDataSets, 0), }, }, } } func (l *LineChart) SetID(s string) *LineChart { l.ID = s return l } func (l *LineChart) SetTitle(s template.HTML) *LineChart { l.Title = s return l } func (l *LineChart) SetHeight(s int) *LineChart { l.Height = s return l } func (l *LineChart) SetLabels(s []string) *LineChart { l.JsContent.Data.Labels = s return l } func (l *LineChart) AddDataSet(s string) *LineChart { l.dataSetIndex++ l.JsContent.Data.DataSets = l.JsContent.Data.DataSets.Add(&LineDataSet{ Type: "line", Label: s, }) return l } func (l *LineChart) DSLabel(s string) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetLabel(s) return l } func (l *LineChart) DSData(data []float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetData(data) return l } func (l *LineChart) DSType(t string) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetType(t) return l } func (l *LineChart) DSBackgroundColor(backgroundColor Color) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBackgroundColor(backgroundColor) return l } func (l *LineChart) DSBorderCapStyle(borderCapStyle string) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderCapStyle(borderCapStyle) return l } func (l *LineChart) DSBorderColor(borderColor Color) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderColor(borderColor) return l } func (l *LineChart) DSBorderDash(borderDash []int) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderDash(borderDash) return l } func (l *LineChart) DSBorderDashOffset(borderDashOffset float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderDashOffset(borderDashOffset) return l } func (l *LineChart) DSBorderJoinStyle(borderJoinStyle string) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderJoinStyle(borderJoinStyle) return l } func (l *LineChart) DSBorderWidth(borderWidth float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderWidth(borderWidth) return l } func (l *LineChart) DSCubicInterpolationMode(cubicInterpolationMode string) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetCubicInterpolationMode(cubicInterpolationMode) return l } func (l *LineChart) DSFill(fill bool) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetFill(fill) return l } func (l *LineChart) DSHoverBackgroundColor(hoverBackgroundColor Color) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBackgroundColor(hoverBackgroundColor) return l } func (l *LineChart) DSHoverBorderCapStyle(hoverBorderCapStyle string) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBorderCapStyle(hoverBorderCapStyle) return l } func (l *LineChart) DSHoverBorderColor(hoverBorderColor Color) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBorderColor(hoverBorderColor) return l } func (l *LineChart) DSHoverBorderDash(hoverBorderDash float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBorderDash(hoverBorderDash) return l } func (l *LineChart) DSHoverBorderDashOffset(hoverBorderDashOffset float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBorderDashOffset(hoverBorderDashOffset) return l } func (l *LineChart) DSHoverBorderJoinStyle(hoverBorderJoinStyle string) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBorderJoinStyle(hoverBorderJoinStyle) return l } func (l *LineChart) DSHoverBorderWidth(hoverBorderWidth float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBorderWidth(hoverBorderWidth) return l } func (l *LineChart) DSLineTension(lineTension float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetLineTension(lineTension) return l } func (l *LineChart) DSOrder(order float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetOrder(order) return l } func (l *LineChart) DSPointBackgroundColor(pointBackgroundColor Color) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointBackgroundColor(pointBackgroundColor) return l } func (l *LineChart) DSPointBorderColor(pointBorderColor Color) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointBorderColor(pointBorderColor) return l } func (l *LineChart) DSPointBorderWidth(pointBorderWidth float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointBorderWidth(pointBorderWidth) return l } func (l *LineChart) DSPointHitRadius(pointHitRadius float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointHitRadius(pointHitRadius) return l } func (l *LineChart) DSPointHoverBackgroundColor(pointHoverBackgroundColor Color) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointHoverBackgroundColor(pointHoverBackgroundColor) return l } func (l *LineChart) DSPointHoverBorderColor(pointHoverBorderColor Color) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointHoverBorderColor(pointHoverBorderColor) return l } func (l *LineChart) DSPointHoverBorderWidth(pointHoverBorderWidth float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointHoverBorderWidth(pointHoverBorderWidth) return l } func (l *LineChart) DSPointHoverRadius(pointHoverRadius float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointHoverRadius(pointHoverRadius) return l } func (l *LineChart) DSPointRadius(pointRadius float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointRadius(pointRadius) return l } func (l *LineChart) DSPointRotation(pointRotation float64) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointRotation(pointRotation) return l } func (l *LineChart) DSPointStyle(pointStyle string) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetPointStyle(pointStyle) return l } func (l *LineChart) DSShowLine(showLine bool) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetShowLine(showLine) return l } func (l *LineChart) DSSpanGaps(spanGaps bool) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetSpanGaps(spanGaps) return l } func (l *LineChart) DSSteppedLine(steppedLine bool) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetSteppedLine(steppedLine) return l } func (l *LineChart) DSXAxisID(xAxisID string) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetXAxisID(xAxisID) return l } func (l *LineChart) DSYAxisID(yAxisID string) *LineChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetYAxisID(yAxisID) return l } func (l *LineChart) GetContent() template.HTML { buffer := new(bytes.Buffer) tmpl, defineName := l.GetTemplate() if l.JsContentOptions != nil { l.JsContent.Options = l.JsContentOptions } jsonByte, _ := json.Marshal(l.JsContent) l.Js = template.JS(string(jsonByte)) err := tmpl.ExecuteTemplate(buffer, defineName, l) if err != nil { fmt.Println("ComposeHtml Error:", err) } return template.HTML(buffer.String()) } ================================================ FILE: template/chartjs/pie.go ================================================ package chartjs import ( "bytes" "encoding/json" "fmt" "html/template" template2 "github.com/GoAdminGroup/go-admin/template" ) type PieChart struct { *Chart JsContent PieJsContent } type PieJsContent struct { JsContent Data PieAttributes `json:"data"` } type PieAttributes struct { Attributes DataSets PieDataSets `json:"datasets"` } type PieDataSets []*PieDataSet func (l PieDataSets) Add(ds *PieDataSet) PieDataSets { return append(l, ds) } type PieDataSet struct { Label string `json:"label"` Data []float64 `json:"data"` Type string `json:"type,omitempty"` BackgroundColor []Color `json:"backgroundColor,omitempty"` BorderColor Color `json:"borderColor,omitempty"` BorderWidth float64 `json:"borderWidth,omitempty"` BorderAlign string `json:"borderAlign,omitempty"` HoverBackgroundColor Color `json:"hoverBackgroundColor,omitempty"` HoverBorderColor Color `json:"hoverBorderColor,omitempty"` HoverBorderWidth float64 `json:"hoverBorderWidth,omitempty"` Weight int `json:"weight,omitempty"` } func (l *PieDataSet) SetLabel(label string) *PieDataSet { l.Label = label return l } func (l *PieDataSet) SetData(data []float64) *PieDataSet { l.Data = data return l } func (l *PieDataSet) SetType(t string) *PieDataSet { l.Type = t return l } func (l *PieDataSet) SetBackgroundColor(backgroundColor []Color) *PieDataSet { l.BackgroundColor = backgroundColor return l } func (l *PieDataSet) SetBorderAlign(align string) *PieDataSet { l.BorderAlign = align return l } func (l *PieDataSet) SetBorderColor(borderColor Color) *PieDataSet { l.BorderColor = borderColor return l } func (l *PieDataSet) SetBorderWidth(borderWidth float64) *PieDataSet { l.BorderWidth = borderWidth return l } func (l *PieDataSet) SetWeight(weight int) *PieDataSet { l.Weight = weight return l } func (l *PieDataSet) SetHoverBackgroundColor(hoverBackgroundColor Color) *PieDataSet { l.HoverBackgroundColor = hoverBackgroundColor return l } func (l *PieDataSet) SetHoverBorderColor(hoverBorderColor Color) *PieDataSet { l.HoverBorderColor = hoverBorderColor return l } func (l *PieDataSet) SetHoverBorderWidth(hoverBorderWidth float64) *PieDataSet { l.HoverBorderWidth = hoverBorderWidth return l } func Pie() *PieChart { return &PieChart{ Chart: &Chart{ BaseComponent: &template2.BaseComponent{ Name: "chartjs", HTMLData: List["chartjs"], }, dataSetIndex: -1, }, JsContent: PieJsContent{ JsContent: JsContent{ Type: "pie", }, Data: PieAttributes{ Attributes: Attributes{ Labels: make([]string, 0), }, DataSets: make(PieDataSets, 0), }, }, } } func (l *PieChart) SetID(s string) *PieChart { l.ID = s return l } func (l *PieChart) SetTitle(s template.HTML) *PieChart { l.Title = s return l } func (l *PieChart) SetHeight(s int) *PieChart { l.Height = s return l } func (l *PieChart) SetLabels(s []string) *PieChart { l.JsContent.Data.Labels = s return l } func (l *PieChart) AddDataSet(s string) *PieChart { l.dataSetIndex++ l.JsContent.Data.DataSets = l.JsContent.Data.DataSets.Add(&PieDataSet{ Type: "pie", Label: s, }) return l } func (l *PieChart) DSLabel(s string) *PieChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetLabel(s) return l } func (l *PieChart) DSData(data []float64) *PieChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetData(data) return l } func (l *PieChart) DSType(t string) *PieChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetType(t) return l } func (l *PieChart) DSBackgroundColor(backgroundColor []Color) *PieChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBackgroundColor(backgroundColor) return l } func (l *PieChart) DSBorderColor(borderColor Color) *PieChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderColor(borderColor) return l } func (l *PieChart) DSBorderWidth(borderWidth float64) *PieChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetBorderWidth(borderWidth) return l } func (l *PieChart) DSWeight(weight int) *PieChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetWeight(weight) return l } func (l *PieChart) DSHoverBackgroundColor(hoverBackgroundColor Color) *PieChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBackgroundColor(hoverBackgroundColor) return l } func (l *PieChart) DSHoverBorderColor(hoverBorderColor Color) *PieChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBorderColor(hoverBorderColor) return l } func (l *PieChart) DSHoverBorderWidth(hoverBorderWidth float64) *PieChart { l.JsContent.Data.DataSets[l.dataSetIndex].SetHoverBorderWidth(hoverBorderWidth) return l } func (l *PieChart) GetContent() template.HTML { buffer := new(bytes.Buffer) tmpl, defineName := l.GetTemplate() if l.JsContentOptions != nil { l.JsContent.Options = l.JsContentOptions } jsonByte, _ := json.Marshal(l.JsContent) l.Js = template.JS(string(jsonByte)) err := tmpl.ExecuteTemplate(buffer, defineName, l) if err != nil { fmt.Println("ComposeHtml Error:", err) } return template.HTML(buffer.String()) } ================================================ FILE: template/chartjs/radar.go ================================================ package chartjs ================================================ FILE: template/chartjs/template.go ================================================ package chartjs var List = map[string]string{ "chartjs": `{{define "chartjs"}} {{if ne .Title ""}}

    {{langHtml .Title}}

    {{end}}
    {{end}}`, } ================================================ FILE: template/color/color.go ================================================ package color const ( IndianRed = "#CD5C5C" LightCoral = "#F08080" Salmon = "#FA8072" DarkSalmon = "#E9967A" LightSalmon = "#FFA07A" Crimson = "#DC143C" Red = "#FF0000" FireBrick = "#B22222" DarkRed = "#8B0000" Cornsilk = "#FFF8DC" BlanchedAlmond = "#FFEBCD" Bisque = "#FFE4C4" NavajoWhite = "#FFDEAD" Wheat = "#F5DEB3" BurlyWood = "#DEB887" Tan = "#D2B48C" RosyBrown = "#BC8F8F" SandyBrown = "#F4A460" Goldenrod = "#DAA520" DarkGoldenrod = "#B8860B" Peru = "#CD853F" Chocolate = "#D2691E" SaddleBrown = "#8B4513" Sienna = "#A0522D" Brown = "#A52A2A" Maroon = "#800000" Pink = "#FFC0CB" LightPink = "#FFB6C1" HotPink = "#FF69B4" DeepPink = "#FF1493" MediumVioletRed = "#C71585" PaleVioletRed = "#DB7093" GreenYellow = "#ADFF2F" Chartreuse = "#7FFF00" LawnGreen = "#7CFC00" Lime = "#00FF00" LimeGreen = "#32CD32" PaleGreen = "#98FB98" LightGreen = "#90EE90" MediumSpringGreen = "#00FA9A" SpringGreen = "#00FF7F" MediumSeaGreen = "#3CB371" SeaGreen = "#2E8B57" ForestGreen = "#228B22" Green = "#008000" DarkGreen = "#006400" YellowGreen = "#9ACD32" OliveDrab = "#6B8E23" Olive = "#808000" DarkOliveGreen = "#556B2F" MediumAquamarine = "#66CDAA" DarkSeaGreen = "#8FBC8F" LightSeaGreen = "#20B2AA" DarkCyan = "#008B8B" Teal = "#008080" Coral = "#FF7F50" Tomato = "#FF6347" OrangeRed = "#FF4500" DarkOrange = "#FF8C00" Orange = "#FFA500" White = "#FFFFFF" Snow = "#FFFAFA" Honeydew = "#F0FFF0" MintCream = "#F5FFFA" Azure = "#F0FFFF" AliceBlue = "#F0F8FF" GhostWhite = "#F8F8FF" WhiteSmoke = "#F5F5F5" Seashell = "#FFF5EE" Beige = "#F5F5DC" OldLace = "#FDF5E6" FloralWhite = "#FFFAF0" Ivory = "#FFFFF0" AntiqueWhite = "#FAEBD7" Linen = "#FAF0E6" LavenderBlush = "#FFF0F5" MistyRose = "#FFE4E1" Gold = "#FFD700" Yellow = "#FFFF00" LightYellow = "#FFFFE0" LemonChiffon = "#FFFACD" LightGoldenrodYellow = "#FAFAD2" PapayaWhip = "#FFEFD5" Moccasin = "#FFE4B5" PeachPuff = "#FFDAB9" PaleGoldenrod = "#EEE8AA" Khaki = "#F0E68C" DarkKhaki = "#BDB76B" Gainsboro = "#DCDCDC" LightGrey = "#D3D3D3" Silver = "#C0C0C0" DarkGray = "#A9A9A9" Gray = "#808080" DimGray = "#696969" LightSlateGray = "#778899" SlateGray = "#708090" DarkSlateGray = "#2F4F4F" Black = "#000000" Aqua = "#00FFFF" Cyan = "#00FFFF" LightCyan = "#E0FFFF" PaleTurquoise = "#AFEEEE" Aquamarine = "#7FFFD4" Turquoise = "#40E0D0" MediumTurquoise = "#48D1CC" DarkTurquoise = "#00CED1" CadetBlue = "#5F9EA0" SteelBlue = "#4682B4" LightSteelBlue = "#B0C4DE" PowderBlue = "#B0E0E6" LightBlue = "#ADD8E6" SkyBlue = "#87CEEB" LightSkyBlue = "#87CEFA" DeepSkyBlue = "#00BFFF" DodgerBlue = "#1E90FF" CornflowerBlue = "#6495ED" MediumSlateBlue = "#7B68EE" RoyalBlue = "#4169E1" Blue = "#0000FF" MediumBlue = "#0000CD" DarkBlue = "#00008B" Navy = "#000080" MidnightBlue = "#191970" Lavender = "#E6E6FA" Thistle = "#D8BFD8" Plum = "#DDA0DD" Violet = "#EE82EE" Orchid = "#DA70D6" Fuchsia = "#FF00FF" Magenta = "#FF00FF" MediumOrchid = "#BA55D3" MediumPurple = "#9370DB" Amethyst = "#9966CC" BlueViolet = "#8A2BE2" DarkViolet = "#9400D3" DarkOrchid = "#9932CC" DarkMagenta = "#8B008B" Purple = "#800080" Indigo = "#4B0082" SlateBlue = "#6A5ACD" DarkSlateBlue = "#483D8B" ) ================================================ FILE: template/components/alert.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/template/types" ) type AlertAttribute struct { Name string Theme string Title template.HTML Content template.HTML types.Attribute } func (compo *AlertAttribute) SetTheme(value string) types.AlertAttribute { compo.Theme = value return compo } func (compo *AlertAttribute) SetTitle(value template.HTML) types.AlertAttribute { compo.Title = value return compo } func (compo *AlertAttribute) SetContent(value template.HTML) types.AlertAttribute { compo.Content = value return compo } func (compo *AlertAttribute) Warning(msg string) template.HTML { return compo.SetTitle(errors.MsgWithIcon). SetTheme("warning"). SetContent(language.GetFromHtml(template.HTML(msg))). GetContent() } func (compo *AlertAttribute) GetContent() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "alert") } ================================================ FILE: template/components/base.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/menu" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/form" ) type Base struct { Attribute types.Attribute } func (b Base) Box() types.BoxAttribute { return &BoxAttribute{ Name: "box", Header: template.HTML(""), Body: template.HTML(""), Footer: template.HTML(""), Title: "", HeadBorder: "", Attribute: b.Attribute, } } func (b Base) Col() types.ColAttribute { return &ColAttribute{ Name: "col", Size: "col-md-2", Content: "", Attribute: b.Attribute, } } func (b Base) Form() types.FormAttribute { return &FormAttribute{ Name: "form", Content: []types.FormField{}, Url: "/", Method: "post", HiddenFields: make(map[string]string), Layout: form.LayoutDefault, Title: "edit", Attribute: b.Attribute, CdnUrl: config.GetAssetUrl(), HeadWidth: 2, InputWidth: 8, } } func (b Base) Image() types.ImgAttribute { return &ImgAttribute{ Name: "image", Width: "50", Height: "50", Src: "", Attribute: b.Attribute, } } func (b Base) Tabs() types.TabsAttribute { return &TabsAttribute{ Name: "tabs", Attribute: b.Attribute, } } func (b Base) Alert() types.AlertAttribute { return &AlertAttribute{ Name: "alert", Attribute: b.Attribute, } } func (b Base) Label() types.LabelAttribute { return &LabelAttribute{ Name: "label", Type: "", Content: "", Attribute: b.Attribute, } } func (b Base) Link() types.LinkAttribute { return &LinkAttribute{ Name: "link", Content: "", Attribute: b.Attribute, } } func (b Base) Popup() types.PopupAttribute { return &PopupAttribute{ Name: "popup", Attribute: b.Attribute, } } func (b Base) Paginator() types.PaginatorAttribute { return &PaginatorAttribute{ Name: "paginator", Attribute: b.Attribute, } } func (b Base) Row() types.RowAttribute { return &RowAttribute{ Name: "row", Content: "", Attribute: b.Attribute, } } func (b Base) Button() types.ButtonAttribute { return &ButtonAttribute{ Name: "button", Attribute: b.Attribute, } } func (b Base) Table() types.TableAttribute { return &TableAttribute{ Name: "table", Thead: make(types.Thead, 0), InfoList: make([]map[string]types.InfoItem, 0), Type: "table", Style: "hover", Layout: "auto", Attribute: b.Attribute, } } func (b Base) DataTable() types.DataTableAttribute { return &DataTableAttribute{ TableAttribute: *(b.Table(). SetStyle("hover"). SetName("data-table"). SetType("data-table").(*TableAttribute)), Attribute: b.Attribute, } } func (b Base) Tree() types.TreeAttribute { return &TreeAttribute{ Name: "tree", Tree: make([]menu.Item, 0), Attribute: b.Attribute, } } func (b Base) TreeView() types.TreeViewAttribute { return &TreeViewAttribute{ Name: "treeview", Attribute: b.Attribute, } } ================================================ FILE: template/components/box.go ================================================ package components import ( "fmt" "html/template" "github.com/GoAdminGroup/go-admin/template/types" ) type BoxAttribute struct { Name string Header template.HTML Body template.HTML Footer template.HTML Title template.HTML Theme string HeadBorder string Attr template.HTMLAttr HeadColor string Class string SecondHeaderClass string SecondHeader template.HTML SecondHeadBorder string SecondHeadColor string Style template.HTMLAttr Padding string types.Attribute } func (compo *BoxAttribute) SetTheme(value string) types.BoxAttribute { compo.Theme = value return compo } func (compo *BoxAttribute) SetClass(value string) types.BoxAttribute { compo.Class = value return compo } func (compo *BoxAttribute) SetHeader(value template.HTML) types.BoxAttribute { compo.Header = value return compo } func (compo *BoxAttribute) SetBody(value template.HTML) types.BoxAttribute { compo.Body = value return compo } func (compo *BoxAttribute) SetStyle(value template.HTMLAttr) types.BoxAttribute { compo.Style = value return compo } func (compo *BoxAttribute) SetAttr(attr template.HTMLAttr) types.BoxAttribute { compo.Attr = attr return compo } func (compo *BoxAttribute) SetIframeStyle(iframe bool) types.BoxAttribute { if iframe { compo.Attr = `style="border-radius: 0px;box-shadow:none;border-top:none;margin-bottom: 0px;"` } return compo } func (compo *BoxAttribute) SetFooter(value template.HTML) types.BoxAttribute { compo.Footer = value return compo } func (compo *BoxAttribute) SetTitle(value template.HTML) types.BoxAttribute { compo.Title = value return compo } func (compo *BoxAttribute) SetHeadColor(value string) types.BoxAttribute { compo.HeadColor = value return compo } func (compo *BoxAttribute) WithHeadBorder() types.BoxAttribute { compo.HeadBorder = "with-border" return compo } func (compo *BoxAttribute) SetSecondHeader(value template.HTML) types.BoxAttribute { compo.SecondHeader = value return compo } func (compo *BoxAttribute) SetSecondHeadColor(value string) types.BoxAttribute { compo.SecondHeadColor = value return compo } func (compo *BoxAttribute) SetSecondHeaderClass(value string) types.BoxAttribute { compo.SecondHeaderClass = value return compo } func (compo *BoxAttribute) SetNoPadding() types.BoxAttribute { compo.Padding = "padding:0;" return compo } func (compo *BoxAttribute) WithSecondHeadBorder() types.BoxAttribute { compo.SecondHeadBorder = "with-border" return compo } func (compo *BoxAttribute) GetContent() template.HTML { if compo.Style == "" { compo.Style = template.HTMLAttr(fmt.Sprintf(`style="%s"`, compo.Padding)) } else { compo.Style = template.HTMLAttr(fmt.Sprintf(`style="%s"`, string(compo.Style)+compo.Padding)) } return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "box") } ================================================ FILE: template/components/button.go ================================================ package components import ( "fmt" "html/template" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/template/icon" "github.com/GoAdminGroup/go-admin/template/types" ) type ButtonAttribute struct { Name string Content template.HTML Orientation string LoadingText template.HTML Theme string Type string Size string Href string Class string ID string Style template.HTMLAttr MarginLeft int MarginRight int types.Attribute } func (compo *ButtonAttribute) SetContent(value template.HTML) types.ButtonAttribute { compo.Content = value return compo } func (compo *ButtonAttribute) SetOrientationRight() types.ButtonAttribute { compo.Orientation = "pull-right" return compo } func (compo *ButtonAttribute) SetOrientationLeft() types.ButtonAttribute { compo.Orientation = "pull-left" return compo } func (compo *ButtonAttribute) SetMarginLeft(px int) types.ButtonAttribute { compo.MarginLeft = px return compo } func (compo *ButtonAttribute) SetSmallSize() types.ButtonAttribute { compo.Size = "btn-sm" return compo } func (compo *ButtonAttribute) SetMiddleSize() types.ButtonAttribute { compo.Size = "btn-md" return compo } func (compo *ButtonAttribute) SetMarginRight(px int) types.ButtonAttribute { compo.MarginRight = px return compo } func (compo *ButtonAttribute) SetLoadingText(value template.HTML) types.ButtonAttribute { compo.LoadingText = value return compo } func (compo *ButtonAttribute) SetThemePrimary() types.ButtonAttribute { compo.Theme = "primary" return compo } func (compo *ButtonAttribute) SetThemeDefault() types.ButtonAttribute { compo.Theme = "default" return compo } func (compo *ButtonAttribute) SetThemeWarning() types.ButtonAttribute { compo.Theme = "warning" return compo } func (compo *ButtonAttribute) SetHref(href string) types.ButtonAttribute { compo.Href = href return compo } func (compo *ButtonAttribute) AddClass(class string) types.ButtonAttribute { compo.Class += " " + class return compo } func (compo *ButtonAttribute) SetID(id string) types.ButtonAttribute { compo.ID = id return compo } func (compo *ButtonAttribute) SetTheme(value string) types.ButtonAttribute { compo.Theme = value return compo } func (compo *ButtonAttribute) SetType(value string) types.ButtonAttribute { compo.Type = value return compo } func (compo *ButtonAttribute) GetContent() template.HTML { if compo.MarginLeft != 0 { compo.Style = template.HTMLAttr(fmt.Sprintf(`style="margin-left:%dpx;"`, compo.MarginLeft)) } if compo.MarginRight != 0 { compo.Style = template.HTMLAttr(fmt.Sprintf(`style="margin-right:%dpx;"`, compo.MarginRight)) } if compo.LoadingText == "" { compo.LoadingText = icon.Icon(icon.Spinner, 1) + language.GetFromHtml(`Save`) } if compo.ID == "" { compo.ID = utils.Uuid(15) + "_btn" } return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "button") } ================================================ FILE: template/components/col.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/template/types" ) type ColAttribute struct { Name string Content template.HTML Size string types.Attribute } func (compo *ColAttribute) SetContent(value template.HTML) types.ColAttribute { compo.Content = value return compo } func (compo *ColAttribute) AddContent(value template.HTML) types.ColAttribute { compo.Content += value return compo } func (compo *ColAttribute) SetSize(value types.S) types.ColAttribute { compo.Size = "" for key, size := range value { compo.Size += "col-" + key + "-" + size + " " } return compo } func (compo *ColAttribute) GetContent() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "col") } ================================================ FILE: template/components/composer.go ================================================ package components import ( "bytes" "html/template" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/utils" template2 "github.com/GoAdminGroup/go-admin/template" ) func ComposeHtml(temList map[string]string, separation bool, compo interface{}, templateName ...string) template.HTML { tmplName := "" if len(templateName) > 0 { tmplName = templateName[0] + " " } var ( tmpl *template.Template err error ) if separation { files := make([]string, 0) root := config.GetAssetRootPath() + "pages/" for _, v := range templateName { files = append(files, root+temList["components/"+v]+".tmpl") } tmpl, err = template.New("comp").Funcs(template2.DefaultFuncMap).ParseFiles(files...) } else { var text = "" for _, v := range templateName { text += temList["components/"+v] } tmpl, err = template.New("comp").Funcs(template2.DefaultFuncMap).Parse(text) } if err != nil { logger.Panic(tmplName + "ComposeHtml Error:" + err.Error()) return "" } buf := new(bytes.Buffer) defineName := utils.ReplaceAll(templateName[0], "table/", "", "form/", "") err = tmpl.ExecuteTemplate(buf, defineName, compo) if err != nil { logger.Error(tmplName+" ComposeHtml Error:", err) } return template.HTML(buf.String()) } ================================================ FILE: template/components/form.go ================================================ package components import ( "fmt" "html/template" "strings" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/utils" form2 "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/template/types/form" ) type FormAttribute struct { Name string Id string Header template.HTML Content types.FormFields ContentList []types.FormFields Layout form.Layout TabContents []types.FormFields TabHeaders []string Footer template.HTML Url string FieldsHTML template.HTML Method string PrimaryKey string Ajax bool AjaxSuccessJS template.JS AjaxErrorJS template.JS HeadWidth int InputWidth int HiddenFields map[string]string Title template.HTML OperationFooter template.HTML Prefix string CdnUrl string Horizontal bool types.Attribute } func (compo *FormAttribute) SetHeader(value template.HTML) types.FormAttribute { compo.Header = value return compo } func (compo *FormAttribute) SetPrimaryKey(value string) types.FormAttribute { compo.PrimaryKey = value return compo } func (compo *FormAttribute) SetHorizontal(value bool) types.FormAttribute { compo.Horizontal = value return compo } func (compo *FormAttribute) SetContent(value types.FormFields) types.FormAttribute { compo.Content = value return compo } func (compo *FormAttribute) SetId(id string) types.FormAttribute { compo.Id = id return compo } func (compo *FormAttribute) SetAjax(successJS, errorJS template.JS) types.FormAttribute { if successJS != template.JS("") && errorJS != template.JS("") { compo.Ajax = true compo.AjaxErrorJS = errorJS compo.AjaxSuccessJS = successJS } return compo } func (compo *FormAttribute) SetTabContents(value []types.FormFields) types.FormAttribute { compo.TabContents = value return compo } func (compo *FormAttribute) SetTabHeaders(value []string) types.FormAttribute { compo.TabHeaders = value return compo } func (compo *FormAttribute) SetHeadWidth(width int) types.FormAttribute { if width > 0 { if width > 12 { width = 12 } compo.HeadWidth = width } return compo } func (compo *FormAttribute) SetInputWidth(width int) types.FormAttribute { if width > 0 { if width > 12 { width = 12 } compo.InputWidth = width } return compo } func (compo *FormAttribute) SetFieldsHTML(html template.HTML) types.FormAttribute { compo.FieldsHTML = html return compo } func (compo *FormAttribute) SetFooter(value template.HTML) types.FormAttribute { compo.Footer = value return compo } func (compo *FormAttribute) SetLayout(layout form.Layout) types.FormAttribute { compo.Layout = layout return compo } func (compo *FormAttribute) SetPrefix(value string) types.FormAttribute { compo.Prefix = value return compo } func (compo *FormAttribute) SetUrl(value string) types.FormAttribute { compo.Url = value return compo } func (compo *FormAttribute) SetHiddenFields(fields map[string]string) types.FormAttribute { compo.HiddenFields = fields return compo } func (compo *FormAttribute) SetMethod(value string) types.FormAttribute { compo.Method = value return compo } func (compo *FormAttribute) SetTitle(value template.HTML) types.FormAttribute { compo.Title = value return compo } func (compo *FormAttribute) GetDefaultBoxHeader(hideBack bool) template.HTML { if hideBack { return template.HTML(fmt.Sprintf(`

    %s

    `, language.GetFromHtml(compo.Title))) } return template.HTML(fmt.Sprintf(`

    %s

    `, language.GetFromHtml(compo.Title), compo.HiddenFields[form2.PreviousKey], language.Get("Back"))) } func (compo *FormAttribute) GetDetailBoxHeader(editUrl, deleteUrl string) template.HTML { var ( editBtn string deleteBtn string ) if editUrl != "" { editBtn = fmt.Sprintf(` `, editUrl, language.Get("Edit")) } if deleteUrl != "" { deleteBtn = fmt.Sprintf(` `, language.Get("Delete")) } return template.HTML(`

    `) + language.GetFromHtml(compo.Title) + template.HTML(`

    `+deleteBtn+editBtn+`
    `) } func (compo *FormAttribute) GetBoxHeaderNoButton() template.HTML { return template.HTML(fmt.Sprintf(`

    %s

    `, language.GetFromHtml(compo.Title))) } func (compo *FormAttribute) SetOperationFooter(value template.HTML) types.FormAttribute { compo.OperationFooter = value return compo } func (compo *FormAttribute) GetContent() template.HTML { compo.CdnUrl = config.GetAssetUrl() if compo.Id == "" { compo.Id = utils.Uuid(10) } if col := compo.Layout.Col(); col > 0 { compo.ContentList = make([]types.FormFields, col) index := 0 for i := 0; i < len(compo.Content); i++ { ii := index % col compo.ContentList[ii] = append(compo.ContentList[ii], compo.Content[i]) if i < len(compo.Content)-1 { if strings.Contains(compo.Content[i+1].Field, "__goadmin_operator__") { compo.ContentList[ii] = append(compo.ContentList[ii], compo.Content[i+1]) i++ } } index++ } } return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "form", "form/default", "form/file", "form/multi_file", "form/textarea", "form/custom", "form/rate", "form/slider", "form/selectbox", "form/text", "form/table", "form/radio", "form/switch", "form/checkbox", "form/checkbox_single", "form/checkbox_stacked", "form/password", "form/code", "form/array", "form/select", "form/singleselect", "form/richtext", "form/iconpicker", "form/datetime", "form/number", "form/number_range", "form/email", "form/url", "form/ip", "form/color", "form/currency", "form_components", "form/datetime_range", "form_layout_default", "form_layout_two_col", "form_layout_tab", "form_components_layout", "form_layout_flow", "form_layout_filter") } ================================================ FILE: template/components/image.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/plugins/admin/modules" "github.com/GoAdminGroup/go-admin/template/types" ) type ImgAttribute struct { Name string Width string Height string Uuid string HasModal bool Src template.URL types.Attribute } func (compo *ImgAttribute) SetWidth(value string) types.ImgAttribute { compo.Width = value return compo } func (compo *ImgAttribute) SetHeight(value string) types.ImgAttribute { compo.Height = value return compo } func (compo *ImgAttribute) WithModal() types.ImgAttribute { compo.HasModal = true compo.Uuid = modules.Uuid() return compo } func (compo *ImgAttribute) SetSrc(value template.HTML) types.ImgAttribute { compo.Src = template.URL(value) return compo } func (compo *ImgAttribute) GetContent() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "image") } ================================================ FILE: template/components/label.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/template/types" ) type LabelAttribute struct { Name string Color template.HTML Type string Content template.HTML types.Attribute } func (compo *LabelAttribute) SetType(value string) types.LabelAttribute { compo.Type = value return compo } func (compo *LabelAttribute) SetColor(value template.HTML) types.LabelAttribute { compo.Color = value return compo } func (compo *LabelAttribute) SetContent(value template.HTML) types.LabelAttribute { compo.Content = value return compo } func (compo *LabelAttribute) GetContent() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "label") } ================================================ FILE: template/components/link.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/template/types" ) type LinkAttribute struct { Name string URL string Class template.HTML Title template.HTML Attributes template.HTMLAttr Content template.HTML types.Attribute } func (compo *LinkAttribute) OpenInNewTab() types.LinkAttribute { compo.Class += " new-tab-link" return compo } func (compo *LinkAttribute) SetURL(value string) types.LinkAttribute { compo.URL = value return compo } func (compo *LinkAttribute) SetClass(class template.HTML) types.LinkAttribute { compo.Class = class return compo } func (compo *LinkAttribute) SetAttributes(attr template.HTMLAttr) types.LinkAttribute { compo.Attributes = attr return compo } func (compo *LinkAttribute) NoPjax() types.LinkAttribute { compo.Class += " no-pjax" return compo } func (compo *LinkAttribute) SetTabTitle(value template.HTML) types.LinkAttribute { compo.Title = value return compo } func (compo *LinkAttribute) SetContent(value template.HTML) types.LinkAttribute { compo.Content = value return compo } func (compo *LinkAttribute) GetContent() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "link") } ================================================ FILE: template/components/paninator.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/template/types" ) type PaginatorAttribute struct { Name string CurPageStartIndex string CurPageEndIndex string Total string PreviousClass string PreviousUrl string Pages []map[string]string NextClass string NextUrl string PageSizeList []string Option map[string]template.HTML Url string ExtraInfo template.HTML EntriesInfo template.HTML types.Attribute } func (compo *PaginatorAttribute) SetCurPageStartIndex(value string) types.PaginatorAttribute { compo.CurPageStartIndex = value return compo } func (compo *PaginatorAttribute) SetCurPageEndIndex(value string) types.PaginatorAttribute { compo.CurPageEndIndex = value return compo } func (compo *PaginatorAttribute) SetTotal(value string) types.PaginatorAttribute { compo.Total = value return compo } func (compo *PaginatorAttribute) SetExtraInfo(value template.HTML) types.PaginatorAttribute { compo.ExtraInfo = value return compo } func (compo *PaginatorAttribute) SetEntriesInfo(value template.HTML) types.PaginatorAttribute { compo.EntriesInfo = value return compo } func (compo *PaginatorAttribute) SetPreviousClass(value string) types.PaginatorAttribute { compo.PreviousClass = value return compo } func (compo *PaginatorAttribute) SetPreviousUrl(value string) types.PaginatorAttribute { compo.PreviousUrl = value return compo } func (compo *PaginatorAttribute) SetPages(value []map[string]string) types.PaginatorAttribute { compo.Pages = value return compo } func (compo *PaginatorAttribute) SetPageSizeList(value []string) types.PaginatorAttribute { compo.PageSizeList = value return compo } func (compo *PaginatorAttribute) SetNextClass(value string) types.PaginatorAttribute { compo.NextClass = value return compo } func (compo *PaginatorAttribute) SetNextUrl(value string) types.PaginatorAttribute { compo.NextUrl = value return compo } func (compo *PaginatorAttribute) SetOption(value map[string]template.HTML) types.PaginatorAttribute { compo.Option = value return compo } func (compo *PaginatorAttribute) SetUrl(value string) types.PaginatorAttribute { compo.Url = value return compo } func (compo *PaginatorAttribute) GetContent() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "paginator") } ================================================ FILE: template/components/popup.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/template/types" ) type PopupAttribute struct { Name string ID string Body template.HTML Footer template.HTML FooterHTML template.HTML Title template.HTML Size string HideFooter bool Height string Width string Draggable bool types.Attribute } func (compo *PopupAttribute) SetID(value string) types.PopupAttribute { compo.ID = value return compo } func (compo *PopupAttribute) SetTitle(value template.HTML) types.PopupAttribute { compo.Title = value return compo } func (compo *PopupAttribute) SetFooter(value template.HTML) types.PopupAttribute { compo.Footer = value return compo } func (compo *PopupAttribute) SetFooterHTML(value template.HTML) types.PopupAttribute { compo.FooterHTML = value return compo } func (compo *PopupAttribute) SetWidth(width string) types.PopupAttribute { compo.Width = width return compo } func (compo *PopupAttribute) SetHeight(height string) types.PopupAttribute { compo.Height = height return compo } func (compo *PopupAttribute) SetDraggable() types.PopupAttribute { compo.Draggable = true return compo } func (compo *PopupAttribute) SetHideFooter() types.PopupAttribute { compo.HideFooter = true return compo } func (compo *PopupAttribute) SetBody(value template.HTML) types.PopupAttribute { compo.Body = value return compo } func (compo *PopupAttribute) SetSize(value string) types.PopupAttribute { compo.Size = value return compo } func (compo *PopupAttribute) GetContent() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "popup") } ================================================ FILE: template/components/product.go ================================================ package components ================================================ FILE: template/components/row.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/template/types" ) type RowAttribute struct { Name string Content template.HTML types.Attribute } func (compo *RowAttribute) SetContent(value template.HTML) types.RowAttribute { compo.Content = value return compo } func (compo *RowAttribute) AddContent(value template.HTML) types.RowAttribute { compo.Content += value return compo } func (compo *RowAttribute) GetContent() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "row") } ================================================ FILE: template/components/table.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/template/types" ) type TableAttribute struct { Name string Thead types.Thead InfoList []map[string]types.InfoItem Type string PrimaryKey string Style string Class string HideThead bool NoAction bool Action template.HTML EditUrl string MinWidth string DeleteUrl string DetailUrl string SortUrl string UpdateUrl string Layout string IsTab bool ExportUrl string ActionFold bool types.Attribute } func (compo *TableAttribute) SetThead(value types.Thead) types.TableAttribute { compo.Thead = value return compo } func (compo *TableAttribute) SetInfoList(value []map[string]types.InfoItem) types.TableAttribute { compo.InfoList = value return compo } func (compo *TableAttribute) SetType(value string) types.TableAttribute { compo.Type = value return compo } func (compo *TableAttribute) SetName(name string) types.TableAttribute { compo.Name = name return compo } func (compo *TableAttribute) SetHideThead() types.TableAttribute { compo.HideThead = true return compo } func (compo *TableAttribute) SetStyle(style string) types.TableAttribute { compo.Style = style return compo } func (compo *TableAttribute) SetSticky(sticky bool) types.TableAttribute { if sticky { compo.Class = "sticky_table" } return compo } func (compo *TableAttribute) SetMinWidth(value string) types.TableAttribute { compo.MinWidth = value return compo } func (compo *TableAttribute) SetLayout(value string) types.TableAttribute { compo.Layout = value return compo } func (compo *TableAttribute) GetContent() template.HTML { if compo.MinWidth == "" { compo.MinWidth = "1000px" } return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "table") } type DataTableAttribute struct { TableAttribute EditUrl string NewUrl string UpdateUrl string Class string HideThead bool DetailUrl string SortUrl template.URL DeleteUrl string PrimaryKey string IsTab bool ExportUrl string InfoUrl string Buttons template.HTML ActionJs template.JS IsHideFilterArea bool IsHideRowSelector bool NoAction bool HasFilter bool Action template.HTML ActionFold bool types.Attribute } func (compo *DataTableAttribute) GetDataTableHeader() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "table/box-header") } func (compo *DataTableAttribute) SetThead(value types.Thead) types.DataTableAttribute { compo.Thead = value return compo } func (compo *DataTableAttribute) SetSticky(sticky bool) types.DataTableAttribute { if sticky { compo.Class = "sticky_table" } return compo } func (compo *DataTableAttribute) SetLayout(value string) types.DataTableAttribute { compo.Layout = value return compo } func (compo *DataTableAttribute) SetIsTab(value bool) types.DataTableAttribute { compo.IsTab = value return compo } func (compo *DataTableAttribute) SetHideThead() types.DataTableAttribute { compo.HideThead = true return compo } func (compo *DataTableAttribute) SetButtons(btns template.HTML) types.DataTableAttribute { compo.Buttons = btns return compo } func (compo *DataTableAttribute) SetHideFilterArea(value bool) types.DataTableAttribute { compo.IsHideFilterArea = value return compo } func (compo *DataTableAttribute) SetActionJs(aj template.JS) types.DataTableAttribute { compo.ActionJs = aj return compo } func (compo *DataTableAttribute) SetActionFold(fold bool) types.DataTableAttribute { compo.ActionFold = fold return compo } func (compo *DataTableAttribute) SetHasFilter(hasFilter bool) types.DataTableAttribute { compo.HasFilter = hasFilter return compo } func (compo *DataTableAttribute) SetInfoUrl(value string) types.DataTableAttribute { compo.InfoUrl = value return compo } func (compo *DataTableAttribute) SetAction(action template.HTML) types.DataTableAttribute { compo.Action = action return compo } func (compo *DataTableAttribute) SetStyle(style string) types.DataTableAttribute { compo.Style = style return compo } func (compo *DataTableAttribute) SetExportUrl(value string) types.DataTableAttribute { compo.ExportUrl = value return compo } func (compo *DataTableAttribute) SetHideRowSelector(value bool) types.DataTableAttribute { compo.IsHideRowSelector = value return compo } func (compo *DataTableAttribute) SetUpdateUrl(value string) types.DataTableAttribute { compo.UpdateUrl = value return compo } func (compo *DataTableAttribute) SetDetailUrl(value string) types.DataTableAttribute { compo.DetailUrl = value return compo } func (compo *DataTableAttribute) SetSortUrl(value string) types.DataTableAttribute { compo.SortUrl = template.URL(value) return compo } func (compo *DataTableAttribute) SetPrimaryKey(value string) types.DataTableAttribute { compo.PrimaryKey = value return compo } func (compo *DataTableAttribute) SetInfoList(value []map[string]types.InfoItem) types.DataTableAttribute { compo.InfoList = value return compo } func (compo *DataTableAttribute) SetEditUrl(value string) types.DataTableAttribute { compo.EditUrl = value return compo } func (compo *DataTableAttribute) SetDeleteUrl(value string) types.DataTableAttribute { compo.DeleteUrl = value return compo } func (compo *DataTableAttribute) SetNewUrl(value string) types.DataTableAttribute { compo.NewUrl = value return compo } func (compo *DataTableAttribute) SetNoAction() types.DataTableAttribute { compo.NoAction = true return compo } func (compo *DataTableAttribute) GetContent() template.HTML { if compo.MinWidth == "" { compo.MinWidth = "1600px" } if !compo.NoAction && compo.EditUrl == "" && compo.DeleteUrl == "" && compo.DetailUrl == "" && compo.Action == "" { compo.NoAction = true } return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "table") } ================================================ FILE: template/components/tabs.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/template/types" ) type TabsAttribute struct { Name string Data []map[string]template.HTML types.Attribute } func (compo *TabsAttribute) SetData(value []map[string]template.HTML) types.TabsAttribute { compo.Data = value return compo } func (compo *TabsAttribute) GetContent() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "tabs") } ================================================ FILE: template/components/tree.go ================================================ package components import ( "html/template" "github.com/GoAdminGroup/go-admin/modules/menu" "github.com/GoAdminGroup/go-admin/template/types" ) type TreeAttribute struct { Name string Tree []menu.Item EditUrl string DeleteUrl string UrlPrefix string OrderUrl string types.Attribute } func (compo *TreeAttribute) SetTree(value []menu.Item) types.TreeAttribute { compo.Tree = value return compo } func (compo *TreeAttribute) SetEditUrl(value string) types.TreeAttribute { compo.EditUrl = value return compo } func (compo *TreeAttribute) SetUrlPrefix(value string) types.TreeAttribute { compo.UrlPrefix = value return compo } func (compo *TreeAttribute) SetDeleteUrl(value string) types.TreeAttribute { compo.DeleteUrl = value return compo } func (compo *TreeAttribute) SetOrderUrl(value string) types.TreeAttribute { compo.OrderUrl = value return compo } func (compo *TreeAttribute) GetContent() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "tree") } func (compo *TreeAttribute) GetTreeHeader() template.HTML { return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "tree-header") } ================================================ FILE: template/components/treeview.go ================================================ package components import ( "encoding/json" "html/template" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/template/types" ) type TreeViewAttribute struct { Name string ID string Tree types.TreeViewData TreeJSON template.JS UrlPrefix string types.Attribute } func (compo *TreeViewAttribute) SetID(id string) types.TreeViewAttribute { compo.ID = id return compo } func (compo *TreeViewAttribute) SetTree(value types.TreeViewData) types.TreeViewAttribute { compo.Tree = value return compo } func (compo *TreeViewAttribute) SetUrlPrefix(value string) types.TreeViewAttribute { compo.UrlPrefix = value return compo } func (compo *TreeViewAttribute) GetContent() template.HTML { if compo.ID == "" { compo.ID = utils.Uuid(10) } b, _ := json.Marshal(compo.Tree) compo.TreeJSON = template.JS(b) return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "treeview") } ================================================ FILE: template/icon/icon.go ================================================ package icon import ( "html/template" "github.com/GoAdminGroup/html" ) func Icon(class string, num ...int) template.HTML { space := template.HTML("") if len(num) > 0 { for i := 0; i < num[0]; i++ { space += " " } } return html.IEl().SetClass("icon fa", class).Get() + space } func IconWithStyle(class string, style html.Style, num ...int) template.HTML { space := template.HTML("") if len(num) > 0 { for i := 0; i < num[0]; i++ { space += " " } } i := html.IEl().SetClass("icon fa", class) for k, s := range style { i.SetStyle(k, s) } return i.Get() + space } const ( Adjust = "fa-adjust" // https://fontawesome.com/icons/adjust Adn = "fa-adn" // https://fontawesome.com/icons/adn AlignCenter = "fa-align-center" // https://fontawesome.com/icons/align-center AlignJustify = "fa-align-justify" // https://fontawesome.com/icons/align-justify AlignLeft = "fa-align-left" // https://fontawesome.com/icons/align-left AlignRight = "fa-align-right" // https://fontawesome.com/icons/align-right Amazon = "fa-amazon" // https://fontawesome.com/icons/amazon Ambulance = "fa-ambulance" // https://fontawesome.com/icons/ambulance AmericanSignLanguageInterpreting = "fa-american-sign-language-interpreting" // https://fontawesome.com/icons/american-sign-language-interpreting Anchor = "fa-anchor" // https://fontawesome.com/icons/anchor Android = "fa-android" // https://fontawesome.com/icons/android Angellist = "fa-angellist" // https://fontawesome.com/icons/angellist AngleDoubleDown = "fa-angle-double-down" // https://fontawesome.com/icons/angle-double-down AngleDoubleLeft = "fa-angle-double-left" // https://fontawesome.com/icons/angle-double-left AngleDoubleRight = "fa-angle-double-right" // https://fontawesome.com/icons/angle-double-right AngleDoubleUp = "fa-angle-double-up" // https://fontawesome.com/icons/angle-double-up AngleDown = "fa-angle-down" // https://fontawesome.com/icons/angle-down AngleLeft = "fa-angle-left" // https://fontawesome.com/icons/angle-left AngleRight = "fa-angle-right" // https://fontawesome.com/icons/angle-right AngleUp = "fa-angle-up" // https://fontawesome.com/icons/angle-up Apple = "fa-apple" // https://fontawesome.com/icons/apple Archive = "fa-archive" // https://fontawesome.com/icons/archive AreaChart = "fa-area-chart" // https://fontawesome.com/icons/area-chart ArrowCircleDown = "fa-arrow-circle-down" // https://fontawesome.com/icons/arrow-circle-down ArrowCircleLeft = "fa-arrow-circle-left" // https://fontawesome.com/icons/arrow-circle-left ArrowCircleODown = "fa-arrow-circle-o-down" // https://fontawesome.com/icons/arrow-circle-o-down ArrowCircleOLeft = "fa-arrow-circle-o-left" // https://fontawesome.com/icons/arrow-circle-o-left ArrowCircleORight = "fa-arrow-circle-o-right" // https://fontawesome.com/icons/arrow-circle-o-right ArrowCircleOUp = "fa-arrow-circle-o-up" // https://fontawesome.com/icons/arrow-circle-o-up ArrowCircleRight = "fa-arrow-circle-right" // https://fontawesome.com/icons/arrow-circle-right ArrowCircleUp = "fa-arrow-circle-up" // https://fontawesome.com/icons/arrow-circle-up ArrowDown = "fa-arrow-down" // https://fontawesome.com/icons/arrow-down ArrowLeft = "fa-arrow-left" // https://fontawesome.com/icons/arrow-left ArrowRight = "fa-arrow-right" // https://fontawesome.com/icons/arrow-right ArrowUp = "fa-arrow-up" // https://fontawesome.com/icons/arrow-up Arrows = "fa-arrows" // https://fontawesome.com/icons/arrows ArrowsAlt = "fa-arrows-alt" // https://fontawesome.com/icons/arrows-alt ArrowsH = "fa-arrows-h" // https://fontawesome.com/icons/arrows-h ArrowsV = "fa-arrows-v" // https://fontawesome.com/icons/arrows-v AslInterpreting = "fa-asl-interpreting" // https://fontawesome.com/icons/asl-interpreting AssistiveListeningSystems = "fa-assistive-listening-systems" // https://fontawesome.com/icons/assistive-listening-systems Asterisk = "fa-asterisk" // https://fontawesome.com/icons/asterisk At = "fa-at" // https://fontawesome.com/icons/at AudioDescription = "fa-audio-description" // https://fontawesome.com/icons/audio-description Automobile = "fa-automobile" // https://fontawesome.com/icons/automobile Backward = "fa-backward" // https://fontawesome.com/icons/backward BalanceScale = "fa-balance-scale" // https://fontawesome.com/icons/balance-scale Ban = "fa-ban" // https://fontawesome.com/icons/ban Bank = "fa-bank" // https://fontawesome.com/icons/bank BarChart = "fa-bar-chart" // https://fontawesome.com/icons/bar-chart BarChartO = "fa-bar-chart-o" // https://fontawesome.com/icons/bar-chart-o Barcode = "fa-barcode" // https://fontawesome.com/icons/barcode Bars = "fa-bars" // https://fontawesome.com/icons/bars Battery0 = "fa-battery-0" // https://fontawesome.com/icons/battery-0 Battery1 = "fa-battery-1" // https://fontawesome.com/icons/battery-1 Battery2 = "fa-battery-2" // https://fontawesome.com/icons/battery-2 Battery3 = "fa-battery-3" // https://fontawesome.com/icons/battery-3 Battery4 = "fa-battery-4" // https://fontawesome.com/icons/battery-4 BatteryEmpty = "fa-battery-empty" // https://fontawesome.com/icons/battery-empty BatteryFull = "fa-battery-full" // https://fontawesome.com/icons/battery-full BatteryHalf = "fa-battery-half" // https://fontawesome.com/icons/battery-half BatteryQuarter = "fa-battery-quarter" // https://fontawesome.com/icons/battery-quarter BatteryThreeQuarters = "fa-battery-three-quarters" // https://fontawesome.com/icons/battery-three-quarters Bed = "fa-bed" // https://fontawesome.com/icons/bed Beer = "fa-beer" // https://fontawesome.com/icons/beer Behance = "fa-behance" // https://fontawesome.com/icons/behance BehanceSquare = "fa-behance-square" // https://fontawesome.com/icons/behance-square Bell = "fa-bell" // https://fontawesome.com/icons/bell BellO = "fa-bell-o" // https://fontawesome.com/icons/bell-o BellSlash = "fa-bell-slash" // https://fontawesome.com/icons/bell-slash BellSlashO = "fa-bell-slash-o" // https://fontawesome.com/icons/bell-slash-o Bicycle = "fa-bicycle" // https://fontawesome.com/icons/bicycle Binoculars = "fa-binoculars" // https://fontawesome.com/icons/binoculars BirthdayCake = "fa-birthday-cake" // https://fontawesome.com/icons/birthday-cake Bitbucket = "fa-bitbucket" // https://fontawesome.com/icons/bitbucket BitbucketSquare = "fa-bitbucket-square" // https://fontawesome.com/icons/bitbucket-square Bitcoin = "fa-bitcoin" // https://fontawesome.com/icons/bitcoin BlackTie = "fa-black-tie" // https://fontawesome.com/icons/black-tie Blind = "fa-blind" // https://fontawesome.com/icons/blind Bluetooth = "fa-bluetooth" // https://fontawesome.com/icons/bluetooth BluetoothB = "fa-bluetooth-b" // https://fontawesome.com/icons/bluetooth-b Bold = "fa-bold" // https://fontawesome.com/icons/bold Bolt = "fa-bolt" // https://fontawesome.com/icons/bolt Bomb = "fa-bomb" // https://fontawesome.com/icons/bomb Book = "fa-book" // https://fontawesome.com/icons/book Bookmark = "fa-bookmark" // https://fontawesome.com/icons/bookmark BookmarkO = "fa-bookmark-o" // https://fontawesome.com/icons/bookmark-o Braille = "fa-braille" // https://fontawesome.com/icons/braille Briefcase = "fa-briefcase" // https://fontawesome.com/icons/briefcase Btc = "fa-btc" // https://fontawesome.com/icons/btc Bug = "fa-bug" // https://fontawesome.com/icons/bug Building = "fa-building" // https://fontawesome.com/icons/building BuildingO = "fa-building-o" // https://fontawesome.com/icons/building-o Bullhorn = "fa-bullhorn" // https://fontawesome.com/icons/bullhorn Bullseye = "fa-bullseye" // https://fontawesome.com/icons/bullseye Bus = "fa-bus" // https://fontawesome.com/icons/bus Buysellads = "fa-buysellads" // https://fontawesome.com/icons/buysellads Cab = "fa-cab" // https://fontawesome.com/icons/cab Calculator = "fa-calculator" // https://fontawesome.com/icons/calculator Calendar = "fa-calendar" // https://fontawesome.com/icons/calendar CalendarCheckO = "fa-calendar-check-o" // https://fontawesome.com/icons/calendar-check-o CalendarMinusO = "fa-calendar-minus-o" // https://fontawesome.com/icons/calendar-minus-o CalendarO = "fa-calendar-o" // https://fontawesome.com/icons/calendar-o CalendarPlusO = "fa-calendar-plus-o" // https://fontawesome.com/icons/calendar-plus-o CalendarTimesO = "fa-calendar-times-o" // https://fontawesome.com/icons/calendar-times-o Camera = "fa-camera" // https://fontawesome.com/icons/camera CameraRetro = "fa-camera-retro" // https://fontawesome.com/icons/camera-retro Car = "fa-car" // https://fontawesome.com/icons/car CaretDown = "fa-caret-down" // https://fontawesome.com/icons/caret-down CaretLeft = "fa-caret-left" // https://fontawesome.com/icons/caret-left CaretRight = "fa-caret-right" // https://fontawesome.com/icons/caret-right CaretSquareODown = "fa-caret-square-o-down" // https://fontawesome.com/icons/caret-square-o-down CaretSquareOLeft = "fa-caret-square-o-left" // https://fontawesome.com/icons/caret-square-o-left CaretSquareORight = "fa-caret-square-o-right" // https://fontawesome.com/icons/caret-square-o-right CaretSquareOUp = "fa-caret-square-o-up" // https://fontawesome.com/icons/caret-square-o-up CaretUp = "fa-caret-up" // https://fontawesome.com/icons/caret-up CartArrowDown = "fa-cart-arrow-down" // https://fontawesome.com/icons/cart-arrow-down CartPlus = "fa-cart-plus" // https://fontawesome.com/icons/cart-plus Cc = "fa-cc" // https://fontawesome.com/icons/cc CcAmex = "fa-cc-amex" // https://fontawesome.com/icons/cc-amex CcDinersClub = "fa-cc-diners-club" // https://fontawesome.com/icons/cc-diners-club CcDiscover = "fa-cc-discover" // https://fontawesome.com/icons/cc-discover CcJcb = "fa-cc-jcb" // https://fontawesome.com/icons/cc-jcb CcMastercard = "fa-cc-mastercard" // https://fontawesome.com/icons/cc-mastercard CcPaypal = "fa-cc-paypal" // https://fontawesome.com/icons/cc-paypal CcStripe = "fa-cc-stripe" // https://fontawesome.com/icons/cc-stripe CcVisa = "fa-cc-visa" // https://fontawesome.com/icons/cc-visa Certificate = "fa-certificate" // https://fontawesome.com/icons/certificate Chain = "fa-chain" // https://fontawesome.com/icons/chain ChainBroken = "fa-chain-broken" // https://fontawesome.com/icons/chain-broken Check = "fa-check" // https://fontawesome.com/icons/check CheckCircle = "fa-check-circle" // https://fontawesome.com/icons/check-circle CheckCircleO = "fa-check-circle-o" // https://fontawesome.com/icons/check-circle-o CheckSquare = "fa-check-square" // https://fontawesome.com/icons/check-square CheckSquareO = "fa-check-square-o" // https://fontawesome.com/icons/check-square-o ChevronCircleDown = "fa-chevron-circle-down" // https://fontawesome.com/icons/chevron-circle-down ChevronCircleLeft = "fa-chevron-circle-left" // https://fontawesome.com/icons/chevron-circle-left ChevronCircleRight = "fa-chevron-circle-right" // https://fontawesome.com/icons/chevron-circle-right ChevronCircleUp = "fa-chevron-circle-up" // https://fontawesome.com/icons/chevron-circle-up ChevronDown = "fa-chevron-down" // https://fontawesome.com/icons/chevron-down ChevronLeft = "fa-chevron-left" // https://fontawesome.com/icons/chevron-left ChevronRight = "fa-chevron-right" // https://fontawesome.com/icons/chevron-right ChevronUp = "fa-chevron-up" // https://fontawesome.com/icons/chevron-up Child = "fa-child" // https://fontawesome.com/icons/child Chrome = "fa-chrome" // https://fontawesome.com/icons/chrome Circle = "fa-circle" // https://fontawesome.com/icons/circle CircleO = "fa-circle-o" // https://fontawesome.com/icons/circle-o CircleONotch = "fa-circle-o-notch" // https://fontawesome.com/icons/circle-o-notch CircleThin = "fa-circle-thin" // https://fontawesome.com/icons/circle-thin Clipboard = "fa-clipboard" // https://fontawesome.com/icons/clipboard ClockO = "fa-clock-o" // https://fontawesome.com/icons/clock-o Clone = "fa-clone" // https://fontawesome.com/icons/clone Close = "fa-close" // https://fontawesome.com/icons/close Cloud = "fa-cloud" // https://fontawesome.com/icons/cloud CloudDownload = "fa-cloud-download" // https://fontawesome.com/icons/cloud-download CloudUpload = "fa-cloud-upload" // https://fontawesome.com/icons/cloud-upload Cny = "fa-cny" // https://fontawesome.com/icons/cny Code = "fa-code" // https://fontawesome.com/icons/code CodeFork = "fa-code-fork" // https://fontawesome.com/icons/code-fork Codepen = "fa-codepen" // https://fontawesome.com/icons/codepen Codiepie = "fa-codiepie" // https://fontawesome.com/icons/codiepie Coffee = "fa-coffee" // https://fontawesome.com/icons/coffee Cog = "fa-cog" // https://fontawesome.com/icons/cog Cogs = "fa-cogs" // https://fontawesome.com/icons/cogs Columns = "fa-columns" // https://fontawesome.com/icons/columns Comment = "fa-comment" // https://fontawesome.com/icons/comment CommentO = "fa-comment-o" // https://fontawesome.com/icons/comment-o Commenting = "fa-commenting" // https://fontawesome.com/icons/commenting CommentingO = "fa-commenting-o" // https://fontawesome.com/icons/commenting-o Comments = "fa-comments" // https://fontawesome.com/icons/comments CommentsO = "fa-comments-o" // https://fontawesome.com/icons/comments-o Compass = "fa-compass" // https://fontawesome.com/icons/compass Compress = "fa-compress" // https://fontawesome.com/icons/compress Connectdevelop = "fa-connectdevelop" // https://fontawesome.com/icons/connectdevelop Contao = "fa-contao" // https://fontawesome.com/icons/contao Copy = "fa-copy" // https://fontawesome.com/icons/copy Copyright = "fa-copyright" // https://fontawesome.com/icons/copyright CreativeCommons = "fa-creative-commons" // https://fontawesome.com/icons/creative-commons CreditCard = "fa-credit-card" // https://fontawesome.com/icons/credit-card CreditCardAlt = "fa-credit-card-alt" // https://fontawesome.com/icons/credit-card-alt Crop = "fa-crop" // https://fontawesome.com/icons/crop Crosshairs = "fa-crosshairs" // https://fontawesome.com/icons/crosshairs Css3 = "fa-css3" // https://fontawesome.com/icons/css3 Cube = "fa-cube" // https://fontawesome.com/icons/cube Cubes = "fa-cubes" // https://fontawesome.com/icons/cubes Cut = "fa-cut" // https://fontawesome.com/icons/cut Cutlery = "fa-cutlery" // https://fontawesome.com/icons/cutlery Dashboard = "fa-dashboard" // https://fontawesome.com/icons/dashboard Dashcube = "fa-dashcube" // https://fontawesome.com/icons/dashcube Database = "fa-database" // https://fontawesome.com/icons/database Deaf = "fa-deaf" // https://fontawesome.com/icons/deaf Deafness = "fa-deafness" // https://fontawesome.com/icons/deafness Dedent = "fa-dedent" // https://fontawesome.com/icons/dedent Delicious = "fa-delicious" // https://fontawesome.com/icons/delicious Desktop = "fa-desktop" // https://fontawesome.com/icons/desktop Deviantart = "fa-deviantart" // https://fontawesome.com/icons/deviantart Diamond = "fa-diamond" // https://fontawesome.com/icons/diamond Digg = "fa-digg" // https://fontawesome.com/icons/digg Dollar = "fa-dollar" // https://fontawesome.com/icons/dollar DotCircleO = "fa-dot-circle-o" // https://fontawesome.com/icons/dot-circle-o Download = "fa-download" // https://fontawesome.com/icons/download Dribbble = "fa-dribbble" // https://fontawesome.com/icons/dribbble Dropbox = "fa-dropbox" // https://fontawesome.com/icons/dropbox Drupal = "fa-drupal" // https://fontawesome.com/icons/drupal Edge = "fa-edge" // https://fontawesome.com/icons/edge Edit = "fa-edit" // https://fontawesome.com/icons/edit Eject = "fa-eject" // https://fontawesome.com/icons/eject EllipsisH = "fa-ellipsis-h" // https://fontawesome.com/icons/ellipsis-h EllipsisV = "fa-ellipsis-v" // https://fontawesome.com/icons/ellipsis-v Empire = "fa-empire" // https://fontawesome.com/icons/empire Envelope = "fa-envelope" // https://fontawesome.com/icons/envelope EnvelopeO = "fa-envelope-o" // https://fontawesome.com/icons/envelope-o EnvelopeSquare = "fa-envelope-square" // https://fontawesome.com/icons/envelope-square Envira = "fa-envira" // https://fontawesome.com/icons/envira Eraser = "fa-eraser" // https://fontawesome.com/icons/eraser Eur = "fa-eur" // https://fontawesome.com/icons/eur Euro = "fa-euro" // https://fontawesome.com/icons/euro Exchange = "fa-exchange" // https://fontawesome.com/icons/exchange Exclamation = "fa-exclamation" // https://fontawesome.com/icons/exclamation ExclamationCircle = "fa-exclamation-circle" // https://fontawesome.com/icons/exclamation-circle ExclamationTriangle = "fa-exclamation-triangle" // https://fontawesome.com/icons/exclamation-triangle Expand = "fa-expand" // https://fontawesome.com/icons/expand Expeditedssl = "fa-expeditedssl" // https://fontawesome.com/icons/expeditedssl ExternalLink = "fa-external-link" // https://fontawesome.com/icons/external-link ExternalLinkSquare = "fa-external-link-square" // https://fontawesome.com/icons/external-link-square Eye = "fa-eye" // https://fontawesome.com/icons/eye EyeSlash = "fa-eye-slash" // https://fontawesome.com/icons/eye-slash Eyedropper = "fa-eyedropper" // https://fontawesome.com/icons/eyedropper Fa = "fa-fa" // https://fontawesome.com/icons/fa Facebook = "fa-facebook" // https://fontawesome.com/icons/facebook FacebookF = "fa-facebook-f" // https://fontawesome.com/icons/facebook-f FacebookOfficial = "fa-facebook-official" // https://fontawesome.com/icons/facebook-official FacebookSquare = "fa-facebook-square" // https://fontawesome.com/icons/facebook-square FastBackward = "fa-fast-backward" // https://fontawesome.com/icons/fast-backward FastForward = "fa-fast-forward" // https://fontawesome.com/icons/fast-forward Fax = "fa-fax" // https://fontawesome.com/icons/fax Feed = "fa-feed" // https://fontawesome.com/icons/feed Female = "fa-female" // https://fontawesome.com/icons/female FighterJet = "fa-fighter-jet" // https://fontawesome.com/icons/fighter-jet File = "fa-file" // https://fontawesome.com/icons/file FileArchiveO = "fa-file-archive-o" // https://fontawesome.com/icons/file-archive-o FileAudioO = "fa-file-audio-o" // https://fontawesome.com/icons/file-audio-o FileCodeO = "fa-file-code-o" // https://fontawesome.com/icons/file-code-o FileExcelO = "fa-file-excel-o" // https://fontawesome.com/icons/file-excel-o FileImageO = "fa-file-image-o" // https://fontawesome.com/icons/file-image-o FileMovieO = "fa-file-movie-o" // https://fontawesome.com/icons/file-movie-o FileO = "fa-file-o" // https://fontawesome.com/icons/file-o FilePdfO = "fa-file-pdf-o" // https://fontawesome.com/icons/file-pdf-o FilePhotoO = "fa-file-photo-o" // https://fontawesome.com/icons/file-photo-o FilePictureO = "fa-file-picture-o" // https://fontawesome.com/icons/file-picture-o FilePowerpointO = "fa-file-powerpoint-o" // https://fontawesome.com/icons/file-powerpoint-o FileSoundO = "fa-file-sound-o" // https://fontawesome.com/icons/file-sound-o FileText = "fa-file-text" // https://fontawesome.com/icons/file-text FileTextO = "fa-file-text-o" // https://fontawesome.com/icons/file-text-o FileVideoO = "fa-file-video-o" // https://fontawesome.com/icons/file-video-o FileWordO = "fa-file-word-o" // https://fontawesome.com/icons/file-word-o FileZipO = "fa-file-zip-o" // https://fontawesome.com/icons/file-zip-o FilesO = "fa-files-o" // https://fontawesome.com/icons/files-o Film = "fa-film" // https://fontawesome.com/icons/film Filter = "fa-filter" // https://fontawesome.com/icons/filter Fire = "fa-fire" // https://fontawesome.com/icons/fire FireExtinguisher = "fa-fire-extinguisher" // https://fontawesome.com/icons/fire-extinguisher Firefox = "fa-firefox" // https://fontawesome.com/icons/firefox FirstOrder = "fa-first-order" // https://fontawesome.com/icons/first-order Flag = "fa-flag" // https://fontawesome.com/icons/flag FlagCheckered = "fa-flag-checkered" // https://fontawesome.com/icons/flag-checkered FlagO = "fa-flag-o" // https://fontawesome.com/icons/flag-o Flash = "fa-flash" // https://fontawesome.com/icons/flash Flask = "fa-flask" // https://fontawesome.com/icons/flask Flickr = "fa-flickr" // https://fontawesome.com/icons/flickr FloppyO = "fa-floppy-o" // https://fontawesome.com/icons/floppy-o Folder = "fa-folder" // https://fontawesome.com/icons/folder FolderO = "fa-folder-o" // https://fontawesome.com/icons/folder-o FolderOpen = "fa-folder-open" // https://fontawesome.com/icons/folder-open FolderOpenO = "fa-folder-open-o" // https://fontawesome.com/icons/folder-open-o Font = "fa-font" // https://fontawesome.com/icons/font FontAwesome = "fa-font-awesome" // https://fontawesome.com/icons/font-awesome Fonticons = "fa-fonticons" // https://fontawesome.com/icons/fonticons FortAwesome = "fa-fort-awesome" // https://fontawesome.com/icons/fort-awesome Forumbee = "fa-forumbee" // https://fontawesome.com/icons/forumbee Forward = "fa-forward" // https://fontawesome.com/icons/forward Foursquare = "fa-foursquare" // https://fontawesome.com/icons/foursquare FrownO = "fa-frown-o" // https://fontawesome.com/icons/frown-o FutbolO = "fa-futbol-o" // https://fontawesome.com/icons/futbol-o Gamepad = "fa-gamepad" // https://fontawesome.com/icons/gamepad Gavel = "fa-gavel" // https://fontawesome.com/icons/gavel Gbp = "fa-gbp" // https://fontawesome.com/icons/gbp Ge = "fa-ge" // https://fontawesome.com/icons/ge Gear = "fa-gear" // https://fontawesome.com/icons/gear Gears = "fa-gears" // https://fontawesome.com/icons/gears Genderless = "fa-genderless" // https://fontawesome.com/icons/genderless GetPocket = "fa-get-pocket" // https://fontawesome.com/icons/get-pocket Gg = "fa-gg" // https://fontawesome.com/icons/gg GgCircle = "fa-gg-circle" // https://fontawesome.com/icons/gg-circle Gift = "fa-gift" // https://fontawesome.com/icons/gift Git = "fa-git" // https://fontawesome.com/icons/git GitSquare = "fa-git-square" // https://fontawesome.com/icons/git-square Github = "fa-github" // https://fontawesome.com/icons/github GithubAlt = "fa-github-alt" // https://fontawesome.com/icons/github-alt GithubSquare = "fa-github-square" // https://fontawesome.com/icons/github-square Gitlab = "fa-gitlab" // https://fontawesome.com/icons/gitlab Gittip = "fa-gittip" // https://fontawesome.com/icons/gittip Glass = "fa-glass" // https://fontawesome.com/icons/glass Glide = "fa-glide" // https://fontawesome.com/icons/glide GlideG = "fa-glide-g" // https://fontawesome.com/icons/glide-g Globe = "fa-globe" // https://fontawesome.com/icons/globe Google = "fa-google" // https://fontawesome.com/icons/google GooglePlus = "fa-google-plus" // https://fontawesome.com/icons/google-plus GooglePlusCircle = "fa-google-plus-circle" // https://fontawesome.com/icons/google-plus-circle GooglePlusOfficial = "fa-google-plus-official" // https://fontawesome.com/icons/google-plus-official GooglePlusSquare = "fa-google-plus-square" // https://fontawesome.com/icons/google-plus-square GoogleWallet = "fa-google-wallet" // https://fontawesome.com/icons/google-wallet GraduationCap = "fa-graduation-cap" // https://fontawesome.com/icons/graduation-cap Gratipay = "fa-gratipay" // https://fontawesome.com/icons/gratipay Group = "fa-group" // https://fontawesome.com/icons/group HSquare = "fa-h-square" // https://fontawesome.com/icons/h-square HackerNews = "fa-hacker-news" // https://fontawesome.com/icons/hacker-news HandGrabO = "fa-hand-grab-o" // https://fontawesome.com/icons/hand-grab-o HandLizardO = "fa-hand-lizard-o" // https://fontawesome.com/icons/hand-lizard-o HandODown = "fa-hand-o-down" // https://fontawesome.com/icons/hand-o-down HandOLeft = "fa-hand-o-left" // https://fontawesome.com/icons/hand-o-left HandORight = "fa-hand-o-right" // https://fontawesome.com/icons/hand-o-right HandOUp = "fa-hand-o-up" // https://fontawesome.com/icons/hand-o-up HandPaperO = "fa-hand-paper-o" // https://fontawesome.com/icons/hand-paper-o HandPeaceO = "fa-hand-peace-o" // https://fontawesome.com/icons/hand-peace-o HandPointerO = "fa-hand-pointer-o" // https://fontawesome.com/icons/hand-pointer-o HandRockO = "fa-hand-rock-o" // https://fontawesome.com/icons/hand-rock-o HandScissorsO = "fa-hand-scissors-o" // https://fontawesome.com/icons/hand-scissors-o HandSpockO = "fa-hand-spock-o" // https://fontawesome.com/icons/hand-spock-o HandStopO = "fa-hand-stop-o" // https://fontawesome.com/icons/hand-stop-o HardOfHearing = "fa-hard-of-hearing" // https://fontawesome.com/icons/hard-of-hearing Hashtag = "fa-hashtag" // https://fontawesome.com/icons/hashtag HddO = "fa-hdd-o" // https://fontawesome.com/icons/hdd-o Header = "fa-header" // https://fontawesome.com/icons/header Headphones = "fa-headphones" // https://fontawesome.com/icons/headphones Heart = "fa-heart" // https://fontawesome.com/icons/heart HeartO = "fa-heart-o" // https://fontawesome.com/icons/heart-o Heartbeat = "fa-heartbeat" // https://fontawesome.com/icons/heartbeat History = "fa-history" // https://fontawesome.com/icons/history Home = "fa-home" // https://fontawesome.com/icons/home HospitalO = "fa-hospital-o" // https://fontawesome.com/icons/hospital-o Hotel = "fa-hotel" // https://fontawesome.com/icons/hotel Hourglass = "fa-hourglass" // https://fontawesome.com/icons/hourglass Hourglass1 = "fa-hourglass-1" // https://fontawesome.com/icons/hourglass-1 Hourglass2 = "fa-hourglass-2" // https://fontawesome.com/icons/hourglass-2 Hourglass3 = "fa-hourglass-3" // https://fontawesome.com/icons/hourglass-3 HourglassEnd = "fa-hourglass-end" // https://fontawesome.com/icons/hourglass-end HourglassHalf = "fa-hourglass-half" // https://fontawesome.com/icons/hourglass-half HourglassO = "fa-hourglass-o" // https://fontawesome.com/icons/hourglass-o HourglassStart = "fa-hourglass-start" // https://fontawesome.com/icons/hourglass-start Houzz = "fa-houzz" // https://fontawesome.com/icons/houzz Html5 = "fa-html5" // https://fontawesome.com/icons/html5 ICursor = "fa-i-cursor" // https://fontawesome.com/icons/i-cursor Ils = "fa-ils" // https://fontawesome.com/icons/ils Image = "fa-image" // https://fontawesome.com/icons/image Inbox = "fa-inbox" // https://fontawesome.com/icons/inbox Indent = "fa-indent" // https://fontawesome.com/icons/indent Industry = "fa-industry" // https://fontawesome.com/icons/industry Info = "fa-info" // https://fontawesome.com/icons/info InfoCircle = "fa-info-circle" // https://fontawesome.com/icons/info-circle Inr = "fa-inr" // https://fontawesome.com/icons/inr Instagram = "fa-instagram" // https://fontawesome.com/icons/instagram Institution = "fa-institution" // https://fontawesome.com/icons/institution InternetExplorer = "fa-internet-explorer" // https://fontawesome.com/icons/internet-explorer Intersex = "fa-intersex" // https://fontawesome.com/icons/intersex Ioxhost = "fa-ioxhost" // https://fontawesome.com/icons/ioxhost Italic = "fa-italic" // https://fontawesome.com/icons/italic Joomla = "fa-joomla" // https://fontawesome.com/icons/joomla Jpy = "fa-jpy" // https://fontawesome.com/icons/jpy Jsfiddle = "fa-jsfiddle" // https://fontawesome.com/icons/jsfiddle Key = "fa-key" // https://fontawesome.com/icons/key KeyboardO = "fa-keyboard-o" // https://fontawesome.com/icons/keyboard-o Krw = "fa-krw" // https://fontawesome.com/icons/krw Language = "fa-language" // https://fontawesome.com/icons/language Laptop = "fa-laptop" // https://fontawesome.com/icons/laptop Lastfm = "fa-lastfm" // https://fontawesome.com/icons/lastfm LastfmSquare = "fa-lastfm-square" // https://fontawesome.com/icons/lastfm-square Leaf = "fa-leaf" // https://fontawesome.com/icons/leaf Leanpub = "fa-leanpub" // https://fontawesome.com/icons/leanpub Legal = "fa-legal" // https://fontawesome.com/icons/legal LemonO = "fa-lemon-o" // https://fontawesome.com/icons/lemon-o LevelDown = "fa-level-down" // https://fontawesome.com/icons/level-down LevelUp = "fa-level-up" // https://fontawesome.com/icons/level-up LifeBouy = "fa-life-bouy" // https://fontawesome.com/icons/life-bouy LifeBuoy = "fa-life-buoy" // https://fontawesome.com/icons/life-buoy LifeRing = "fa-life-ring" // https://fontawesome.com/icons/life-ring LifeSaver = "fa-life-saver" // https://fontawesome.com/icons/life-saver LightbulbO = "fa-lightbulb-o" // https://fontawesome.com/icons/lightbulb-o LineChart = "fa-line-chart" // https://fontawesome.com/icons/line-chart Link = "fa-link" // https://fontawesome.com/icons/link Linkedin = "fa-linkedin" // https://fontawesome.com/icons/linkedin LinkedinSquare = "fa-linkedin-square" // https://fontawesome.com/icons/linkedin-square Linux = "fa-linux" // https://fontawesome.com/icons/linux List = "fa-list" // https://fontawesome.com/icons/list ListAlt = "fa-list-alt" // https://fontawesome.com/icons/list-alt ListOl = "fa-list-ol" // https://fontawesome.com/icons/list-ol ListUl = "fa-list-ul" // https://fontawesome.com/icons/list-ul LocationArrow = "fa-location-arrow" // https://fontawesome.com/icons/location-arrow Lock = "fa-lock" // https://fontawesome.com/icons/lock LongArrowDown = "fa-long-arrow-down" // https://fontawesome.com/icons/long-arrow-down LongArrowLeft = "fa-long-arrow-left" // https://fontawesome.com/icons/long-arrow-left LongArrowRight = "fa-long-arrow-right" // https://fontawesome.com/icons/long-arrow-right LongArrowUp = "fa-long-arrow-up" // https://fontawesome.com/icons/long-arrow-up LowVision = "fa-low-vision" // https://fontawesome.com/icons/low-vision Magic = "fa-magic" // https://fontawesome.com/icons/magic Magnet = "fa-magnet" // https://fontawesome.com/icons/magnet MailForward = "fa-mail-forward" // https://fontawesome.com/icons/mail-forward MailReply = "fa-mail-reply" // https://fontawesome.com/icons/mail-reply MailReplyAll = "fa-mail-reply-all" // https://fontawesome.com/icons/mail-reply-all Male = "fa-male" // https://fontawesome.com/icons/male Map = "fa-map" // https://fontawesome.com/icons/map MapMarker = "fa-map-marker" // https://fontawesome.com/icons/map-marker MapO = "fa-map-o" // https://fontawesome.com/icons/map-o MapPin = "fa-map-pin" // https://fontawesome.com/icons/map-pin MapSigns = "fa-map-signs" // https://fontawesome.com/icons/map-signs Mars = "fa-mars" // https://fontawesome.com/icons/mars MarsDouble = "fa-mars-double" // https://fontawesome.com/icons/mars-double MarsStroke = "fa-mars-stroke" // https://fontawesome.com/icons/mars-stroke MarsStrokeH = "fa-mars-stroke-h" // https://fontawesome.com/icons/mars-stroke-h MarsStrokeV = "fa-mars-stroke-v" // https://fontawesome.com/icons/mars-stroke-v Maxcdn = "fa-maxcdn" // https://fontawesome.com/icons/maxcdn Meanpath = "fa-meanpath" // https://fontawesome.com/icons/meanpath Medium = "fa-medium" // https://fontawesome.com/icons/medium Medkit = "fa-medkit" // https://fontawesome.com/icons/medkit MehO = "fa-meh-o" // https://fontawesome.com/icons/meh-o Mercury = "fa-mercury" // https://fontawesome.com/icons/mercury Microphone = "fa-microphone" // https://fontawesome.com/icons/microphone MicrophoneSlash = "fa-microphone-slash" // https://fontawesome.com/icons/microphone-slash Minus = "fa-minus" // https://fontawesome.com/icons/minus MinusCircle = "fa-minus-circle" // https://fontawesome.com/icons/minus-circle MinusSquare = "fa-minus-square" // https://fontawesome.com/icons/minus-square MinusSquareO = "fa-minus-square-o" // https://fontawesome.com/icons/minus-square-o Mixcloud = "fa-mixcloud" // https://fontawesome.com/icons/mixcloud Mobile = "fa-mobile" // https://fontawesome.com/icons/mobile MobilePhone = "fa-mobile-phone" // https://fontawesome.com/icons/mobile-phone Modx = "fa-modx" // https://fontawesome.com/icons/modx Money = "fa-money" // https://fontawesome.com/icons/money MoonO = "fa-moon-o" // https://fontawesome.com/icons/moon-o MortarBoard = "fa-mortar-board" // https://fontawesome.com/icons/mortar-board Motorcycle = "fa-motorcycle" // https://fontawesome.com/icons/motorcycle MousePointer = "fa-mouse-pointer" // https://fontawesome.com/icons/mouse-pointer Music = "fa-music" // https://fontawesome.com/icons/music Navicon = "fa-navicon" // https://fontawesome.com/icons/navicon Neuter = "fa-neuter" // https://fontawesome.com/icons/neuter NewspaperO = "fa-newspaper-o" // https://fontawesome.com/icons/newspaper-o ObjectGroup = "fa-object-group" // https://fontawesome.com/icons/object-group ObjectUngroup = "fa-object-ungroup" // https://fontawesome.com/icons/object-ungroup Odnoklassniki = "fa-odnoklassniki" // https://fontawesome.com/icons/odnoklassniki OdnoklassnikiSquare = "fa-odnoklassniki-square" // https://fontawesome.com/icons/odnoklassniki-square Opencart = "fa-opencart" // https://fontawesome.com/icons/opencart Openid = "fa-openid" // https://fontawesome.com/icons/openid Opera = "fa-opera" // https://fontawesome.com/icons/opera OptinMonster = "fa-optin-monster" // https://fontawesome.com/icons/optin-monster Outdent = "fa-outdent" // https://fontawesome.com/icons/outdent Pagelines = "fa-pagelines" // https://fontawesome.com/icons/pagelines PaintBrush = "fa-paint-brush" // https://fontawesome.com/icons/paint-brush PaperPlane = "fa-paper-plane" // https://fontawesome.com/icons/paper-plane PaperPlaneO = "fa-paper-plane-o" // https://fontawesome.com/icons/paper-plane-o Paperclip = "fa-paperclip" // https://fontawesome.com/icons/paperclip Paragraph = "fa-paragraph" // https://fontawesome.com/icons/paragraph Paste = "fa-paste" // https://fontawesome.com/icons/paste Pause = "fa-pause" // https://fontawesome.com/icons/pause PauseCircle = "fa-pause-circle" // https://fontawesome.com/icons/pause-circle PauseCircleO = "fa-pause-circle-o" // https://fontawesome.com/icons/pause-circle-o Paw = "fa-paw" // https://fontawesome.com/icons/paw Paypal = "fa-paypal" // https://fontawesome.com/icons/paypal Pencil = "fa-pencil" // https://fontawesome.com/icons/pencil PencilSquare = "fa-pencil-square" // https://fontawesome.com/icons/pencil-square PencilSquareO = "fa-pencil-square-o" // https://fontawesome.com/icons/pencil-square-o Percent = "fa-percent" // https://fontawesome.com/icons/percent Phone = "fa-phone" // https://fontawesome.com/icons/phone PhoneSquare = "fa-phone-square" // https://fontawesome.com/icons/phone-square Photo = "fa-photo" // https://fontawesome.com/icons/photo PictureO = "fa-picture-o" // https://fontawesome.com/icons/picture-o PieChart = "fa-pie-chart" // https://fontawesome.com/icons/pie-chart PiedPiper = "fa-pied-piper" // https://fontawesome.com/icons/pied-piper PiedPiperAlt = "fa-pied-piper-alt" // https://fontawesome.com/icons/pied-piper-alt PiedPiperPp = "fa-pied-piper-pp" // https://fontawesome.com/icons/pied-piper-pp Pinterest = "fa-pinterest" // https://fontawesome.com/icons/pinterest PinterestP = "fa-pinterest-p" // https://fontawesome.com/icons/pinterest-p PinterestSquare = "fa-pinterest-square" // https://fontawesome.com/icons/pinterest-square Plane = "fa-plane" // https://fontawesome.com/icons/plane Play = "fa-play" // https://fontawesome.com/icons/play PlayCircle = "fa-play-circle" // https://fontawesome.com/icons/play-circle PlayCircleO = "fa-play-circle-o" // https://fontawesome.com/icons/play-circle-o Plug = "fa-plug" // https://fontawesome.com/icons/plug Plus = "fa-plus" // https://fontawesome.com/icons/plus PlusCircle = "fa-plus-circle" // https://fontawesome.com/icons/plus-circle PlusSquare = "fa-plus-square" // https://fontawesome.com/icons/plus-square PlusSquareO = "fa-plus-square-o" // https://fontawesome.com/icons/plus-square-o PowerOff = "fa-power-off" // https://fontawesome.com/icons/power-off Print = "fa-print" // https://fontawesome.com/icons/print ProductHunt = "fa-product-hunt" // https://fontawesome.com/icons/product-hunt PuzzlePiece = "fa-puzzle-piece" // https://fontawesome.com/icons/puzzle-piece Qq = "fa-qq" // https://fontawesome.com/icons/qq Qrcode = "fa-qrcode" // https://fontawesome.com/icons/qrcode Question = "fa-question" // https://fontawesome.com/icons/question QuestionCircle = "fa-question-circle" // https://fontawesome.com/icons/question-circle QuestionCircleO = "fa-question-circle-o" // https://fontawesome.com/icons/question-circle-o QuoteLeft = "fa-quote-left" // https://fontawesome.com/icons/quote-left QuoteRight = "fa-quote-right" // https://fontawesome.com/icons/quote-right Ra = "fa-ra" // https://fontawesome.com/icons/ra Random = "fa-random" // https://fontawesome.com/icons/random Rebel = "fa-rebel" // https://fontawesome.com/icons/rebel Recycle = "fa-recycle" // https://fontawesome.com/icons/recycle Reddit = "fa-reddit" // https://fontawesome.com/icons/reddit RedditAlien = "fa-reddit-alien" // https://fontawesome.com/icons/reddit-alien RedditSquare = "fa-reddit-square" // https://fontawesome.com/icons/reddit-square Refresh = "fa-refresh" // https://fontawesome.com/icons/refresh Registered = "fa-registered" // https://fontawesome.com/icons/registered Remove = "fa-remove" // https://fontawesome.com/icons/remove Renren = "fa-renren" // https://fontawesome.com/icons/renren Reorder = "fa-reorder" // https://fontawesome.com/icons/reorder Repeat = "fa-repeat" // https://fontawesome.com/icons/repeat Reply = "fa-reply" // https://fontawesome.com/icons/reply ReplyAll = "fa-reply-all" // https://fontawesome.com/icons/reply-all Resistance = "fa-resistance" // https://fontawesome.com/icons/resistance Retweet = "fa-retweet" // https://fontawesome.com/icons/retweet Rmb = "fa-rmb" // https://fontawesome.com/icons/rmb Road = "fa-road" // https://fontawesome.com/icons/road Rocket = "fa-rocket" // https://fontawesome.com/icons/rocket RotateLeft = "fa-rotate-left" // https://fontawesome.com/icons/rotate-left RotateRight = "fa-rotate-right" // https://fontawesome.com/icons/rotate-right Rouble = "fa-rouble" // https://fontawesome.com/icons/rouble Rss = "fa-rss" // https://fontawesome.com/icons/rss RssSquare = "fa-rss-square" // https://fontawesome.com/icons/rss-square Rub = "fa-rub" // https://fontawesome.com/icons/rub Ruble = "fa-ruble" // https://fontawesome.com/icons/ruble Rupee = "fa-rupee" // https://fontawesome.com/icons/rupee Safari = "fa-safari" // https://fontawesome.com/icons/safari Save = "fa-save" // https://fontawesome.com/icons/save Scissors = "fa-scissors" // https://fontawesome.com/icons/scissors Scribd = "fa-scribd" // https://fontawesome.com/icons/scribd Search = "fa-search" // https://fontawesome.com/icons/search SearchMinus = "fa-search-minus" // https://fontawesome.com/icons/search-minus SearchPlus = "fa-search-plus" // https://fontawesome.com/icons/search-plus Sellsy = "fa-sellsy" // https://fontawesome.com/icons/sellsy Send = "fa-send" // https://fontawesome.com/icons/send SendO = "fa-send-o" // https://fontawesome.com/icons/send-o Server = "fa-server" // https://fontawesome.com/icons/server Share = "fa-share" // https://fontawesome.com/icons/share ShareAlt = "fa-share-alt" // https://fontawesome.com/icons/share-alt ShareAltSquare = "fa-share-alt-square" // https://fontawesome.com/icons/share-alt-square ShareSquare = "fa-share-square" // https://fontawesome.com/icons/share-square ShareSquareO = "fa-share-square-o" // https://fontawesome.com/icons/share-square-o Shekel = "fa-shekel" // https://fontawesome.com/icons/shekel Sheqel = "fa-sheqel" // https://fontawesome.com/icons/sheqel Shield = "fa-shield" // https://fontawesome.com/icons/shield Ship = "fa-ship" // https://fontawesome.com/icons/ship Shirtsinbulk = "fa-shirtsinbulk" // https://fontawesome.com/icons/shirtsinbulk ShoppingBag = "fa-shopping-bag" // https://fontawesome.com/icons/shopping-bag ShoppingBasket = "fa-shopping-basket" // https://fontawesome.com/icons/shopping-basket ShoppingCart = "fa-shopping-cart" // https://fontawesome.com/icons/shopping-cart SignIn = "fa-sign-in" // https://fontawesome.com/icons/sign-in SignLanguage = "fa-sign-language" // https://fontawesome.com/icons/sign-language SignOut = "fa-sign-out" // https://fontawesome.com/icons/sign-out Signal = "fa-signal" // https://fontawesome.com/icons/signal Signing = "fa-signing" // https://fontawesome.com/icons/signing Simplybuilt = "fa-simplybuilt" // https://fontawesome.com/icons/simplybuilt Sitemap = "fa-sitemap" // https://fontawesome.com/icons/sitemap Skyatlas = "fa-skyatlas" // https://fontawesome.com/icons/skyatlas Skype = "fa-skype" // https://fontawesome.com/icons/skype Slack = "fa-slack" // https://fontawesome.com/icons/slack Sliders = "fa-sliders" // https://fontawesome.com/icons/sliders Slideshare = "fa-slideshare" // https://fontawesome.com/icons/slideshare SmileO = "fa-smile-o" // https://fontawesome.com/icons/smile-o Snapchat = "fa-snapchat" // https://fontawesome.com/icons/snapchat SnapchatGhost = "fa-snapchat-ghost" // https://fontawesome.com/icons/snapchat-ghost SnapchatSquare = "fa-snapchat-square" // https://fontawesome.com/icons/snapchat-square SoccerBallO = "fa-soccer-ball-o" // https://fontawesome.com/icons/soccer-ball-o Sort = "fa-sort" // https://fontawesome.com/icons/sort SortAlphaAsc = "fa-sort-alpha-asc" // https://fontawesome.com/icons/sort-alpha-asc SortAlphaDesc = "fa-sort-alpha-desc" // https://fontawesome.com/icons/sort-alpha-desc SortAmountAsc = "fa-sort-amount-asc" // https://fontawesome.com/icons/sort-amount-asc SortAmountDesc = "fa-sort-amount-desc" // https://fontawesome.com/icons/sort-amount-desc SortAsc = "fa-sort-asc" // https://fontawesome.com/icons/sort-asc SortDesc = "fa-sort-desc" // https://fontawesome.com/icons/sort-desc SortDown = "fa-sort-down" // https://fontawesome.com/icons/sort-down SortNumericAsc = "fa-sort-numeric-asc" // https://fontawesome.com/icons/sort-numeric-asc SortNumericDesc = "fa-sort-numeric-desc" // https://fontawesome.com/icons/sort-numeric-desc SortUp = "fa-sort-up" // https://fontawesome.com/icons/sort-up Soundcloud = "fa-soundcloud" // https://fontawesome.com/icons/soundcloud SpaceShuttle = "fa-space-shuttle" // https://fontawesome.com/icons/space-shuttle Spinner = "fa-spinner" // https://fontawesome.com/icons/spinner Spoon = "fa-spoon" // https://fontawesome.com/icons/spoon Spotify = "fa-spotify" // https://fontawesome.com/icons/spotify Square = "fa-square" // https://fontawesome.com/icons/square SquareO = "fa-square-o" // https://fontawesome.com/icons/square-o StackExchange = "fa-stack-exchange" // https://fontawesome.com/icons/stack-exchange StackOverflow = "fa-stack-overflow" // https://fontawesome.com/icons/stack-overflow Star = "fa-star" // https://fontawesome.com/icons/star StarHalf = "fa-star-half" // https://fontawesome.com/icons/star-half StarHalfEmpty = "fa-star-half-empty" // https://fontawesome.com/icons/star-half-empty StarHalfFull = "fa-star-half-full" // https://fontawesome.com/icons/star-half-full StarHalfO = "fa-star-half-o" // https://fontawesome.com/icons/star-half-o StarO = "fa-star-o" // https://fontawesome.com/icons/star-o Steam = "fa-steam" // https://fontawesome.com/icons/steam SteamSquare = "fa-steam-square" // https://fontawesome.com/icons/steam-square StepBackward = "fa-step-backward" // https://fontawesome.com/icons/step-backward StepForward = "fa-step-forward" // https://fontawesome.com/icons/step-forward Stethoscope = "fa-stethoscope" // https://fontawesome.com/icons/stethoscope StickyNote = "fa-sticky-note" // https://fontawesome.com/icons/sticky-note StickyNoteO = "fa-sticky-note-o" // https://fontawesome.com/icons/sticky-note-o Stop = "fa-stop" // https://fontawesome.com/icons/stop StopCircle = "fa-stop-circle" // https://fontawesome.com/icons/stop-circle StopCircleO = "fa-stop-circle-o" // https://fontawesome.com/icons/stop-circle-o StreetView = "fa-street-view" // https://fontawesome.com/icons/street-view Strikethrough = "fa-strikethrough" // https://fontawesome.com/icons/strikethrough Stumbleupon = "fa-stumbleupon" // https://fontawesome.com/icons/stumbleupon StumbleuponCircle = "fa-stumbleupon-circle" // https://fontawesome.com/icons/stumbleupon-circle Subscript = "fa-subscript" // https://fontawesome.com/icons/subscript Subway = "fa-subway" // https://fontawesome.com/icons/subway Suitcase = "fa-suitcase" // https://fontawesome.com/icons/suitcase SunO = "fa-sun-o" // https://fontawesome.com/icons/sun-o Superscript = "fa-superscript" // https://fontawesome.com/icons/superscript Support = "fa-support" // https://fontawesome.com/icons/support Table = "fa-table" // https://fontawesome.com/icons/table Tablet = "fa-tablet" // https://fontawesome.com/icons/tablet Tachometer = "fa-tachometer" // https://fontawesome.com/icons/tachometer Tag = "fa-tag" // https://fontawesome.com/icons/tag Tags = "fa-tags" // https://fontawesome.com/icons/tags Tasks = "fa-tasks" // https://fontawesome.com/icons/tasks Taxi = "fa-taxi" // https://fontawesome.com/icons/taxi Television = "fa-television" // https://fontawesome.com/icons/television TencentWeibo = "fa-tencent-weibo" // https://fontawesome.com/icons/tencent-weibo Terminal = "fa-terminal" // https://fontawesome.com/icons/terminal TextHeight = "fa-text-height" // https://fontawesome.com/icons/text-height TextWidth = "fa-text-width" // https://fontawesome.com/icons/text-width Th = "fa-th" // https://fontawesome.com/icons/th ThLarge = "fa-th-large" // https://fontawesome.com/icons/th-large ThList = "fa-th-list" // https://fontawesome.com/icons/th-list Themeisle = "fa-themeisle" // https://fontawesome.com/icons/themeisle ThumbTack = "fa-thumb-tack" // https://fontawesome.com/icons/thumb-tack ThumbsDown = "fa-thumbs-down" // https://fontawesome.com/icons/thumbs-down ThumbsODown = "fa-thumbs-o-down" // https://fontawesome.com/icons/thumbs-o-down ThumbsOUp = "fa-thumbs-o-up" // https://fontawesome.com/icons/thumbs-o-up ThumbsUp = "fa-thumbs-up" // https://fontawesome.com/icons/thumbs-up Ticket = "fa-ticket" // https://fontawesome.com/icons/ticket Times = "fa-times" // https://fontawesome.com/icons/times TimesCircle = "fa-times-circle" // https://fontawesome.com/icons/times-circle TimesCircleO = "fa-times-circle-o" // https://fontawesome.com/icons/times-circle-o Tint = "fa-tint" // https://fontawesome.com/icons/tint ToggleDown = "fa-toggle-down" // https://fontawesome.com/icons/toggle-down ToggleLeft = "fa-toggle-left" // https://fontawesome.com/icons/toggle-left ToggleOff = "fa-toggle-off" // https://fontawesome.com/icons/toggle-off ToggleOn = "fa-toggle-on" // https://fontawesome.com/icons/toggle-on ToggleRight = "fa-toggle-right" // https://fontawesome.com/icons/toggle-right ToggleUp = "fa-toggle-up" // https://fontawesome.com/icons/toggle-up Trademark = "fa-trademark" // https://fontawesome.com/icons/trademark Train = "fa-train" // https://fontawesome.com/icons/train Transgender = "fa-transgender" // https://fontawesome.com/icons/transgender TransgenderAlt = "fa-transgender-alt" // https://fontawesome.com/icons/transgender-alt Trash = "fa-trash" // https://fontawesome.com/icons/trash TrashO = "fa-trash-o" // https://fontawesome.com/icons/trash-o Tree = "fa-tree" // https://fontawesome.com/icons/tree Trello = "fa-trello" // https://fontawesome.com/icons/trello Tripadvisor = "fa-tripadvisor" // https://fontawesome.com/icons/tripadvisor Trophy = "fa-trophy" // https://fontawesome.com/icons/trophy Truck = "fa-truck" // https://fontawesome.com/icons/truck Try = "fa-try" // https://fontawesome.com/icons/try Tty = "fa-tty" // https://fontawesome.com/icons/tty Tumblr = "fa-tumblr" // https://fontawesome.com/icons/tumblr TumblrSquare = "fa-tumblr-square" // https://fontawesome.com/icons/tumblr-square TurkishLira = "fa-turkish-lira" // https://fontawesome.com/icons/turkish-lira Tv = "fa-tv" // https://fontawesome.com/icons/tv Twitch = "fa-twitch" // https://fontawesome.com/icons/twitch Twitter = "fa-twitter" // https://fontawesome.com/icons/twitter TwitterSquare = "fa-twitter-square" // https://fontawesome.com/icons/twitter-square Umbrella = "fa-umbrella" // https://fontawesome.com/icons/umbrella Underline = "fa-underline" // https://fontawesome.com/icons/underline Undo = "fa-undo" // https://fontawesome.com/icons/undo UniversalAccess = "fa-universal-access" // https://fontawesome.com/icons/universal-access University = "fa-university" // https://fontawesome.com/icons/university Unlink = "fa-unlink" // https://fontawesome.com/icons/unlink Unlock = "fa-unlock" // https://fontawesome.com/icons/unlock UnlockAlt = "fa-unlock-alt" // https://fontawesome.com/icons/unlock-alt Unsorted = "fa-unsorted" // https://fontawesome.com/icons/unsorted Upload = "fa-upload" // https://fontawesome.com/icons/upload Usb = "fa-usb" // https://fontawesome.com/icons/usb Usd = "fa-usd" // https://fontawesome.com/icons/usd User = "fa-user" // https://fontawesome.com/icons/user UserMd = "fa-user-md" // https://fontawesome.com/icons/user-md UserPlus = "fa-user-plus" // https://fontawesome.com/icons/user-plus UserSecret = "fa-user-secret" // https://fontawesome.com/icons/user-secret UserTimes = "fa-user-times" // https://fontawesome.com/icons/user-times Users = "fa-users" // https://fontawesome.com/icons/users Venus = "fa-venus" // https://fontawesome.com/icons/venus VenusDouble = "fa-venus-double" // https://fontawesome.com/icons/venus-double VenusMars = "fa-venus-mars" // https://fontawesome.com/icons/venus-mars Viacoin = "fa-viacoin" // https://fontawesome.com/icons/viacoin Viadeo = "fa-viadeo" // https://fontawesome.com/icons/viadeo ViadeoSquare = "fa-viadeo-square" // https://fontawesome.com/icons/viadeo-square VideoCamera = "fa-video-camera" // https://fontawesome.com/icons/video-camera Vimeo = "fa-vimeo" // https://fontawesome.com/icons/vimeo VimeoSquare = "fa-vimeo-square" // https://fontawesome.com/icons/vimeo-square Vine = "fa-vine" // https://fontawesome.com/icons/vine Vk = "fa-vk" // https://fontawesome.com/icons/vk VolumeControlPhone = "fa-volume-control-phone" // https://fontawesome.com/icons/volume-control-phone VolumeDown = "fa-volume-down" // https://fontawesome.com/icons/volume-down VolumeOff = "fa-volume-off" // https://fontawesome.com/icons/volume-off VolumeUp = "fa-volume-up" // https://fontawesome.com/icons/volume-up Warning = "fa-warning" // https://fontawesome.com/icons/warning Wechat = "fa-wechat" // https://fontawesome.com/icons/wechat Weibo = "fa-weibo" // https://fontawesome.com/icons/weibo Weixin = "fa-weixin" // https://fontawesome.com/icons/weixin Whatsapp = "fa-whatsapp" // https://fontawesome.com/icons/whatsapp Wheelchair = "fa-wheelchair" // https://fontawesome.com/icons/wheelchair WheelchairAlt = "fa-wheelchair-alt" // https://fontawesome.com/icons/wheelchair-alt Wifi = "fa-wifi" // https://fontawesome.com/icons/wifi WikipediaW = "fa-wikipedia-w" // https://fontawesome.com/icons/wikipedia-w Windows = "fa-windows" // https://fontawesome.com/icons/windows Won = "fa-won" // https://fontawesome.com/icons/won Wordpress = "fa-wordpress" // https://fontawesome.com/icons/wordpress Wpbeginner = "fa-wpbeginner" // https://fontawesome.com/icons/wpbeginner Wpforms = "fa-wpforms" // https://fontawesome.com/icons/wpforms Wrench = "fa-wrench" // https://fontawesome.com/icons/wrench Xing = "fa-xing" // https://fontawesome.com/icons/xing XingSquare = "fa-xing-square" // https://fontawesome.com/icons/xing-square YCombinator = "fa-y-combinator" // https://fontawesome.com/icons/y-combinator YCombinatorSquare = "fa-y-combinator-square" // https://fontawesome.com/icons/y-combinator-square Yahoo = "fa-yahoo" // https://fontawesome.com/icons/yahoo Yc = "fa-yc" // https://fontawesome.com/icons/yc YcSquare = "fa-yc-square" // https://fontawesome.com/icons/yc-square Yelp = "fa-yelp" // https://fontawesome.com/icons/yelp Yen = "fa-yen" // https://fontawesome.com/icons/yen Yoast = "fa-yoast" // https://fontawesome.com/icons/yoast Youtube = "fa-youtube" // https://fontawesome.com/icons/youtube YoutubePlay = "fa-youtube-play" // https://fontawesome.com/icons/youtube-play YoutubeSquare = "fa-youtube-square" // https://fontawesome.com/icons/youtube-square IonIosGearOutline = "ion-ios-gear-outline" // https://fontawesome.com/icons/ion-ios-gear-outline IonIosCartOutline = "ion-ios-cart-outline" // https://fontawesome.com/icons/ion-ios-cart-outline IonIosPeopleOutline = "ion-ios-people-outline" // https://fontawesome.com/icons/ion-ios-people-outline ) ================================================ FILE: template/installation/Makefile ================================================ all: find ./ -name ".DS_Store" -depth -exec rm {} \; adm combine js --path=./assets/src/js/combine/ --out=./assets/login/dist/all.min.js adm combine css --path=./assets/src/css/ --out=./assets/login/dist/all.min.css adm compile asset --path=./assets/login/dist/ --out=./ --pa=login ================================================ FILE: template/installation/assets/src/css/main.css ================================================ @import url(font-awesome.min.css); @import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,300i,400i"); /* Reset */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } table { border-collapse: collapse; border-spacing: 0; } body { -webkit-text-size-adjust: none; } .copyrights{ text-indent:-9999px; height:0; line-height:0; font-size:0; overflow:hidden; } /* Box Model */ *, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } /* Page */ @-moz-keyframes load-spinner { 0% { -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @-webkit-keyframes load-spinner { 0% { -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @-ms-keyframes load-spinner { 0% { -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @keyframes load-spinner { 0% { -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @-ms-viewport { width: device-width; } html { width: 100%; height: 100%; } body { display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-align-items: center; -webkit-align-items: center; -ms-align-items: center; align-items: center; -moz-justify-content: -moz-flex-start; -webkit-justify-content: -webkit-flex-start; -ms-justify-content: -ms-flex-start; justify-content: flex-start; -ms-overflow-style: scrollbar; width: 100%; height: 100%; min-height: 30rem; overflow: hidden; } body:before { -moz-animation: load-spinner 1s infinite linear; -webkit-animation: load-spinner 1s infinite linear; -ms-animation: load-spinner 1s infinite linear; animation: load-spinner 1s infinite linear; -moz-transition: opacity 0.25s ease; -webkit-transition: opacity 0.25s ease; -ms-transition: opacity 0.25s ease; transition: opacity 0.25s ease; -moz-transition-delay: 0s; -webkit-transition-delay: 0s; -ms-transition-delay: 0s; transition-delay: 0s; -moz-pointer-events: none; -webkit-pointer-events: none; -ms-pointer-events: none; pointer-events: none; content: ''; display: block; position: absolute; top: 50%; left: 50%; width: 4rem; height: 4rem; margin: -2rem 0 0 -2rem; background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='96px' height='96px' viewBox='0 0 96 96' zoomAndPan='disable'%3E%3Cstyle%3Ecircle %7Bfill: transparent%3B stroke: %232e2b37%3B stroke-width: 1.5px%3B %7D%3C/style%3E%3Cdefs%3E%3CclipPath id='corner'%3E%3Cpolygon points='0,0 48,0 48,48 96,48 96,96 0,96' /%3E%3C/clipPath%3E%3C/defs%3E%3Cg clip-path='url(%23corner)'%3E%3Ccircle cx='48' cy='48' r='32'/%3E%3C/g%3E%3C/svg%3E"); background-position: center; background-repeat: no-repeat; background-size: 4rem; opacity: 0; } body:after { -moz-pointer-events: none; -webkit-pointer-events: none; -ms-pointer-events: none; pointer-events: none; content: ''; display: block; position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; background-attachment: fixed; background-color: #e1e6e1; background-image: url("../../images/overlay.png"), url("../../images/bg.jpg"); background-repeat: repeat, repeat-x; background-size: 128px 128px, cover; } body.is-loading *, body.is-loading *:before, body.is-loading *:after { -moz-animation: none !important; -webkit-animation: none !important; -ms-animation: none !important; animation: none !important; -moz-transition: none !important; -webkit-transition: none !important; -ms-transition: none !important; transition: none !important; } body.is-loading:before { -moz-transition: opacity 1s ease; -webkit-transition: opacity 1s ease; -ms-transition: opacity 1s ease; transition: opacity 1s ease; -moz-transition-delay: 0.75s; -webkit-transition-delay: 0.75s; -ms-transition-delay: 0.75s; transition-delay: 0.75s; opacity: 0.25; } @media screen and (max-width: 736px) { html { height: auto; } body { height: auto; overflow-x: hidden; overflow-y: auto; } } @media screen and (max-width: 480px) { html, body { min-width: 320px; } } /* Typography */ html { font-size: 18pt; font-size: 1vmax; } @media screen and (max-width: 1680px) { html { font-size: 12pt; font-size: 1.1vmax; } } @media screen and (max-width: 1280px) { html { font-size: 11pt; font-size: 1.5vmax; } } body, input, select, textarea { color: rgba(255, 255, 255, 0.75); font-family: "Source Sans Pro", Helvetica, sans-serif; font-size: 1rem; font-weight: 300; line-height: 1.65; } a { -moz-transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out; -webkit-transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out; -ms-transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out; transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out; color: inherit; border-bottom: dotted 1px; text-decoration: none; } a:hover { border-bottom-color: transparent; color: #ffe4b4; } strong, b { color: rgba(255, 255, 255, 0.875); font-weight: 400; } em, i { font-style: italic; } p { margin: 0 0 1.5rem 0; } body.is-ie p { width: 100%; } h1, h2, h3, h4, h5, h6 { color: rgba(255, 255, 255, 0.875); font-family: Arial, Helvetica, sans-serif; font-weight: 700; line-height: 1.3; margin: 0 0 0.75rem 0; letter-spacing: -0.05em; } h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { color: inherit; text-decoration: none; } h1.major, h2.major, h3.major { position: relative; } h1.major:after, h2.major:after, h3.major:after { content: ''; position: absolute; left: 0; width: 3.5rem; height: 0.1rem; background-color: rgba(255, 255, 255, 0.25); } h1 { font-size: 3rem; line-height: 1.2; } h1.major { margin: 0 0 2.625rem 0; } h1.major:after { bottom: -1.325rem; } h2 { font-size: 1.75rem; line-height: 1.2; } h2.major { margin: 0 0 1.9875rem 0; } h2.major:after { bottom: -1.2rem; } h3 { font-size: 1.325rem; } h3.major { margin: 0 0 1.875rem 0; } h3.major:after { bottom: -0.75rem; } h4 { font-size: 1rem; } h5 { font-size: 0.9rem; } h6 { font-size: 0.7rem; } sub { font-size: 0.8rem; position: relative; top: 0.5rem; } sup { font-size: 0.8rem; position: relative; top: -0.5rem; } blockquote { border-left: solid 0.25rem rgba(255, 255, 255, 0.25); font-style: italic; margin: 0 0 1.5rem 0; padding: 0.375rem 0 0.375rem 1.5rem; } code { background: rgba(255, 255, 255, 0.075); border-radius: 0.25rem; font-family: "Courier New", monospace; font-size: 0.8rem; margin: 0 0.25rem; padding: 0.25rem 0.65rem; } pre { -webkit-overflow-scrolling: touch; font-family: "Courier New", monospace; font-size: 0.8rem; margin: 0 0 1.5rem 0; white-space: pre-wrap; } pre code { display: block; line-height: 1.625; padding: 1rem 1.5rem; overflow-x: auto; margin: 0; } hr { border: 0; border-bottom: solid 2px rgba(255, 255, 255, 0.25); margin: 1.875rem 0; } .align-left { text-align: left; } .align-center { text-align: center; } .align-right { text-align: right; } @media screen and (max-width: 736px) { html { font-size: 12pt; } h1 { font-size: 2.25rem; line-height: 1.2; } h1.major { margin: 0 0 2.625rem 0; } h1.major:after { bottom: -1.325rem; } h2 { font-size: 1.5rem; line-height: 1.2; } h2.major { margin: 0 0 1.9875rem 0; } h2.major:after { bottom: -1.2rem; } h3 { font-size: 1rem; } h3.major { margin: 0 0 1.875rem 0; } h3.major:after { bottom: -0.75rem; } h4 { font-size: 1rem; } h5 { font-size: 0.9rem; } h6 { font-size: 0.7rem; } h1 br, h2 br, h3 br, h4 br, h5 br, h6 br { display: none; } } @media screen and (max-width: 360px) { html { font-size: 11pt; } } /* Form */ form { display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-flex-wrap: wrap; -webkit-flex-wrap: wrap; -ms-flex-wrap: wrap; flex-wrap: wrap; width: calc(100% + 3rem); margin: -1.5rem 0 1.5rem -1.5rem; } form > .field { -moz-flex-grow: 0; -webkit-flex-grow: 0; -ms-flex-grow: 0; flex-grow: 0; -moz-flex-shrink: 0; -webkit-flex-shrink: 0; -ms-flex-shrink: 0; flex-shrink: 0; padding: 1.5rem 0 0 1.5rem; width: calc(100% - 1.5rem); } form > .field.half { width: calc(50% - 0.75rem); } form > .field.third { width: calc(100%/3 - 0.5rem); } form > .field.quarter { width: calc(25% - 0.375rem); } form > .actions { -moz-flex-grow: 0; -webkit-flex-grow: 0; -ms-flex-grow: 0; flex-grow: 0; -moz-flex-shrink: 1; -webkit-flex-shrink: 1; -ms-flex-shrink: 1; flex-shrink: 1; margin: 1.5rem 0 0 1.5rem; } label { color: rgba(255, 255, 255, 0.875); display: block; font-family: Arial, Helvetica, sans-serif; font-size: 0.8rem; font-weight: 700; margin: 0 0 0.4875rem 0; } input[type="text"], input[type="password"], input[type="email"], input[type="tel"], select, textarea { -moz-appearance: none; -webkit-appearance: none; -ms-appearance: none; appearance: none; background: transparent; border: solid 2px rgba(255, 255, 255, 0.25); border-radius: 0.25rem; color: inherit; display: block; outline: 0; padding: 0 0.75rem; text-decoration: none; width: 100%; } input[type="text"]:invalid, input[type="password"]:invalid, input[type="email"]:invalid, input[type="tel"]:invalid, select:invalid, textarea:invalid { box-shadow: none; } input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus, input[type="tel"]:focus, select:focus, textarea:focus { border-color: #ffe4b4; } option { background-color: rgba(255, 255, 255, 0.875); color: #2e2b37; } .select-wrapper { text-decoration: none; display: block; position: relative; } .select-wrapper:before { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; font-family: FontAwesome; font-style: normal; font-weight: normal; text-transform: none !important; } .select-wrapper:before { display: block; content: '\f107'; position: absolute; top: 0; right: 0; width: 2.5rem; height: 2.5rem; line-height: 2.5rem; color: rgba(255, 255, 255, 0.75); pointer-events: none; text-align: center; } body.is-ie .select-wrapper:before { line-height: 2.5; } .select-wrapper select::-ms-expand { display: none; } input[type="text"], input[type="password"], input[type="email"], select { height: 2.5rem; } textarea { padding: 0.75rem 1rem; } input[type="checkbox"], input[type="radio"] { -moz-appearance: none; -webkit-appearance: none; -ms-appearance: none; appearance: none; display: block; float: left; margin-right: -2rem; opacity: 0; width: 1rem; z-index: -1; } input[type="checkbox"] + label, input[type="radio"] + label { text-decoration: none; position: relative; color: rgba(255, 255, 255, 0.75); cursor: pointer; display: inline-block; font-size: 1rem; font-weight: 300; margin-bottom: 0; padding-left: 2.5rem; padding-right: 1rem; } input[type="checkbox"] + label:before, input[type="radio"] + label:before { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; font-family: FontAwesome; font-style: normal; font-weight: normal; text-transform: none !important; } input[type="checkbox"] + label:before, input[type="radio"] + label:before { content: ''; display: inline-block; position: absolute; top: 0; left: 0; width: 1.5rem; height: 1.5rem; line-height: 1.4375rem; background: rgba(255, 255, 255, 0.075); border: solid 1px rgba(255, 255, 255, 0.25); border-radius: 0.25rem; color: #2e2b37; text-align: center; } body.is-ie input[type="checkbox"] + label:before, body.is-ie input[type="radio"] + label:before { line-height: 1.5; } input[type="checkbox"]:checked + label:before, input[type="radio"]:checked + label:before { content: '\f00c'; background: rgba(255, 255, 255, 0.875); border-color: rgba(255, 255, 255, 0.875); } input[type="checkbox"]:focus + label:before, input[type="radio"]:focus + label:before { border-color: #ffe4b4; box-shadow: 0 0 0 1px #ffe4b4; } input[type="checkbox"]:focus:checked + label:before, input[type="radio"]:focus:checked + label:before { background: #ffe4b4; } input[type="checkbox"].color1 + label:before, input[type="radio"].color1 + label:before { color: #726193; } input[type="checkbox"].color2 + label:before, input[type="radio"].color2 + label:before { color: #e37b7c; } input[type="checkbox"].color3 + label:before, input[type="radio"].color3 + label:before { color: #ffe4b4; } input[type="checkbox"].color4 + label:before, input[type="radio"].color4 + label:before { color: #353865; } input[type="checkbox"] + label:before { border-radius: 0.25rem; } input[type="radio"] + label:before { border-radius: 100%; } ::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.5) !important; opacity: 1.0; } :-moz-placeholder { color: rgba(255, 255, 255, 0.5) !important; opacity: 1.0; } ::-moz-placeholder { color: rgba(255, 255, 255, 0.5) !important; opacity: 1.0; } :-ms-input-placeholder { color: rgba(255, 255, 255, 0.5) !important; opacity: 1.0; } .formerize-placeholder { color: rgba(255, 255, 255, 0.5) !important; opacity: 1.0; } @media screen and (max-width: 736px) { form { margin: -1.5rem 0 1.5rem 0; width: 100%; } form > .field { padding: 1.5rem 0 0 0; width: 100% !important; } form > .actions { margin: 1.5rem 0 0 0; } } /* Icon */ .icon { text-decoration: none; position: relative; border-bottom: none; } .icon:before { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; font-family: FontAwesome; font-style: normal; font-weight: normal; text-transform: none !important; } .icon > .label { display: none; } /* Image */ .image { display: inline-block; position: relative; border: 0; } .image.filtered:after { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; -moz-pointer-events: none; -webkit-pointer-events: none; -ms-pointer-events: none; pointer-events: none; content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 1; z-index: 1; } .image.filtered.tinted:after { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)), linear-gradient(0deg, rgba(0, 0, 0, 0.125), rgba(0, 0, 0, 0.125)); background-size: 128px 128px, auto, auto; } .image[data-position] img { -moz-object-fit: cover; -webkit-object-fit: cover; -ms-object-fit: cover; object-fit: cover; display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .image[data-position="top left"] img { -moz-object-position: top left; -webkit-object-position: top left; -ms-object-position: top left; object-position: top left; } .image[data-position="top"] img { -moz-object-position: top; -webkit-object-position: top; -ms-object-position: top; object-position: top; } .image[data-position="top right"] img { -moz-object-position: top right; -webkit-object-position: top right; -ms-object-position: top right; object-position: top right; } .image[data-position="right"] img { -moz-object-position: right; -webkit-object-position: right; -ms-object-position: right; object-position: right; } .image[data-position="bottom right"] img { -moz-object-position: bottom right; -webkit-object-position: bottom right; -ms-object-position: bottom right; object-position: bottom right; } .image[data-position="bottom"] img { -moz-object-position: bottom; -webkit-object-position: bottom; -ms-object-position: bottom; object-position: bottom; } .image[data-position="bottom left"] img { -moz-object-position: bottom left; -webkit-object-position: bottom left; -ms-object-position: bottom left; object-position: bottom left; } .image[data-position="left"] img { -moz-object-position: left; -webkit-object-position: left; -ms-object-position: left; object-position: left; } .image[data-position="center"] img { -moz-object-position: center; -webkit-object-position: center; -ms-object-position: center; object-position: center; } .image[data-position="25% 25%"] img { -moz-object-position: 25% 25%; -webkit-object-position: 25% 25%; -ms-object-position: 25% 25%; object-position: 25% 25%; } .image[data-position="75% 25%"] img { -moz-object-position: 75% 25%; -webkit-object-position: 75% 25%; -ms-object-position: 75% 25%; object-position: 75% 25%; } .image[data-position="75% 75%"] img { -moz-object-position: 75% 75%; -webkit-object-position: 75% 75%; -ms-object-position: 75% 75%; object-position: 75% 75%; } .image[data-position="25% 75%"] img { -moz-object-position: 25% 75%; -webkit-object-position: 25% 75%; -ms-object-position: 25% 75%; object-position: 25% 75%; } .image img { display: block; } .image.left, .image.right { max-width: 40%; } .image.left img, .image.right img { width: 100%; } .image.left { float: left; padding: 0 1.5rem 1rem 0; top: 0.25rem; } .image.right { float: right; padding: 0 0 1rem 1.5rem; top: 0.25rem; } .image.fit { display: block; margin: 0 0 1.5rem 0; width: 100%; } .image.fit img { width: 100%; } .image.main { display: block; margin: 0 0 2.25rem 0; width: 100%; } .image.main img { width: 100%; } /* List */ ol { list-style: decimal; margin: 0 0 1.5rem 0; padding-left: 1.25rem; } ol li { padding-left: 0.25rem; } ul { list-style: disc; margin: 0 0 1.5rem 0; padding-left: 1rem; } ul li { padding-left: 0.5rem; } ul.alt { list-style: none; padding-left: 0; } ul.alt li { border-top: solid 1px rgba(255, 255, 255, 0.25); padding: 0.5rem 0; } ul.alt li:first-child { border-top: 0; padding-top: 0; } ul.icons { cursor: default; list-style: none; padding-left: 0; } ul.icons li { display: inline-block; padding: 0 1rem 0 0; } ul.icons li:last-child { padding-right: 0; } ul.icons li .icon:before { font-size: 1.25em; } ul.actions { cursor: default; list-style: none; padding-left: 0; } ul.actions li { display: inline-block; padding: 0 0.75rem 0 0; vertical-align: middle; } ul.actions li:last-child { padding-right: 0; } ul.actions.small li { padding: 0 0.375rem 0 0; } ul.actions.vertical li { display: block; padding: 0.75rem 0 0 0; } ul.actions.vertical li:first-child { padding-top: 0; } ul.actions.vertical li > * { margin-bottom: 0; } ul.actions.vertical.small li { padding: 0.375rem 0 0 0; } ul.actions.vertical.small li:first-child { padding-top: 0; } ul.actions.fit { display: table; margin-left: -0.75rem; padding: 0; table-layout: fixed; width: calc(100% + 0.75rem); } ul.actions.fit li { display: table-cell; padding: 0 0 0 0.75rem; } ul.actions.fit li > * { margin-bottom: 0; } ul.actions.fit.small { margin-left: -0.375rem; width: calc(100% + 0.375rem); } ul.actions.fit.small li { padding: 0 0 0 0.375rem; } ul.contact-icons { list-style: none; padding-left: 0; } ul.contact-icons > li { margin: 1.25rem 0 0 0; padding-left: 0; } ul.contact-icons > li:before { display: inline-block; width: 2.25rem; height: 2.25rem; line-height: 2.25rem; border-radius: 2.25rem; background-color: white; color: #2e2b37; cursor: default; font-size: 1.125rem; margin-right: 1rem; text-align: center; vertical-align: middle; } body.is-ie ul.contact-icons > li:before { line-height: 2.125; } ul.contact-icons > li a { border-bottom: 0; } ul.contact-icons.color1 > li:before { color: #726193; } ul.contact-icons.color2 > li:before { color: #e37b7c; } ul.contact-icons.color3 > li:before { color: #ffe4b4; } ul.contact-icons.color4 > li:before { color: #353865; } ul.grid-icons { display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-flex-wrap: wrap; -webkit-flex-wrap: wrap; -ms-flex-wrap: wrap; flex-wrap: wrap; -moz-justify-content: center; -webkit-justify-content: center; -ms-justify-content: center; justify-content: center; list-style: none; margin: 0 0 1.5rem 0; padding-left: 0; } ul.grid-icons .icon { display: block; position: relative; width: 100%; text-align: center; } ul.grid-icons .icon:before { display: block; width: 6rem; height: 6rem; line-height: 6rem; border-radius: 6rem; box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.25); font-size: 2.5rem; margin: 0 auto; text-align: center; } body.is-ie ul.grid-icons .icon:before { line-height: 2.375; } ul.grid-icons > li { -moz-flex-grow: 0; -webkit-flex-grow: 0; -ms-flex-grow: 0; flex-grow: 0; -moz-flex-shrink: 0; -webkit-flex-shrink: 0; -ms-flex-shrink: 0; flex-shrink: 0; position: relative; margin: 1.5rem 0 0 1.5rem; padding-left: 0; } ul.grid-icons.connected > li:before { content: ''; display: block; position: absolute; width: 1.5rem; height: 2px; top: 50%; left: -1.5rem; background-color: rgba(255, 255, 255, 0.25); } ul.grid-icons.connected > li:after { content: ''; display: block; position: absolute; width: 2px; height: 1.5rem; top: -1.5rem; left: 50%; background-color: rgba(255, 255, 255, 0.25); } ul.grid-icons.two { width: 14rem; } ul.grid-icons.two > li:nth-child(-n + 2) { margin-top: 0; } ul.grid-icons.two > li:nth-child(-n + 2):after { display: none; } ul.grid-icons.two > li:nth-child(2n - 1) { margin-left: 0; } ul.grid-icons.two > li:nth-child(2n - 1):before { display: none; } ul.grid-icons.three { width: 21.5rem; } ul.grid-icons.three > li:nth-child(-n + 3) { margin-top: 0; } ul.grid-icons.three > li:nth-child(-n + 3):after { display: none; } ul.grid-icons.three > li:nth-child(3n - 2) { margin-left: 0; } ul.grid-icons.three > li:nth-child(3n - 2):before { display: none; } ul.grid-icons.four { width: 29rem; } ul.grid-icons.four > li:nth-child(-n + 4) { margin-top: 0; } ul.grid-icons.four > li:nth-child(-n + 4):after { display: none; } ul.grid-icons.four > li:nth-child(4n - 3) { margin-left: 0; } ul.grid-icons.four > li:nth-child(4n - 3):before { display: none; } dl { margin: 0 0 1.5rem 0; } dl dt { display: block; font-weight: 400; margin: 0 0 0.75rem 0; } dl dd { margin-left: 1.5rem; } @media screen and (max-width: 736px) { ul.grid-icons { -moz-justify-content: -moz-flex-start; -webkit-justify-content: -webkit-flex-start; -ms-justify-content: -ms-flex-start; justify-content: flex-start; width: 100% !important; margin: -1rem 0 1.5rem -1rem; } ul.grid-icons .icon:before { width: 4.5rem; height: 4.5rem; line-height: 4.5rem; font-size: 1.75rem; } ul.grid-icons > li { margin: 1rem 0 0 1rem !important; } ul.grid-icons > li:before { display: none !important; } ul.grid-icons > li:after { display: none !important; } } /* Table */ .table-wrapper { -webkit-overflow-scrolling: touch; overflow-x: auto; } table { margin: 0 0 1.5rem 0; width: 100%; } table tbody tr { border: solid 1px rgba(255, 255, 255, 0.25); border-left: 0; border-right: 0; } table tbody tr:nth-child(2n + 1) { background-color: rgba(255, 255, 255, 0.075); } table td { padding: 0.75rem 0.75rem; } table th { color: rgba(255, 255, 255, 0.875); font-size: 0.9rem; font-weight: 400; padding: 0 0.75rem 0.75rem 0.75rem; text-align: left; } table thead { border-bottom: solid 2px rgba(255, 255, 255, 0.25); } table tfoot { border-top: solid 2px rgba(255, 255, 255, 0.25); } table.alt { border-collapse: separate; } table.alt tbody tr td { border: solid 1px rgba(255, 255, 255, 0.25); border-left-width: 0; border-top-width: 0; } table.alt tbody tr td:first-child { border-left-width: 1px; } table.alt tbody tr:first-child td { border-top-width: 1px; } table.alt thead { border-bottom: 0; } table.alt tfoot { border-top: 0; } /* Button */ input[type="submit"], input[type="reset"], input[type="button"], button, .button { -moz-appearance: none; -webkit-appearance: none; -ms-appearance: none; appearance: none; -moz-transition: background-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out, color 0.2s ease-in-out; -webkit-transition: background-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out, color 0.2s ease-in-out; -ms-transition: background-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out, color 0.2s ease-in-out; transition: background-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out, color 0.2s ease-in-out; background-color: transparent; border: 0; border-radius: 0.25rem; box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.25); color: rgba(255, 255, 255, 0.875) !important; cursor: pointer; display: inline-block; font-family: Arial, Helvetica, sans-serif; font-size: 0.6rem; font-weight: 700; height: 2.75rem; letter-spacing: 0.15rem; line-height: 2.75rem; padding: 0 1.5rem 0 1.65rem; text-align: center; text-decoration: none; text-transform: uppercase; white-space: nowrap; } input[type="submit"]:hover, input[type="reset"]:hover, input[type="button"]:hover, button:hover, .button:hover { box-shadow: inset 0 0 0 2px #ffe4b4; color: #ffe4b4 !important; } input[type="submit"]:active, input[type="reset"]:active, input[type="button"]:active, button:active, .button:active { background-color: rgba(255, 228, 180, 0.125); } input[type="submit"].icon:before, input[type="reset"].icon:before, input[type="button"].icon:before, button.icon:before, .button.icon:before { display: inline-block; position: relative; top: -0.075rem; vertical-align: middle; font-size: 0.8rem; margin: 0 0.375rem 0 -0.325rem; } input[type="submit"].icon.circle, input[type="reset"].icon.circle, input[type="button"].icon.circle, button.icon.circle, .button.icon.circle { position: relative; width: 3.125rem; height: 3.125rem; line-height: 3.125rem; text-indent: 3.125rem; border-radius: 100%; overflow: hidden; padding: 0; letter-spacing: 0; } input[type="submit"].icon.circle:before, input[type="reset"].icon.circle:before, input[type="button"].icon.circle:before, button.icon.circle:before, .button.icon.circle:before { display: block; position: absolute; top: 0; left: 0; width: inherit; height: inherit; font-size: 1.25rem; line-height: inherit; margin: 0; text-indent: 0; } input[type="submit"].icon.circle.fa-angle-left:before, input[type="reset"].icon.circle.fa-angle-left:before, input[type="button"].icon.circle.fa-angle-left:before, button.icon.circle.fa-angle-left:before, .button.icon.circle.fa-angle-left:before { position: relative; left: -0.1rem; font-size: 1.75rem; } input[type="submit"].icon.circle.fa-angle-right:before, input[type="reset"].icon.circle.fa-angle-right:before, input[type="button"].icon.circle.fa-angle-right:before, button.icon.circle.fa-angle-right:before, .button.icon.circle.fa-angle-right:before { position: relative; left: 0.1rem; font-size: 1.75rem; } input[type="submit"].fit, input[type="reset"].fit, input[type="button"].fit, button.fit, .button.fit { display: block; margin: 0 0 0.75rem 0; width: 100%; } input[type="submit"].small, input[type="reset"].small, input[type="button"].small, button.small, .button.small { font-size: 0.4rem; height: 1.875rem; line-height: 1.875rem; padding: 0 1.25rem 0 1.4rem; } input[type="submit"].large, input[type="reset"].large, input[type="button"].large, button.large, .button.large { font-size: 0.8rem; height: 3.3125rem; line-height: 3.3125rem; padding: 0 2rem 0 2.15rem; } input[type="submit"].special, input[type="reset"].special, input[type="button"].special, button.special, .button.special { background-color: white; box-shadow: none; color: #2e2b37 !important; } input[type="submit"].special.color1, input[type="reset"].special.color1, input[type="button"].special.color1, button.special.color1, .button.special.color1 { color: #726193 !important; } input[type="submit"].special.color2, input[type="reset"].special.color2, input[type="button"].special.color2, button.special.color2, .button.special.color2 { color: #e37b7c !important; } input[type="submit"].special.color3, input[type="reset"].special.color3, input[type="button"].special.color3, button.special.color3, .button.special.color3 { color: #ffe4b4 !important; } input[type="submit"].special.color4, input[type="reset"].special.color4, input[type="button"].special.color4, button.special.color4, .button.special.color4 { color: #353865 !important; } input[type="submit"].special:hover, input[type="reset"].special:hover, input[type="button"].special:hover, button.special:hover, .button.special:hover { background-color: #ffe4b4; } input[type="submit"].special:active, input[type="reset"].special:active, input[type="button"].special:active, button.special:active, .button.special:active { background-color: #fdd997; } input[type="submit"].disabled, input[type="submit"]:disabled, input[type="reset"].disabled, input[type="reset"]:disabled, input[type="button"].disabled, input[type="button"]:disabled, button.disabled, button:disabled, .button.disabled, .button:disabled { -moz-pointer-events: none; -webkit-pointer-events: none; -ms-pointer-events: none; pointer-events: none; cursor: default; opacity: 0.5; } /* Gallery */ @-moz-keyframes gallery-modal-spinner { 0% { -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @-webkit-keyframes gallery-modal-spinner { 0% { -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @-ms-keyframes gallery-modal-spinner { 0% { -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @keyframes gallery-modal-spinner { 0% { -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } .gallery { -moz-align-items: stretch; -webkit-align-items: stretch; -ms-align-items: stretch; align-items: stretch; display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; height: 100%; } .gallery > * { width: 20rem; height: 100%; } .gallery .image { display: block; position: relative; border-bottom: 0; overflow: hidden; } .gallery .image img { -moz-transition: -moz-transform 0.2s ease-in-out; -webkit-transition: -webkit-transform 0.2s ease-in-out; -ms-transition: -ms-transform 0.2s ease-in-out; transition: transform 0.2s ease-in-out; } .gallery .image:after { -moz-transition: opacity 0.2s ease-in-out; -webkit-transition: opacity 0.2s ease-in-out; -ms-transition: opacity 0.2s ease-in-out; transition: opacity 0.2s ease-in-out; } .gallery .image:hover img { -moz-transform: scale(1.025); -webkit-transform: scale(1.025); -ms-transform: scale(1.025); transform: scale(1.025); } .gallery .image:hover:after { opacity: 0; } .gallery .group { display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-flex-wrap: wrap; -webkit-flex-wrap: wrap; -ms-flex-wrap: wrap; flex-wrap: wrap; } .gallery .group > * { height: 50%; } .gallery .modal { display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-align-items: center; -webkit-align-items: center; -ms-align-items: center; align-items: center; -moz-justify-content: center; -webkit-justify-content: center; -ms-justify-content: center; justify-content: center; -moz-pointer-events: none; -webkit-pointer-events: none; -ms-pointer-events: none; pointer-events: none; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; -moz-transition: opacity 0.5s ease, visibility 0.5s, z-index 0.5s; -webkit-transition: opacity 0.5s ease, visibility 0.5s, z-index 0.5s; -ms-transition: opacity 0.5s ease, visibility 0.5s, z-index 0.5s; transition: opacity 0.5s ease, visibility 0.5s, z-index 0.5s; -webkit-tap-highlight-color: transparent; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(46, 43, 55, 0.875); opacity: 0; outline: 0; visibility: none; z-index: 0; } .gallery .modal:before { -moz-animation: gallery-modal-spinner 1s infinite linear; -webkit-animation: gallery-modal-spinner 1s infinite linear; -ms-animation: gallery-modal-spinner 1s infinite linear; animation: gallery-modal-spinner 1s infinite linear; -moz-transition: opacity 0.25s ease; -webkit-transition: opacity 0.25s ease; -ms-transition: opacity 0.25s ease; transition: opacity 0.25s ease; -moz-transition-delay: 0.5s; -webkit-transition-delay: 0.5s; -ms-transition-delay: 0.5s; transition-delay: 0.5s; content: ''; display: block; position: absolute; top: 50%; left: 50%; width: 4rem; height: 4rem; margin: -2rem 0 0 -2rem; background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='96px' height='96px' viewBox='0 0 96 96' zoomAndPan='disable'%3E%3Cstyle%3Ecircle %7Bfill: transparent%3B stroke: rgba(255, 255, 255, 0.875)%3B stroke-width: 1.5px%3B %7D%3C/style%3E%3Cdefs%3E%3CclipPath id='corner'%3E%3Cpolygon points='0,0 48,0 48,48 96,48 96,96 0,96' /%3E%3C/clipPath%3E%3C/defs%3E%3Cg clip-path='url(%23corner)'%3E%3Ccircle cx='48' cy='48' r='32'/%3E%3C/g%3E%3C/svg%3E"); background-position: center; background-repeat: no-repeat; background-size: 4rem; opacity: 0; } .gallery .modal:after { content: ''; display: block; position: absolute; top: 0.5rem; right: 0.5rem; width: 4rem; height: 4rem; background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='64px' height='64px' viewBox='0 0 64 64' zoomAndPan='disable'%3E%3Cstyle%3Eline %7Bstroke: rgba(255, 255, 255, 0.875)%3Bstroke-width: 1.5px%3B%7D%3C/style%3E%3Cline x1='20' y1='20' x2='44' y2='44' /%3E%3Cline x1='20' y1='44' x2='44' y2='20' /%3E%3C/svg%3E"); background-position: center; background-repeat: no-repeat; background-size: 3rem; cursor: pointer; } .gallery .modal .inner { -moz-transform: translateY(0.75rem); -webkit-transform: translateY(0.75rem); -ms-transform: translateY(0.75rem); transform: translateY(0.75rem); -moz-transition: opacity 0.25s ease, -moz-transform 0.25s ease; -webkit-transition: opacity 0.25s ease, -webkit-transform 0.25s ease; -ms-transition: opacity 0.25s ease, -ms-transform 0.25s ease; transition: opacity 0.25s ease, transform 0.25s ease; opacity: 0; } .gallery .modal .inner img { display: block; max-width: 90vw; max-height: 85vh; box-shadow: 0 1rem 3rem 0 rgba(0, 0, 0, 0.35); } .gallery .modal.visible { -moz-pointer-events: auto; -webkit-pointer-events: auto; -ms-pointer-events: auto; pointer-events: auto; opacity: 1; visibility: visible; z-index: 11000; } .gallery .modal.visible:before { opacity: 1; } .gallery .modal.loaded .inner { -moz-transform: translateY(0); -webkit-transform: translateY(0); -ms-transform: translateY(0); transform: translateY(0); -moz-transition: opacity 0.5s ease, -moz-transform 0.5s ease; -webkit-transition: opacity 0.5s ease, -webkit-transform 0.5s ease; -ms-transition: opacity 0.5s ease, -ms-transform 0.5s ease; transition: opacity 0.5s ease, transform 0.5s ease; opacity: 1; } .gallery .modal.loaded:before { -moz-transition-delay: 0s; -webkit-transition-delay: 0s; -ms-transition-delay: 0s; transition-delay: 0s; opacity: 0; } @media screen and (max-width: 980px) { .gallery .modal .inner img { max-width: 100vw; } } @media screen and (max-width: 736px) { .gallery { -moz-flex-direction: column; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; height: auto; } .gallery > * { height: auto; width: 100%; } .gallery .image { width: 100%; height: 40rem; } .gallery .group .span-0-25 { width: 8.33333%; } .gallery .group .span-0-5 { width: 16.66666%; } .gallery .group .span-0-75 { width: 25%; } .gallery .group .span-1 { width: 33.33333%; } .gallery .group .span-1-25 { width: 41.66666%; } .gallery .group .span-1-5 { width: 50%; } .gallery .group .span-1-75 { width: 58.33333%; } .gallery .group .span-2 { width: 66.66666%; } .gallery .group .span-2-25 { width: 74.99999%; } .gallery .group .span-2-5 { width: 83.33332%; } .gallery .group .span-2-75 { width: 91.66666%; } .gallery .group .span-3 { width: 99.99999%; } .gallery .group .span-3-25 { width: 108.33332%; } .gallery .group .span-3-5 { width: 116.66666%; } .gallery .group .span-3-75 { width: 124.99999%; } .gallery .group .span-4 { width: 133.33332%; } .gallery .group .span-4-25 { width: 141.66665%; } .gallery .group .span-4-5 { width: 149.99998%; } .gallery .group .span-4-75 { width: 158.33332%; } .gallery .group .span-5 { width: 166.66665%; } .gallery .group .span-5-25 { width: 174.99998%; } .gallery .group .span-5-5 { width: 183.33331%; } .gallery .group .span-5-75 { width: 191.66665%; } .gallery .group .span-6 { width: 199.99998%; } .gallery .group .span-6-25 { width: 208.33331%; } .gallery .group .span-6-5 { width: 216.66665%; } .gallery .group .span-6-75 { width: 224.99998%; } .gallery .group .span-7 { width: 233.33331%; } .gallery .group .span-7-25 { width: 241.66664%; } .gallery .group .span-7-5 { width: 249.99997%; } .gallery .group .span-7-75 { width: 258.33331%; } .gallery .group .span-8 { width: 266.66664%; } .gallery .group .span-8-25 { width: 274.99997%; } .gallery .group .span-8-5 { width: 283.33331%; } .gallery .group .span-8-75 { width: 291.66664%; } .gallery .group .span-9 { width: 299.99997%; } .gallery .group .span-9-25 { width: 308.3333%; } .gallery .group .span-9-5 { width: 316.66664%; } .gallery .group .span-9-75 { width: 324.99997%; } .gallery .group .span-10 { width: 333.3333%; } .gallery .group .image { height: 20rem; } } @media screen and (max-width: 480px) { .gallery .image { height: 30rem; } .gallery .group .image { height: 12.5rem; } } /* Panel */ .panel { display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-flex-grow: 0; -webkit-flex-grow: 0; -ms-flex-grow: 0; flex-grow: 0; -moz-flex-shrink: 0; -webkit-flex-shrink: 0; -ms-flex-shrink: 0; flex-shrink: 0; -moz-justify-content: center; -webkit-justify-content: center; -ms-justify-content: center; justify-content: center; -moz-align-items: stretch; -webkit-align-items: stretch; -ms-align-items: stretch; align-items: stretch; height: 100%; overflow-x: hidden; overflow-y: auto; } .panel > * { position: relative; min-width: 10rem; } .panel > *.color0 { background-image: url("../../images/overlay.png"), linear-gradient(45deg, #726193 20%, #e37b7c 60%, #ffe4b4); background-size: 128px 128px, auto; } .panel > *.color1 { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #726193; } .panel > *.color2 { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #e37b7c; } .panel > *.color3 { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #ffe4b4; } .panel > *.color4 { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #353865; } .panel > *.color1-alt { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #6c5e86; } .panel > *.color2-alt { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #de7172; } .panel > *.color3-alt { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #fedea6; } .panel > *.color4-alt { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #323459; } .panel > .intro { padding: 3.5rem 3.5rem 2rem 3.5rem ; display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-flex-grow: 0; -webkit-flex-grow: 0; -ms-flex-grow: 0; flex-grow: 0; -moz-flex-shrink: 0; -webkit-flex-shrink: 0; -ms-flex-shrink: 0; flex-shrink: 0; -moz-justify-content: center; -webkit-justify-content: center; -ms-justify-content: center; justify-content: center; -moz-align-items: -moz-flex-start; -webkit-align-items: -webkit-flex-start; -ms-align-items: -ms-flex-start; align-items: flex-start; -moz-flex-direction: column; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; width: 22rem; } .panel > .intro.joined { width: 18.5rem; padding-right: 0; } .panel > .intro.joined + .inner { padding-left: 2.625rem; } .panel > .inner { padding: 3.5rem 3.5rem 2rem 3.5rem ; display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-flex-grow: 1; -webkit-flex-grow: 1; -ms-flex-grow: 1; flex-grow: 1; -moz-flex-shrink: 1; -webkit-flex-shrink: 1; -ms-flex-shrink: 1; flex-shrink: 1; -moz-justify-content: center; -webkit-justify-content: center; -ms-justify-content: center; justify-content: center; -moz-align-items: -moz-flex-start; -webkit-align-items: -webkit-flex-start; -ms-align-items: -ms-flex-start; align-items: flex-start; -moz-flex-direction: column; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; position: relative; width: 100%; } .panel > .inner.columns { display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-justify-content: center; -webkit-justify-content: center; -ms-justify-content: center; justify-content: center; -moz-align-items: center; -webkit-align-items: center; -ms-align-items: center; align-items: center; -moz-flex-direction: row; -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; } .panel > .inner.columns > * { -moz-flex-grow: 0; -webkit-flex-grow: 0; -ms-flex-grow: 0; flex-grow: 0; -moz-flex-shrink: 0; -webkit-flex-shrink: 0; -ms-flex-shrink: 0; flex-shrink: 0; margin-left: 3.5rem; } .panel > .inner.columns > :first-child { margin-left: 0; } .panel > .inner.columns.divided > * { margin-left: 7rem; } .panel > .inner.columns.divided > *:before { content: ''; position: absolute; top: 3.5rem; width: 2px; height: calc(100% - 7rem); margin-left: -3.5rem; background-color: rgba(255, 255, 255, 0.25); } .panel > .inner.columns.divided > :first-child { margin-left: 0; } .panel > .inner.columns.divided > :first-child:before { display: none; } .panel > .inner.columns.aligned { -moz-align-items: -moz-flex-start; -webkit-align-items: -webkit-flex-start; -ms-align-items: -ms-flex-start; align-items: flex-start; } .panel .span-0-25 { width: 2.5rem; } .panel .span-0-5 { width: 5rem; } .panel .span-0-75 { width: 7.5rem; } .panel .span-1 { width: 10rem; } .panel .span-1-25 { width: 12.5rem; } .panel .span-1-5 { width: 15rem; } .panel .span-1-75 { width: 17.5rem; } .panel .span-2 { width: 20rem; } .panel .span-2-25 { width: 22.5rem; } .panel .span-2-5 { width: 25rem; } .panel .span-2-75 { width: 27.5rem; } .panel .span-3 { width: 30rem; } .panel .span-3-25 { width: 32.5rem; } .panel .span-3-5 { width: 35rem; } .panel .span-3-75 { width: 37.5rem; } .panel .span-4 { width: 40rem; } .panel .span-4-25 { width: 42.5rem; } .panel .span-4-5 { width: 45rem; } .panel .span-4-75 { width: 47.5rem; } .panel .span-5 { width: 50rem; } .panel .span-5-25 { width: 52.5rem; } .panel .span-5-5 { width: 55rem; } .panel .span-5-75 { width: 57.5rem; } .panel .span-6 { width: 60rem; } .panel .span-6-25 { width: 62.5rem; } .panel .span-6-5 { width: 65rem; } .panel .span-6-75 { width: 67.5rem; } .panel .span-7 { width: 70rem; } .panel .span-7-25 { width: 72.5rem; } .panel .span-7-5 { width: 75rem; } .panel .span-7-75 { width: 77.5rem; } .panel .span-8 { width: 80rem; } .panel .span-8-25 { width: 82.5rem; } .panel .span-8-5 { width: 85rem; } .panel .span-8-75 { width: 87.5rem; } .panel .span-9 { width: 90rem; } .panel .span-9-25 { width: 92.5rem; } .panel .span-9-5 { width: 95rem; } .panel .span-9-75 { width: 97.5rem; } .panel .span-10 { width: 100rem; } .panel.small { width: 35rem; } .panel.medium { width: 50rem; } .panel.large { width: 65rem; } .panel.small .span-0-25, .panel.medium .span-0-25, .panel.large .span-0-25 { width: 2.5%; } .panel.small .span-0-5, .panel.medium .span-0-5, .panel.large .span-0-5 { width: 5%; } .panel.small .span-0-75, .panel.medium .span-0-75, .panel.large .span-0-75 { width: 7.5%; } .panel.small .span-1, .panel.medium .span-1, .panel.large .span-1 { width: 10%; } .panel.small .span-1-25, .panel.medium .span-1-25, .panel.large .span-1-25 { width: 12.5%; } .panel.small .span-1-5, .panel.medium .span-1-5, .panel.large .span-1-5 { width: 15%; } .panel.small .span-1-75, .panel.medium .span-1-75, .panel.large .span-1-75 { width: 17.5%; } .panel.small .span-2, .panel.medium .span-2, .panel.large .span-2 { width: 20%; } .panel.small .span-2-25, .panel.medium .span-2-25, .panel.large .span-2-25 { width: 22.5%; } .panel.small .span-2-5, .panel.medium .span-2-5, .panel.large .span-2-5 { width: 25%; } .panel.small .span-2-75, .panel.medium .span-2-75, .panel.large .span-2-75 { width: 27.5%; } .panel.small .span-3, .panel.medium .span-3, .panel.large .span-3 { width: 30%; } .panel.small .span-3-25, .panel.medium .span-3-25, .panel.large .span-3-25 { width: 32.5%; } .panel.small .span-3-5, .panel.medium .span-3-5, .panel.large .span-3-5 { width: 35%; } .panel.small .span-3-75, .panel.medium .span-3-75, .panel.large .span-3-75 { width: 37.5%; } .panel.small .span-4, .panel.medium .span-4, .panel.large .span-4 { width: 40%; } .panel.small .span-4-25, .panel.medium .span-4-25, .panel.large .span-4-25 { width: 42.5%; } .panel.small .span-4-5, .panel.medium .span-4-5, .panel.large .span-4-5 { width: 45%; } .panel.small .span-4-75, .panel.medium .span-4-75, .panel.large .span-4-75 { width: 47.5%; } .panel.small .span-5, .panel.medium .span-5, .panel.large .span-5 { width: 50%; } .panel.small .span-5-25, .panel.medium .span-5-25, .panel.large .span-5-25 { width: 52.5%; } .panel.small .span-5-5, .panel.medium .span-5-5, .panel.large .span-5-5 { width: 55%; } .panel.small .span-5-75, .panel.medium .span-5-75, .panel.large .span-5-75 { width: 57.5%; } .panel.small .span-6, .panel.medium .span-6, .panel.large .span-6 { width: 60%; } .panel.small .span-6-25, .panel.medium .span-6-25, .panel.large .span-6-25 { width: 62.5%; } .panel.small .span-6-5, .panel.medium .span-6-5, .panel.large .span-6-5 { width: 65%; } .panel.small .span-6-75, .panel.medium .span-6-75, .panel.large .span-6-75 { width: 67.5%; } .panel.small .span-7, .panel.medium .span-7, .panel.large .span-7 { width: 70%; } .panel.small .span-7-25, .panel.medium .span-7-25, .panel.large .span-7-25 { width: 72.5%; } .panel.small .span-7-5, .panel.medium .span-7-5, .panel.large .span-7-5 { width: 75%; } .panel.small .span-7-75, .panel.medium .span-7-75, .panel.large .span-7-75 { width: 77.5%; } .panel.small .span-8, .panel.medium .span-8, .panel.large .span-8 { width: 80%; } .panel.small .span-8-25, .panel.medium .span-8-25, .panel.large .span-8-25 { width: 82.5%; } .panel.small .span-8-5, .panel.medium .span-8-5, .panel.large .span-8-5 { width: 85%; } .panel.small .span-8-75, .panel.medium .span-8-75, .panel.large .span-8-75 { width: 87.5%; } .panel.small .span-9, .panel.medium .span-9, .panel.large .span-9 { width: 90%; } .panel.small .span-9-25, .panel.medium .span-9-25, .panel.large .span-9-25 { width: 92.5%; } .panel.small .span-9-5, .panel.medium .span-9-5, .panel.large .span-9-5 { width: 95%; } .panel.small .span-9-75, .panel.medium .span-9-75, .panel.large .span-9-75 { width: 97.5%; } .panel.small .span-10, .panel.medium .span-10, .panel.large .span-10 { width: 100%; } .panel.color0 { background-image: url("../../images/overlay.png"), linear-gradient(45deg, #726193 20%, #e37b7c 60%, #ffe4b4); background-size: 128px 128px, auto; } .panel.color1 { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #726193; } .panel.color2 { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #e37b7c; } .panel.color3 { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #ffe4b4; } .panel.color4 { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #353865; } .panel.color1-alt { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #6c5e86; } .panel.color2-alt { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #de7172; } .panel.color3-alt { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #fedea6; } .panel.color4-alt { background-image: url("../../images/overlay.png"), linear-gradient(45deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #323459; } @media screen and (max-width: 736px) { .panel { -moz-flex-direction: column; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; height: auto; } .panel > *.color1 { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #726193; } .panel > *.color2 { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #e37b7c; } .panel > *.color3 { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #ffe4b4; } .panel > *.color4 { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #353865; } .panel > *.color1-alt { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #6c5e86; } .panel > *.color2-alt { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #de7172; } .panel > *.color3-alt { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #fedea6; } .panel > *.color4-alt { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #323459; } .panel > .intro { padding: 2.8875rem 1.75rem 1.3875rem 1.75rem ; width: 100% !important; } .panel > .intro.joined { padding-bottom: 0; padding-right: 1.75rem; } .panel > .intro.joined + .inner { padding-top: 0; padding-left: 1.75rem; } .panel > .inner { padding: 2.8875rem 1.75rem 1.3875rem 1.75rem ; } .panel > .inner.columns { -moz-flex-direction: column; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; } .panel > .inner.columns > * { margin-left: 0; margin-top: 0; } .panel > .inner.columns > :first-child { margin-top: 0; } .panel > .inner.columns.divided > * { margin-left: 0; margin-top: 3.5rem; } .panel > .inner.columns.divided > *:before { content: ''; position: absolute; top: auto; left: 1.75rem; width: calc(100% - 3.5rem); height: 2px; margin-left: 0; margin-top: -1.75rem; } .panel > .inner.columns.divided > :first-child { margin-top: 0; } .panel .span-0-25 { width: 100%; } .panel .span-0-5 { width: 100%; } .panel .span-0-75 { width: 100%; } .panel .span-1 { width: 100%; } .panel .span-1-25 { width: 100%; } .panel .span-1-5 { width: 100%; } .panel .span-1-75 { width: 100%; } .panel .span-2 { width: 100%; } .panel .span-2-25 { width: 100%; } .panel .span-2-5 { width: 100%; } .panel .span-2-75 { width: 100%; } .panel .span-3 { width: 100%; } .panel .span-3-25 { width: 100%; } .panel .span-3-5 { width: 100%; } .panel .span-3-75 { width: 100%; } .panel .span-4 { width: 100%; } .panel .span-4-25 { width: 100%; } .panel .span-4-5 { width: 100%; } .panel .span-4-75 { width: 100%; } .panel .span-5 { width: 100%; } .panel .span-5-25 { width: 100%; } .panel .span-5-5 { width: 100%; } .panel .span-5-75 { width: 100%; } .panel .span-6 { width: 100%; } .panel .span-6-25 { width: 100%; } .panel .span-6-5 { width: 100%; } .panel .span-6-75 { width: 100%; } .panel .span-7 { width: 100%; } .panel .span-7-25 { width: 100%; } .panel .span-7-5 { width: 100%; } .panel .span-7-75 { width: 100%; } .panel .span-8 { width: 100%; } .panel .span-8-25 { width: 100%; } .panel .span-8-5 { width: 100%; } .panel .span-8-75 { width: 100%; } .panel .span-9 { width: 100%; } .panel .span-9-25 { width: 100%; } .panel .span-9-5 { width: 100%; } .panel .span-9-75 { width: 100%; } .panel .span-10 { width: 100%; } .panel.small, .panel.medium, .panel.large { width: 100% !important; } .panel.small .span-0-25, .panel.medium .span-0-25, .panel.large .span-0-25 { width: 100%; } .panel.small .span-0-5, .panel.medium .span-0-5, .panel.large .span-0-5 { width: 100%; } .panel.small .span-0-75, .panel.medium .span-0-75, .panel.large .span-0-75 { width: 100%; } .panel.small .span-1, .panel.medium .span-1, .panel.large .span-1 { width: 100%; } .panel.small .span-1-25, .panel.medium .span-1-25, .panel.large .span-1-25 { width: 100%; } .panel.small .span-1-5, .panel.medium .span-1-5, .panel.large .span-1-5 { width: 100%; } .panel.small .span-1-75, .panel.medium .span-1-75, .panel.large .span-1-75 { width: 100%; } .panel.small .span-2, .panel.medium .span-2, .panel.large .span-2 { width: 100%; } .panel.small .span-2-25, .panel.medium .span-2-25, .panel.large .span-2-25 { width: 100%; } .panel.small .span-2-5, .panel.medium .span-2-5, .panel.large .span-2-5 { width: 100%; } .panel.small .span-2-75, .panel.medium .span-2-75, .panel.large .span-2-75 { width: 100%; } .panel.small .span-3, .panel.medium .span-3, .panel.large .span-3 { width: 100%; } .panel.small .span-3-25, .panel.medium .span-3-25, .panel.large .span-3-25 { width: 100%; } .panel.small .span-3-5, .panel.medium .span-3-5, .panel.large .span-3-5 { width: 100%; } .panel.small .span-3-75, .panel.medium .span-3-75, .panel.large .span-3-75 { width: 100%; } .panel.small .span-4, .panel.medium .span-4, .panel.large .span-4 { width: 100%; } .panel.small .span-4-25, .panel.medium .span-4-25, .panel.large .span-4-25 { width: 100%; } .panel.small .span-4-5, .panel.medium .span-4-5, .panel.large .span-4-5 { width: 100%; } .panel.small .span-4-75, .panel.medium .span-4-75, .panel.large .span-4-75 { width: 100%; } .panel.small .span-5, .panel.medium .span-5, .panel.large .span-5 { width: 100%; } .panel.small .span-5-25, .panel.medium .span-5-25, .panel.large .span-5-25 { width: 100%; } .panel.small .span-5-5, .panel.medium .span-5-5, .panel.large .span-5-5 { width: 100%; } .panel.small .span-5-75, .panel.medium .span-5-75, .panel.large .span-5-75 { width: 100%; } .panel.small .span-6, .panel.medium .span-6, .panel.large .span-6 { width: 100%; } .panel.small .span-6-25, .panel.medium .span-6-25, .panel.large .span-6-25 { width: 100%; } .panel.small .span-6-5, .panel.medium .span-6-5, .panel.large .span-6-5 { width: 100%; } .panel.small .span-6-75, .panel.medium .span-6-75, .panel.large .span-6-75 { width: 100%; } .panel.small .span-7, .panel.medium .span-7, .panel.large .span-7 { width: 100%; } .panel.small .span-7-25, .panel.medium .span-7-25, .panel.large .span-7-25 { width: 100%; } .panel.small .span-7-5, .panel.medium .span-7-5, .panel.large .span-7-5 { width: 100%; } .panel.small .span-7-75, .panel.medium .span-7-75, .panel.large .span-7-75 { width: 100%; } .panel.small .span-8, .panel.medium .span-8, .panel.large .span-8 { width: 100%; } .panel.small .span-8-25, .panel.medium .span-8-25, .panel.large .span-8-25 { width: 100%; } .panel.small .span-8-5, .panel.medium .span-8-5, .panel.large .span-8-5 { width: 100%; } .panel.small .span-8-75, .panel.medium .span-8-75, .panel.large .span-8-75 { width: 100%; } .panel.small .span-9, .panel.medium .span-9, .panel.large .span-9 { width: 100%; } .panel.small .span-9-25, .panel.medium .span-9-25, .panel.large .span-9-25 { width: 100%; } .panel.small .span-9-5, .panel.medium .span-9-5, .panel.large .span-9-5 { width: 100%; } .panel.small .span-9-75, .panel.medium .span-9-75, .panel.large .span-9-75 { width: 100%; } .panel.small .span-10, .panel.medium .span-10, .panel.large .span-10 { width: 100%; } .panel.color1 { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #726193; } .panel.color2 { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #e37b7c; } .panel.color3 { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #ffe4b4; } .panel.color4 { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.25) 25%, rgba(227, 123, 124, 0.25) 50%, rgba(255, 228, 180, 0.25)); background-size: 128px 128px, auto; background-color: #353865; } .panel.color1-alt { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #6c5e86; } .panel.color2-alt { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #de7172; } .panel.color3-alt { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #fedea6; } .panel.color4-alt { background-image: url("../../images/overlay.png"), linear-gradient(135deg, rgba(114, 97, 147, 0.175) 25%, rgba(227, 123, 124, 0.175) 50%, rgba(255, 228, 180, 0.175)); background-size: 128px 128px, auto; background-color: #323459; } } /* Panel (Banner) */ .panel.banner { -moz-align-items: stretch; -webkit-align-items: stretch; -ms-align-items: stretch; align-items: stretch; } .panel.banner .content { padding: 3.5rem 3.5rem 2rem 3.5rem ; display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-flex-direction: column; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; -moz-justify-content: center; -webkit-justify-content: center; -ms-justify-content: center; justify-content: center; -moz-flex-grow: 0; -webkit-flex-grow: 0; -ms-flex-grow: 0; flex-grow: 0; -moz-flex-shrink: 0; -webkit-flex-shrink: 0; -ms-flex-shrink: 0; flex-shrink: 0; } .panel.banner .content > .actions:last-child { margin-bottom: 0; } .panel.banner .image { -moz-flex-grow: 0; -webkit-flex-grow: 0; -ms-flex-grow: 0; flex-grow: 0; -moz-flex-shrink: 0; -webkit-flex-shrink: 0; -ms-flex-shrink: 0; flex-shrink: 0; position: relative; } .panel.banner .image img { -moz-object-fit: cover; -webkit-object-fit: cover; -ms-object-fit: cover; object-fit: cover; display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .panel.banner.left { -moz-flex-direction: row; -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; } .panel.banner.right { -moz-flex-direction: row-reverse; -webkit-flex-direction: row-reverse; -ms-flex-direction: row-reverse; flex-direction: row-reverse; } @media screen and (max-width: 736px) { .panel.banner .content { padding: 2.8875rem 1.75rem 1.3875rem 1.75rem ; -moz-flex-basis: 60%; -webkit-flex-basis: 60%; -ms-flex-basis: 60%; flex-basis: 60%; } .panel.banner .content > .actions:last-child { margin-bottom: 1.5rem; } .panel.banner .image { -moz-flex-basis: 40%; -webkit-flex-basis: 40%; -ms-flex-basis: 40%; flex-basis: 40%; } } @media screen and (max-width: 736px) and (orientation: portrait) { .panel.banner .content { -moz-flex-basis: auto; -webkit-flex-basis: auto; -ms-flex-basis: auto; flex-basis: auto; } .panel.banner .image { -moz-flex-basis: auto; -webkit-flex-basis: auto; -ms-flex-basis: auto; flex-basis: auto; height: 18rem; } .panel.banner.left { -moz-flex-direction: column; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; } .panel.banner.right { -moz-flex-direction: column-reverse; -webkit-flex-direction: column-reverse; -ms-flex-direction: column-reverse; flex-direction: column-reverse; } } /* Panel (Spotlight) */ .panel.spotlight { -moz-align-items: stretch; -webkit-align-items: stretch; -ms-align-items: stretch; align-items: stretch; position: relative; } .panel.spotlight > * { z-index: 1; } .panel.spotlight .content { display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-flex-direction: column; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; -moz-justify-content: center; -webkit-justify-content: center; -ms-justify-content: center; justify-content: center; padding: 3.5rem 3.5rem 2rem 3.5rem ; } .panel.spotlight .image { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 0; } .panel.spotlight .image img { -moz-object-fit: cover; -webkit-object-fit: cover; -ms-object-fit: cover; object-fit: cover; display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .panel.spotlight.left { -moz-justify-content: -moz-flex-start; -webkit-justify-content: -webkit-flex-start; -ms-justify-content: -ms-flex-start; justify-content: flex-start; } .panel.spotlight.left .content { background-image: linear-gradient(-90deg, transparent 0%, rgba(0, 0, 0, 0.125) 30%, rgba(0, 0, 0, 0.175) 50%); } .panel.spotlight.right { -moz-justify-content: -moz-flex-end; -webkit-justify-content: -webkit-flex-end; -ms-justify-content: -ms-flex-end; justify-content: flex-end; } .panel.spotlight.right .content { background-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.125) 30%, rgba(0, 0, 0, 0.175) 50%); } @media screen and (max-width: 736px) { .panel.spotlight .content { padding: 2.8875rem 1.75rem 1.3875rem 1.75rem ; -moz-flex-direction: column !important; -webkit-flex-direction: column !important; -ms-flex-direction: column !important; flex-direction: column !important; background-image: linear-gradient(0deg, rgba(0, 0, 0, 0.25) 70%, rgba(0, 0, 0, 0.175)) !important; min-height: 25rem; } } @media screen and (max-width: 480px) { .panel.spotlight .content { min-height: 30rem; } } /* Page Wrapper */ .page-wrapper { display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-align-items: center; -webkit-align-items: center; -ms-align-items: center; align-items: center; -moz-justify-content: -moz-flex-start; -webkit-justify-content: -webkit-flex-start; -ms-justify-content: -ms-flex-start; justify-content: flex-start; -moz-flex-grow: 1; -webkit-flex-grow: 1; -ms-flex-grow: 1; flex-grow: 1; -moz-flex-shrink: 1; -webkit-flex-shrink: 1; -ms-flex-shrink: 1; flex-shrink: 1; height: 100%; padding: 5rem; } @media screen and (orientation: portrait) { .page-wrapper { padding-left: 2rem; padding-right: 2rem; } } @media screen and (min-aspect-ratio: 16 / 7) { .page-wrapper { padding: 6vh; } } @media screen and (min-aspect-ratio: 16 / 6) { .page-wrapper { padding: 0; } } @media screen and (max-width: 736px) { .page-wrapper { height: auto; padding: 1rem; } } @media screen and (max-width: 480px) { .page-wrapper { padding: 0; } } /* Wrapper */ .wrapper { display: -moz-flex; display: -webkit-flex; display: -ms-flex; display: flex; -moz-flex-direction: row; -webkit-flex-direction: row; -ms-flex-direction: row; flex-direction: row; -moz-transition: opacity 1s ease-out, -moz-transform 0.75s ease-out; -webkit-transition: opacity 1s ease-out, -webkit-transform 0.75s ease-out; -ms-transition: opacity 1s ease-out, -ms-transform 0.75s ease-out; transition: opacity 1s ease-out, transform 0.75s ease-out; -moz-transition-delay: 0.25s; -webkit-transition-delay: 0.25s; -ms-transition-delay: 0.25s; transition-delay: 0.25s; cursor: default; position: relative; height: 32rem; box-shadow: 0 2rem 4rem 0.25rem rgba(46, 43, 55, 0.575); } .wrapper > .scrollZone { position: fixed; width: 6rem; height: inherit; cursor: -moz-grab; cursor: -webkit-grab; cursor: -ms-grab; cursor: grab; z-index: 10100; } .wrapper > .scrollZone.left { left: 0; } .wrapper > .scrollZone.right { right: 0; } .wrapper > .copyright { position: absolute; bottom: -3rem; right: 31%; font-size: 0.8rem; color: rgba(0, 0, 0, 0.93); margin-bottom: 0; } .wrapper > .copyright a:hover { color: inherit; } .wrapper.is-dragging { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; cursor: -moz-grab; cursor: -webkit-grab; cursor: -ms-grab; cursor: grab; } .wrapper.is-dragging * { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; } .wrapper.is-dragging *:not(a, .image) { cursor: -moz-grab; cursor: -webkit-grab; cursor: -ms-grab; cursor: grab; } .wrapper.is-dragged * { -moz-pointer-events: none; -webkit-pointer-events: none; -ms-pointer-events: none; pointer-events: none; } body.is-loading .wrapper { -moz-transform: translateX(2rem); -webkit-transform: translateX(2rem); -ms-transform: translateX(2rem); transform: translateX(2rem); opacity: 0; } @media screen and (max-width: 736px) { .wrapper { -moz-flex-direction: column; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; height: auto; margin: 0 0 5rem 0; box-shadow: 0 0.25rem 1.5rem 0.25rem rgba(46, 43, 55, 0.5); } .wrapper > .scrollZone { display: none; } .wrapper > .copyright { display: block; width: 100%; text-align: center; } body.is-loading .wrapper { -moz-transform: translateY(1rem); -webkit-transform: translateY(1rem); -ms-transform: translateY(1rem); transform: translateY(1rem); } } @media screen and (max-width: 480px) { .wrapper { box-shadow: none; } body.is-loading .wrapper { -moz-transform: none; -webkit-transform: none; -ms-transform: none; transform: none; } } ================================================ FILE: template/installation/assets/src/css/noscript.css ================================================ /* Ethereal by HTML5 UP html5up.net | @ajlkn Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) */ /* Page */ body { overflow-x: scroll; } ================================================ FILE: template/installation/assets/src/js/main.js ================================================ /* Ethereal by HTML5 UP html5up.net | @ajlkn Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) */ (function($) { // Settings. var settings = { // Keyboard shortcuts. keyboardShortcuts: { // If true, enables scrolling via keyboard shortcuts. enabled: true, // Sets the distance to scroll when using the left/right arrow keys. distance: 50 }, // Scroll wheel. scrollWheel: { // If true, enables scrolling via the scroll wheel. enabled: true, // Sets the scroll wheel factor. (Ideally) a value between 0 and 1 (lower = slower scroll, higher = faster scroll). factor: 1 }, // Scroll zones. scrollZones: { // If true, enables scrolling via scroll zones on the left/right edges of the scren. enabled: true, // Sets the speed at which the page scrolls when a scroll zone is active (higher = faster scroll, lower = slower scroll). speed: 15 }, // Dragging. dragging: { // If true, enables scrolling by dragging the main wrapper with the mouse. enabled: true, // Sets the momentum factor. Must be a value between 0 and 1 (lower = less momentum, higher = more momentum, 0 = disable momentum scrolling). momentum: 0.875, // Sets the drag threshold (in pixels). threshold: 10 }, // If set to a valid selector , prevents key/mouse events from bubbling from these elements. excludeSelector: 'input:focus, select:focus, textarea:focus, audio, video, iframe', // Link scroll speed. linkScrollSpeed: 1000 }; // Skel. skel.breakpoints({ xlarge: '(max-width: 1680px)', large: '(max-width: 1280px)', medium: '(max-width: 980px)', small: '(max-width: 736px)', xsmall: '(max-width: 480px)', xxsmall: '(max-width: 360px)', short: '(min-aspect-ratio: 16/7)', xshort: '(min-aspect-ratio: 16/6)' }); // Ready event. $(function() { // Vars. var $window = $(window), $document = $(document), $body = $('body'), $html = $('html'), $bodyHtml = $('body,html'), $wrapper = $('#wrapper'); // Disable animations/transitions until the page has loaded. $body.addClass('is-loading'); $window.on('load', function() { window.setTimeout(function() { $body.removeClass('is-loading'); }, 100); }); // Tweaks/fixes. // Mobile: Revert to native scrolling. if (skel.vars.mobile) { // Disable all scroll-assist features. settings.keyboardShortcuts.enabled = false; settings.scrollWheel.enabled = false; settings.scrollZones.enabled = false; settings.dragging.enabled = false; // Re-enable overflow on body. $body.css('overflow-x', 'auto'); } // IE: Various fixes. if (skel.vars.browser == 'ie') { // Enable IE mode. $body.addClass('is-ie'); // Page widths. $window .on('load resize', function() { // Calculate wrapper width. var w = 0; $wrapper.children().each(function() { w += $(this).width(); }); // Apply to page. $html.css('width', w + 'px'); }); } // Polyfill: Object fit. if (!skel.canUse('object-fit')) { $('.image[data-position]').each(function() { var $this = $(this), $img = $this.children('img'); // Apply img as background. $this .css('background-image', 'url("' + $img.attr('src') + '")') .css('background-position', $this.data('position')) .css('background-size', 'cover') .css('background-repeat', 'no-repeat'); // Hide img. $img .css('opacity', '0'); }); } // Keyboard shortcuts. if (settings.keyboardShortcuts.enabled) (function() { $wrapper // Prevent keystrokes inside excluded elements from bubbling. .on('keypress keyup keydown', settings.excludeSelector, function(event) { // Stop propagation. event.stopPropagation(); }); $window // Keypress event. .on('keydown', function(event) { var scrolled = false; switch (event.keyCode) { // Left arrow. case 37: $document.scrollLeft($document.scrollLeft() - settings.keyboardShortcuts.distance); scrolled = true; break; // Right arrow. case 39: $document.scrollLeft($document.scrollLeft() + settings.keyboardShortcuts.distance); scrolled = true; break; // Page Up. case 33: $document.scrollLeft($document.scrollLeft() - $window.width() + 100); scrolled = true; break; // Page Down, Space. case 34: case 32: $document.scrollLeft($document.scrollLeft() + $window.width() - 100); scrolled = true; break; // Home. case 36: $document.scrollLeft(0); scrolled = true; break; // End. case 35: $document.scrollLeft($document.width()); scrolled = true; break; } // Scrolled? if (scrolled) { // Prevent default. event.preventDefault(); event.stopPropagation(); // Stop link scroll. $bodyHtml.stop(); } }); })(); // Scroll wheel. // WARN: broke scroll so, comment it. 禁止了滚轮事件,于是注释它 if (false) // (settings.scrollWheel.enabled) (function() { // Based on code by @miorel + @pieterv of Facebook (thanks guys :) // github.com/facebook/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js var normalizeWheel = function(event) { var pixelStep = 10, lineHeight = 40, pageHeight = 800, sX = 0, sY = 0, pX = 0, pY = 0; // Legacy. if ('detail' in event) sY = event.detail; else if ('wheelDelta' in event) sY = event.wheelDelta / -120; else if ('wheelDeltaY' in event) sY = event.wheelDeltaY / -120; if ('wheelDeltaX' in event) sX = event.wheelDeltaX / -120; // Side scrolling on FF with DOMMouseScroll. if ('axis' in event && event.axis === event.HORIZONTAL_AXIS) { sX = sY; sY = 0; } // Calculate. pX = sX * pixelStep; pY = sY * pixelStep; if ('deltaY' in event) pY = event.deltaY; if ('deltaX' in event) pX = event.deltaX; if ((pX || pY) && event.deltaMode) { if (event.deltaMode == 1) { pX *= lineHeight; pY *= lineHeight; } else { pX *= pageHeight; pY *= pageHeight; } } // Fallback if spin cannot be determined. if (pX && !sX) sX = (pX < 1) ? -1 : 1; if (pY && !sY) sY = (pY < 1) ? -1 : 1; // Return. return { spinX: sX, spinY: sY, pixelX: pX, pixelY: pY }; }; // Wheel event. $body.on('wheel', function(event) { // Disable on <=small. if (skel.breakpoint('small').active) return; // Prevent default. event.preventDefault(); event.stopPropagation(); // Stop link scroll. $bodyHtml.stop(); // Calculate delta, direction. var n = normalizeWheel(event.originalEvent), x = (n.pixelX != 0 ? n.pixelX : n.pixelY), delta = Math.min(Math.abs(x), 150) * settings.scrollWheel.factor, direction = x > 0 ? 1 : -1; // Scroll page. $document.scrollLeft($document.scrollLeft() + (delta * direction)); }); })(); // Scroll zones. if (settings.scrollZones.enabled) (function() { var $left = $('
    '), $right = $('
    '), $zones = $left.add($right), paused = false, intervalId = null, direction, activate = function(d) { // Disable on <=small. if (skel.breakpoint('small').active) return; // Paused? Bail. if (paused) return; // Stop link scroll. $bodyHtml.stop(); // Set direction. direction = d; // Initialize interval. clearInterval(intervalId); intervalId = setInterval(function() { $document.scrollLeft($document.scrollLeft() + (settings.scrollZones.speed * direction)); }, 25); }, deactivate = function() { // Unpause. paused = false; // Clear interval. clearInterval(intervalId); }; $zones .appendTo($wrapper) .on('mouseleave mousedown', function(event) { deactivate(); }); $left .css('left', '0') .on('mouseenter', function(event) { activate(-1); }); $right .css('right', '0') .on('mouseenter', function(event) { activate(1); }); $wrapper .on('---pauseScrollZone', function(event) { // Pause. paused = true; // Unpause after delay. setTimeout(function() { paused = false; }, 500); }); })(); // Dragging. if (settings.dragging.enabled) (function() { var dragging = false, dragged = false, distance = 0, startScroll, momentumIntervalId, velocityIntervalId, startX, currentX, previousX, velocity, direction; $wrapper // Prevent image drag and drop. .on('mouseup mousemove mousedown', '.image, img', function(event) { event.preventDefault(); }) // Prevent mouse events inside excluded elements from bubbling. .on('mouseup mousemove mousedown', settings.excludeSelector, function(event) { // Prevent event from bubbling. event.stopPropagation(); // End drag. dragging = false; $wrapper.removeClass('is-dragging'); clearInterval(velocityIntervalId); clearInterval(momentumIntervalId); // Pause scroll zone. $wrapper.triggerHandler('---pauseScrollZone'); }) // Mousedown event. .on('mousedown', function(event) { // Disable on <=small. if (skel.breakpoint('small').active) return; // Clear momentum interval. clearInterval(momentumIntervalId); // Stop link scroll. $bodyHtml.stop(); // Start drag. dragging = true; $wrapper.addClass('is-dragging'); // Initialize and reset vars. startScroll = $document.scrollLeft(); startX = event.clientX; previousX = startX; currentX = startX; distance = 0; direction = 0; // Initialize velocity interval. clearInterval(velocityIntervalId); velocityIntervalId = setInterval(function() { // Calculate velocity, direction. velocity = Math.abs(currentX - previousX); direction = (currentX > previousX ? -1 : 1); // Update previous X. previousX = currentX; }, 50); }) // Mousemove event. .on('mousemove', function(event) { // Not dragging? Bail. if (!dragging) return; // Velocity. currentX = event.clientX; // Scroll page. $document.scrollLeft(startScroll + (startX - currentX)); // Update distance. distance = Math.abs(startScroll - $document.scrollLeft()); // Distance exceeds threshold? Disable pointer events on all descendents. if (!dragged && distance > settings.dragging.threshold) { $wrapper.addClass('is-dragged'); dragged = true; } }) // Mouseup/mouseleave event. .on('mouseup mouseleave', function(event) { var m; // Not dragging? Bail. if (!dragging) return; // Dragged? Re-enable pointer events on all descendents. if (dragged) { setTimeout(function() { $wrapper.removeClass('is-dragged'); }, 100); dragged = false; } // Distance exceeds threshold? Prevent default. if (distance > settings.dragging.threshold) event.preventDefault(); // End drag. dragging = false; $wrapper.removeClass('is-dragging'); clearInterval(velocityIntervalId); clearInterval(momentumIntervalId); // Pause scroll zone. $wrapper.triggerHandler('---pauseScrollZone'); // Initialize momentum interval. if (settings.dragging.momentum > 0) { m = velocity; momentumIntervalId = setInterval(function() { // Scroll page. $document.scrollLeft($document.scrollLeft() + (m * direction)); // Decrease momentum. m = m * settings.dragging.momentum; // Negligible momentum? Clear interval and end. if (Math.abs(m) < 1) clearInterval(momentumIntervalId); }, 15); } }); })(); // Link scroll. $wrapper .on('mousedown mouseup', 'a[href^="#"]', function(event) { // Stop propagation. event.stopPropagation(); }) .on('click', 'a[href^="#"]', function(event) { var $this = $(this), href = $this.attr('href'), $target, x, y; // Get target. if (href == '#' || ($target = $(href)).length == 0) return; // Prevent default. event.preventDefault(); event.stopPropagation(); // Calculate x, y. if (skel.breakpoint('small').active) { x = $target.offset().top - (Math.max(0, $window.height() - $target.outerHeight()) / 2); y = { scrollTop: x }; } else { x = $target.offset().left - (Math.max(0, $window.width() - $target.outerWidth()) / 2); y = { scrollLeft: x }; } // Scroll. $bodyHtml .stop() .animate( y, settings.linkScrollSpeed, 'swing' ); }); // Gallery. $('.gallery') .on('click', 'a', function(event) { var $a = $(this), $gallery = $a.parents('.gallery'), $modal = $gallery.children('.modal'), $modalImg = $modal.find('img'), href = $a.attr('href'); // Not an image? Bail. if (!href.match(/\.(jpg|gif|png|mp4)$/)) return; // Prevent default. event.preventDefault(); event.stopPropagation(); // Locked? Bail. if ($modal[0]._locked) return; // Lock. $modal[0]._locked = true; // Set src. $modalImg.attr('src', href); // Set visible. $modal.addClass('visible'); // Focus. $modal.focus(); // Delay. setTimeout(function() { // Unlock. $modal[0]._locked = false; }, 600); }) .on('click', '.modal', function(event) { var $modal = $(this), $modalImg = $modal.find('img'); // Locked? Bail. if ($modal[0]._locked) return; // Already hidden? Bail. if (!$modal.hasClass('visible')) return; // Stop propagation. event.stopPropagation(); // Lock. $modal[0]._locked = true; // Clear visible, loaded. $modal .removeClass('loaded') // Delay. setTimeout(function() { $modal .removeClass('visible') // Pause scroll zone. $wrapper.triggerHandler('---pauseScrollZone'); setTimeout(function() { // Clear src. $modalImg.attr('src', ''); // Unlock. $modal[0]._locked = false; // Focus. $body.focus(); }, 475); }, 125); }) .on('keypress', '.modal', function(event) { var $modal = $(this); // Escape? Hide modal. if (event.keyCode == 27) $modal.trigger('click'); }) .on('mouseup mousedown mousemove', '.modal', function(event) { // Stop propagation. event.stopPropagation(); }) .prepend('') .find('img') .on('load', function(event) { var $modalImg = $(this), $modal = $modalImg.parents('.modal'); setTimeout(function() { // No longer visible? Bail. if (!$modal.hasClass('visible')) return; // Set loaded. $modal.addClass('loaded'); }, 275); }); }); })(jQuery); ================================================ FILE: template/installation/assets.go ================================================ // Code generated by go-bindata. DO NOT EDIT. // sources: // assets/login/dist/all.min.css // assets/login/dist/all.min.js // assets/login/dist/respond.min.js package login import ( "bytes" "compress/gzip" "fmt" "io" "io/ioutil" "os" "path/filepath" "strings" "time" ) func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { return nil, fmt.Errorf("Read %q: %v", name, err) } var buf bytes.Buffer _, err = io.Copy(&buf, gz) clErr := gz.Close() if err != nil { return nil, fmt.Errorf("Read %q: %v", name, err) } if clErr != nil { return nil, err } return buf.Bytes(), nil } type asset struct { bytes []byte info os.FileInfo } type bindataFileInfo struct { name string size int64 mode os.FileMode modTime time.Time } func (fi bindataFileInfo) Name() string { return fi.name } func (fi bindataFileInfo) Size() int64 { return fi.size } func (fi bindataFileInfo) Mode() os.FileMode { return fi.mode } func (fi bindataFileInfo) ModTime() time.Time { return fi.modTime } func (fi bindataFileInfo) IsDir() bool { return false } func (fi bindataFileInfo) Sys() interface{} { return nil } var _assetsLoginDistAllMinCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x6b\xb7\xe3\xb6\xb1\x20\xfa\xfd\xfc\x0a\xc6\x5e\xbd\xdc\xed\x16\xd9\x24\xf5\xda\x92\x56\xfa\xc6\x76\xe2\x19\xdf\x39\x19\xdf\x35\x27\x9e\x49\xc6\xf1\x9d\x05\x91\x90\x44\x37\x45\x32\x24\xb5\x1f\xd6\x68\x7e\xfb\x2c\xe2\x41\xe2\x51\x00\x49\xed\xdd\xaf\x64\x9f\x3e\x49\xb4\x51\x85\x42\xa1\xaa\x50\x05\x14\xf1\xf8\xc3\x2e\xcf\x6a\x77\x87\x22\x7c\x66\xbf\x8e\x49\xfa\xb0\xce\x0b\x9c\x39\x15\xca\xaa\x0d\x29\xad\xea\x87\x14\xaf\xb3\xbc\x3c\xa2\x94\x96\xdc\xe1\x64\x7f\xa8\xd7\x53\xdf\xdf\x54\x65\xb4\x4e\xf3\x08\xa5\x2f\xbf\xfa\xb1\xa9\xf6\x1f\x28\xab\x9c\x7f\x6f\xc0\x5f\xbd\x9a\x08\x80\xa6\xdc\xe5\xe5\xa7\x32\x7d\x79\xa8\xeb\xa2\x5a\xbf\x79\xd3\x10\xac\xbc\x7d\x55\xa3\x3a\x89\xbc\x28\x3f\xbe\xa9\xde\x34\x0c\x34\xed\xbf\xb9\x0d\x96\x6f\x8e\xf8\x38\xff\x1b\xfa\x4f\x55\x10\x2e\xfe\x9c\xfc\xcf\xe2\xdb\x6f\xdc\x9f\xfe\xeb\xff\x2a\x6f\x7e\xfc\xab\x7b\x28\xfe\xcb\x7f\xf9\x8f\xbf\xfc\x3a\xff\xff\xfe\x87\x77\x97\xef\x76\xe1\xab\x5d\xc3\x63\xfd\xf2\x2b\xf2\xd7\x57\xaf\x36\xa7\x2c\x89\xf2\x18\xbb\x25\xca\xf6\x78\xfd\xd3\x6b\x7f\xb6\xf0\x5d\x7f\x1e\x7e\x3f\xf9\xe9\x75\xf0\xdd\x8d\xef\x06\xdf\xdd\xdc\x4c\x7e\x7a\x1d\xfa\xdf\xce\x9a\xff\xf9\xe3\x9f\x7c\x37\xfc\xe3\xf7\x0d\xf8\x9b\xc5\xcc\x77\xbf\x59\xac\x9a\xdf\xdf\xff\x29\xfc\x93\xfb\xfd\x9f\xc2\xef\x2f\x9f\xb5\xc0\xfe\xfb\xe9\x0a\x81\xf9\xbe\xeb\xcf\xe6\x8d\x14\xfc\xd9\xaa\xf9\xbd\x0a\xc8\xef\x6f\x9b\xdf\xdf\x36\xbf\xc3\x20\x58\x7c\xde\x82\xf9\xeb\x78\xc1\x04\xdf\xfb\xbe\x1b\x7c\xff\xfd\x67\x6e\x12\x3f\xe1\xf1\x26\x31\x5d\xfa\xae\x3f\xfd\xdc\x7b\xfe\xd7\x2b\x7a\x1e\xf8\xa1\xeb\x07\xfe\xb4\x19\x00\x41\xe0\xbb\x7e\x10\x34\x03\x20\xf8\xd3\x37\xbe\x1b\xfc\xe9\xfb\x15\xf1\x24\xdf\x7c\xfb\x99\x0b\xe6\xc7\x6b\x04\xe3\xbb\x7e\x38\x23\x5e\x22\x9c\xaf\x88\x4c\x7c\x22\x93\xef\x89\x4c\x42\x9f\x8a\xc6\x77\x1b\xf9\xd0\xdf\x7f\x74\x43\xff\xbb\xef\xa9\xff\x68\x24\x1a\x7e\xb7\xf0\xdd\xf0\xbb\x25\x71\xbe\xcb\xd0\x77\xbf\x59\x7e\xee\x36\xf6\x13\xf7\x2b\x77\x43\x05\xe9\x37\x82\xf4\x89\xd4\xfc\x60\x4a\x3c\x6d\x30\x6f\x8c\x6e\x4e\x8c\x2e\xfc\xf6\x5b\xd7\x0f\xbf\xfd\x8e\xfc\xfe\x6e\x41\xfe\xe7\x8f\xdf\xd0\xff\xf9\x8e\x88\xd5\x6f\x44\xbc\xa0\x52\x5f\xce\xa8\xa4\x09\x24\x08\x43\xf2\x3f\x2b\xea\xb2\x57\x44\xe4\x61\x10\xd2\xff\x99\x93\x28\x47\xda\xfd\xfe\xfb\xef\xff\xf8\x58\xb1\xcf\x4c\x62\xff\x6f\x78\x7f\x4a\x51\x09\x08\xbe\x83\x8c\x15\xfd\x8d\x22\xfa\xef\xff\xc7\xff\xeb\x6f\x77\x37\xc5\xbb\x6f\x8a\x05\xfa\x4c\x26\x06\x1f\x57\x60\x3f\xfd\xcf\x2b\x04\xf6\x61\x26\x06\x1f\xd9\x92\xc6\x0b\xe6\xc9\x26\x06\x1f\xb7\xe7\xff\xbd\x18\x6f\x12\x4f\x35\x31\xf8\xc8\x3a\xbf\xa2\xe7\x1f\x68\x62\xf0\x91\x05\x33\xbf\x46\x30\x9f\xe8\xc4\xe0\x23\x8f\x2e\xee\x57\xf6\xff\x62\x13\x83\xa5\x49\xec\xdf\xe6\x69\x0c\xc8\x9c\x15\x3f\x7a\x36\xb6\x2c\xf7\x9f\x63\xbe\xe0\x63\x8a\xeb\x13\xce\x16\x7c\x54\x2b\xfa\x88\xb9\x82\x8f\xd9\xef\x8f\x99\x29\xf8\xa8\xfa\xfe\x74\xf3\x04\x1f\x55\x2c\xff\x4c\x59\x82\x8f\x3a\xae\x3e\xdb\x1c\xc1\x9b\xaf\x7f\xf7\xb5\xf3\x6d\x9e\xd7\x55\x5d\xa2\xc2\xb9\x9d\x7a\x53\x6f\xe9\x10\x89\xac\xdf\xbc\xd9\xe3\x7a\xcb\x61\x8d\x3c\x5e\xfd\xdb\xd7\xce\x77\x79\xf1\x50\x36\x12\x77\x42\x3f\x08\xdc\xd0\x0f\x16\xce\x5f\xee\x92\xba\xc6\xe5\xc4\xf9\x21\x8b\xbc\x7f\xfb\xda\xf9\xf7\x24\xc2\x59\x85\x63\xe7\x94\xc5\xb8\x74\xfe\xfc\xc3\x5f\x9c\x56\xc8\xfb\xa4\x3e\x9c\xb6\x44\xba\xf5\xdd\xb6\x7a\xd3\x36\xf0\x66\x9b\xe6\xdb\x37\x47\x54\xd5\xb8\x7c\xf3\xef\x3f\x7c\xf7\xa7\xff\xfa\x1f\x7f\x7a\xf5\xf5\x9b\x37\x5f\xff\x8e\x6a\x3b\xf9\x0d\x7b\x51\x55\x35\x3c\xfa\xde\xd4\xf9\xdf\x84\x2c\x6b\xc9\xf9\xdf\x8e\x40\x37\xc3\x51\x9e\xa2\xea\x8d\x54\xef\xeb\x37\x87\xfa\x98\x4a\xa6\xd5\xe8\xd5\xad\x70\x99\xec\x36\xee\x1d\xde\xbe\x4b\x6a\xb7\xc6\xf7\xb5\x5b\x25\xbf\x61\x17\xc5\xbf\x9e\xaa\x7a\x1d\xf8\xfe\x8b\x8d\x7b\xac\x60\xc8\x65\x9b\xc7\x0f\xe7\x23\x2a\xf7\x49\xb6\xf6\x2f\xa8\xac\x93\x28\xc5\x13\x54\x25\x31\x9e\xc4\xb8\x46\x49\x5a\x4d\x76\xc9\x3e\x42\x45\x9d\xe4\x59\xf3\xf3\x54\xe2\xc9\x2e\xcf\x1b\x71\x1d\x30\x8a\x9b\xff\xd9\x97\xf9\xa9\x98\x1c\x51\x92\x4d\x8e\x38\x3b\x4d\x32\x74\x3b\xa9\x70\x44\x6a\x54\xa7\xe3\x11\x95\x0f\xe7\x38\xa9\x8a\x14\x3d\xac\xb7\x69\x1e\xbd\xbb\xa0\x53\x9c\xe4\x93\x08\x65\xb7\xa8\x9a\x14\x65\xbe\x2f\x71\x55\x4d\x6e\x93\x18\xe7\x2d\x66\x92\xa5\x49\x86\x5d\x52\x61\x73\x8b\x1b\xd6\x50\xea\xa2\x34\xd9\x67\xeb\x2d\xaa\x70\x03\xa5\x84\xd6\x59\x5e\xbf\xfc\x39\xca\xb3\xba\xcc\xd3\xea\x97\x57\x2d\x89\x2c\xcf\xf0\xe6\x40\xc7\x97\x7f\xf9\xf9\x90\xc4\x31\xce\x7e\x99\xd4\xf8\x58\xa4\xa8\xc6\x12\xde\x05\x9d\xb7\x28\x7a\xd7\xf4\x25\x8b\xdd\x28\x4f\xf3\x72\x5d\x97\x28\xab\x0a\x54\xe2\xac\xbe\xa0\x35\x8a\xea\xe4\x16\x4f\xd0\xfa\x90\xdf\xe2\xf2\x9c\x9f\xea\x86\x85\x46\x6c\xdb\x6d\xf9\x73\x9d\xd4\x29\xfe\xe5\xbc\xcd\xcb\x18\x97\xee\x36\xaf\xeb\xfc\xb8\x0e\x8a\x7b\x27\xce\xeb\x1a\xc7\x97\xed\xa4\xaa\xcb\x3c\xdb\x9f\x95\x41\x7f\x89\x77\xd9\x59\x70\x0d\x49\x8d\xd2\x24\xba\x1c\x02\xae\x16\x6f\xb1\xc4\x47\xc7\x67\xee\x23\xf9\x0d\xaf\x43\x7c\xbc\x1c\x51\xf9\xee\x4c\xb9\xfc\xd2\xf7\xfd\x4d\xc7\xfb\xfa\xcb\xdd\xce\xbf\x54\x47\x94\x32\x6b\x21\x75\x6e\xfc\x17\x97\xea\xb4\x9d\x54\xa7\xe2\x5c\xe4\x55\xd2\x28\x67\x5d\xe2\x14\x35\x7d\x12\x68\x2f\xe7\x2f\x36\x44\xee\x5c\x6c\x46\xd1\x37\x94\xea\xbc\x58\xbb\xde\x1c\x1f\x1b\xda\x67\xd6\x69\xd7\x0b\x9b\x92\xe4\xb8\x67\xd2\x58\xfb\x97\xea\x76\x4f\xb4\xb4\x2e\xf3\xbc\x7e\x75\x6e\x04\xb8\x4b\xf3\xbb\x35\x55\xc9\x85\xda\x15\xef\x71\x80\x8f\xce\xcc\x2f\xee\x2f\x87\xf2\xdc\xb2\xc1\x2d\x7c\x9b\xdf\x37\x9c\x26\xd9\x7e\xdd\x68\x1c\x67\xa4\x68\xe3\x1e\xf3\xdf\x4c\x30\xb8\xf8\x52\x94\xb8\x63\x04\x9d\xea\xfc\xd2\xf8\xb8\xc9\xbb\x6d\x3c\x29\x4a\x3c\xa9\xd0\xb1\x90\x86\xdb\x31\xcf\xf2\xaa\x40\x11\x9e\xb4\xbf\x04\xc1\x05\xf8\x78\xd9\x9e\xea\x3a\xcf\x26\x49\x56\x9c\xea\x49\x5e\xd4\x74\x60\x54\x38\xc5\x51\x3d\x69\x06\x20\x2a\x31\x6a\x87\x1b\xa9\xbc\x4e\xb2\x03\x2e\x93\x7a\x43\x75\xc9\xfe\x62\x94\x3a\xf6\x6e\x93\x2a\xd9\xa6\x98\xb7\x40\x49\x9e\xc9\x98\x26\x46\xda\x38\x6c\x6a\xc6\x0c\xa3\x71\x16\x0e\x61\xe4\xe7\xfa\xa1\xc0\xbf\xa7\xc5\xbf\x4c\x84\xa2\x12\x57\xb8\x96\x4a\xaa\xd3\xf6\x98\xd4\xbf\x9c\xb9\xac\x51\x51\x60\x54\xa2\x2c\xc2\x6b\x5a\x7f\x13\x9d\xca\x2a\x2f\xd7\x45\x9e\x64\x35\x2e\x59\x63\x3f\xc7\x49\x85\xb6\x29\x8e\x7f\x11\x9b\x6d\x0b\xcf\xac\x52\x8c\x77\xe8\x94\xf2\xbe\xad\xd7\x44\x65\xbb\x3c\x3a\x55\x6e\x92\x65\xb8\xa4\x9c\xe8\xe5\xe7\x02\xc5\x71\xa3\x3c\x7f\xd3\xda\x13\x41\x3d\x8b\x86\x4a\x9d\xe5\x45\xe8\x4d\x74\xc0\xd1\xbb\x6d\x7e\x2f\x77\x1a\xc5\x49\xde\xf5\x50\x30\x8d\x76\xe4\xea\xc6\x24\x80\xe0\xd2\x96\x43\xb1\xfd\xec\x74\xdc\xe2\xf2\x97\xf5\x9a\x37\x46\x7a\xe3\x56\x45\x92\xb9\xa2\xa5\x18\xb0\xf3\x53\x2d\x63\xf3\xb1\x40\x4c\x55\xd4\x1a\x46\x65\x74\x00\xfb\xf4\xb8\x11\xb2\x01\xec\xa0\x31\xb9\x5d\x82\xd3\x18\xe0\xa0\xe3\x9d\x16\xb8\x51\x53\x25\x05\x3a\x6b\xaa\x10\xe3\x28\x2f\x51\xe3\x9b\x20\x1b\x24\xf6\x4d\x1a\xaf\x70\xdd\x5a\x85\x37\x9d\xe3\xa3\xe3\x2d\x42\xf2\x3f\xcb\x39\x3e\x6e\xf8\x08\x73\xc2\xe2\x9e\xdb\x4c\xe3\x8a\xab\x3c\x4d\x62\xa7\x4a\xd2\x5b\x5c\x5e\x52\xbc\xc7\x59\x0c\x19\x57\x3b\x52\x65\xef\xc0\x07\xb4\xe6\xc1\xeb\xc6\xce\xb9\xe7\x6f\xfc\x82\x48\xaf\x09\x25\x29\x2a\x2a\xbc\xe6\x3f\x2e\x75\x3c\xa9\x0f\x5d\xc3\xcd\x24\xe6\x3f\xf2\x53\x19\xe1\xb5\x03\xcc\x32\x0e\xf3\x6d\x41\x62\xff\xdc\xdd\xe6\x49\x8a\x4b\x12\xbb\xa4\xd9\x46\x55\x46\x6f\xa2\xaa\x7a\xd3\x84\x60\x3a\x57\xf8\xc3\x11\xc7\x09\x72\x8a\x32\xc9\xea\xf3\xd7\x93\x35\xda\x35\x01\x7b\xbd\xc5\xbb\xbc\xc4\x42\xdc\xf8\x5d\x72\x2c\xf2\xb2\x46\x59\xbd\xa1\x13\x84\x03\x8a\xf3\x3b\x22\x69\x01\x24\x04\x17\xdf\x11\xeb\x48\x26\x07\x57\x35\x41\x2e\x68\x82\x88\x5b\xab\x71\x4c\x1d\x59\xa7\xfc\x35\x99\x77\xd1\x00\xff\xf3\xa1\xc4\xbb\x5f\x68\x07\xce\xcc\x38\xd7\x5f\x38\x2f\xbf\x70\x50\x5d\x97\x2f\x1b\xe8\xab\x2f\x5e\x7d\x21\x06\x61\x23\x32\x01\x53\x6c\x42\xf6\xff\xff\xfd\x17\xbf\xa2\x5b\x54\x45\x65\x52\xd4\xeb\x2f\x58\xc5\x49\x0b\xfc\xf2\x0b\x8d\xd6\x17\x17\x32\x21\xf9\xc7\x29\xaf\x71\x13\x26\xce\x9a\x79\x7d\xb9\x5a\xad\x36\x05\xda\x63\x77\x5b\x62\xf4\xce\x4d\xb2\x66\x36\xb5\x46\xb7\x79\x12\x5f\xea\x66\xce\xd4\xce\x3b\x88\xe1\xb8\x74\x1a\xe5\x12\xdb\x6a\xa2\xe6\xa4\x6e\x5c\x1e\x5c\xbf\x09\xaa\x47\x74\xef\xde\x25\x71\x7d\x20\x53\x38\x41\xa2\x87\x70\x72\x98\x4e\x8a\x73\x5e\x16\x07\x94\x55\xeb\xe9\xe6\x2e\x89\xf3\xbb\x6a\x3d\xa5\x20\x91\x2a\xe9\x16\x23\xea\x65\xe8\x76\x8b\x4a\x79\x3a\xe4\x6d\xeb\xec\xad\x17\xa1\x12\xd7\x13\x2f\x2e\xf3\xe2\x54\xbc\x15\xca\xb8\xb9\xd7\x79\xe1\x42\xe6\x74\xf1\x52\xb4\xc5\x29\x20\x1e\xdf\xf7\x2f\x9e\x34\x64\xb4\x11\x22\x92\x21\x98\x4e\x1d\x4f\xf8\xaf\x83\x3e\x4f\xfb\x72\xb7\xdb\x69\x75\x5c\x4a\x1d\xc7\x5d\x65\xa1\xe8\x00\x70\x16\xc7\xb1\x40\xc5\xb4\xa0\xdb\xa7\x0f\xc5\x21\x89\xf2\xac\x72\x0e\x28\xdd\xa5\x49\xb6\xaf\xc8\xca\x8d\x2f\xc5\xd6\x6f\xde\x3c\xa0\xac\x3a\x24\x5e\x75\x8a\x50\x72\x38\xe5\x64\x1c\x1f\xf3\x18\xa5\xd5\x9b\x70\xf1\x26\x5c\x2c\x67\x6f\x62\x7c\xcc\xe9\x8a\xed\x4d\x47\xd1\x6d\x29\xba\x25\xcd\xf4\x7a\x38\xaf\x5f\xbd\x5f\xf2\xff\x4f\xbb\xdc\xc3\xc7\x2d\x8e\x63\x1c\xbb\xcd\xaa\xb1\x71\xd4\xc2\x02\xf3\x69\x9b\x05\x97\x99\xef\xb1\x2d\xa9\xa9\xf7\xd6\x52\x5d\x77\x0d\xd5\xe5\x09\xbf\x57\x11\x56\xb7\xfb\xb6\xb1\xea\x76\xff\xd5\xab\x8b\xd7\xe2\x03\x53\xfc\x66\xaa\x1e\x14\xf7\x1b\x70\x79\xd5\x6b\xdf\xfd\x1f\x32\xc4\xb9\x58\xd0\x06\x06\x5a\xef\x98\xe7\xf5\xa1\x89\x75\x28\xab\x13\x94\x26\xa8\xc2\x31\x9d\x8f\xe4\xd5\xbd\x8a\xb3\x2f\xd1\x43\x15\xa1\x14\x0b\xfd\x71\x49\x9c\x4b\xaa\x77\x5d\x04\x63\xfe\xf8\xef\xbe\x1f\xa2\x2f\x44\xd4\x22\x3d\x55\x20\xda\x56\x42\xc3\xa7\x92\x61\x4d\xe4\xd2\x5c\xaf\x1c\xfa\x28\x92\x2a\x1f\x93\x0c\x6a\x24\x0c\x83\x50\xc2\x8b\xd2\xfc\x14\x03\x78\x0b\x3f\x90\x99\xc9\x6e\x71\x9a\x17\x18\x40\x5d\xfa\x2b\xb9\x7b\x38\x8b\x92\x14\x44\xdc\x49\x88\xfb\x14\x55\x00\x8f\xd8\x57\xda\x3e\x9e\xaa\x24\x02\xf1\xe4\xbe\xd0\x29\x1a\x88\x38\x95\x10\x0f\x18\x95\x35\x88\x37\x97\x09\xd6\xa8\x04\xd1\x16\x1a\x9a\x8b\x8f\x45\xfd\x00\x22\x2f\x25\xe4\x53\x85\x61\x9a\x37\x12\xda\x2e\x49\x8f\x20\x9a\x2c\xeb\xfa\xe0\xa6\xa8\xdc\x03\x6a\xc1\x7e\xe0\x2b\xa8\x20\x52\xa0\xd1\x4b\x2a\x50\x36\x8a\xe1\xe4\x80\xa5\x63\x3f\x90\x05\x5d\xe2\x63\x7e\x0b\x33\x37\x93\x10\x7f\xcb\xf3\xa3\x9b\x64\x20\xe6\x5c\xc7\xcc\x4f\x30\x8b\xb2\x5e\xf2\xdd\x0e\xc4\x92\x15\x52\x25\xfb\x0c\x01\xe6\x8a\xfd\x40\x56\x49\x94\xef\x41\x2c\x45\x23\x25\xaa\x40\x49\x87\xb2\x3a\x0e\xf9\x11\x14\x4c\x18\xa8\x76\x00\xa3\xc9\xda\xa8\x13\x03\x35\x45\x1f\x39\x02\x06\x3b\xf6\x43\x59\x1b\x71\x7e\x97\xa5\x39\x8a\x5d\x94\x82\x72\x0e\xe7\x20\x3a\x88\x2a\xab\xe4\x54\x18\x11\x65\xad\x24\xd9\x36\xbf\x07\xf1\x6e\x14\x5f\x8a\x1e\xdc\x28\x29\x23\x83\x98\x56\x8a\x3d\x16\x18\x81\x5d\x9a\xfa\x0a\xe2\xae\xc4\xb0\x1e\xa7\xb2\x82\x9a\xe1\x62\x92\xd3\x54\x56\x52\x13\xc8\x40\x34\x59\x49\xbb\x14\x81\x86\x36\x9d\xa9\x4e\x2c\x2e\x0e\x79\x86\x41\x17\x3a\x95\x55\x74\x9b\xa7\xa7\x23\x36\x8d\x88\xe9\x02\x42\x6e\xd4\x0a\x62\x2f\x21\xec\x53\x01\xe2\xca\xda\xfa\x47\x19\xe5\x31\xa8\xa8\xa9\xac\xa8\x2d\x32\x62\xce\x14\xb7\x06\x0b\x6b\x16\xa8\x58\xa0\x98\x66\xb2\x86\xb6\x39\xec\xd6\x66\x53\x0d\xed\x88\x4a\x18\x55\xd6\x12\x59\xdf\x82\x78\xb2\x82\x22\x74\xc4\x25\x02\x11\x65\xe5\x90\x94\x1c\x84\xb6\x54\x58\x4c\xc1\x61\x36\x93\x15\x42\x73\xb9\x20\xa2\xe2\xd6\x9a\xf5\x2f\x9b\x3c\x01\xd8\x73\x5f\xc7\xa6\x2b\x40\x08\x59\xd6\x0d\xc9\xda\xba\x29\xde\xc1\x94\x43\x00\x39\xc2\x59\x0d\x87\xd1\xf9\x14\x40\x2f\x8d\x6c\xcf\x00\xec\x5f\x4f\x55\x9d\xec\xc0\x58\x3e\x9f\x6b\x63\x1f\x44\x5b\x28\xbe\x2c\xc6\x59\x6d\xee\xa1\xea\xf9\x08\xb6\x99\x67\x65\xa2\x80\x22\xdc\x78\x7f\x97\x7c\x9b\x00\x2b\x28\xd3\xb3\x24\xaa\x4f\x25\x38\xb4\x16\xb2\x16\x8f\xa8\x70\x1b\x33\x87\x25\xbd\x50\x14\x43\xbf\xd9\x40\x88\x53\x25\x54\xc1\x06\xbc\x90\x75\x81\xe3\x04\x46\x53\xa6\x68\x07\x64\xe8\x8b\xac\x03\x92\x6a\x05\xf1\x64\xe9\x9b\xe6\x2b\x8b\x1b\x65\xca\x87\x0b\xb7\x59\xe5\xdf\xa1\x12\x1c\x67\x8b\x95\xa2\xa5\xaa\xb6\xe2\x2f\x7d\xc5\xff\x59\x50\x03\x2d\x02\x82\x68\xb2\x7e\x0a\x74\xaa\xc0\x9e\x2d\xa7\x4a\xcf\x72\xd0\x93\x2f\x67\x8a\x1b\x2a\x8d\xfc\xcd\xf5\xae\xdb\xd0\xd5\xc9\x34\x2e\xac\xe8\xb2\xbe\xf0\xaf\x38\x02\xed\x64\x79\xa3\xea\xff\xb6\xcc\xcd\x6e\x66\xb9\x02\xd1\x8d\xa3\xf0\xc6\xd7\x96\x74\x64\x26\x09\xe2\x06\xfa\xd2\xcc\x8c\x1c\x02\x33\x68\x33\xf6\x54\x99\x94\x9b\x31\x65\xfd\xfd\xe3\x84\xab\x66\xf9\x6d\xc6\x9f\x2b\x5e\x69\x97\x9b\x71\x15\x15\x46\x25\xc6\x59\x75\xc8\x61\xc9\x2d\xa1\x0e\x9a\xa7\x70\x37\x37\x6a\x17\x2d\xb8\xea\x2c\x22\xb3\x20\xaf\x64\x15\xa2\xb2\xcc\xef\x8c\xf6\xb1\x0a\x00\x64\xa3\x75\xac\x42\x00\x1b\x9e\x21\xad\xa6\x00\xaa\x69\xea\xb5\x9a\xe9\xce\xcf\x34\xf9\x5c\xcd\x15\x39\x93\x4f\xeb\xbb\x53\x0a\xae\x75\x56\x0b\x08\x9b\x7c\xa3\x05\xd1\x95\x51\x78\x1f\xa5\xe8\x88\x6c\x06\x15\x28\x8b\xfa\x7d\x02\x0a\x3a\x50\xd6\xf4\x29\x46\xd0\x94\x35\x50\x56\xf4\xbb\x04\x8c\x02\x81\xaf\x04\x95\x07\x4c\x32\x87\x20\xea\x5c\x43\x8d\xd2\x1c\xf4\x99\x81\x92\x00\xb8\x43\x65\x96\x64\x7b\x73\xd7\x97\xaa\xc7\xce\x60\xb2\x8a\xcf\x42\x29\xce\x62\x30\x05\x11\x28\x79\x80\x12\x65\x71\x0e\x25\x0c\x02\x25\x0b\x10\xe5\xc7\x23\x06\x03\x70\xa0\xa4\x02\x8e\x68\x9f\x61\x18\x31\x04\x7d\x25\x68\xdf\x81\x92\x11\xe0\xc8\x06\x0b\x0f\x94\xbc\x40\x89\xeb\x3b\x6c\xe0\x42\x9d\x08\xe4\x45\xd1\x28\x21\x82\x73\x3b\x41\xa0\xce\xa3\x53\x92\xd9\x37\xa9\x58\xc9\x12\x30\x74\x93\xf1\x28\xa9\x02\x36\x7c\xf8\xc6\x04\xb0\x86\xba\x32\x25\x35\x0e\x79\x99\xfc\x96\x67\x35\x5c\x47\x4d\x21\xc4\x50\x84\x0c\x94\x0c\xc2\xf6\x94\xa6\x87\xbc\x04\xd9\x56\xb2\x08\x5b\x0c\x8e\xf6\x40\xc9\x22\x44\x4d\xb7\x76\x49\x84\x6a\x50\x72\x4a\x32\xa1\x3e\x9c\x8e\xdb\xca\x60\x1d\x4a\x26\x81\xe1\x9a\x8c\x43\x49\x26\x1c\x50\x16\x1b\x7d\x70\xa0\x24\x14\x08\xb2\xc1\xbb\x07\x4a\x52\x81\xe0\x1a\x18\x5e\xe9\x98\x26\x76\x95\x9c\x02\x8d\x44\x3d\xa1\x23\x50\xd2\x0b\x52\x25\x13\xfb\x4a\x9e\x41\xaa\x03\x77\x43\x49\x39\x48\x35\x8c\xdd\x91\xf5\xba\x4f\xf3\x2d\xa8\x7f\x25\xf5\x70\x57\xe2\x0c\xcc\xca\x06\x4a\xda\xa1\x46\xd5\x3b\x68\x91\x1e\x28\x09\x87\x5d\x92\xc2\x8b\xbf\x40\xc9\x36\x6c\xcb\x04\xef\x22\x04\x8f\x6f\x25\xe1\xd0\xc4\x45\x3a\x6f\x81\x90\x95\x9c\x43\x8c\xaa\xc3\x36\x87\x27\xa8\x81\x92\x79\x28\x50\x81\xcb\x28\x4d\x40\x35\x28\xe9\x07\x92\x97\x36\x66\x92\x03\x25\x0b\x91\x26\x19\xb4\xa2\x09\xd4\x0c\xc4\x21\x87\xa3\x8d\x92\x81\x28\x4e\xd5\xa1\x00\x53\xb0\x81\x92\x82\x38\x55\x70\xc7\x65\xe9\xef\xb7\x70\x97\x65\xb9\x57\x39\xec\xad\x95\x84\x42\x83\xe6\x6e\x1f\x5c\x94\x16\x07\xb4\x85\x03\x82\x92\x56\x50\xab\x18\xe6\x49\x81\x92\x60\xe0\xd5\xe8\xb7\x57\x08\x7f\x6a\xc6\x37\xb6\x31\x83\x59\xab\xeb\x32\xd9\x9e\x6a\x30\x85\x17\x28\xc9\x06\xbd\x92\xb1\x35\x45\x5d\x19\x59\xfc\x62\x50\x69\x73\x75\x22\x57\xa0\x0c\x46\x54\x93\xe1\xf4\x43\xb8\xd1\x5b\x28\x59\x87\x16\x1f\xf6\x47\x4a\xe6\x21\xcd\xf7\xf0\xd7\x80\x60\x11\xa8\xb9\x52\x30\x4b\x1b\x2c\xd4\xd4\xeb\xde\xf0\xd1\x20\x50\xd2\x13\x19\xbe\x73\xef\x92\x2c\xce\xef\x40\x64\x75\x7a\x12\xe5\xb0\x17\x50\xd3\x14\x08\x4c\x2b\x04\x4a\x96\xc2\x34\xbd\x50\x92\x14\x0d\x35\xb8\x55\x25\xbb\x47\xb6\x0a\x80\x88\x2b\x55\xed\x06\x44\x25\x2f\x51\x61\xd8\x3a\x96\xaa\x5a\xf2\xa2\x78\x70\x63\xf0\x7b\x28\x0e\x94\xd4\x04\xc3\x36\xf6\x6a\xa9\xe6\xc7\x09\xba\xf1\xdb\x52\xa0\xa6\x2a\x3a\xf2\x20\xf6\x1c\xc2\x36\x69\x42\xc9\x56\x44\x25\x8e\x93\xba\x99\x73\xc2\x9c\xcb\x7a\xa3\x1b\x21\x61\xb7\xa2\xe6\x2b\x4e\x75\x8a\x4b\x30\x0c\x28\xa9\x0a\xba\x39\x07\x42\xbc\xd1\xa6\xfe\x45\x89\xab\x0a\x16\xb2\x92\xa4\xc0\xa8\x34\x06\x0e\x25\x45\x41\xf0\x4c\xbe\x48\x49\x50\xd4\xf9\x9d\x81\x57\xc5\x43\xd6\xa8\x06\x9d\xa2\x92\x96\xa8\x62\x63\xde\x33\x50\xb2\x12\x07\x1b\xaa\x32\xbe\x4e\x5b\xb2\x11\x0b\xe6\x40\xc9\x04\x92\x5d\x3e\x55\x8d\x4b\x03\x69\x35\xde\x9d\xc8\x8c\x31\xdd\x82\xba\x5d\xa9\x61\xaf\xc1\x9e\xbb\x01\x88\xab\xc6\xbb\x06\x77\x61\xc0\x55\x83\x5c\x83\xbb\x34\xe0\x2a\x73\x43\x7e\x1c\xc1\x35\x7c\xf2\x08\x56\xaa\x53\xdc\x27\x55\x4d\xf7\xc9\x99\xeb\x28\x9f\x3f\xd2\xfc\x14\xdb\x3e\x24\x06\x4a\xc6\x81\x56\x30\x7e\x4e\x0c\x56\x37\xca\xc8\xc3\xd8\x8d\xf2\x2c\x31\x8c\xbe\x95\xfa\x11\x17\x63\x37\xc6\x51\x12\x9f\x72\x68\x1b\x05\x0e\x7d\x65\x6c\x41\x4c\x84\x4a\xca\xa3\xf1\x40\xa6\x0f\xba\xa1\x92\xf7\x68\xfc\x8f\x19\x57\x99\x08\xe2\x5b\x9c\xc2\x81\x35\x54\x12\x20\x8d\x32\x41\x34\x65\x2e\x88\x2a\x70\x6d\x17\x2a\x89\x0f\x94\x62\x30\x6c\x84\x4a\x7a\x02\xff\xe3\x44\x8e\x89\x40\xb2\x0f\x95\x0c\xc5\x3b\xb2\x73\x19\x40\x0b\xd4\x04\x26\xe8\xa1\xd5\x0d\x2e\x05\x02\xe7\x27\xa1\x92\x97\xd8\x26\xd5\x01\x4c\x7c\x87\x4a\x46\xe2\x5d\x66\x58\xb9\x85\x4a\x42\x62\x8b\xb6\x0f\xee\x2e\x2f\x8f\xa7\x14\xfa\xae\x17\x2a\xf9\x88\x1a\xcc\xca\x84\x8b\x9d\xbc\x77\x68\x9b\xa2\xe8\x9d\x69\xed\x11\x2a\x69\x88\x2d\xe8\xea\x43\x25\xf5\x80\x8a\x02\x32\xb3\xdd\xcd\x4e\xde\xae\x83\x4b\x78\x29\x15\x2a\x09\x87\x43\x7e\x2a\x0d\x5b\x7b\xc2\x69\x20\xef\x71\x4a\xd1\x11\x14\xba\x92\x71\x88\x4f\x45\x6a\xca\x37\x84\x4a\xbe\xa1\x48\xf6\xfb\x07\x77\x8b\xc0\xc5\x51\xa8\x24\x1c\xaa\x28\xa9\xaa\xbc\x04\x87\xb8\x92\x6d\xd8\x26\x75\x94\x83\x93\xd2\x50\x49\x35\x6c\x6b\xe8\x8b\xaa\x8a\x75\xbf\x05\xad\x48\xc1\x7a\x80\x8c\xdc\xf7\x91\xdc\x8d\x5f\xa1\x51\xad\x61\x95\xa7\x2d\xa4\xe8\xd0\xdf\xc6\x2a\xde\x00\x2c\xb2\x03\x0e\xea\x81\x92\xf6\x48\x22\xec\xa6\x79\x9a\x82\x7e\x47\xc9\x76\xb4\xb8\x6e\xdd\x78\x20\xd0\x7a\x95\x64\x07\x8e\x4f\x11\xdd\x92\x0d\xe1\x2a\x9f\x47\xc8\x19\x31\x7b\x92\x2d\x54\xd2\x1c\xac\x8e\x25\x95\x17\x2a\x09\x8f\x23\xce\x4e\xee\x01\x1d\xb7\xa7\x72\x0f\x7b\x3c\x25\xf1\x41\xb6\x57\x9a\x17\x1d\xa1\x92\xff\xc8\xa1\xcd\x75\x38\x54\x92\x1f\xfb\x12\xc1\xc6\xaa\x24\x3e\xaa\x53\x46\x06\x2b\x38\xd9\x09\xd5\xcd\x16\xfc\x88\x1e\x88\x1b\xe8\xb8\x74\xf7\x33\x84\x1c\xea\xc8\xc2\x26\x7e\xa8\x86\xa2\xcb\xed\xaf\x38\xaa\xd9\x27\x7b\xf8\x9b\x65\xa8\x64\x42\xa4\x2a\xec\x28\x18\x54\x6b\x6e\xae\x65\x37\x1d\x25\x4f\x22\xd5\x34\xe4\xee\x42\x65\xdf\x86\x54\xc7\x66\x74\x4a\xb6\x45\xaa\x67\x4a\x2e\x86\xea\xa6\x8e\x32\x41\xd9\x3e\xc5\xe6\x0a\xea\xbe\x0e\x5e\xc1\xd4\x1b\x25\x07\xd3\xe2\x9b\xa5\xad\xa4\x5f\xda\x1a\x06\x95\xce\xd5\xc9\x69\x56\xe5\xb0\x1b\x52\x73\x2e\xa7\x02\x97\xec\x1c\x05\x84\x3d\x57\x57\x00\x16\xdc\x85\x3e\xde\x8d\x02\x59\xea\xb8\x66\x69\xdf\xe8\xc8\x86\xfc\x4a\xa8\xe4\x57\x08\x2e\x3c\x05\x5c\xf8\x5f\x5c\xbe\x7e\xe2\xf3\x64\x17\xe5\xbc\xce\x13\x53\xef\x0e\x12\xd3\x93\x8b\x7e\xd1\x1d\xf5\xaa\x51\xe1\x1e\x92\xfd\x21\x25\x6b\x12\xfd\x18\x2c\x39\x30\x2c\x6e\x17\x3f\xe0\xf4\x16\x37\xe3\xc8\xc9\xf0\x09\x4f\xfe\x33\xff\x73\xf2\x4d\x99\xa0\x74\x22\x9c\x51\x16\x5a\x9c\x15\xf7\xf2\x86\x71\x6f\x16\xde\xcc\x97\xc1\x6c\xca\xce\x41\x7e\x39\x9d\x4e\x37\xe0\x39\x0f\xf9\x90\xa5\x7a\xb6\x52\xe4\x8c\x9f\xac\xec\xda\xe5\x25\x62\xd3\xfc\xc4\x25\x3a\xb7\x2d\x2f\xd1\x76\xb9\x51\x8f\x24\xd1\x33\xc2\x6b\x72\x2e\xb1\x3d\x03\xcc\xaa\x84\xd3\x79\xb8\x8c\xb4\x2a\xc2\x29\x26\x5a\xaf\x3d\x33\x3c\x2f\xee\x1d\x74\xaa\x73\xa7\xdb\x27\x1f\x9d\x2a\xb7\x24\x5f\xd8\x1a\x9a\x1b\x86\xe9\xe6\xbb\x5d\x85\xeb\xb5\x1b\x16\xf7\xca\x29\x59\x9f\x1c\x06\x52\x4e\xe7\x1e\x93\x38\x4e\xf1\xc5\x8b\x50\x99\x9f\x2a\x9c\xd2\x33\x87\x6f\xbd\xa4\xc6\xc7\xb7\xe8\x6d\x72\xdc\x4f\x60\x18\x81\x24\xc7\xbd\x5b\xe2\xaa\xc8\xb3\x2a\xb9\xc5\x13\x8f\x7c\x30\xca\x50\x92\x3a\xac\x6a\x5b\xd0\xfc\x29\x9f\xe9\xde\xc8\xc7\x92\x36\xe2\x61\x45\x4a\xb8\x51\x24\x8e\xf9\xa1\x9f\x12\xc5\xc9\xa9\x5a\x2f\x8a\x7b\x0a\x6e\x49\xc3\x07\xc0\xcd\xd4\xdb\xc3\x97\x16\xa3\x02\x2d\x49\x3f\x19\xf8\x65\x1c\xc7\x1b\x99\xbf\x99\x38\x36\x9a\x71\x40\x8f\x55\xa0\x34\x75\xbc\xb0\x72\x30\xaa\xb0\x9b\x64\x6e\x7e\xaa\x37\x6e\xde\x87\x61\x07\x53\x39\xd0\x8f\x45\x8a\x94\xe6\xfe\x8b\xcb\xa1\x64\x9a\x27\xce\x3b\x6c\x06\x2d\xfb\x9b\xb9\x7f\x52\xc4\x0f\x31\x6e\xba\xf3\x59\x62\x07\x31\xc6\x17\xaf\x2a\xdd\x3c\x4b\x1f\xba\x43\x22\x68\x5b\xe5\xe9\xa9\xc6\x1b\x26\xe1\xe2\x9e\x0b\xb8\xf9\xd9\x9d\x90\x64\x96\xe7\x36\xa5\xca\x11\xee\x0d\xf9\x08\x53\xe2\xa8\x7e\xe9\x4f\xc8\xbf\x57\xdd\x81\x4a\xde\x22\x35\x73\xd4\xcc\x93\xd9\x61\x7a\x00\x42\x47\x4a\xcb\x1b\xbd\xcd\x82\x71\x46\xf4\x2d\xea\xbe\x3d\x4b\xad\x9e\x94\xa6\xfc\x10\xeb\xfb\xb9\xcc\xd3\xf6\x00\xf4\x59\x39\xc1\xec\x1d\x82\x89\x77\x08\x27\xde\x61\x3a\xf1\x0e\xb3\x89\x77\x98\x4f\xbc\xc3\x62\x72\x08\x26\xf4\x38\xdd\x61\x36\x39\xcc\x27\x87\x85\xd9\xb5\xb0\x43\x30\x73\xf5\x10\x8c\x17\x28\x87\xba\xbd\x43\xe0\x78\x64\xd3\xc7\xa4\xf9\xc9\x7f\x85\x5d\x61\xd8\x16\x4e\xbb\xc2\x69\x5b\x38\xeb\x0a\x67\x6d\xe1\xbc\x2b\x9c\xb7\x85\x8b\xae\x70\xc1\x0a\xbb\xc6\xdb\xb6\xbb\xa6\xdb\x96\xbb\x86\xdb\x76\xbb\x66\xdb\x56\xbb\x46\xdb\x36\xbb\x26\x79\x8b\x67\xfb\x11\x21\x36\x10\x97\xcb\xa5\xa4\x04\x2e\xf8\x1e\x63\x6f\x82\xd6\x63\x05\x7a\xad\x44\x84\xd8\xb9\x98\xbf\xb8\x48\x66\xc3\xad\x45\xe0\x3e\x30\x72\xff\x38\x7d\x3e\x4a\x2d\xfc\xb2\x07\x22\xfb\x43\x20\x14\x4e\x89\x4b\x6e\x74\x10\x8a\xa5\x94\xe3\x69\xa3\x19\xe1\x26\x8a\x19\xed\xc7\xe4\x30\x13\x27\x14\x37\xa4\x74\x3e\x39\xcc\xcf\x72\xd0\xbf\x10\x19\x2d\xc4\xd2\x26\xb0\x15\x6d\x4c\x73\x7c\x87\xca\x26\xc5\x28\x3e\x03\xfe\x4d\xa8\xb9\xe0\x7f\x0a\xf7\xec\x2a\xfe\xff\x42\xcf\x41\xbf\x3c\x26\x19\x8b\x1e\xcb\xc5\x4d\x71\xff\xea\x4c\xe9\x0b\x1d\x09\x8a\xfb\xcb\x85\x49\x4a\xbb\x3b\xa3\x11\xd3\x11\x95\xef\x26\xe4\xd6\x8d\xf6\xe0\x79\x88\x8f\x50\x64\x89\x76\x37\x78\x7a\xf1\xc8\x6c\xa0\x99\xb8\xd2\xd3\xcd\x34\x3e\x37\x7f\x33\x10\x99\xa7\x8a\x30\x52\xc0\x80\x74\x0b\xb6\x08\xa5\x25\x0c\xcc\x36\x51\x8b\x70\x56\xc4\x10\xb2\xfc\xae\x44\xc5\xf9\xee\x90\xd4\x98\x1c\x49\xc7\x6b\x5a\xc4\xf9\xca\xef\x70\x19\xa1\x0a\xab\x77\x48\xb4\x00\x86\x78\x2a\x0a\x18\xb1\x05\x70\x8e\x51\x41\xb6\xbb\xff\xa6\x61\x76\x10\x86\x7a\x3c\xd5\x38\x3e\x8b\xe3\x9f\x14\x17\x65\x42\xae\x8a\x91\xe6\x61\x17\x24\x01\xf9\xfc\x4b\x2e\x94\x27\x63\x37\x0b\x7f\xe5\x33\x9a\xd5\x29\x8a\x70\x55\xb5\x34\xa3\xe5\x62\x1a\x73\x9a\x0c\x28\xd3\xe4\x85\x32\xcd\xed\x7c\x16\x46\x8c\x66\x92\xed\xf2\x96\x60\xb0\xf4\x6f\x76\x9c\x60\x03\x91\xa9\x91\x12\x99\xd4\x6c\x1e\x2e\x56\x8c\x14\xdb\xda\xc6\x61\x37\x68\x11\x4f\xb7\x9c\x1a\x03\xca\x04\x79\xa1\x44\x73\xb1\x98\x07\x2d\x7b\x31\xca\xf6\x1d\x08\xad\x66\xb3\x59\xc8\x49\x52\x98\x4c\x91\x95\x49\x04\x6f\x66\xd3\xf9\x74\x76\xf1\xb6\x7b\x55\x2b\x64\xde\xa4\xd9\x7c\xab\xab\xae\x42\xdb\x88\x50\x44\xdb\xd0\xab\x73\x95\x6d\xf7\xad\xc2\x74\xa4\x78\xb7\xf3\xe3\x1b\xda\x86\xaa\x39\xa1\xc8\xd4\x46\x14\xe0\x70\x3b\x25\x6d\x10\x05\x02\x0d\xac\x70\xbc\x63\x9d\x90\x34\xc9\xff\x36\x91\x46\xbb\x78\xd5\xcc\xab\xb6\xfb\x56\xa1\x46\xb7\x80\x04\x2c\xb1\x01\x59\xaf\x40\xf5\x25\x8e\xb6\x73\xd2\x06\x53\x30\x80\x13\xc6\x38\xc6\xb4\x09\x45\xd3\x5d\x89\xa9\x01\x3c\xdb\xae\xb6\xab\x8b\x47\xee\x08\xa0\x5f\x3d\xb9\xa7\xe3\x0e\x78\xd5\xc6\xb1\xf5\xcc\x2f\xee\x1d\xdf\x11\xa6\x9c\xe2\x95\x47\xc2\x64\x33\x4f\x27\xa7\x54\x8c\x86\x3e\x14\x0a\xf3\xd4\xc9\xd3\x49\x9e\x3a\xa7\x06\xdd\x21\x95\x9c\xae\x1e\x43\xf5\x2f\x1e\x39\x0f\x76\xca\xc8\x49\xe4\xf6\xee\x0e\x9a\x1e\x68\x9c\x7f\xd5\x1d\x52\xce\x30\xc3\xa6\xcb\x08\x15\x97\x51\x26\x7f\xb9\x73\xb2\x72\x30\x57\x7e\x9b\x26\xf0\xaa\x84\x13\xa5\x39\x87\x79\x37\x59\xa6\x84\xe7\xc5\xfd\x25\xb6\xf6\xbe\x11\xe0\x25\x8e\x27\xb1\x7c\x99\x4d\xb7\x74\xb9\xc4\xb5\x7e\x63\x54\x1b\x19\x69\x67\xcc\x51\x2e\x4e\x85\x9c\x9a\xd3\x90\x4a\x73\x54\x93\x28\xc4\xe7\xfa\x0b\x1f\x9c\xcc\x63\x54\x52\x34\x35\x40\xd1\x82\xb6\x02\x4e\xd3\xa4\xa8\x92\x6a\x03\x85\x1a\xa5\x79\x99\xed\xe0\xa6\xe9\x3b\xbd\xb7\x23\x46\x35\x72\xf3\x32\xd9\x27\x19\x4a\x5d\x7a\x8b\xc7\x44\xbc\x56\x8b\xcd\xda\x0f\x38\x2d\x00\x7b\xa3\x57\x6c\x39\x34\x96\x24\x59\x42\x0e\x99\x57\x47\x21\x84\xaf\xfc\x17\x1b\x63\x00\xeb\x6e\xf4\x68\x63\x7b\x63\x95\x8e\x30\xed\x24\x33\x13\x75\x02\xb2\xf4\xe6\x9d\xf9\x73\x85\x8b\xc6\xdf\x11\x76\xf2\x74\x9d\xa2\xaa\x76\xa3\x43\x92\xc6\x13\x01\x50\x18\xca\x4f\x62\x05\x6d\x20\x08\x88\x6c\xd2\x22\x94\xb0\xeb\xd9\x84\x12\x3a\xa3\x91\xd7\xeb\xd2\xdd\x60\x3d\xd9\x98\x46\xb0\x5a\x93\x2c\x3b\xa5\xb7\x0c\x00\xc0\xad\xee\x5f\xfd\x3d\xf4\x83\x99\xf3\x77\xdf\xff\xc6\xff\xea\xe2\x75\xe8\x6e\x89\x6f\x71\x59\x89\x14\xbc\xe2\x94\xa6\x6c\xce\x24\x8f\xba\x40\x1b\x76\xbe\x6e\xb4\x7c\x39\xcd\xc7\xa9\xa0\x25\x49\x81\x3e\xc4\x86\xd2\x5f\x08\x43\xee\x38\x84\x61\x10\x99\xd0\x2f\xa3\x58\x45\x1c\x93\x84\x45\x1c\x58\xd8\xa0\x84\x79\x9b\x34\xdf\x68\xe9\x99\x19\x41\x24\x60\xed\x97\x0d\x45\x6a\xc5\xd6\x2b\xf9\x3a\x9e\xaf\x88\xed\x38\xc4\x8e\xbe\xba\xa0\x38\x2e\x9b\xb9\x83\x71\xd9\x20\xde\x5f\x61\x70\xb7\xf6\x2b\xe0\xfe\x8c\xb3\x34\x9f\xfc\x39\xcf\x50\x94\x4f\xbe\x23\xd9\x71\x54\x4d\xa2\xfc\x54\x26\xb8\x74\x32\x7c\xd7\x5d\x0d\x47\x28\xb5\xfe\x24\x2c\xee\x9d\x99\xe4\x3d\x1a\x8f\xc4\xa7\x26\xcb\x70\x3e\xc3\xd0\x52\x62\xb5\x0b\x77\x33\x3d\x23\x75\x79\xb7\x8d\x87\x91\x36\x4d\xd7\xa6\x0a\xd1\xa9\x90\xe6\x12\xae\x6c\x4a\xb2\x0a\xd7\x8e\xef\xb8\x01\x09\xf7\xe5\x7e\x8b\x58\x7a\xc7\x0b\xe7\xaf\x36\x83\x31\x1b\x86\x1d\x91\x69\xf1\x3a\x43\x92\xd0\x53\xaf\x42\x35\xdc\x2c\xa5\xde\x27\x45\x2e\xf1\x93\xfd\x1a\x6f\x62\x45\xbc\xb3\xb2\xb0\x14\x9b\x9d\x0e\x4a\x42\xdf\xe5\x65\x4c\xef\x4c\x5a\xb3\x9b\x93\xd2\x94\x16\x36\x31\x8e\x95\x35\x7f\x43\xfa\x9b\x37\xff\x80\x3c\x63\x14\x45\x80\x56\x8b\x12\x3b\x92\xd5\xf8\x40\xee\x5a\x4a\x29\x49\x51\xb7\x28\x31\xe1\x49\x67\x44\x48\xe0\x2b\xcd\xfa\x17\xaf\xa9\x56\x45\x65\x9e\xa6\xe4\x4e\xa6\x23\xba\xe7\x02\x99\xce\xc4\xb9\x81\xfb\xb0\xa6\x68\x17\xaf\x19\x7e\x28\x11\xae\xe6\x33\xba\xe2\xa0\xd3\x01\xc3\x11\xd2\x76\x14\x85\xe4\xe8\x8c\x33\x98\xae\x29\x56\x3e\x27\xb3\x06\x0d\x7f\xb5\x0a\x41\xfc\xd5\x12\xc6\x0f\x42\xdf\x07\x2b\x04\x01\xad\xd1\x01\xdc\x5d\x7a\x4a\xe2\x27\xeb\xaa\x57\xe6\x77\x67\x09\xcf\x15\xab\xd2\x19\x69\x53\xd2\xb0\x90\xba\xe9\xde\x0d\x26\xed\x2f\xbf\xfb\x29\x94\x86\xed\xcf\xee\xd7\xb4\xfd\x35\x6b\x7f\xcd\xdb\x5f\x8b\xf6\xd7\xb2\xfd\x75\xd3\xfe\x5a\xd1\x5f\xc7\x98\x37\xdd\xfc\xf2\xbb\x9f\x42\x69\xd8\xfe\xec\x7e\x4d\xdb\x5f\xb3\xf6\xd7\xbc\xfd\xb5\x68\x7f\x2d\xdb\x5f\x37\xed\x2f\xd6\x74\x75\xe4\x4d\x37\xbf\xfc\xee\xa7\x50\x1a\xb6\x3f\xbb\x5f\xd3\xf6\xd7\xac\xfd\x35\x6f\x7f\x2d\xda\x5f\xcb\xf6\xd7\x4d\xfb\x8b\x35\x7d\x5f\xf1\xa6\x9b\x5f\x7e\xf7\x53\x28\x0d\xdb\x9f\xdd\xaf\x69\xfb\x6b\xd6\xfe\x9a\xb7\xbf\x16\xed\xaf\x65\xfb\xeb\xa6\xfd\xb5\x02\x2e\x6c\x6a\x6c\x55\xcf\xc2\x5b\xcd\xef\xf2\x11\x3b\xd0\xad\x2c\x3a\x2e\xc2\x73\xf7\xc9\xa6\x2b\x0d\xf8\xd0\x0c\xbc\x05\xfd\xbf\xa5\x00\xf5\x19\xf4\x66\xea\x4d\xd9\xff\x75\xd0\x55\xeb\x05\xba\xb2\x1b\x56\xb6\x58\x00\xe4\x96\x0c\x38\xbf\x01\xa8\x2d\x38\x50\xe0\x6e\xce\xca\x66\x10\x73\x33\x06\x9c\x42\xbc\x4d\x19\x30\x14\x78\x6b\x05\x00\xf1\xc6\xe5\x00\xb1\x46\xe6\x3d\x41\x78\x66\xda\x16\xe5\x47\x41\x01\x03\x81\x42\xa4\x28\x3e\x43\x01\x25\x49\x50\x56\x0c\x43\x14\x27\x01\xdc\x30\x00\x28\x53\x82\xb1\x64\x18\xa0\x60\x09\xc6\x82\x63\xa8\xbc\xcf\x19\x00\x14\x31\xc1\x98\x31\x0c\x50\xce\x04\x63\xca\x30\x42\x95\xf3\x56\x64\x46\xce\xb9\xe4\x8c\x8c\x73\xb9\x51\x6f\xdd\x42\xaa\x43\xa3\x10\x3a\xd6\x64\x7d\x34\x90\x80\x42\x0c\xea\x68\x30\x7c\x8a\x61\xd0\x46\x75\x70\x57\x14\x41\x56\x46\x75\x70\x6f\x68\xb9\x41\x17\xd5\xc1\x5d\x52\x04\x83\x2a\xaa\x83\xbb\x60\x08\x2a\xd7\x73\x5a\x6e\x50\x44\x75\x70\x67\x14\xc1\xa0\x87\xea\xe0\x4e\x29\x42\xa8\xf2\xcc\x05\x65\xe4\x99\xc9\xcb\xc8\x32\x93\x96\xa4\x03\xfa\x2d\xbc\xd1\x82\x94\x47\x10\x95\xc1\x51\x02\x09\x05\xd4\x0a\x47\xf5\x25\x54\x50\x3d\x0c\x75\x25\x61\x8a\x7a\x62\x08\x37\x12\x02\xa8\x30\x86\xb9\x94\x30\x41\xcd\x31\xcc\x85\x8c\xa9\xf7\x75\x2e\x21\x80\xba\x64\x98\x33\x09\x13\x54\x2a\xc3\x9c\x4a\x98\xa1\xde\x53\x45\x05\x96\x9e\xca\x9a\xb0\x74\xd4\x1f\x9a\xd4\xfa\x68\xf3\x03\x2d\xc6\x91\x56\xb4\x18\x47\xd8\x30\xc6\x38\xc2\xaf\x31\xc6\x91\x66\x94\x18\xd7\x30\x61\x8c\x71\x0d\xaf\xc6\x18\xd7\x74\x49\x8d\x71\x4d\x87\x8d\x31\xae\x91\x8b\x31\xc6\x35\xe2\x53\x63\x5c\x23\x5c\x63\x8c\x6b\xba\x6a\x8a\x71\xd5\xd1\x18\xe3\x5a\x90\x39\xc6\xb5\x28\xe6\x18\xc7\x51\xb4\x18\xc7\x01\xe6\x18\xc7\x31\xcc\x31\x8e\x63\x68\x31\x8e\x03\xcc\x31\x8e\x63\x98\x63\x1c\xc7\xd0\x62\x1c\x07\x98\x63\x5c\x2b\x17\x53\x8c\xe3\x08\x7a\x8c\x23\x10\x30\xc6\xb5\x10\x63\x8c\x6b\x31\x8c\x31\x8e\x63\xa8\x31\x8e\x97\x1b\x63\x1c\x47\x30\xc6\x38\x8e\xa0\xc6\x38\x5e\x6e\x8c\x71\x1c\xc1\x18\xe3\x38\x82\x1a\xe3\x78\xb9\x31\xc6\xb5\xe2\x30\xc4\x38\x0e\xd7\x62\x5c\x75\xec\x8d\x71\x02\x4a\x5f\x8c\x13\x50\xfb\x62\x5c\x87\x6a\x88\x71\x1d\x42\x5f\x8c\xeb\x30\xfb\x62\x5c\x87\x69\x88\x71\x1d\x42\x5f\x8c\xeb\x30\xfb\x62\x5c\x87\x69\x88\x71\x1d\x42\x5f\x8c\x13\xe4\x6b\x8f\x71\x1d\xa2\x1a\xe3\x6c\x79\x8c\x8f\xb4\xfe\xd6\x82\x1c\x69\x45\x0b\x72\x84\x0d\x63\x90\x23\xfc\x1a\x83\x1c\x69\x46\x09\x72\x0d\x13\xc6\x20\xd7\xf0\x6a\x0c\x72\x4d\x97\xd4\x20\xd7\x74\xd8\x18\xe4\x1a\xb9\x18\x83\x5c\x23\x3e\x35\xc8\x35\xc2\x35\x06\xb9\xa6\xab\xa6\x20\x77\x8c\x8d\x41\xae\x05\x99\x83\x5c\x8b\x62\x0e\x72\x1c\x45\x0b\x72\x1c\x60\x0e\x72\x1c\xc3\x1c\xe4\x38\x86\x16\xe4\x38\xc0\x1c\xe4\x38\x86\x39\xc8\x71\x0c\x2d\xc8\x71\x80\x39\xc8\xb5\x72\x31\x05\x39\x8e\xa0\x07\x39\x02\x01\x83\x5c\x0b\x31\x06\xb9\x16\xc3\x18\xe4\x38\x86\x1a\xe4\x78\xb9\x31\xc8\x71\x04\x63\x90\xe3\x08\x6a\x90\xe3\xe5\xc6\x20\xc7\x11\x8c\x41\x8e\x23\xa8\x41\x8e\x97\x1b\x83\x5c\x2b\x0e\x43\x90\xe3\x70\x2d\xc8\x1d\xe3\xde\x20\x27\xa0\xf4\x05\x39\x01\xb5\x2f\xc8\x75\xa8\x86\x20\xd7\x21\xf4\x05\xb9\x0e\xb3\x2f\xc8\x75\x98\x86\x20\xd7\x21\xf4\x05\xb9\x0e\xb3\x2f\xc8\x75\x98\x86\x20\xd7\x21\xf4\x05\x39\x41\xbe\xf6\x20\xd7\x21\xf6\x07\x39\x21\xf9\xfe\x91\x12\xdc\x5a\x94\x23\xad\x68\x51\x8e\xb0\x61\x8c\x72\x84\x5f\x63\x94\x23\xcd\x28\x51\xae\x61\xc2\x18\xe5\x1a\x5e\x8d\x51\xae\xe9\x92\x1a\xe5\x9a\x0e\x1b\xa3\x5c\x23\x17\x63\x94\x6b\xc4\xa7\x46\xb9\x46\xb8\xc6\x28\xd7\x74\xd5\x14\xe5\xd2\xbd\x31\xca\xb5\x20\x73\x94\x6b\x51\xcc\x51\x8e\xa3\x68\x51\x8e\x03\xcc\x51\x8e\x63\x98\xa3\x1c\xc7\xd0\xa2\x1c\x07\x98\xa3\x1c\xc7\x30\x47\x39\x8e\xa1\x45\x39\x0e\x30\x47\xb9\x56\x2e\xa6\x28\xc7\x11\xf4\x28\x47\x20\x60\x94\x6b\x21\xc6\x28\xd7\x62\x18\xa3\x1c\xc7\x50\xa3\x1c\x2f\x37\x46\x39\x8e\x60\x8c\x72\x1c\x41\x8d\x72\xbc\xdc\x18\xe5\x38\x82\x31\xca\x71\x04\x35\xca\xf1\x72\x63\x94\x6b\xc5\x61\x88\x72\x1c\xae\x45\xb9\x74\xdf\x1b\xe5\x04\x94\xbe\x28\x27\xa0\xf6\x45\xb9\x0e\xd5\x10\xe5\x3a\x84\xbe\x28\xd7\x61\xf6\x45\xb9\x0e\xd3\x10\xe5\x3a\x84\xbe\x28\xd7\x61\xf6\x45\xb9\x0e\xd3\x10\xe5\x3a\x84\xbe\x28\x27\xc8\xd7\x1e\xe5\x3a\x44\x2d\xca\xb1\x27\x8d\x6c\x6f\x48\xb2\x67\x34\xdb\x4f\xc9\x75\x5e\xac\x6f\x84\x0f\x79\x6c\xc7\x4a\x53\xd4\x6d\xbc\xda\xa8\xdb\xc7\xeb\x03\xb0\xa3\x9c\x34\x2e\x1c\x90\x52\xce\x4b\x01\xbb\x0e\x69\x9d\xb7\xf5\x36\x8f\x1f\xde\xd6\xe5\xdb\xf6\x95\x24\xa1\xe8\xd0\x16\xed\xf2\xbc\x56\xb0\xda\xa2\x0e\xeb\x80\x51\xac\x60\xb5\x45\xdd\x8b\x67\x37\xe6\x8d\x17\xca\x71\xb6\x3a\x2f\x0c\x07\x99\xe2\x38\xbe\x00\x4d\xa8\x8f\x55\x92\xfe\x2a\x3b\x06\x43\x90\x0a\xd3\xcd\x6b\x4e\x6d\xbd\x4b\x4a\xbe\xfd\x4e\xe8\x8f\x1d\xad\x95\x44\x94\xa7\xe4\x3d\xaf\x5e\x72\x76\x3c\x59\xb2\x32\xcc\x44\xb2\x1f\xf5\x20\x3c\xde\xb5\xf6\x25\x43\x78\x4d\xfe\x5b\x84\x83\xd2\x72\x3c\x83\xb5\x93\x13\x9a\xec\xb1\xad\x28\xcf\x62\xf2\x8c\x2e\x60\x63\x20\xf0\x00\x00\x35\xbb\x03\x81\x50\x4d\xcd\x16\x41\x60\x67\x95\xf3\x76\x4c\xb4\xcf\x84\xc1\x6f\x84\xa9\x58\x50\xf7\x00\xd8\x41\x87\xe9\x9d\x03\x60\x40\x3d\xbd\x6b\x00\xcc\xf0\xc2\x99\xce\xfd\x28\x6a\x6c\x10\x31\xdf\x12\x76\x32\xab\xea\x32\x29\x84\x0e\xaf\xb3\xfa\xe0\xe6\x3b\xb7\x7e\x28\xf0\xcb\x3c\x8e\x5f\x41\xc6\xb2\x6a\xfe\x71\x0a\x64\x67\x7a\x57\xdf\xb8\x13\x9e\x6c\xaa\xa2\xee\xd6\x89\xf2\xf4\xe7\x28\x45\x55\xf5\xf5\xef\x1b\xf7\xfc\x8b\x76\x6e\x50\x7e\x6a\x2f\xca\xd3\xd3\x31\xdb\xd0\xc9\x3f\xd9\x3f\xc6\x9f\x97\x93\xa8\x4c\xf8\x53\x73\xa3\x68\xe3\x34\x15\x29\x2b\xce\xd4\xa3\x27\x1e\x01\x37\xdb\x42\x0e\xba\x03\x8e\x3d\x7e\x50\x52\x73\xcd\x2a\x84\x19\x0c\xd0\x8e\x0a\x81\xbc\xba\x81\x1a\xd0\x0e\x33\x09\xa0\x1d\x15\x02\xc5\x05\x03\xb5\xae\x1d\xb3\xc6\x41\x33\x61\xb5\xd6\xac\xb4\x35\x61\x2b\xd6\x01\xc6\x62\x60\x99\x45\x05\xa7\xeb\x02\xc5\x36\x61\x1d\x24\x2c\xe8\xbc\xc5\x4d\xf3\x4f\xb3\x12\x76\x8c\x05\x32\x93\x16\x04\xda\x09\x83\x42\x86\xa2\x82\xb8\x3d\x00\x6d\x69\x20\xd0\x56\x0c\x04\xa1\xb6\xb8\x4d\x00\x6d\x69\x20\xd0\x5e\x0c\x04\x85\xb6\xcc\x67\x85\x60\x5b\x90\x4e\x0a\x99\x4d\x46\x41\xeb\xb1\x19\x99\x4d\xc0\x68\x24\x72\x66\xab\xe9\x3b\xc6\x14\xfb\x78\x15\x2d\x34\xb3\x49\xb2\x5d\x0e\xd9\x0c\x2d\x07\x0d\xa6\x01\x41\xd6\x22\x95\x73\x7b\x50\xe9\xcb\xe5\xa0\x91\x40\x74\x34\xfa\xdc\x06\x54\xfa\x72\x39\x68\x18\x10\x1d\x4e\xdf\x7c\xba\x0b\xd6\x75\x77\xbc\xcb\x6c\x0f\x22\x4e\x8f\x31\x08\xac\x01\x96\xd0\x11\x32\x9b\x81\xf5\xbc\x59\x34\xc3\xd3\xdd\x54\xb3\x01\x76\x84\x0c\x32\x83\x16\x04\x5a\x02\x83\x42\xc6\xa0\x82\xb8\xde\x81\xb6\x34\x10\x68\x15\x06\x82\x50\x5b\xdc\x06\x80\xb6\x34\x10\x68\x21\x06\x82\x42\x5b\xe6\x73\x7a\xb0\x0d\x48\xa7\xf4\xcc\xa6\xa2\xa0\xf5\x58\x8b\xcc\x26\x60\x30\x12\x39\xb3\xcd\xf4\x1e\x21\x44\xbb\x30\x8a\x34\xb3\xa1\xe7\x02\x21\xab\xe1\x10\xd0\x68\x28\x10\xb2\x19\x05\xc2\xed\x42\x6f\x47\x85\x80\x06\x03\x53\x03\xda\xe1\x36\xa1\xb7\xa3\x42\x40\x63\x81\xa9\x75\xed\x98\xcf\x5b\xc2\x36\x20\x1e\xb7\x34\x5b\x8a\x8c\xd5\x63\x28\x12\x8b\x80\x9d\x88\xc4\xcc\x66\xd2\x77\x0e\x74\x1b\x45\xad\x95\x08\xb7\xc1\x9c\x85\xfd\xc8\x9e\x1f\xbc\xe8\xce\x05\xdc\x8b\x5b\xf8\x1d\x7a\xcd\xbb\x83\xb2\xd8\x79\xd9\x25\x21\x96\x8b\x25\x49\xf8\x6b\x54\x8d\x39\x0a\xb2\xc3\x59\x38\x7b\xc0\x4e\x26\xba\xc7\xaa\x3d\x7c\xc8\x0e\xf4\x34\x45\x0d\x07\x87\x84\x24\x51\xe8\x21\x85\x2d\x2a\xe1\xfb\x5d\xf4\x9e\xbd\x65\x8b\x59\xed\xb0\xa9\x01\x11\x5a\xef\xd9\x90\x0e\x16\x24\x7d\x05\x68\x43\xb2\x51\xd2\x57\x71\x36\xa4\x03\x7c\x35\x00\x5c\x4f\x5b\x0f\x9b\x65\x03\x2e\x8a\xc5\xec\x83\x91\x39\x70\xc9\x3c\xb6\x66\x27\xce\xab\x6b\x8e\x6e\xb3\x13\xfc\xd5\x35\xa5\x36\xcf\xca\x79\xc4\x51\x92\x16\xce\x92\x8e\x13\xf4\xb8\x8a\x82\x9c\xaf\xac\x38\xb6\x45\x41\xca\x57\x56\x14\x5b\x3c\x4b\xe7\x41\xc7\x08\x59\x20\x62\x1b\x6a\x3d\x15\xcd\x03\x59\x97\xd5\xf8\x16\xa1\x8a\x4a\xfe\x66\xed\x5f\x2e\xbb\x04\xa7\x71\x85\xeb\x73\xf7\x61\xd6\xd7\x2f\x7b\xf2\xbb\x6b\x9c\x52\xbc\xc7\x59\xac\x1c\xb7\x13\x1c\xb8\x5a\xd7\x70\x71\x4b\x18\x28\xf9\x5f\xf9\x68\x9b\x70\x3a\xb1\xbb\xc6\x0a\xb8\x5c\x60\xde\xfc\xbb\xa4\x68\x8b\x87\x5d\x19\x26\xf3\x34\x57\x2e\x8f\x59\xfa\xfe\x85\x5c\x29\xf7\x73\xfd\x50\xe0\xdf\xd3\xc7\xae\x7f\x79\xea\x9b\xf7\x84\x16\xc8\xab\x11\xdb\xfc\xfe\x97\x89\x50\x58\xa2\x38\xc9\x7f\xe1\xb7\xe1\xcc\xc8\x51\xca\x56\x9a\x2c\x03\xfe\xf7\x95\x24\x3c\x7a\x9c\x55\xa4\xbc\x4b\x52\xfc\x8b\xac\xa5\x8b\xd4\x46\xb6\x57\xe1\x82\x16\x2f\xf4\x4a\xbd\x9f\x8f\xa7\xb4\x4e\x8a\x14\xff\xc2\xee\xd8\xfb\xb9\xd1\xdd\x2f\x67\xf1\x5a\x37\xb5\x4d\x76\xdb\x04\xd4\x49\x1d\x44\xbb\xfa\x24\xf7\xe2\xe5\xa7\xba\x38\xd5\xf0\x31\x50\x22\xb5\xa5\x7c\xf0\xb3\xff\xf6\xc1\xf9\x7c\x7e\xf1\x76\x79\x79\x74\xa3\x3c\xab\xcb\x5c\x3d\x3b\xaf\xdf\x44\x37\x9d\x09\x37\xa5\x2d\x8a\x7b\x27\x08\xaf\x68\xd4\x74\x51\x5d\x57\x9a\x1c\xd1\x1e\xf3\xa3\xb0\x83\x8e\x95\xda\xce\xf5\x36\x75\x9b\xff\x88\xc7\x75\xfd\x25\x7c\xb2\xd7\x88\x0b\x5c\x8f\xc7\x98\x20\x5d\x10\xaf\xb8\x73\xbc\x60\x5e\x4d\x74\x86\x34\x1c\xe5\x32\x3d\x3b\x3d\x1b\x9d\xa7\x20\x22\x9b\x02\x33\x59\x91\xda\xfa\xcb\xc5\x02\xed\xf0\x8a\x5b\xe7\x1a\x3c\xbf\xdc\x27\xc8\x89\xef\xf8\xce\x0d\x07\x04\x7e\x38\x09\x96\xf3\x49\x38\x9d\x4e\xbc\xc5\x28\x8d\x58\x09\x29\x9d\x59\x13\x1f\x56\xa4\x28\xc2\x07\xf2\x08\x1b\xbf\xe8\x67\xb5\x5a\x6d\xf2\x02\x45\x49\xfd\xb0\x0e\x94\x4a\xcd\x8c\x9b\x0c\x65\x43\x45\xad\x0d\x26\x8c\x51\x75\x8e\x15\x7b\x2f\xc7\xfa\x4d\x55\xb8\x64\x50\xac\xff\x73\x9c\x90\xdb\x04\xe3\x5f\x26\x72\x79\x89\x51\x9c\x67\xe9\xc3\x2f\x13\x1e\xfe\x3a\x54\x47\x1e\xf2\xc0\xda\x08\x63\x93\x4c\x84\x06\x7b\x09\xb3\xcb\x4c\xb2\xbc\x76\x51\x9a\xe6\x77\x38\xbe\xf0\x0b\x4c\x65\x44\x83\xb3\x55\x83\x13\x2a\x0a\x8c\x4a\x94\x45\xec\xea\x1a\x60\x25\xc6\x51\x9b\x50\x1f\xe3\xdb\x24\xc2\x6e\x91\xdc\xe3\xd4\x25\x57\x95\xae\xfd\x57\x67\x81\x7e\x8c\x6a\xfc\x8b\xc4\x89\xe8\xb8\xeb\xe4\x68\x81\x36\x75\xc9\x83\xc9\x69\x1e\xa1\xd4\x8c\x77\xcc\xb3\xfa\x20\x83\xa5\x1b\x70\xa6\xe4\xb6\x38\x6a\x30\xe4\x0b\xa9\x5b\x1d\x1d\x95\xc7\x89\x05\x81\xb0\x69\x43\x50\x38\xb5\xa1\x52\x66\xd5\x6e\xfe\xc2\x6a\x54\x47\x5d\x3c\x10\x44\x15\x0d\x84\xc3\xc4\xc2\x41\xb2\x48\x7c\x55\x24\xe9\xbe\x47\x24\x32\x02\x20\x12\x9d\x82\x51\x24\x32\xaa\x5d\x24\xe9\xde\x24\x12\x19\x02\x8b\x44\xc6\x91\x44\x92\xee\x25\x91\xcc\x16\xe4\xa8\x3e\xb1\x22\xc2\xe5\x59\x4f\x22\x5c\x3c\x3e\x0b\x99\x78\x64\xd2\x01\x9c\xb5\x56\x6f\xb2\xed\xbf\xbb\x91\xd3\x74\xc8\x04\x94\x51\xa6\x7f\x88\x99\x12\x32\xf5\x95\xce\x69\x03\x77\x59\xfa\x1b\xf5\xa6\x4c\xf5\x92\xd2\xb6\x35\x70\x02\xd9\x82\xd9\x75\x55\x06\x2c\xca\xa2\x36\x05\x63\x00\xa0\x2e\x9b\x8d\xea\xd7\xc4\x0a\x02\x9a\x91\x09\xa9\x74\x77\x41\x28\x09\xe8\xb5\x2a\xfe\xd7\x4c\x0b\x02\x11\x57\x52\x13\xe3\x44\xe6\xcb\xa2\x34\xf0\x46\xae\xe1\xb2\x06\x6f\x50\x36\x6a\x80\xb1\xf3\xda\xce\xed\x6b\x99\x77\xe8\x02\x30\xb6\x19\x8c\x5c\xeb\xac\xc5\x0b\x50\x81\x76\x3c\xa6\x4c\xa8\xa6\xc7\x2b\x80\x50\x21\x72\x69\xe4\xc0\x9a\x14\xd4\x55\x83\xe2\x99\x2a\x9e\x8e\x90\x24\x99\xae\x18\x0a\x9a\xaa\x88\x21\x1c\x49\xce\x36\x46\xda\xa6\xa4\x11\xab\x96\xda\xd8\xb0\xa0\x88\xa3\x1f\x62\x42\x0c\x73\x2e\xdd\x3d\x20\x7a\x09\x71\xf1\xd0\x2e\x58\x94\x4d\x61\x4b\xdd\x94\x41\xba\x9d\x0f\xb5\x40\xab\xa3\x72\x9d\x89\xaf\xdc\xa0\x75\xe9\x10\x85\xe8\xb3\x11\xf6\xca\x68\xd7\xe9\x84\xda\x02\x67\xae\x5f\x32\xc4\x56\x97\x30\x75\x2d\xd8\xa9\x4b\xd1\x2e\x64\xb6\xf3\x25\x95\x10\xdd\x81\xd9\x05\x84\x26\x92\x83\x93\xaa\x27\xea\x8f\xd2\x14\xeb\x9e\xb1\x41\x3d\x9e\x43\xf5\x85\x1e\x4b\xf3\x27\x05\xb9\x7f\xd2\x68\x13\x04\xb7\x43\x91\x3d\xd1\x26\x43\x75\x41\xdb\x2f\x9f\x4b\x17\xa5\x85\x00\xbd\x91\x2e\xd5\xeb\xae\xed\x6d\xef\x0a\x56\xc8\xb0\x1d\x97\x1b\xfd\xa2\x78\xc9\x78\x94\x46\xb4\x69\x81\xc1\x78\xd2\xbd\x6a\x3c\x1d\x21\x4d\x66\xe9\x1e\x36\x9e\xa7\xed\x96\xd2\xa2\xc5\x86\xe0\x9e\x82\xf5\x87\xd8\x50\xba\x1f\x69\x43\xaa\x3c\x14\x1b\x22\xec\x89\x36\x74\x23\x8a\x29\x18\x23\xa6\x8b\x77\x40\x95\xbb\xc3\x38\x6e\x96\x61\x7a\xf4\x97\xe1\x8a\x96\x64\xdf\x36\x0b\xbd\x79\x2b\x25\xce\xb8\x4e\xb9\x9d\xdd\xd0\x30\xcd\xfd\xe2\x6f\x6e\x92\xc5\xf8\x7e\x1d\x6e\xa0\x14\x10\xf1\xdc\xa2\x17\x57\xd7\x30\x1b\xed\x0a\xe7\x0d\x9b\x53\xb8\xf8\x16\x67\x75\xc5\x36\x8b\x59\x84\xfc\x1a\xe6\x5c\x9d\x9d\xf7\xa0\x19\x11\xf8\x09\x92\x45\xd7\x93\x7e\x33\x53\x9d\xc9\x20\x1e\xab\x63\x0f\x9a\x11\x81\x1f\x64\xf1\x05\x69\xc3\xee\xb4\xb1\x0a\xb6\x87\xc6\x11\x66\x9e\x60\x71\x3b\x75\x93\xa1\xac\x6d\x36\x4d\x90\x60\x07\x9c\x16\x74\xa2\xa9\x00\xc8\x04\x00\x2a\x83\xda\xd0\x16\x0f\x10\x8c\xcf\xc7\x01\x14\x61\xb6\x01\x00\xa4\x8a\xca\xc5\xd7\x32\x83\x72\xb6\x43\xca\x67\x51\xfc\xf7\x9d\x3a\xb4\xf0\x03\x66\xd9\xe8\x35\xdc\x57\xe7\xd6\x9a\x28\xf6\xe5\x62\xb9\x0d\x16\x37\xa3\xd3\x69\x42\x5d\x85\x6b\xd1\xc2\x51\x1c\xe7\x99\x2c\x73\x20\xa5\x4b\x77\xa7\x6d\x20\x89\x5b\x24\xd2\x0d\x06\xa0\x06\xdb\xfb\xa1\x9a\xbc\x56\x2c\x99\x63\x07\xd5\x4d\xbe\x85\xa9\x26\xdf\x02\x04\x93\x97\xcb\xa0\x36\x40\x93\x57\x61\x80\xc9\x73\x14\xcd\xe4\x25\x00\x68\xf2\xec\x32\x75\x99\x41\x8b\xc9\x53\xfc\x0f\x63\xf2\x20\x3f\x86\xc4\xf2\x3c\x78\xac\xc9\x47\x3e\x0a\x16\xdb\xeb\x4c\x9e\xd6\x55\xb8\x36\x9a\x3c\x93\xa1\x69\x57\xd5\x06\x92\xb8\x45\x22\x9a\xc9\x8b\x35\x70\x59\xe6\xa5\x6a\xf0\x4a\xa1\x64\x8a\x1c\xa6\x1b\x3b\x83\xa8\xa6\xce\x8a\x05\x43\x17\x4b\x74\xda\xa0\x91\xcb\x10\xc0\xc4\x29\x82\x66\xe0\x42\x31\x68\xde\xec\x62\x7f\x91\x2d\x8b\x71\x53\xec\x0f\x63\xdc\x00\x37\xa0\x69\xd3\x47\x06\x1e\x69\xda\xf8\x66\x76\x33\xbd\xd2\xb4\x49\x5d\x89\x67\xa3\x61\x33\xf9\x99\xf6\x80\x6d\x20\x69\x1b\xa5\xa1\x99\xb5\x88\xdf\x4e\x69\x89\xb6\xff\x8f\xa1\x22\x39\x99\x33\xe7\x13\x1e\xb9\x0e\x7f\x53\xc9\x56\xd7\xbf\x08\xd6\xae\x3d\xe4\xd5\x66\xab\xe6\x60\xf6\xb3\x3d\x9c\x36\x6d\xfe\x99\x2f\xea\x22\xcd\x33\xdb\x15\x73\xb4\x86\xaf\xf5\x72\x9a\xce\xf0\xb0\x99\x4e\x53\xfd\x42\x2b\x51\x15\x9e\x8d\x1a\x4b\x90\xaf\x6d\x20\xba\x4a\x35\xc1\x6c\x54\x74\xb2\x37\x63\x50\xdb\x02\x11\x07\x5a\xb2\x81\x78\x9a\xc1\x0e\x45\xde\xd6\xd9\xb9\x13\x8e\x99\x95\xb7\xb2\x90\xc5\x03\xf2\x52\x15\xc9\xab\xaa\x5b\xe9\x06\xf5\xbf\x73\xe4\x52\x31\x4d\x16\xdb\x4c\x06\x7a\x57\x61\x5c\x93\xdc\xef\xea\x0d\x33\x9f\xab\x26\xc7\x60\x2a\x70\xda\x1d\x20\x6a\xc9\xb1\x77\xd7\xbf\x4a\xa7\x4b\x65\x2a\xe6\xa5\xaf\x3a\xca\x59\x45\xe1\x15\x06\x55\xce\x10\xa8\x0d\x6d\x1a\x06\x8b\x85\x70\xb9\xfa\xd4\x06\xcf\x64\xda\xf4\x34\x8e\x41\xf6\xe5\x40\xf8\xbe\xb2\x6c\x17\xa6\x22\x9e\xfe\x41\xc8\x7e\xd3\xb2\xdd\x85\x49\xcc\x49\x76\x6e\xe8\x69\x6b\x84\xda\xeb\x4e\x00\xaf\x43\x94\xd9\x5d\xfa\x3b\x82\x55\x25\xa5\x60\xe6\x3c\x08\xb4\xa4\x0c\x70\x69\xc7\x90\x76\xaa\xa3\xad\x9d\x85\x96\x40\xbc\x5c\xbc\xc6\x11\xd9\xbe\xe4\x74\x9b\x69\xc0\x0f\x39\xdd\xe6\x1a\xeb\x6b\x73\xdd\x66\x1b\x3d\x1f\xa3\xef\x84\x35\x7c\x13\x72\x8f\x95\x5b\xe7\xa7\xe8\xe0\xa2\x88\x0c\xd6\x23\xca\x92\xe2\x94\x92\xd7\x3e\x37\x66\x88\xfc\x2d\xa9\x9d\xf0\x9c\x2a\x5c\xba\x34\x59\x47\x37\xf4\x90\xad\x18\x40\x69\xa5\x17\x6a\x05\x03\xb7\x08\x99\x6f\x82\x27\xdf\xdb\xb7\x75\xc6\xce\xad\x79\x74\xc3\x96\x50\xb2\x16\x4a\xba\x9f\x6b\x0d\x7d\xad\xa1\x3f\xc9\x26\x2f\xb5\x5d\xe1\xa7\xf4\x74\xd5\x74\x3a\x85\xdf\x6e\x15\xba\x22\xf2\x79\x86\x25\x37\x68\x27\xcf\xb4\xb8\x77\xe6\xca\x1c\x33\x30\x3c\x8c\x60\xc2\xa5\x7c\x75\x9f\xc7\xb6\x75\xd6\xb3\x97\xa4\x19\x31\xfa\x47\xa6\xcd\x2e\x49\xc9\x13\x1a\x69\x71\x40\x2f\xd9\x2e\x95\xdf\x2f\x84\xfd\x59\x3d\x4f\x29\xb4\x3b\x5b\xbc\xc5\xfc\x82\x64\xae\x00\x36\x08\xc6\x19\xcc\x65\x6e\xeb\xcc\x8d\xf1\x0e\x9d\xd2\xfa\xdc\xf7\x9c\xaf\x32\x73\x26\x47\x0f\x84\xfa\x82\xc6\x79\x11\xb3\x26\x2b\x61\xbc\x68\xfe\xa9\xcb\xcd\xa8\xf9\x27\x91\xd7\x4d\x67\x20\x2d\x14\x37\xff\x64\x56\x05\xdb\x6a\xe9\xf3\xb2\xbc\xc0\xd9\x5b\x2f\x2e\xf3\x22\xce\xef\x9a\x50\xb8\xdf\xa7\x78\xb8\xa0\x46\xf2\x00\x48\x4d\x1f\xc4\x2a\x84\x1d\x1b\xd1\xb9\x87\x74\x60\xa4\xb6\x96\xa9\xf5\xf6\x9b\x13\xef\x45\x5c\x0f\x46\x1c\xa0\xd3\x78\xd6\xfc\xeb\xb7\x8f\x47\xea\x14\x74\x2d\x72\x03\x7c\x40\x41\x2a\xe3\x30\x48\x69\x2d\x4c\x57\x5b\x37\x48\x01\xa2\x1d\x10\xa0\x2a\x00\x29\x59\x83\xfb\x51\x94\xd7\x83\xb5\x1e\x86\x65\x3c\xb6\xd6\xeb\x24\x1c\x6f\x8b\xe2\x3d\xee\x7b\xa2\x70\x4a\x2b\x8d\x78\xd0\x50\x69\x37\xc4\x8b\x18\xcd\x24\x2a\xa2\x84\xa5\x87\x0f\xed\xe4\xe9\x83\x87\x0a\xf9\x20\x0c\xb7\x33\x5f\x22\x2f\xdb\xf2\x08\x5a\xa1\x3f\x8b\x97\x0a\xab\xa2\x2d\x73\xfa\xfd\xb6\x3c\x48\x5c\x23\x79\x00\xa4\x06\xf8\x27\x05\x22\x18\xba\xcc\x3d\xa4\x03\x23\xb5\xc1\xfe\x49\x51\x70\x2f\x62\xbf\x7f\x1a\xa3\x53\x22\xba\x7e\xfb\x78\xa4\x4e\x2d\xfe\x89\x37\x00\xf9\x27\x15\x06\x29\x0d\xf2\x4f\x0c\x06\xfb\x27\x0d\x08\x50\x1d\xec\x9f\x64\xe5\xf5\x60\xf5\xf8\xa7\xbe\xc7\x4b\x87\xba\x0a\xc5\x4b\xf1\x6a\xf0\x0d\x3a\x4d\x3d\xe5\xed\x5a\xd8\x52\xe6\xd1\xf6\x66\x1e\x29\xad\xcf\x22\x84\x67\x91\x44\x45\x14\xb5\xf4\x7a\xaa\x9d\xfc\x6c\xb6\x8a\x67\xaa\x21\x86\xf3\xf9\x22\x9c\x4b\xe4\x87\x18\x35\x48\x6b\xba\xba\x99\x4d\x57\x32\xab\xa2\x51\x73\xfa\xfd\x46\x3d\x48\x5c\x23\x79\x00\xa4\x06\x38\x2a\x05\x22\x58\xbc\xcc\x3d\xa4\x03\x23\xb5\xc1\x8e\x4a\x51\x70\x2f\x62\xbf\xa3\x1a\xa1\x53\x2a\xba\x7e\xfb\x78\xa4\x4e\x2d\x8e\x8a\x37\x00\x39\x2a\x15\x06\x29\x0d\x72\x54\x0c\x06\x3b\x2a\x0d\x08\x50\x1d\xec\xa8\x64\xe5\xf5\x60\xf5\x38\xaa\xbe\xab\x43\x86\xba\x0a\xc5\x51\xf1\x6a\x66\x47\x25\x3e\x88\x6d\xf0\x52\xdb\xc8\xd7\xbe\x92\xcc\x16\xdb\x9b\x18\x75\x24\x44\x21\x77\xef\x2f\xf7\xd8\x5f\xb0\xf5\xe3\xb9\x1a\x28\xb7\x8b\xf8\x66\xde\x11\x1e\x64\xc8\x10\xa1\x70\xb1\x42\xdb\x48\xe0\x50\xb4\x62\x42\xb9\xdf\x84\xfb\x85\x33\xa6\x69\x55\x46\x80\x37\x12\x8b\x05\x9b\x16\xd8\xd5\x04\x0d\x13\x19\xec\x81\x44\xe5\xd9\xb1\xfa\x7d\xcf\x50\x7d\x51\xf9\xf4\x28\xfe\x6a\x7d\x59\xfc\x0d\xa1\x0b\x39\x1b\x09\xa0\x29\x04\x72\x33\x0d\x00\xf6\x31\x32\x44\x25\x36\xd8\xbb\x08\x8a\xb1\xa1\xf4\xf8\x15\xeb\x5d\x34\x83\x46\xb6\xea\x51\x58\x1d\xb3\x47\x51\xde\xc5\x87\x4d\x60\xe7\xa3\x78\xa6\x36\x8d\x31\x0a\xa7\x0b\x89\x8a\x28\x58\xe9\xe5\x75\x3b\x79\x1c\xad\x96\x81\xba\xf4\x5c\xdd\xcc\x77\x7e\x2c\x91\x1f\x62\xad\x20\xad\x78\x7e\x33\x0f\x42\x99\x55\xd1\x60\x39\xfd\x7e\x9b\x1d\x24\xae\x91\x3c\x00\x52\x03\x9c\x8d\x02\x11\x8c\x5b\xe6\x1e\xd2\x81\x91\xda\x60\xc7\xa3\x28\xb8\x17\xb1\xdf\xfd\x8c\xd0\x29\x15\x5d\xbf\x7d\x3c\x52\xa7\x16\x57\xc4\x1b\x80\xbc\x91\x0a\x83\x94\x06\xf9\x24\x06\x83\xdd\x92\x06\x04\xa8\x0e\x76\x4e\xb2\xf2\x7a\xb0\x7a\x5c\x54\xef\xd5\x47\x03\x5d\x85\x9a\x49\x62\xd5\xcc\x8e\x8a\xdd\x0d\x64\x37\x94\xd5\x7c\x3a\xd3\x06\xde\x6c\xba\x9b\x22\x91\x88\x94\xac\xa3\x77\xf4\x0c\xf0\x52\xd1\x6a\xea\x87\x6a\x1c\x5c\x2e\x82\x28\x58\x89\xc4\x87\x18\x34\x48\x0a\x45\xe1\x8a\xcf\xe5\x19\x9f\x52\x4e\x94\x52\x1f\x90\x12\x1d\x20\xa8\x71\x0c\xe8\xf2\x82\x72\xdc\x12\x40\xcc\x95\x8a\x8c\x03\xa2\x37\x91\x1a\x9e\xdf\x96\x94\xda\x87\x37\x20\xbb\x3d\x58\x8f\x54\x62\xbd\x26\xf1\x28\x3d\xda\x32\xdb\x94\x3a\x98\xd8\x96\x41\x80\xa2\xc0\xb4\x36\x01\x19\xb2\xda\x0a\x4c\x27\x39\x3c\xa7\x2d\x2a\xcc\x8e\xd4\x97\xd1\xb6\xdf\xb0\x35\xd0\x1f\x28\xbe\x88\xd7\x32\xfb\xa2\x34\xc9\xde\x9d\xb5\x93\xa4\x50\x92\xaa\x7b\xfc\x9b\xd7\x9b\xb4\xbf\x24\xb3\x68\x0a\xd6\x6a\x41\xff\xe7\x49\xca\x8a\xf5\xd8\xfe\xd0\xf7\xdd\x01\x0e\x35\x86\x44\xa5\x93\xbf\x99\xe4\x45\x01\x8b\xd7\xb0\xf7\x55\xe4\x4b\x8c\xe9\x3c\x5c\x46\xda\xc7\xe4\x53\x16\xe3\x32\x4d\x32\x20\x2e\x80\x8d\xc0\xc6\xa9\x40\xec\xa6\x29\xf0\x6a\x45\x91\xd8\x6f\xaf\x8e\x87\x3e\x84\xb7\xfb\x42\xde\x36\x7f\x31\x96\xf6\xe7\xa7\x3b\xd2\xd4\xb5\x51\x1d\x85\x36\xba\x83\x87\x8f\x39\x73\xd7\x11\xbf\xaf\x04\xe2\xf7\x55\xd7\x01\xfa\xb5\xfd\x4a\xda\xd0\xae\x48\x71\xe7\x5b\x8b\xf3\x5a\x40\x97\xb7\x4d\x8a\xf7\x35\x6c\x4f\x75\x9d\x67\xbf\x74\xb8\xd2\x69\x5a\x5c\xe1\xda\x00\xab\x4e\xdb\x63\x22\x02\xe5\xfd\x77\x28\xc6\x67\xfe\xd1\xde\x87\xae\x61\x61\x40\x72\x89\x89\xd3\xf4\x1d\x95\xca\xc5\x2a\x10\x86\x1d\x4c\xdb\xf5\x92\xec\x2c\xdc\x84\x11\xe5\x69\x8a\x8a\x0a\xb7\x32\xa3\x86\xc6\x8b\x1b\x6c\xf9\x3e\xa2\xba\x04\x81\xec\x6e\xab\xfc\xee\x42\xae\xcd\xb2\xe3\x50\x13\x68\x5b\x69\x26\xcb\xfa\x36\x3a\xa6\x6c\xbf\xbd\x4a\xb0\xbd\x48\x50\x13\x97\x5b\x27\xc7\x24\xdb\xbb\xbb\x53\x46\x37\xf1\x60\x54\x61\x59\x5e\x30\x4a\x2f\x09\xbd\xa9\xf8\xc4\x46\xa4\x37\x55\x2f\xbb\x51\x60\xe6\x4a\x3a\xd5\xa2\xcc\x0b\x5c\xd6\x0f\x6b\xda\xeb\xc9\x6d\x52\x25\xdb\x24\x4d\xea\x07\xa5\x09\x0b\xe2\x20\xac\x8b\x17\xa1\x12\xd7\xb6\x3d\xb7\x7e\x27\x7a\xe9\x71\x8e\xe2\xde\xb0\xbb\x4a\x78\x73\x60\x56\xdc\x3b\x31\xaa\x0e\x38\x56\x4b\xc9\x2e\xa6\xbf\xb7\x09\x67\x76\xc0\xcf\xb6\xbd\x89\x3e\x33\x02\x61\x5c\xda\x09\xce\x84\xfc\x3a\x15\xd0\x31\x43\x65\x12\xa4\xec\x65\xf2\x05\x84\x23\xce\x4e\x86\xe3\x84\xe4\xa6\x28\xba\x95\xb3\x3d\x50\x18\xf8\xbe\xbf\x11\xc7\xcb\xa6\x7b\x93\x6a\x23\xbc\x95\xb5\x50\x0f\x2a\xb7\x57\xb3\x85\xec\x7e\x30\x65\x23\x9c\xf2\x38\xc8\x26\x4d\xaa\x9a\x5d\x95\xa9\x6e\x15\x13\xe6\x91\x6d\x40\x16\xa0\x69\x52\xac\xbb\x63\xe8\xf7\x1b\x2b\xcc\x72\x1b\x95\x50\x2a\x6d\x7f\x22\x3b\xa5\x06\x5c\x57\x45\x37\xec\x37\x1e\x5c\xae\xaf\x1c\x4f\xb0\xa0\x29\x6a\xf2\xc8\xcb\x49\xc4\x7a\xce\xfc\xa0\xa7\xf0\x80\x8f\x84\xeb\x78\x71\x72\x9b\xc4\xb8\xe4\xa7\x5c\x83\x76\x2f\xe2\x7a\x45\xd4\xa1\xba\x16\x20\xf7\x42\x2f\xab\x93\x09\xbf\x4d\x93\xb7\x08\xbe\xb5\xac\x09\x45\x0e\xb9\xbd\x22\x4a\x31\x2a\xd7\xdb\xbc\x3e\x0c\xdd\xe0\x28\x6c\x7c\x81\xee\xf8\xd4\x59\xe0\xd3\x12\x00\x22\xcf\x87\x16\xcd\x3f\x70\x4e\x01\xd9\x14\xbb\xb4\x5f\xa6\xca\xdf\x06\x40\x6a\x73\x2d\x00\xe6\xa6\x03\x6b\x0b\xa0\x81\xfc\xb0\x19\xb0\x69\xe0\xbe\x6d\x97\x1e\x00\x6f\x1d\xc8\xc0\x9d\x80\xa0\xce\xc1\x2c\xed\x0c\x25\x06\xf6\x10\xd8\x01\x68\xbf\x27\x0b\xdc\xe6\xc8\x36\x0d\x16\x65\xbe\x4f\xe2\xf5\x1f\xff\xfa\x43\x03\xfa\x4b\x53\x6d\x97\x97\x47\xef\xcf\x49\x54\xe6\x55\xbe\xab\xbd\x7d\x33\x42\x71\x56\xbf\xc4\x19\x61\xee\xf7\x3b\x94\x56\xf8\xd5\x45\x5d\x2a\x12\x27\x28\xc7\x7a\x8a\x82\x8c\x3e\x73\xe0\x38\x24\x9e\x5c\x78\xeb\x6c\xc3\xb7\xc6\xb7\x58\x07\x8c\x9a\x61\xda\x33\xa2\xac\x53\x42\x75\x14\x35\x93\x68\xeb\x28\x6a\xc4\xda\xfc\xd1\x39\xfe\x5d\x72\x8f\x63\xe5\x10\x79\xbb\x67\x59\x89\x01\xab\x95\x7f\x11\x7c\x91\x2a\x47\x83\x48\x4e\x85\x43\xe3\xef\xc4\xcb\xd0\xed\x16\x95\x2e\x69\x93\xed\x8c\x76\x5a\x22\x0c\xeb\x1c\xe5\x59\x8d\xb3\x7a\xfd\xc5\x17\x62\x38\x55\xef\xd6\xd4\x83\xae\x00\x60\x71\xb7\x6b\x5f\x62\xb4\x97\x0f\xb9\x5b\x4d\xeb\x44\x83\xed\x99\x22\xfd\x85\x2a\xdb\x4e\x77\xd6\x18\x91\x8e\x4a\x1b\x10\x99\x05\xdd\x64\x53\xc2\x12\x63\x22\xac\x36\xf8\xc4\x65\xe8\x65\x44\x86\x33\x28\x3a\x41\x61\x11\xc3\x4e\xdd\xd0\xcd\xb5\x6a\x2b\xe2\xab\x95\x06\x2a\xd2\xfa\x1d\x80\xaf\xfb\xe0\xc2\x22\x15\x02\x0b\x89\x99\x8e\x55\xbd\x51\x43\x5b\x70\x13\x02\xe5\x73\x7b\xdf\x82\xd0\x43\xb2\xc4\x7d\xad\xc8\xa8\x2b\xd4\x14\xe5\x74\x3f\xc1\x5a\x02\x48\x3e\x25\xc2\x8e\x84\xf0\x75\x60\x9d\xe7\xe9\x16\x95\x32\x74\xae\x40\x9d\xae\x05\xb1\x44\x64\xaa\x2d\x17\x0f\x8a\xa9\xba\x64\x48\x6f\x35\x72\x6f\x0d\xe4\xde\x4a\xe4\xa4\x67\xf7\xa4\x45\x32\x95\x6e\x96\xd7\x2f\xc5\x6b\xa6\x5f\xd1\x92\xee\x8e\x60\x5a\xa0\xce\x77\x5f\x9d\xc1\x9c\x91\xa8\x4c\xe1\xea\x6a\xe5\xd0\x92\x19\x73\x64\xe3\x75\x5e\xd0\xf1\xdb\xb2\x21\xfb\x28\x05\xa8\xb5\xdc\x35\xa4\xcb\x41\xb2\x43\x75\xb6\xaf\x61\x8b\x1c\x35\xdd\x34\x31\x24\xc1\x54\x7e\x0c\x16\xa0\x22\x0c\xd0\x19\x75\x14\x3d\x2a\x62\xd4\x6c\xe2\x57\xc5\xa4\x0e\xce\x41\x24\x14\xe1\x3d\x91\xf2\x58\xd3\x36\x15\xea\x86\xf8\x48\x2d\x39\x9a\x21\x68\x9e\x8c\xcc\x6a\x34\x3c\x71\x92\x23\x77\xe3\xb5\x86\x2a\xdf\x52\x73\xa3\x5e\x14\x78\xa3\x0f\x62\x72\x89\x8b\x9d\x4c\x10\xaa\x74\x82\x50\x22\x64\xe0\xfb\x43\x9c\x72\xb1\x31\xd0\xa5\x8d\xc7\x64\x86\xf9\x0c\x07\xf0\x3b\xe4\xc8\x1b\x01\x32\x95\xb3\xc7\x93\x19\x83\xaa\x25\xb0\xa4\x45\x37\xc1\xb1\xd0\xf0\x1d\x46\x65\x48\x28\x97\x01\xe6\x39\xc5\x5b\x35\xfa\xcb\xd3\xd8\xee\x61\xb9\x8d\xf1\x95\x4f\x23\x3b\x22\x59\xf1\x85\x3a\x03\xba\x1a\x33\x01\xe8\xa0\x7e\xd8\xe9\x18\x83\x30\xb9\x11\x32\x50\xce\x69\xfa\x46\x6e\x07\x78\x49\x8b\x83\x54\x27\x3f\x16\x07\x67\x72\x2a\xb3\xe2\x7e\x63\x72\x75\x02\x0c\x74\x76\x03\xfd\x91\xc2\xa5\xcd\x17\xf6\xba\xbe\x71\xee\x58\xef\x80\xd2\xf5\x1e\xa3\x7b\x82\x18\x06\x92\xbd\x32\x98\x5d\x41\xcb\x10\xd5\x9e\x4e\x9d\xef\x25\xc0\xe9\x5a\x16\xdb\xff\xf5\x54\xd5\xc9\x2e\xc1\xb1\x9c\x55\x17\x5d\x0b\x4d\xb3\xa7\xe8\x21\x3f\xd5\x6c\x4d\xdb\x7d\x50\x23\x49\xf9\x75\x85\x0b\x54\xa2\x1a\x83\x94\x35\x3f\x28\x43\x94\xdb\x12\x68\x6b\xca\x13\x9a\x9c\x9d\x17\xe6\x06\x84\x49\xfd\x19\x76\x84\x30\xbe\xbc\x68\xec\x16\x8b\x3f\xc7\xa8\x46\x4c\xd3\xec\xbb\x4d\xf5\x0b\xa9\x09\x9f\xee\x1f\x86\xcf\xee\x66\x35\x23\x0b\x0e\x7a\x6c\x3b\x86\xaa\xc6\xbb\x7b\x49\xe2\xb6\xc4\x51\xcd\xc2\xb3\xff\x0a\xbe\x90\x4e\x5c\x5b\x98\x97\xbb\xd4\x6c\xcc\x86\x21\x50\x91\xdf\x52\x15\xb4\x3c\xec\x26\xd2\xbd\x7e\x31\x06\xc0\x57\x77\x5b\x9f\x90\x4c\x37\x3e\x02\x62\x23\xce\x12\xfd\x9c\xe0\x54\xbd\x79\xfb\xad\x72\x47\x87\x0a\x05\x6e\xe6\xb0\xa1\x6c\xeb\x8c\xfa\xc1\xf7\x7f\x71\xa6\xa1\x07\x06\x1c\xbd\x1f\x03\x10\xc1\xde\x0c\xbd\xa1\xd3\xca\x9f\x05\xdb\xc4\xe9\xc0\x2a\x9c\x67\xf5\x7a\x50\x03\x3b\x46\x2c\x9d\x8d\x41\xa8\xaa\xc8\x68\xee\x4a\xbe\x3e\xd1\x66\x73\x0d\xb4\xc7\xe6\x54\x14\xb5\xc9\xf7\x71\xc5\xaf\x81\x75\x03\xce\x20\x63\x1b\xd4\x8d\xa1\x77\x09\x5b\xf9\xb3\x60\x8f\x34\x36\x13\xcf\xb0\x6d\x68\xec\x18\xb1\x06\x1a\x5b\x9f\xc8\x34\x63\x53\x6f\x20\xea\xb1\x2c\x71\xbd\xd2\x85\x72\x9b\x77\xed\x9f\x16\x02\x8d\x8e\xae\x75\xed\xf2\x60\x40\x77\xf9\xdc\x64\xf0\xf5\x21\x00\xd5\x73\xdf\x83\x41\xd6\x4f\x7e\xe2\xbb\x41\xfa\xad\x26\xf0\xeb\x25\x03\xdf\x0c\x02\x78\xd5\x6e\x0e\x37\x7a\x08\x60\x53\x8d\x89\xda\x90\x2d\x47\xc0\xe6\x22\x8d\x9c\xe1\xea\x25\x2b\x9e\xf4\xd6\x96\xcb\x2e\x45\xb3\x4c\x07\xc4\xb7\xfd\x74\xcb\x34\x82\x95\x89\x3b\x9b\x16\xf7\x61\x08\xb3\xba\x1e\x64\x65\x79\xa2\x63\x0b\xaf\xc0\xa9\xcb\x32\x75\xcd\xd4\x5b\xf9\x7d\xa7\x6d\xad\x72\xd5\x1e\xed\x33\x2b\x4b\x5c\xfb\xe9\x34\x4d\x50\xb3\x22\x0c\x2b\xb2\xfe\xea\x50\xba\xb9\x47\xc6\x03\x35\x38\x00\xd7\x92\x8f\x1d\x91\x14\xb5\xc9\x4f\x7d\xab\x52\x75\x92\xc0\x17\xac\x76\x70\xfb\xe0\x87\x55\x30\x4a\x01\xdb\x72\x20\x3c\x92\x4b\x02\x3e\xe5\x40\xb8\x6d\x42\x17\x04\xb2\x0f\x54\x20\x4c\xfb\x4c\xf5\x54\xa3\x5d\xbd\xaa\x0c\x60\xfd\x4a\x5b\xe9\xb8\xdd\xe8\xd2\xc9\xd0\xad\x72\xbf\x9d\x76\xd3\x96\xb2\x83\x88\xd4\x79\x9b\x26\x7d\x0f\xe9\x70\xbc\xb7\xa8\xf7\xc9\x1d\x39\x0a\xcc\x19\x5f\xd2\xf6\x94\xf6\x6f\xcb\xa6\x08\x30\xe8\x71\x52\xc2\xc6\x0a\x69\x7f\x86\x06\x95\x5b\xb4\x6d\xee\x80\x37\x9f\x8c\xdc\x9a\x41\x38\x70\xd8\x2e\x89\x89\xf8\x87\xc0\x48\x5b\x64\x7c\xb7\x19\xab\xe7\x5b\xe8\x8e\x17\x46\x3d\x43\xb7\xee\xd3\xed\x63\xe2\xba\x78\x9b\x1c\xf7\xe7\x2e\x09\xdd\x1a\x87\x5b\xa3\x6d\x75\x36\xbe\xdd\x49\x9e\x61\xe6\x68\x8d\x21\x89\x3b\xdf\x24\xdb\x6b\x4d\x94\xa3\xbe\x45\xf2\x30\xb1\x6c\xe1\x18\x77\xf9\x99\xc3\x5e\xdb\x54\x5a\x83\xf6\x92\x37\xb2\x76\xe8\x7f\xa9\x3d\x11\xf6\x37\x41\xa5\x82\x42\x75\x98\x64\x5c\xcd\xa4\x8e\xd9\x11\xbb\xe5\xc6\x7a\x7f\x96\x22\x5d\xc5\xa3\xc3\x26\x47\x38\x20\x3f\xba\x74\xa0\x90\x2a\x91\xb5\xe7\x9b\xaa\x74\xea\x93\xb5\xaf\x61\x75\x9a\x13\x9e\x60\xd5\xe6\xad\x46\x02\xfd\xbb\x49\xba\x2c\x9e\x6d\xe7\x88\xa1\x0b\x40\x22\xb2\xcb\x3e\x0e\xef\x93\x7f\x19\x84\xdd\xed\x0b\xd2\x26\xde\xa6\xee\xeb\x86\x65\xc2\x50\x8d\xcc\x88\x27\x9a\xb6\x3a\x3c\xc7\x8b\xf0\x2d\xb2\x0e\xf8\x21\x23\xee\x03\xf7\x59\x1e\x1e\xe4\x20\x0d\xe5\xa5\x48\xd2\x54\xf1\x4b\x32\xa0\xeb\xab\xaa\x3a\x8e\xf1\x3a\x4d\xce\xca\xbe\x67\x19\x41\xe9\x9c\x56\x2c\xf6\x48\x07\x0e\xb9\xd1\xa0\x73\xff\x6e\x55\xa3\xe8\x1d\x3c\x56\x3b\x90\xc0\x32\xb9\x5e\x5a\xff\x02\x67\xf2\x15\x97\x7e\x97\x70\xad\x27\x78\x0f\x0e\x60\xdc\xb8\x1f\x3c\xdc\x05\xc9\x18\x5d\xe7\xf5\xee\xc0\x3e\x2c\x86\x0c\x89\xa7\x77\x01\x4f\x3d\xfc\x3f\x40\x1f\xc1\x21\x5f\xa3\xad\xcb\xf6\x48\x92\xc7\xd4\xdd\x02\x65\xea\x51\x16\x09\x87\xdd\x1c\xaa\x4f\x76\x09\x13\xaa\x7d\xaa\x9f\xb5\xaf\xf9\x74\x47\xf7\x30\x42\xd7\x44\x77\x77\x21\xcf\xf5\xd7\x0e\xc9\x86\x57\xdb\x3c\xa8\x6f\x93\x25\xe0\xe6\x7a\xf7\x65\xb2\x6d\xb8\x82\xef\x6c\xf7\x60\xb6\xe7\x84\x94\x4d\x2b\x73\x6d\xd3\x4a\x53\xc2\xe7\xa3\xee\xfd\x9a\x1c\x3d\x49\xbb\xa3\x34\x2d\xa8\x8a\xca\x3c\x4d\x9b\xa5\x03\xb9\x7f\x57\xdc\xe0\x0a\x4f\xfc\x7a\x9e\x1b\xf0\xe9\xd6\x95\x70\x3e\x9f\xf0\xff\x78\x81\xf1\x11\x04\x18\x5b\xeb\x2e\x39\x2d\xc5\x39\x7e\xe8\x77\x51\x92\xa8\x84\x2b\xec\xa5\xdd\xbb\x83\xf7\xc9\xa8\xcc\x68\x87\xb5\x88\xfd\xfe\x2e\x39\x16\x79\x59\xa3\xac\xde\x08\x49\x61\xa1\x54\x79\x8f\x50\x58\x2e\x30\xe5\x74\xb8\x7d\x02\x60\x15\x2e\xf0\xb6\x61\xa5\xae\xb2\xb9\xb8\xce\x0b\x33\x0a\xbd\xb2\x1f\xc4\xe9\x7b\xf0\xf0\xc9\x98\x21\xeb\xa1\xf6\x05\x30\x5f\xd8\xc8\x8c\xee\xf9\xdb\xcb\xec\xc9\xad\x1b\xbf\xb8\x7f\x45\x1f\x68\xce\xcb\x04\x67\x35\x5d\x44\xa6\x28\x8b\xab\x08\x15\xb8\xb3\x86\xa7\x64\x2a\xf4\x7d\x72\xf3\x76\xe3\xce\x50\x92\xe1\xd2\xdd\xa5\xa7\x24\x7e\xab\x93\x35\x61\xd0\x11\x2e\xc0\x6d\x75\x95\x5a\x8f\xbc\x90\xfd\x53\x60\xda\x57\xe6\x45\x17\xdd\xfc\xce\xd2\x29\x2f\x65\xf7\x18\xf1\x1d\xbd\x0e\x40\x20\xa6\x7e\x9f\x00\x6d\x55\xb7\x02\xf5\x4c\x82\xb4\x37\x5e\x3c\x88\x36\xf5\x7b\xb9\xe9\x69\xa9\x87\xc3\x06\x45\x3a\x73\x20\x8b\x02\x6a\xe4\xdc\xfa\x19\x35\x1b\x25\x91\x08\x84\x49\x44\x43\x62\x5b\xa2\x2c\x16\xf3\x09\x62\x70\x6c\xb3\x4c\x73\xfb\xa7\x74\xfa\x82\xb1\x48\x51\x98\x68\x74\x65\xe6\x44\x94\x5c\x99\x64\x49\xe4\xc9\x42\x8f\xb8\xdf\x76\x96\xe8\x48\xa4\x26\x3a\x02\x35\x73\x19\xed\xac\x8f\xa8\x96\x25\xbe\x6d\xd4\x70\xb8\x80\x18\x49\x2b\xa9\x15\xff\xc6\x23\x4c\x62\x6e\xba\x3f\x85\xf0\x2d\x6b\x89\x7c\xb8\x19\x7f\x1c\x69\xec\x7d\xf5\x52\x97\xf4\xa3\x99\x12\xd8\xf1\x92\x28\xcf\xdc\x66\x52\x03\x9d\xec\x0e\xc3\xee\x6d\x41\xfd\x2b\x56\xa0\xb5\xd6\x91\x7b\xdd\x11\x96\x1f\xc6\xee\x1d\x54\x4c\x15\xd2\x4c\xb3\x6d\x26\x43\xb7\x8c\xde\x7a\xe9\xcd\x8b\x7b\xc7\x6d\xf3\xa2\x0c\xcc\x52\xab\xe2\x4b\x0e\xbe\xfe\x70\x70\xa0\x7e\x0e\x0f\x95\x98\xc4\x59\x5b\x8a\xac\xb5\x29\x47\x75\x36\xdb\xda\x0d\xf5\x4f\xfa\x76\x2d\x32\x53\x91\x9e\xfc\xb0\x1b\x02\x55\xf9\xf8\xf9\x8c\x89\x43\x47\x3d\x10\x36\xe9\xab\x21\xc9\x91\x7e\xd6\xe4\xdb\x84\x43\x45\xe4\x96\xfa\x46\x07\x62\xad\xa6\x38\x16\x3b\xae\x96\xfb\x15\xee\x5e\xe9\x35\xb6\xc6\x9e\xb4\x3c\xab\x30\x4a\x58\x4e\x5f\x49\x79\x98\x4d\x6d\x0e\x98\x9a\xe4\x68\x76\x79\x79\x3c\x6b\x89\x7d\xab\x27\x71\x0d\xae\x44\x73\x67\xfd\xf3\x7c\xd3\x62\xf4\xd1\x6b\x81\xc9\xd3\x2d\x14\xac\xa4\xfa\x43\x72\x5e\x1e\x9f\xec\x5d\x2d\x9d\xe6\x23\xdf\xd5\x32\x12\xb4\xbf\xab\x25\x55\xbb\xf6\x5d\x2d\x13\x11\x75\x57\x8b\x19\x0f\xd8\x00\x32\x0c\x59\x7d\x57\xcb\x54\xcb\xf2\xae\x96\x54\xe5\xaa\x77\xb5\x64\x0a\xed\x73\x4a\x52\xf1\x13\xbf\xab\x05\x36\xc9\xdf\xd5\xd2\x1b\x36\xbc\xab\x05\x53\x81\x37\x77\x00\x44\xaf\x78\x57\x4b\xa2\x32\xe2\x5d\xad\xbe\xf8\xa9\x0d\x4e\x2d\xe3\x09\x0d\x11\x75\x27\xb8\x9e\x6e\x1c\xe2\x14\xc4\x94\x81\xe8\xb2\x7d\x7d\x0d\x6f\x5b\xd7\x8c\x0f\xcd\x6a\xc4\x30\x27\xc2\xfc\x47\x64\xc1\xe0\xc5\xb0\xb5\x49\x75\xed\xf0\xe1\x8e\x70\xf0\x59\x79\xb7\x31\x41\x09\x7c\x5d\x94\x13\x91\x3d\x76\x59\x92\x50\x27\xd0\xd3\x7b\x81\x0f\xd4\xba\xaf\xa4\x5a\x33\xbd\x96\x34\x75\xc6\xf7\xb5\x84\x0f\x3c\xf9\x68\x5d\x90\x8b\x74\xf4\xcf\xb8\xfa\x02\xa1\x4d\xef\xf5\xdb\x32\x39\x9c\xdd\xd1\x04\xf2\x4b\xf4\xe6\x00\x61\xe1\x22\xe4\xab\xf4\x89\x85\x5c\xed\xff\xc8\x44\xe4\x91\xd0\x99\x32\xf0\x96\x0b\x4f\x1e\xdf\x34\xff\xd4\x4b\x25\x97\xcd\x3f\xb5\xb6\xb2\x3a\x53\x76\x1f\x18\x11\x95\xc9\x21\x8c\x23\x7f\x36\x26\x5f\xe8\xfb\xb7\x1b\x40\xe4\x88\x0a\x07\xb0\xd6\x4e\x07\x47\xe0\xf6\xf4\x44\xd9\xdb\x21\x5c\x61\x72\x55\x4f\x1a\x72\xf2\x17\x84\x5e\xac\x01\x0c\x5a\xbe\xd4\x03\x3b\x25\xec\x76\x40\xe8\x89\x37\x8e\x0c\xc3\x1b\xc2\xa5\x69\xbb\x0a\xd9\xe8\x79\x95\x5d\x48\xbb\xc7\xf8\x75\x84\x6c\xe3\x83\xb9\x42\x0f\xaf\x0c\xc9\x78\x49\x62\x2f\x7d\x61\x3d\xaf\x57\xbf\xb9\xb9\x31\x56\xd7\xd2\xa6\x2a\x02\x89\xa1\xa3\x86\x35\x11\xbc\xb0\x81\xa7\x07\x67\x88\x1a\xa5\xed\x3e\x43\x4c\xad\x6f\x46\x02\xb4\x62\x59\xcd\x0e\x1b\xdb\x83\xd7\xb5\xe3\xea\x3e\x99\x17\x80\xdb\x18\xe4\x1a\x7a\xaa\x5e\xdb\xbf\x27\x76\x22\x86\x46\x86\x79\x96\xde\xca\x57\x77\xf2\x6a\x1f\x64\xec\x2b\x39\x1a\x3e\xc0\x28\xf5\x7b\x30\xc9\xc3\x5f\x2a\x76\x7b\xda\xdc\x46\x52\xbd\x26\xd4\x08\x1f\xde\x9e\x7e\x19\xe8\x00\x4c\xf3\xe5\xa0\x3d\x1c\x8f\xaa\xa2\x2a\xaa\xed\x44\x92\xdd\xe2\xb2\xc2\x80\x97\x0d\x43\xf5\xfe\x73\xff\xa6\xf9\xa7\x56\x85\xa7\x3f\xab\xb8\xf9\x67\xc7\x55\xa4\x04\xe3\xf4\x6f\x86\x81\xdc\x85\x4a\x4b\x9c\xfe\xf4\xb0\xa6\xce\x80\x06\xa2\xf7\x74\x06\x9e\x04\x5d\xdd\x1f\x78\x12\x64\xc5\x1a\xc0\xe0\xa8\x2d\x48\x3d\xd6\x60\x9a\x04\xf5\xe0\x0d\xe1\xd2\xe4\x80\x66\xb3\xd9\x95\xd6\x01\x4d\x82\xc4\xa1\x0e\x57\xe8\xe1\xb5\x67\x12\xd4\x4f\xdf\x3a\x09\x22\x37\x43\x1b\xaa\x6b\x93\x20\x15\x01\x98\x04\x05\x7e\xf3\xcf\xae\x4e\x65\x12\x64\xc1\x19\xa2\x46\x68\x12\x64\x35\xb5\xbe\x49\x10\xd0\x8a\x29\x84\x29\xb7\xca\x8d\xf2\x73\x96\x6f\x13\x6c\x0f\xf6\x35\x83\xa5\x7f\xba\xd6\xef\x88\x06\xcf\xd8\xc6\xd5\x7d\x32\x97\x35\x74\xc6\x36\xbe\xea\xb5\xfd\x7b\x62\x8f\x37\x7c\xc6\x76\x4d\xe5\xab\x3b\x79\xb5\xc3\x34\xf6\x55\x9c\x5e\xf5\xd8\xa5\x3e\xff\x00\x5d\x97\x3a\x69\x33\x51\x35\xcc\xdb\x74\xf8\xf0\x26\x8d\xf3\x36\x1b\x66\xef\xbc\xcd\xc4\xf1\xa8\x2a\xaa\xba\x2e\xde\xb6\xc4\x28\x8e\xca\xd3\x71\xdb\x7e\x7e\xbb\x51\xbe\xbe\x89\xfb\x03\x07\xdc\x0f\x4c\xee\x72\x05\x1f\x8c\x6f\x9b\x12\x37\xd3\xca\x9f\x74\x24\x9c\xd7\x69\xb2\xde\xe2\x5d\x5e\xb6\x1b\xb2\xe8\x75\x4a\x1b\x61\x85\xd0\xde\x57\xf9\xe6\xef\xbe\x8f\xfc\x2f\x24\x12\x7c\xf3\xa5\x38\x71\x2f\xd0\x3e\xc9\xc8\xee\x0b\xf8\x83\x06\x78\xbc\x89\x74\xde\x01\x37\xdd\x76\xf4\xf4\x5e\x29\xd0\x66\xbc\xca\x05\x55\x81\xec\x57\x37\x6e\xb4\x53\xbf\xea\xa1\xac\xde\xab\x7d\xc9\x55\xb6\x43\x2f\xe2\x35\x1d\x12\x51\x7a\x22\x9d\x4a\x53\x7b\x25\x01\x49\x0f\xa1\x4f\x05\xb6\xbc\xba\xe9\xf6\x20\xb9\x19\xe1\xf8\x9a\xc6\x82\x00\x23\x1c\x5c\x99\xb0\xd7\x5b\xed\xdc\xa6\x5a\xcc\x2e\xbb\xd4\x15\x0c\x57\x20\x10\xe5\x7c\xe0\x46\x7e\x4d\x62\xc8\xc1\x2d\x55\x37\x42\xf4\x83\x4a\x01\x5e\x94\x98\x05\xc2\x1a\x66\x8d\x00\x0b\x4d\xa0\x93\xad\x65\x36\xb6\xd6\x7b\x6a\x09\x7c\x30\x97\x9f\x56\x10\x1b\x14\x63\x22\x5c\x0e\xb1\xa9\x46\x32\x03\x54\xef\xbe\x04\xb2\x52\x16\x44\x20\x9c\x05\x1c\x72\xec\x0f\x78\xcd\x5c\xd1\xb6\x9b\xee\x35\xb7\xc2\xca\xa8\x67\xb9\xea\x4e\x18\xbd\x05\xf3\x70\x07\xe0\xea\x78\x13\x47\xf1\xc2\x3a\xc6\x17\xf2\x68\x63\xb4\x4d\xc3\x5c\x07\x5b\x47\xba\xde\xb4\x0a\x96\xda\xae\x8e\xba\x64\x69\x99\x24\xd9\x81\x37\x9f\xe8\xa4\x2d\x22\xd5\xe1\x36\x91\x4e\xad\x22\x9d\x42\xdd\x32\x8b\x54\x03\x5b\x45\xaa\x37\xad\x82\x49\xdb\xb8\x84\xcf\x0c\xf3\xa0\xaa\xdf\x47\xa1\x9d\x21\x26\x54\x1c\x38\xbe\x12\x00\xeb\x07\xfd\x4d\x98\xb6\x05\x77\xaa\xb6\x19\xb4\xef\xb0\xff\x9c\x24\xdf\xe5\x37\x6f\xbb\xe7\x28\x61\x81\x97\x8c\x3f\x7c\x4c\x2b\x7b\x19\xbe\xaf\xbb\x1e\xd1\x3f\x49\xa7\x84\xaf\x97\x2d\x72\x51\xe2\xdb\x24\x3f\x55\x42\x85\xb6\x48\xa8\x44\x77\x69\x31\x04\xc5\x5b\xca\x45\x72\x4f\x60\x1f\x29\x01\x48\x2b\x57\x38\xb7\x8b\x47\x77\x76\xc8\xaa\x6a\x95\xe4\x85\xf8\xe8\x78\x8b\xe6\xbf\xa6\xf8\x28\x8c\xb0\xe5\xfc\x85\x74\xdb\xc9\xd2\x74\xdb\x49\x7b\xe5\xbf\x64\x5d\xfd\x97\xb0\x6c\x51\x85\xe9\xab\x4d\x92\xca\xbd\x70\x8e\x8f\x17\x44\xb9\x66\x52\xe2\x7f\x0d\x7b\x6a\x80\x49\x86\x5d\xa2\xc6\xfa\xbf\xc6\xc7\xa2\x7e\x50\xce\x10\x91\x0b\x4b\xd9\xc6\x17\x6d\x7e\xc8\x8f\x07\x31\x02\x96\xef\xce\x64\xca\x2b\x21\xfd\x7c\x28\xf1\xae\x5d\x99\x40\x20\xe3\xf3\xad\xe4\x7b\x31\x27\xc7\x5e\xaa\x37\x3e\x72\xaf\xe0\x41\xcd\xca\x20\x53\xb3\xe1\xcd\xc2\x5f\xf9\x9c\x1c\xf0\xca\x37\x67\x8f\xbc\x3d\xad\xe0\x41\xcd\xca\x20\x53\xb3\xf4\xf5\x77\x4e\x4e\x7d\xe9\x97\xb7\x49\x5e\xa7\x15\x91\xa0\x06\x85\x72\x63\xf6\x8e\xbc\xeb\xcc\x09\x01\xef\x79\x72\xcb\x22\xaf\x4c\x2a\x78\x50\x9b\x32\xc8\x78\x11\x00\x79\xe7\xb5\xb5\x10\xed\xbd\x3e\x3e\xed\x20\xef\xc9\xc9\x68\xa0\x1d\x89\x10\x53\x9b\xf4\xe5\xc6\x0b\x7b\xb1\x0e\xde\x54\xd6\xbd\x68\x23\x6e\xc5\x9f\x16\xf7\xce\x52\x8f\xb5\xef\xd5\x15\xf0\x07\x87\xa0\x91\xa5\x46\x04\xb2\xc3\x86\x74\xcb\x3c\xa4\x69\xaf\x6d\x43\x5a\x7b\xb0\x8c\x55\xe2\xef\x96\x71\x1a\xd2\x2e\x2d\xfe\x88\xd9\x05\x31\x06\xb8\x77\xa2\x7f\x5d\xe9\x9d\x9a\x30\x4c\x59\x49\x6a\x7c\xe4\x93\x7a\xce\x4e\x77\xda\xb8\x5d\x42\xbc\x95\xdf\x21\xe4\xb3\x77\x83\xf3\x97\xc9\xf3\xba\x52\x8c\x83\x71\x5e\x33\x54\x69\x1f\xce\x5c\x3d\x35\xdd\xb1\x23\xae\x3f\xc9\xac\xe4\xd7\xd3\x71\x9b\xd7\x65\x77\xab\x16\xd9\xcf\x34\x05\x76\xc4\x4f\xf5\x9d\x54\xa4\x88\x76\x24\xc9\x0e\xb8\x4c\xa0\x85\x0b\x09\xe7\x6d\x33\x8e\x77\x08\x26\xc2\x9f\x87\xe0\x2c\x11\x10\x51\xd5\xed\x7f\xca\x01\x94\x30\x50\x4c\x3e\xf4\x7d\xa1\xfa\xdb\x43\x29\xce\xd7\xf8\x00\x9e\x37\xff\x2e\xe2\x49\x91\xb6\x86\x76\x0a\xca\x01\xc4\x63\x3d\x7b\x09\xdc\xba\x25\xf4\xbc\xa5\x7e\x56\x6e\xa0\xa6\xf9\x77\xa7\x8a\x4a\x8c\x33\x7a\xb2\x4d\xdf\xde\x05\x6b\x6a\x76\xa3\x6b\x6a\x46\xb6\xc5\x3d\xb2\x87\xe2\x03\x5a\xb4\x87\x0b\x5f\xe9\x8f\xa6\xc9\x4e\x37\x8b\x29\xd9\xd3\x5e\x1f\x4e\xc7\x6d\x86\x92\xd4\xf0\xbc\x8c\xbe\xcd\x2e\x54\xcf\x5d\x88\x57\x93\x5c\x3d\x45\x15\x5f\xc8\x12\x1e\xea\xa3\x48\x8e\x17\x56\x0e\x46\x15\x76\x93\xcc\xcd\x4f\xb5\xf2\xd8\x9f\x01\xa9\x17\x43\xe8\xbd\x43\xae\x7c\x99\x74\x05\xec\x06\x18\x61\xcc\x8a\xe7\x3f\xba\x13\xf9\xa8\xab\xc2\x1f\x0b\x11\x8a\x5a\xd7\xd6\x95\x40\xf7\xae\xf0\x59\x48\xc7\x8e\x17\xa1\x82\xe4\xfd\x84\x03\x4b\x1b\xf1\xeb\x19\x4a\x71\x59\x9f\xa5\x83\x5f\x23\x8f\x48\x43\x09\x42\x42\xd5\x39\xcc\xe4\x2d\xad\xca\xf0\xa7\x48\xf4\x7f\xf4\xc7\x59\x97\xcd\x10\x27\xb0\xb7\xc5\x84\xfd\x38\x69\x3b\xbc\x5b\x94\xd7\x85\xfa\xc0\x24\x23\x1c\x27\xd5\x31\xa9\xc8\xac\x7d\x22\x17\x25\x5b\xed\x75\x80\x29\x5c\xd1\xf1\xa2\x34\xaf\xa0\xfa\x0c\x62\x0a\x6e\x4d\xa8\x66\x1b\x2c\x89\x0f\x83\x24\xd0\x4e\xef\xb8\x5a\xa2\xe5\x62\x0a\xad\x1e\xe2\xdd\xce\x8f\xd5\xfd\x94\xf1\x02\xaf\xa2\x85\x42\xca\x01\x1d\x62\xb4\xc2\xe1\x76\xaa\xa2\x8a\xf2\xe7\xb3\xcf\xed\x7c\xd6\xcc\x56\x28\x84\x4c\x03\xdb\x29\xdb\xd2\xbf\x81\xdf\xf0\xc6\xf1\x4e\xcd\x59\x6d\x23\x7c\xb3\x0b\x44\x3a\x30\x63\x68\x81\x03\x2c\xb5\x07\x72\x35\x9b\x87\x8b\x15\xc7\x52\x9e\xf4\xbf\x41\x8b\x78\xba\x85\xfc\x46\xb4\xbb\xc1\x53\x85\xb1\x1d\xc2\xdb\x28\x52\x48\xc1\xbc\xed\x96\x38\xd8\xce\x55\x54\x80\xbd\xc5\x62\x1e\x74\x42\x93\x9f\xf3\x46\xab\xd9\x6c\x16\x42\xdc\x85\x31\x8e\xb5\x77\xd7\xb7\x51\x14\x07\x32\x25\x98\x39\x3c\xdb\xae\x22\x5f\xc1\x04\x78\xbb\x99\x4d\xe7\xd3\xd9\xe5\x0f\xdc\x31\xbe\xc3\x0f\xbb\x12\x1d\x71\xe5\x14\x65\xbe\x2f\x71\x55\xb9\x5b\x72\xa2\xb6\x4c\x0a\x5c\x9d\x77\x65\x7e\x14\x27\xb1\xad\x71\xcf\x48\xf2\xe2\x52\xe7\x20\xd4\x77\xfc\xcb\xe5\x0f\x6e\xfe\x5e\xc9\xbf\x47\xda\x1e\xa7\x78\x16\x4e\xa9\x41\xde\xb0\xff\x1e\x30\xd3\x07\xa1\xbe\x13\x55\xda\xd3\x8c\xc6\x03\x53\x3a\x66\xc7\x3f\xd9\xee\xa0\xdd\xef\xdd\x3e\x38\x4a\x6e\xaf\xb2\xe4\xee\xc2\x6e\xae\x67\x58\x42\x18\x73\xd6\x96\xee\xb9\xc2\x49\x2e\xe9\x7d\xcb\xa1\x98\x40\x54\x27\x1d\x73\xbc\x05\x8d\xc6\x4a\x34\x57\x80\x46\x88\x2c\x37\x66\x49\xf1\xa4\x2b\x65\x25\x8e\x2c\x5f\xed\x94\x21\xe7\x8f\x3e\x03\xec\xb6\x0f\x02\xce\xe6\x31\xde\x4f\x80\x13\x6c\xf3\x57\x4e\x38\x7f\x31\x11\x42\xa9\xf6\xf7\xdc\x7f\x61\xa8\x69\x86\x2c\x15\x1a\xca\xdf\xaf\xf4\xa3\xc5\x6e\xfe\x19\x32\xfd\xc9\x73\x0c\x3c\x18\x4b\xc6\x1b\xf1\x44\x33\x5f\x4e\xc4\xca\x10\xd9\x24\xdb\xc7\xe3\x78\x21\x2b\x50\x0c\x92\xb7\x87\xb2\xe4\x48\x17\xb8\x90\x87\x74\x42\xfe\x50\xb5\x93\x64\xbb\x24\x4b\x6a\x32\x6e\xc6\x57\x1a\x5d\x43\x1d\x67\xbd\x49\x2d\xfb\x00\x84\x08\x3c\x0f\xc4\xe7\x81\xa8\x71\xac\xd8\x5d\x4f\x56\xb3\xc7\xe8\xd4\xda\xcf\x16\xf7\x6c\x71\x7d\x16\xd7\x9f\xd9\xee\x31\x3a\x80\xc0\xb3\xdd\x3d\xdb\x5d\x9f\xdd\xf5\x7e\xda\xe8\x31\x3b\xbd\xfe\xb3\xd5\x3d\x5b\x1d\x60\x75\x24\xa7\xad\x1e\x92\x66\xc5\xd0\xf3\xb7\xec\x2d\x09\x02\x9f\xd0\xff\x71\xb7\x79\xfc\x70\x56\x17\xd6\xbf\xe5\xf9\x71\x1d\x5c\x44\x14\x96\x4b\xc7\xb3\xb6\x05\x37\xdf\xfe\x8a\xa3\x5a\xbd\x6d\x52\x84\x79\xc9\x71\xef\x76\x19\x6a\xf5\x42\x6e\x8a\x4a\xf2\x74\x8c\x9d\xb7\xc2\xa3\xe3\xf2\x46\x0e\xfa\xc1\x8b\xd6\x68\x0a\xe4\x0a\xe4\x44\xb6\xf2\xfd\x40\xa8\xd0\xf4\x60\xa2\x57\x66\xed\x00\x57\xad\x2a\x1f\xe6\xea\xbc\xe0\xa4\xe8\x37\xba\xb3\xe1\xb6\x09\xde\x1c\xb9\x28\x4c\xfd\xd0\x4f\x4a\x39\xce\x01\xa3\x86\xd9\xb3\xe5\x4e\x8b\xb9\xd0\xe3\xa4\xaa\xd5\x8d\x2d\xda\xc6\x95\xee\xfb\x95\xfd\xde\x7c\x7a\x09\x90\xf2\xb5\x6b\xfc\x4d\xf8\xc0\x8d\xe8\xe3\x76\x79\x2a\x1c\x0c\x79\x46\xb0\xe7\x3e\x04\x9d\xa6\xf9\xca\x8a\xc7\x3d\x2e\x89\xd4\x96\x26\xf4\xf1\x3b\x4d\xac\xdd\x39\x4a\xbd\x8e\xa3\x16\x70\xab\x30\x10\x33\xe2\x8b\x47\xfc\xb4\x56\xba\xcd\x23\x4a\x39\xdd\x61\x03\x37\xc5\x2a\x19\x80\xda\x11\xd1\xa1\x5b\x7e\x49\x7a\xee\x62\x10\x95\xf8\xc8\x63\x97\xfa\xa2\x7b\x89\xd4\xcf\xc3\x7c\x3f\xd0\xc4\x08\x69\x77\x0b\x98\xe0\xd7\xed\x93\x24\xdf\x5a\x4d\x34\xcd\x0a\xed\x61\xf3\x9a\x8a\x84\xff\x3e\x93\x68\x3f\x79\x0c\x67\xb9\x91\xfd\x78\x7e\x7b\x6a\x19\x98\xd5\xae\x76\x80\xb7\x01\xe8\x84\x69\xb9\x49\xc7\x0c\x6a\xd8\xf1\x6c\xbb\x96\xdc\xb0\xfb\x17\x6e\x60\x84\xd6\x7a\x2a\xbc\xf5\xaa\x23\x4a\xd3\xf1\xf5\xac\xd5\x46\xdb\xd6\xa0\x6a\x3d\xbc\xf6\xd5\xb6\x57\xb6\x1b\xf5\x95\xd5\xfa\x38\xee\xa9\x4d\x2a\xf7\x8d\x27\x93\xa2\xe0\x71\x61\x17\x95\xb5\xce\x80\x91\x14\x2d\xe3\x18\xeb\x9b\x5e\x46\x7e\xf0\xd4\x23\x09\x27\x60\x08\x0b\x30\x7d\x33\x99\xb1\xe1\xaf\xb7\x9e\xa2\x23\x63\xc3\xa6\x88\xd8\xc2\x6d\x91\x51\x21\xd2\x83\x24\x9f\xc0\x37\x0a\xdc\x27\x1f\x93\x8d\x0c\x75\x3b\x13\xec\x08\x7d\x1d\x93\x6c\xa8\x87\x75\xde\xe6\x20\xac\x41\xc2\x90\xdd\xb2\xdd\x19\x33\x49\xc9\xce\x98\xda\x93\x46\x7e\xc4\x87\x72\x40\xc4\x4d\x6d\x13\xe3\x3a\x65\x03\x81\xd1\xa6\x6c\xad\xd4\x6b\xc7\x4d\x6d\xa3\xae\x09\xd0\xaa\x61\xa1\xba\x0d\x43\xb6\x5d\x93\x60\xa3\x19\x9e\xee\x80\x69\x27\xa1\x61\x36\x5c\x01\x6a\xed\xc9\x20\x93\x15\x9b\xea\x47\xe9\xef\xfa\x18\x4b\x65\x72\x91\x2d\x95\xda\x8a\x46\x7b\xdc\xe6\x09\x40\xa6\x8c\x80\x89\x77\x90\xbe\x99\xcc\x68\xab\xed\xab\xd7\x6b\xb8\x8c\x80\x51\xe3\x1c\x6e\xd5\xb6\x4c\xa4\x07\x49\x52\xa1\x59\xe0\x68\x17\x46\x91\x99\x61\xb3\x1d\xcb\x08\x7d\x1d\x1b\x64\xcd\x4a\x9b\x83\xb0\x06\x09\x63\x84\x59\x73\x49\x49\x66\xcd\xec\x49\x23\x3f\x6a\xd3\x0d\x20\x64\x5a\xdf\xc4\x3c\x44\xdd\x48\x64\xb4\x49\xf7\x54\xeb\xb5\x68\x5a\xdf\xa8\x77\x06\xb6\xea\x5b\x22\x61\xc7\x91\x34\x67\x14\x34\xde\x46\x11\x68\xcd\x94\x8a\xd9\x98\x25\x78\x4f\x9f\x06\x99\xb2\xdc\xe0\x10\xa4\x21\x62\x18\x61\xc7\x5c\x46\x92\x1d\x33\x1b\x32\xea\xbc\x2f\x27\x07\xce\xbd\xf5\xb7\x29\xa5\xe3\x8e\x17\xaf\x40\x99\x76\x53\x6e\xe8\x0f\x4f\x9a\x59\xb7\x7e\x42\x3b\x80\xe8\x86\xa5\x40\xd9\xb0\xe4\xcb\x9b\x7f\x8c\x48\x8c\x61\x9a\xfd\x15\xf7\xa9\x72\x00\x97\x96\x9e\x18\x1c\x72\xc5\x75\xff\x09\x43\xe8\x08\xa0\xd2\x36\xf8\xf6\x16\xbb\x11\x47\x59\xaf\xd1\x7a\x75\x52\xa7\xd8\xa6\x5f\x5f\xdc\xa0\xb5\xd0\x77\x8e\x0a\x64\xda\x55\xa5\x5e\x46\x8f\xba\x75\xa5\xca\x9f\x40\x3d\x56\x0d\xe6\x7a\x97\xe7\x75\x77\xb0\x51\x14\x74\xcf\x06\x38\xf9\x16\x72\xe0\x01\xc6\x9e\x23\x96\xc0\xe9\xce\x0c\xa7\x6f\x85\x01\x30\xe1\x45\x94\x53\x7e\x7b\x8f\x88\xa2\x6f\x1d\xd6\xa8\x68\xee\x77\x00\x59\xad\xce\x59\x7f\x7f\x63\xa3\x3d\xa0\xae\x35\x2d\x66\x9d\x35\x92\xf2\xeb\xd9\xbd\x2c\x0d\xa6\x75\x96\x1e\x4c\x7a\xd4\x50\x90\xda\xef\xb2\xdd\x7a\xf3\xe2\xe3\xd2\xfd\x3d\x19\x46\x49\x7d\x50\xee\x69\xac\x4b\x1a\xe2\xaf\xc7\x98\xc0\x90\x4f\x08\xd6\x8b\x9c\x95\xa6\xaf\x68\x8a\xed\xf9\x14\x83\xc4\x6b\x79\x18\x43\xc8\x06\x85\xd4\x74\xf7\x3c\x83\x02\x7f\xb9\x25\xae\x8a\x3c\xab\xc8\x51\x29\x52\x62\x1c\x6d\x20\x6d\x87\x1d\x53\x90\xa9\xc2\xa5\x7a\x5b\x8e\x72\xc8\xc1\x7a\x72\xe7\x62\x22\x26\xbf\x3a\x4d\xa0\xe0\xb8\xd3\x20\x03\x4e\xa9\x5b\x07\xce\x48\x46\xde\xd6\x4d\x28\x94\x4b\x4a\x33\xa7\x63\x08\x37\x06\x37\x98\xf0\x23\x78\x1a\xd5\xea\xa7\x26\x5e\xa7\x8e\x9f\x46\xda\xbd\xed\x1c\x3e\x88\x56\x9f\xac\x3f\xbd\xed\x58\xfa\xf3\x74\x1a\x78\x3a\x19\x3f\x9d\x14\x1f\x23\x27\x8b\xf9\xbf\x57\x13\x07\xe2\xf4\xfb\xb0\xf0\xa7\x68\x66\x80\x6a\x3e\x48\x33\xe6\xde\x3c\x99\xf4\x9f\x4c\xbe\x4f\x26\xc1\x47\xc8\xc8\x76\xc9\x8a\xd9\xb6\x85\x9b\x5a\x18\x07\x46\xd6\x4c\x33\xc4\x6b\x67\x84\xa3\x78\x61\xea\x11\x0b\xca\x41\x76\x68\x27\xda\xcc\xde\x06\x12\xbd\x96\x99\xe1\xed\x7d\x7a\x62\x1d\x1c\xcd\x1e\xd5\xc6\xc0\xc8\xfc\x08\x4d\x3e\x51\x3f\x7a\xda\xb0\x45\xbf\xa7\x11\xf9\x13\x49\xf5\x89\x04\x77\xb5\x6c\xce\x1f\xc7\x92\x1f\xef\x2e\x7a\x45\xfe\x9e\x3d\xd2\xd3\xf4\xa2\x57\x55\x8f\x77\x81\xd6\x18\xf7\x24\x12\x7d\x1a\xa1\x5d\x2b\x97\x1e\x57\xad\xac\xcf\x9b\x4e\xbe\x56\x56\xfa\x1a\x44\xd0\x9f\xcc\xe3\x6b\x01\xd7\xa8\x72\x11\xe9\x6c\x4c\x14\xca\x43\x6b\xc8\xdc\x69\x32\xb6\xc6\x41\x4a\x83\x29\x63\x99\x82\xb0\xd9\x72\x55\xc4\x33\x7f\x15\xcc\x40\x88\x32\xf4\xb6\x2e\xdf\x5a\x3d\x3c\x80\x6e\x0b\x3a\x1d\x7a\x63\x12\x23\xa8\xb7\xe8\xc3\xa8\x37\xf3\xbb\x11\xd4\x5b\xf4\x61\x01\xf3\x4a\x59\x0d\x22\x70\x2d\x07\x83\xe4\x39\x88\xc0\xb5\x1c\x0c\x92\xf9\x20\x02\x60\x48\xe3\x2f\xfd\xf5\x5b\xab\xd1\x8f\x83\xe2\x1e\x80\x2d\xc8\x76\x0c\xf6\x20\xda\x82\xd4\xc6\x60\x0f\x0a\x88\xd7\x49\x69\xa0\x99\x5e\x55\x7f\x88\x24\x07\x1a\xe9\x55\xf5\x87\x48\x7b\xa0\x89\xea\x21\x8b\xbf\x39\xd7\x63\x74\xb2\x93\xef\xb5\x51\x65\xe1\xda\x67\x1a\x43\xa9\x83\xe8\x2a\xf5\x01\xa6\x60\x6f\x6f\x34\x81\x31\x1c\x0c\xea\xf1\x68\x02\x07\xf5\x2b\x4d\xaf\x3e\xc5\x89\x4d\xbf\x3a\x45\x6c\xb3\x36\x99\xa1\x0f\xa4\x0d\x61\x5f\xa3\x4b\x5b\x6b\x63\xeb\x8f\x69\x7f\x48\x6f\xc7\xd6\xef\xd3\x63\x47\xcf\x70\xd4\xa5\xfb\xc0\x05\x7d\x97\xa5\xa7\x82\x04\xb8\x43\xff\x30\x9d\x9b\x91\x6f\x2d\x57\x6b\xbd\x96\x2b\xb7\x77\x43\xe9\x98\xed\x3e\x02\xb8\x77\x20\xae\xed\xa3\xe0\x64\x54\xbd\x11\x53\x61\x99\xa2\xf6\x31\xcf\xc0\x31\xc5\x53\x1b\x76\x80\x86\xb5\xed\x12\x62\xdb\xed\xad\xab\xf2\x25\x54\x1a\x82\xf2\xf5\xd4\xfa\x56\x9d\xb2\x59\x60\x28\xcd\x81\x42\x1c\x4c\xcf\x91\xef\x71\xe4\x4c\xc1\x8f\x0e\x81\x84\x60\x19\x43\x7c\xb1\x45\x98\xce\x5a\x7b\xc3\x2c\x78\xfc\x43\xc2\x31\x88\xf8\x8a\x53\x25\x36\xb2\x23\xa5\x3c\x84\xa4\x33\xe6\xc2\x4c\x90\xd0\xb5\x82\x96\xb9\x6b\x2f\x10\x01\x2f\x54\x93\x70\x4c\xe6\x7c\xd5\x55\x6d\x36\xca\x63\x8d\x7a\x00\x49\x45\xdc\x9c\x35\xc3\x5e\x77\x03\xad\xab\x4d\x5b\x62\x90\xde\x9e\x01\xde\x11\xd7\x21\x98\x64\x7d\xd5\xd5\x73\x46\xb2\x23\x05\xdd\x4b\x4f\x95\x32\x63\xca\xb0\x4f\x1b\x22\x74\xad\x88\x65\xd6\xda\xbb\x22\xc0\x0b\xef\x24\x1c\x83\xa0\xaf\xbb\x4a\xcf\x46\x79\xa4\xac\x87\x90\x54\x9d\x35\x63\xcd\xb0\x7f\xd8\x40\xeb\x5a\x89\xcb\x0c\xf2\x6b\x12\xc0\x3b\xfc\x44\x14\x83\xbc\xaf\xbb\x1c\xd0\x42\x78\xa4\xb8\x07\x50\x54\xa5\xcd\x18\x33\xec\x72\x85\x49\x5d\x2b\x6c\xce\x1e\x3e\x6e\x71\x2c\x4e\x2e\xfb\x0e\x8a\xb3\x3d\xaf\xdd\x75\xd1\xbe\x7a\x71\x9f\x4e\xd4\xd1\x4a\xd8\x36\x40\x0d\x91\x14\x00\xe5\x09\xb9\x9d\x10\x00\xd0\x9b\x08\x00\xc0\x6d\x12\xe3\xbc\xeb\x0d\xda\x56\x79\x7a\xaa\xe9\x05\xa2\xcd\x2c\x97\xef\xe3\xa5\x47\xe8\x85\xc3\xc9\xe2\x75\x7e\xdd\xcc\x5a\xeb\x40\xb0\xd8\x3e\xac\xce\xca\xc5\xc1\xf3\x85\x17\xce\x5f\x00\xd8\xb3\xed\xc3\x54\x45\x5e\x36\x98\x77\x38\x4d\xcf\xc7\x24\x93\x6e\x09\x6c\xb7\x82\xae\x0c\xf7\xc6\xda\xe7\x7a\xe2\x24\x13\x4f\x9b\x7f\xe3\xaf\x4c\xec\xd9\x57\xdc\x83\x4a\xfb\xe5\x10\x8b\xf9\xc7\x29\xaf\x81\x67\xbc\xe5\x01\xa8\xdc\x4a\x48\xeb\xbb\x69\xb7\xfd\x38\x9c\xc1\xb7\x43\x13\xbc\xea\x28\x5d\xc4\x2b\xa3\x91\x2c\x3c\xbd\x4e\x56\xb8\x0f\xdc\x76\x0d\xb6\xf1\xe6\x77\xdf\x67\x4f\x8c\x48\xbb\xab\x7d\x87\xcc\x0e\x77\x49\x5a\xe3\x72\x8d\xd2\xe2\x80\x5e\xe6\x05\x8a\x92\xfa\xe1\xf7\xa1\xff\x6a\xc3\x7e\xaf\xbd\x90\xf1\xc1\xcf\x35\xd3\x3f\xa4\x6d\xee\x6d\x0b\xf6\x0b\xd5\xe1\xc6\xe6\x62\x63\xed\x39\x7c\xda\xf5\xf6\x1a\xbb\xa2\xc0\xa8\x44\x59\xc4\x5e\x5d\xeb\x46\xb1\xd2\x42\x67\x63\x6b\xdf\x11\xd7\x98\xc7\x3c\x46\xa9\x9b\x17\x38\x53\x2f\x16\x61\xb0\x6e\xd0\xed\x92\x7b\x1c\xb3\x11\xc7\xb2\x4d\xda\xc8\xe3\xe7\xb7\x03\x7f\xee\x6f\xc4\x5b\xee\xb5\xfb\x40\x79\x17\x78\xb9\x5b\x45\x65\x9e\xa6\x0d\xf7\x75\x7e\x8a\x0e\x9b\xfc\x54\x37\x6a\x6b\x99\xf4\x76\x28\xc6\x0e\x63\x38\x4e\x50\x9a\xef\xcf\xc0\x75\x97\x52\xd1\x2e\x2f\x8f\x8e\x37\x65\x17\x51\xeb\x97\x59\xf3\xbf\x74\x3c\x01\xc9\x44\x49\x6d\x88\x22\xa6\xa8\xc6\x2f\xfd\x89\x1b\xce\x5f\xbc\xda\xb8\xc7\xca\x0e\xcf\xad\x60\x0b\x8c\x0b\x25\xc9\x6c\x22\xd1\xea\xfa\x36\x9e\x7c\x0b\x43\xbe\x89\x1b\xff\x95\x68\x44\x8c\x99\xd6\x96\xdc\x7b\xae\xef\xb6\xe4\x81\xde\xe5\x2d\x73\xad\xc7\x29\xea\xc3\x85\x7b\xc0\xf9\x25\x31\xa4\x1a\x7b\xdd\x0f\xa8\x07\x1f\xd0\x00\xee\x99\x8c\xd2\xa4\x58\x77\x4e\x5c\xf6\xc3\x1a\x4c\x73\xc5\xab\xd5\x4a\x2f\x15\x1d\x5f\xf8\x4a\xf7\x70\x9d\x51\xc3\x67\x40\xa6\xc5\xbd\xb3\x52\x1c\xb0\x7a\x04\x04\xc6\xe1\x82\x69\x3a\x11\x97\x79\x71\xed\xb0\x9d\xf9\xd0\x83\xa4\xbe\xaf\xd2\x27\xa3\xf1\x0c\x3a\x2e\xc1\x6f\xe9\xd5\x92\x0c\xae\xa4\x78\x3b\x56\x8d\x3d\x9b\x2b\xdd\xbc\x6e\xcc\xc0\x90\x57\x68\x94\xaa\xfc\xea\x71\x21\xb5\xe5\x86\x9d\x19\x89\x47\x4c\xb4\x63\x40\xfc\xa2\xfd\xb6\x0f\xe4\x70\x8d\x66\x70\xf2\x71\x1b\x8a\xaa\x1e\x02\x69\xf8\x16\xae\x49\xa1\x31\x0b\xce\x61\xc9\xbd\xa0\x84\xc8\x43\x9d\xaf\x9b\xff\xd2\x12\x7c\xe2\x1d\xf9\x1a\x03\x4e\xf7\x66\x88\x4e\xa2\x7d\x28\x12\xaa\x43\x62\xfd\xeb\xee\xa7\xfc\x52\x23\xaf\x41\x5d\xf6\x16\x95\xee\x11\xa3\xea\x54\x62\xc3\x0c\xcd\x5d\xad\x56\x4d\x28\xa7\x63\x7a\xde\x4c\x7a\x98\x94\xe7\xd2\x55\xd1\x94\x5e\xfb\xfe\xb2\xf6\xe6\x83\xe4\x32\x28\x68\xe1\x77\xf7\x4f\x93\x07\x38\x1c\xd1\xbb\x70\x37\x01\x0e\xb6\x39\x3b\x99\x63\x1d\x6d\x06\xa4\x56\x02\xfc\x26\x9c\x69\xc3\xc7\x45\x67\x7d\xb5\x0a\x05\xd6\x53\xce\xf6\x8a\xa2\x7b\x75\x9e\xa7\x75\x52\x00\x72\xeb\x86\xe4\xd2\x57\x26\xed\x64\x76\xb3\x43\xc7\x24\x7d\x58\x1f\x70\x7a\x8b\xeb\x24\x42\x4e\x86\x4f\x78\xf2\x9f\xf9\x9f\x93\x6f\xca\x04\xa5\x93\x0a\x65\x95\x5b\xe1\x32\xd9\x81\x8f\xe3\xf0\x1b\xa9\xca\x23\x4a\xa5\x49\xd3\x4c\x9d\x34\x75\xcf\x4e\x28\xd7\xfd\x88\x7f\x57\x35\x2a\x6b\x78\xc6\x23\x4e\xb4\xba\x82\x2e\xa4\x90\xb2\x14\xd7\x35\x2e\xc9\xb3\x3b\xcd\xb0\x61\x7c\xdd\xe5\x65\xec\x6e\x4b\x8c\xde\x49\x25\x10\xd6\x5d\x89\x8a\xb6\x40\x7a\xc2\x87\xf6\xb0\xcf\x5d\xd1\x3e\xd3\xb6\xa8\x1d\x31\x05\x19\xfd\xd6\x4a\xf4\x5b\xab\x0e\xbf\xce\x0b\xe9\x2d\xc0\x76\xa4\x92\xf1\x40\x66\xb1\x1c\x55\xba\x40\x8d\x3d\x64\xab\x3d\x4c\xc3\x91\xd9\x75\x65\x46\xd2\x12\xb2\x78\xd3\x1a\x40\x58\x62\xc3\x4d\x32\xf9\x29\x96\xd0\x57\x9f\x58\xba\x19\x7f\xe5\x79\x33\x03\x06\xbe\x41\xf0\x36\x51\x59\xe6\x77\x80\xf1\x2b\x97\xb1\xfb\xf2\xf2\x02\x38\x9a\x48\x0d\x99\xb8\x50\x49\x07\x8e\xd2\x94\x1c\xf8\xe6\xfe\x0b\x59\x20\x42\x7c\x61\xbe\x8a\xbe\x9e\xe4\x48\x07\x91\xc4\xa8\x28\xb4\x45\x68\xa8\x0d\xb6\x4f\x10\x6d\x54\x97\xcd\xaf\x62\x7b\x5c\x9b\x84\x7e\x4f\x2f\xf5\xeb\xdf\xae\x6f\x13\x6c\x8f\x7c\x31\xf2\x5f\x6c\xe4\x1b\xec\x88\xa5\x1b\x5b\x92\x5a\xa3\x1b\xad\xa0\xf6\x20\x99\xf2\xe6\xf8\x6c\xa6\xb7\x3d\x9f\xb7\xb8\x11\xb6\x73\x80\xcd\x51\x01\x41\x0d\x0e\x36\x19\xad\x31\x39\x55\x03\x34\x07\x1a\x8e\x38\x61\x13\x34\x08\x77\xf2\x8a\x36\x8d\x8a\xd4\xad\xe6\xfa\x36\x8b\xbc\x20\xeb\x61\x53\xe2\x46\x9b\x7e\x2e\x94\x55\xa3\xe0\x8e\x96\x0b\x31\x97\xc2\x23\xd8\x63\xc2\xe0\xec\x5f\x34\x0c\x7e\xa8\x25\x52\x14\x45\x57\x2c\x91\xcc\x73\x35\x5f\x99\x86\x85\xd0\x5c\x0d\x40\xd2\x82\x3a\x33\x4b\x12\xa4\x45\x1b\xa7\x2b\x4c\x0e\xa5\x71\x59\x1c\xec\x32\x9c\x85\x62\xf1\x4a\x57\x09\x4e\xa2\xaf\x3c\xd9\x16\xe1\x6c\xf1\x21\x3d\xae\xdf\x3d\x00\x26\x1f\x6e\x37\xbc\x48\xbb\x6c\xfe\x59\x16\x44\xdb\xe6\x9f\x22\xe2\xd6\xf7\x3a\xdd\xf8\xec\x96\xd3\x5d\xde\x8d\x30\xd3\x62\xbc\xf5\x88\x83\x98\x28\x7f\xaf\xd1\xae\x06\x87\xb7\x3c\x61\x7d\x5c\x38\x97\x9b\x54\x4e\x8e\x07\x3a\x93\x8c\x29\xd6\xa7\xf5\x17\x5f\xc8\x7e\x4b\x56\x52\x9d\x17\x1d\x61\x76\x37\x2a\x79\x3c\x1f\x74\xf6\x04\xa4\x47\xc8\x2e\x17\x20\x94\x4a\x46\x38\x7f\xa5\x78\xc9\xee\x34\xb1\xc6\x08\xe3\xbf\xd3\xe7\x46\x33\xa2\x4d\xdb\x39\xe7\x0b\x80\x1f\xe1\x7d\x70\x53\x73\xc4\xb8\x79\xcf\xa5\xf8\x4d\x3b\x29\x0d\x0b\xa1\xd7\x52\xa4\x16\xfa\x2d\x96\x1b\x7a\x4e\x82\xae\x95\x11\xb9\xe7\xb4\xa7\x74\xe0\xc1\x5d\x96\x98\x11\x3a\x0d\xb7\x44\xc9\x8a\x7d\x1e\xa3\x6a\x6e\xc3\x60\xb0\x13\x04\x21\x01\x14\x49\x18\x78\x61\xdd\x66\x89\x80\xe1\xda\xb6\xb2\x44\x37\x06\x08\xae\x48\x55\x36\x7b\x72\x6d\x80\xb6\x95\x76\xc4\xc9\x93\xd0\x71\xa1\xd8\xd8\x6d\x81\x0f\xd6\x69\x76\x0a\xbd\x9b\x1f\x1b\x7b\xdc\xcb\x0b\xe9\x71\x84\xca\xfc\x54\x41\x8f\x23\x77\x30\xb6\xd4\x31\xe5\x1c\xc9\xb7\x22\x2d\x19\x2e\x57\x7e\xeb\x25\xf6\x7b\x98\x49\x20\x07\xd2\xd3\xfc\x41\x25\xf6\x2a\xa2\x43\xe6\x0e\x72\x52\x1a\x44\xe9\x81\xc3\xfc\xbd\x65\x0f\x2d\x82\xb0\xe4\xb8\x3f\x4b\x73\x1b\xfe\xee\x26\x4a\x53\xfa\xe8\x66\x3b\x2d\x71\xa7\xf1\xab\xc9\x4b\x2d\xb3\xdc\x14\x9f\x61\xc1\x0c\x4b\xcc\x2f\x6c\x0f\x4d\xca\xb9\xf9\x85\xf1\xb9\x49\x0b\x3d\x61\x46\xb3\x43\x11\x76\x6f\x93\x2a\xd9\x26\x69\xb3\x56\x17\x5e\x25\x33\x80\x78\xed\x02\x97\x55\x81\xe9\x25\x46\x01\x9e\x36\x93\x50\xb5\x04\x96\x3e\xbb\xf9\xc8\x63\x77\xa6\x83\x28\x19\xbe\xaf\xcf\x6c\x16\x6c\xc9\xdc\x4f\xe3\x97\x8d\x55\x4e\x4c\x79\x78\x11\x6e\x67\x86\xde\xa8\x0e\x62\x14\x25\xbe\x1d\xc6\x8b\xdb\xc7\x8c\x3b\x8c\x1b\x8b\x50\xfa\x18\x65\xb3\xb3\x41\xec\xfa\x36\x56\x29\xf0\xa2\xf3\x69\x62\x31\x23\x17\xbe\xaa\xa5\x44\x78\xca\xed\xfa\x30\xc5\x33\xcf\xa1\x8e\x20\x6c\x5a\x3f\x09\x8f\xe6\x82\xe4\xce\x6c\xda\x0a\xc1\x3b\x75\xbb\x66\x02\x06\x35\x68\x1a\x30\x75\x96\x4e\x82\x6d\xad\x88\x83\x04\x64\xb7\x09\x05\x65\x9e\x8e\xfd\xf8\x3f\x17\x9f\xef\xeb\x7f\xad\x4f\xff\x10\xac\x3e\x1e\xb8\x78\xa5\x4f\xc1\xc5\xa9\xeb\xa0\xcf\x1a\x6a\xaf\xa8\x7c\x06\xbf\x1e\x42\xb4\x21\x67\xa2\x1d\x5f\x2a\xf0\x7d\x3f\x78\xe5\x34\x22\x1c\xf6\xb4\xc7\x63\x29\x32\x46\x3b\x7a\x84\xfe\x84\x64\x34\xea\xbc\x98\xd0\x34\x43\xf3\x6b\x57\xe6\xc7\x97\x72\x4b\xaf\x26\x75\xfe\x52\x6b\xeb\xd5\x80\xf7\x3d\xea\xdc\xa1\x6e\x75\x30\xeb\x4c\x3d\x45\x99\xef\x93\x78\xfd\xc7\xbf\xfe\xd0\xd0\xfd\x0b\x77\x09\xde\x9f\x93\xa8\xcc\xab\x7c\x57\x7b\x6d\x1b\x64\x19\xff\x5d\xa3\xe7\xaa\x2e\x7f\xff\xd5\x97\x37\x3e\xfd\xbf\xaf\x26\x38\x8b\x85\x72\xbf\x2d\xff\x4f\xac\xea\x5f\x1e\x0a\xfc\xfb\x40\xea\x46\x89\x0b\x8c\xea\x35\xfd\x1f\xf7\x1e\xb0\x04\x3a\x02\x78\x4e\xab\x7d\xf4\xd8\x2c\xf3\x5e\x55\xd2\xee\xfb\xaa\x8c\x1e\x61\x1c\x23\x29\x3e\xc2\x38\xa8\x25\xa8\xf6\x31\xbf\xde\x38\xac\xac\x3f\xde\x38\x7c\x83\x71\xdc\x3c\x89\x71\xb4\x7b\x4c\xd4\xf2\x61\xef\xf7\x9b\xbf\x5c\xb4\x9f\xa3\xc5\x6f\x18\x6a\x2b\x8e\xb7\x4f\x1f\x8a\x43\x12\xe5\x99\x1b\x1d\xf0\x6d\x99\x67\xae\x12\x17\x2c\x98\xea\xf4\xa7\x45\x25\x58\x4a\xd0\x93\x81\x96\xd8\xd7\xac\x60\x78\xda\x70\xde\xce\xba\x93\x8c\xe6\x7a\x48\xd6\x41\xcf\xec\x3c\xa6\x63\x1d\x43\x86\xf5\xe2\xe0\x16\xfa\x05\xc2\xbf\x1a\x74\x6d\xf0\xc5\x9a\xa1\x91\x81\xa2\xe4\x1f\x76\xba\xef\xaf\xe4\xb7\x98\x48\xa5\x49\x52\x79\x5d\x60\xa3\xb9\xde\xe2\x5d\x5e\xe2\x36\xdb\xf2\xd5\xdf\x43\x7f\xba\xfa\xca\xca\x24\x58\x07\x7d\x25\xcd\x0d\xe2\x24\x42\x75\x5e\x56\x80\xfa\x79\x62\xc4\x17\xd7\xee\x6d\x0a\x79\xbe\xe1\x1f\x86\x5f\x6c\xe0\x97\x75\xd8\xb7\x2f\xf9\xe5\x12\x36\x0d\x20\x47\x53\xc4\x77\x7a\x00\x96\x9c\x34\x39\x83\x06\xd7\xe5\x97\xba\x6d\x87\x5d\x42\x2f\xe0\x7b\x00\x1a\x46\xb3\x9a\x7c\x14\x6f\x66\x25\xa6\x8d\x5a\x42\x22\xfd\xef\x2b\xfb\xd4\x43\x4f\xbd\x0a\xc9\x10\x96\xf7\x53\x4c\x47\xe8\x0e\x9f\x97\x32\xf6\x43\x81\xfd\x50\xcc\x47\x1a\x0e\x1f\x74\x8a\xe6\x17\xcc\x69\x1a\xe3\x57\xcd\xbd\xd8\x88\xfb\x1e\xd9\x6d\x73\x82\xee\xda\x6d\xa8\x64\xd0\x8a\x9b\x27\xa5\x0d\x93\x8f\x9e\xc8\xe9\x4c\x93\x5d\x0f\x67\x35\x3b\xcf\x57\xc4\x55\x54\x62\x9c\xd1\x45\xb1\xbe\x2b\xe1\xd3\x72\x97\x7c\x3b\x42\xa7\xc5\xa9\xaf\x66\x78\xda\x41\x4f\x26\xc7\xd3\x27\xf4\x8d\xef\xcf\x25\xda\x1d\x21\x33\xbd\x92\x39\x35\x96\xca\x0c\x05\x1f\xc0\x0c\x68\x6a\x1a\x06\x67\xf1\x68\xdd\xa5\xdb\x38\xe3\xf2\x97\xc1\xde\x76\x65\x34\x77\x35\xe9\x41\xa2\x5e\x8e\x62\xd5\x79\x9e\x6e\x51\x29\x56\xe4\x45\x1c\x2d\x4a\x31\x2a\x77\xc9\x3d\xc7\x69\xff\x6e\x11\xf2\xac\x46\x49\x86\x4b\x77\x97\x9e\x92\xb8\xc5\x53\x8a\x35\x74\x0d\xb1\x45\x89\x53\xf7\x90\x97\xc9\x6f\x0d\x20\x75\xe2\x96\xa4\x56\xce\x2b\x90\xac\x8f\x00\xa2\x05\x92\x4c\x6c\x28\x9c\x8c\xb8\xdf\x88\xd7\x93\xca\x64\x44\xba\x95\x4b\x46\x64\x65\x1c\x31\x43\xb7\x1c\xde\xfc\x14\x8a\xb7\xa8\x6c\x37\xd2\x0b\x28\x52\xb1\x82\x2e\xb7\x27\x17\xca\xa8\x32\x4e\x0b\x2c\xd0\xbe\xab\x4f\xff\xe8\x40\x7c\x27\x7f\x07\x6f\x4b\x38\x52\x9b\x1e\xa5\x3f\x59\xb8\x94\x9e\xbe\x13\x33\xa4\x23\xac\x55\xb1\x43\xcd\xe6\x7a\x4c\xcc\x68\x20\x03\x94\x0f\xe9\x19\x52\xa9\xa0\x46\x83\xba\x40\xc5\xc8\x9a\x90\x64\xaf\x0b\x5a\x10\x2e\xfb\x58\xd4\x08\x62\xbd\xcd\xeb\xc3\xc5\xa3\x81\x84\xed\x7b\x93\x3f\x64\x49\x4e\x48\xd8\x9b\xea\xb6\xcb\xb5\x8b\xf8\x28\xa2\xb0\x43\xfd\x77\xc9\xb1\xc8\xcb\x1a\x65\xf5\x45\x78\x05\x91\x22\x34\x3f\x45\xf8\x21\x89\x3b\x6d\x37\x71\x48\x04\x56\x87\xfc\x4e\xe6\x4a\x84\x26\x19\x49\x64\xa6\xf8\xac\x25\x34\x2f\x1e\x09\x6f\x84\x78\xe3\xfc\xd7\xfe\x1b\xdf\x41\x1b\x7d\x36\xa1\x7d\xa3\x1e\x32\xf7\xf0\x09\xdb\x31\xce\x8c\x8c\xa3\xdd\x2e\xb9\x57\xb6\xa5\x5e\xfe\xe0\x1e\x2b\xf7\x36\xc1\x77\x0d\x1a\x8b\x5d\x31\xbe\x4d\x22\x4c\x83\xec\xc5\x63\xfd\x71\xd3\xfd\xa4\xfd\x7d\x8c\xbb\xdf\xd5\xb1\xfb\x7d\x5f\x19\x5b\xef\xc8\x50\xc5\x4e\xc4\x12\x3a\x8b\x03\x8a\x54\xdc\x63\x0c\x94\xa8\xb5\xdb\x22\x15\xb7\x3a\x02\x25\x6a\xed\xb6\x48\xc5\xbd\xaf\x80\x12\xb5\x76\x5b\xa4\x98\xaf\x22\x0e\xbe\x4d\xb1\xdd\x5d\xb1\x5c\x2c\xc9\x5c\x06\x90\xa4\x6a\x63\xc4\xfd\x40\x88\x04\x20\x22\x96\x46\x2c\xb7\xcc\xef\x44\xcc\x58\xc0\x9c\xd4\x07\x73\xbd\x08\xa7\xa9\x50\x71\x48\x47\xa0\x81\x3c\x96\x04\x95\xa9\x32\xeb\xbf\x8e\x88\xc2\x8e\x58\x08\x11\x54\x66\x9b\x6c\x0e\xda\x36\xb3\x5a\x05\x52\x33\xd5\x71\xa0\xde\x04\x44\x8b\xde\x54\x2c\xb3\xde\xaa\xa3\xa8\x37\xad\x9e\x49\x6f\xa3\xbb\x37\x54\x9b\xe3\x09\x0f\xd6\xf1\xb5\xa4\xaf\xd5\x3c\xdd\x42\xac\x36\x13\x04\xcd\xf2\x51\x68\xe7\x18\x0f\x54\xbd\x80\x68\x51\xbd\x8a\x65\x56\xfd\x31\x16\x55\xaf\xd5\xeb\x55\xfd\xe0\xfe\x8d\xd6\xfd\x70\xca\xe3\x95\x3f\x96\xf6\xb5\xda\x0f\xc8\x3e\x5c\x81\x62\xba\x1f\xa8\x67\x01\xd1\xa2\x67\x15\xcb\xac\xe7\x74\x2f\xea\x59\xab\xd7\xab\x67\xa0\x27\xa3\x35\x0a\xd1\x18\xaf\x3b\x33\x95\x91\x5a\xd2\xdc\x3d\x9d\x03\x59\x26\x22\x63\xbd\x08\x23\x28\x38\xd4\x5e\x82\x3d\x96\xc9\x28\x0a\xe3\xb4\x97\x62\x2b\x2f\x56\x57\xd0\xbd\x5a\xb7\x15\x69\x51\x26\x59\x6d\x9f\x7f\x38\x14\xc7\x50\xc5\x6e\xdc\x32\xae\xc5\xbe\x01\x44\xb3\x89\x13\x64\xd1\xca\xa1\xda\xaa\xa1\xcb\xc8\x43\x26\x5e\x60\xc7\xfb\xc6\x82\x82\xad\x58\xfd\x88\x76\x7a\xc7\x0b\x88\x7f\x7d\xbf\xae\x18\x59\x9c\x10\xb3\x37\xab\x2d\x5d\xfe\x10\x1d\x50\x59\xe1\xda\xf9\xe2\xa7\xbf\x7c\xef\xde\x7c\xb1\x79\xf3\xf5\xef\xbe\xc9\x92\x23\xaa\xb1\x17\x55\x95\xe3\x3a\x87\xba\x2e\xd6\x6f\xde\xc4\x28\xc3\x31\xce\xbc\x23\x7e\x83\x28\xfc\xdf\xfe\x3d\x89\x70\x56\xe1\xd8\x39\x65\x31\x2e\x9d\xfa\x80\x9d\x3f\xff\xf0\x17\x27\xa5\xc5\x5d\xd5\xbc\xc0\x59\x95\x9f\xca\x08\x7b\x79\xb9\x7f\xc3\xe0\xd5\x9b\x3f\xff\xf0\x97\x7f\xfb\x2e\x2f\x1e\xe8\x97\xac\x97\xd1\x2b\x27\xf4\x83\xb9\xf3\x47\x94\x25\x38\x75\xfe\x14\xe3\xec\xeb\x37\x1e\x6b\x2c\xee\x8e\xed\x92\x82\x24\xcf\xdc\xf8\xc4\xbe\xd3\x04\xd5\x06\x2e\xd5\xeb\xec\x92\x34\x75\x8f\x79\x8c\xc9\x7a\x75\x63\x02\x5c\xda\x76\xdd\x1d\xaa\x6a\x5b\xe3\xde\x1c\x6c\xbd\x29\x7e\x82\xe6\xbd\x24\xdb\x25\x59\x52\x63\x80\x85\xa4\xc6\xb4\x31\x37\xca\x4f\x59\xbd\xe6\xa8\x9b\x7e\x14\xa1\x81\x43\x92\xed\x21\xea\x6d\x4f\x42\xb0\x7f\x61\x25\xd0\xd8\xe6\xa7\x2c\xc2\x3f\x64\x13\xb5\xe8\xc7\x93\x5d\x76\x4b\x83\xf0\x96\x73\x91\xfc\x2e\x4d\x8a\x1f\x4f\xf5\x5f\x27\x5a\xd1\xdf\xae\xa6\xfe\x07\x5e\xf1\x1d\x7e\x20\x37\x2a\x54\x0e\x65\xf9\xbc\x2b\xf3\xe3\x24\xf4\x5f\x4c\xe6\xd3\x17\x93\x1b\xff\xc5\xa4\xce\x81\x56\xea\xe4\x98\x64\x7b\x77\x77\xca\x22\x42\x34\x3a\x6d\x93\xc8\xdd\xe2\xdf\x12\x5c\xbe\xf4\xbd\x30\x98\x4f\x7c\x6f\x11\xf8\x13\xdf\x9b\xce\xe7\x93\xc0\xf3\x7d\xff\xd5\xe6\xb1\xf5\x1f\xbf\x57\x67\xe6\xbf\x98\xcc\xa6\x2f\xc6\xf7\x68\x39\x6f\x38\xf2\xe7\x0d\x47\x37\xf4\xf7\x62\x4c\x8f\x0c\xf5\xfb\x7a\xe4\x4e\xfd\xe2\xde\xd6\x2b\x8e\x70\x59\xfa\x9f\x51\xaf\x82\x79\x4f\xaf\x18\xc2\x65\x25\xf4\xca\x88\x3c\xeb\x21\x46\xe1\x97\xcb\x1f\x9e\x8d\xfd\xd3\x36\x8b\x67\x63\x7f\x3a\x63\x67\x21\x08\x10\x53\x86\x8e\x4d\x9c\x6d\xa0\x1b\xb8\x54\xdf\xae\x9b\x97\xc9\x3e\xe1\x1f\x4a\x1d\xfa\xbd\x6b\x63\x07\x43\x31\x66\x97\xa2\xea\x40\x47\xdd\x9c\x8e\x36\xbe\x79\x24\xb8\x84\xf3\x17\x93\xe5\xfc\xc5\xb9\xbb\x00\x40\x1c\xb0\x23\x6b\x7a\x14\xdf\xd0\x79\x02\x54\xfb\x4e\x0a\x21\xa6\x8b\x53\x5a\x51\x57\x01\x68\xa7\x8a\x50\x4a\xf6\xd0\x4e\x82\x49\x20\xaa\x45\x06\x5c\xe6\xa0\x6e\x5b\x24\xcf\x27\xe3\x9e\xfe\x17\x48\x46\xc6\xb8\x08\x8e\x6a\x3c\x33\xa2\x60\xff\x09\x7b\xe7\xd1\x3e\x19\x94\x4f\x80\xaa\xf2\x49\x21\xa4\xfc\xf2\xb4\xdd\xe2\xf2\x5b\x94\xc5\x8f\x95\xd1\xb4\x47\x46\x61\xe3\x51\x96\x73\x03\x0d\x01\xdc\xf8\x75\x0b\x25\x8a\xd5\xe0\x83\x94\x44\x70\xaf\xde\x48\x64\xba\x31\xf2\xd4\x81\x2f\x8b\xb9\x8d\x92\xb7\xe2\xea\x85\x08\x09\xd0\xcb\xd2\x4a\x87\x60\x11\x74\xa3\x15\x51\xe8\xd3\x8d\x8f\x67\x03\xf8\x57\x34\x00\x4f\x50\xbb\xc1\x8f\x74\x18\xaa\x33\xe9\x20\x90\x47\xa9\x0e\xe8\x1d\x9b\x79\x82\x3c\x8e\x9d\xe5\x05\xfe\x8b\xc9\xb4\x99\xc2\xfa\x2f\x26\x4b\xff\xc5\xa4\x7f\x16\x41\xb6\xc0\xf4\x9c\xc1\x60\x08\x97\x66\x72\xdc\xcc\x23\x17\x3e\x99\x20\xf7\x50\xee\x23\xdc\xd1\x15\x87\xd8\xb3\x44\xe8\x8c\x8d\xca\xc1\x60\x6e\x04\xa8\x5a\x1a\x29\x04\x8d\xec\x2e\xc9\xf6\xe7\x10\x64\xaf\xcc\xeb\x4e\x5c\xc1\x24\x98\xc7\x78\x2f\xb2\x07\xc2\x0d\x3e\x47\xc1\x75\x03\xdf\x4e\x8c\x21\x5c\x16\x43\xa8\xf5\x30\x46\xf9\x82\x55\xa0\x36\xdb\x43\x8a\xc2\x61\x9f\xa1\xa0\xf6\x74\x90\x76\x4f\xb2\xee\x67\x55\x7c\x54\x55\x78\x54\x01\xc6\x35\x4d\x9d\x17\x0e\xdf\x00\x6a\x81\x99\x86\x65\x43\x5c\x1b\x96\x4d\x21\x34\x2c\x6b\x14\xa3\xc7\x4e\x23\x1a\xef\x06\x5b\x53\x17\x4e\x27\xe4\xff\x5f\xa9\xa2\x9d\x2a\x02\x1b\x56\xe1\xd2\xef\x4b\x85\x19\xc1\x84\xfd\x47\xa5\x65\x6a\xbb\xaf\xca\xc5\xee\x6b\x07\x90\x31\x76\xbb\xb7\xce\xd3\xcd\x22\x9f\x15\xff\xaf\xa4\x78\x8f\xa8\xdb\xe0\x31\x1a\x98\xea\x30\x9a\x32\xc8\x5f\xdc\xe5\xdb\x6d\x6a\x5c\x9d\xd3\x5b\x60\xa4\x3f\x2f\x01\x38\x7d\x96\xa6\x32\xe1\x9c\x9e\xaf\xed\x73\xcc\xc3\x2b\x19\x96\x36\x22\x81\xd0\x07\xeb\xab\x1a\x1a\x5a\xe5\x32\xeb\xef\x67\x60\x60\xd9\xd6\xa6\xbd\x92\x21\x56\xca\xf3\x39\xb0\x7e\x68\x69\xd3\x56\xc5\xb0\x1c\x92\x58\x36\x70\x1c\xd8\xba\x69\xab\x03\x1b\x3f\x64\x6c\xa2\x87\x7b\x36\xd5\x67\x53\xfd\x94\x4d\xd5\x63\x06\x6a\xf0\xca\x14\xaa\xfa\x65\x5a\x0a\x79\xe6\x5f\x71\x9a\xe6\x74\xcd\x1a\x04\x5e\xf0\x02\x5e\xb9\x42\x9c\x84\xa1\x17\x82\x01\xed\x1d\xbe\xfb\xeb\x4b\x37\x08\x3d\x62\xa8\xcd\x9f\x7f\xeb\xfe\xdc\x0c\x45\xbc\x4c\xa7\xde\xd4\x4c\x7f\xe1\x85\x42\x2d\xfe\x97\x46\x1d\x46\xbb\xcc\x66\xde\xcc\xc2\xfb\xd4\x0b\xc4\x6a\xdd\xdf\x3a\xf7\x46\xd4\xcb\x7c\xee\xc1\x29\x20\x52\x31\xf0\xe6\x0b\xb1\x62\xf7\xb7\xd6\x86\x19\xf5\xb2\x58\x78\x0b\x4b\x3f\x7c\x6f\x79\x23\xb3\x27\x94\xe8\x7d\xb1\xa2\x5f\x96\x4b\x6f\x69\x6e\xcb\xf7\xa6\x2b\x5f\x62\x53\x2c\xd1\xda\xb2\xa3\x5f\x6e\x6e\xbc\x1b\x6b\xbf\x82\xd5\x7c\xaa\xb2\x2a\x94\x41\x7d\xeb\xa9\x22\x05\x81\xe7\x51\xf1\x3c\x2a\x9e\x47\x05\x4d\x3b\xd0\xb1\x60\x08\x37\x04\xa8\x46\x1b\x5a\xd8\xf3\xf1\xd5\xf4\xd5\xd5\xbc\xa5\xe7\x87\xac\xdb\xe7\x20\xac\xa9\x3e\xa1\xbd\x0e\x17\x5f\xf8\x78\x0b\x7c\x50\x6f\x97\xab\xd3\x09\xf9\x7f\x70\x29\xcb\x61\x17\xfb\x1a\x59\x5c\xfb\xf5\x2c\x0d\x7b\xbe\xb3\xb4\x8b\x67\xdb\xc2\x9a\xcc\xc3\xda\x4f\xd5\x96\xbe\x05\x9e\x3f\x9d\xb4\xff\x65\xf8\xba\x21\x62\x18\xd2\x6d\x1d\x07\xcb\x09\xfb\x0f\xcc\x60\x07\xbe\x88\x5f\xd3\x6d\x2c\x8e\x48\x78\x3c\x9b\xde\xb3\xe9\x7d\x48\xd3\x6b\x37\x61\xda\x37\xbc\xfc\x90\xc1\x5b\x5e\x7e\xc8\x6c\xfe\xf3\x8f\xf9\x1d\x33\xe4\xc6\x80\x97\x73\x92\x0d\xfb\x8c\x8c\x58\x5c\x4f\x91\x5d\x54\x7e\xff\x46\x2b\x86\xd2\x6b\x44\x72\xc5\xb0\x67\xaf\x13\x83\x0f\x58\x2b\xfa\x13\xf6\xcd\xcd\xb6\x71\xca\x1f\xbe\x71\xaa\x87\x31\xc6\xd7\x55\xa9\x8f\x67\x33\x79\x36\x13\x63\xda\x41\x32\x8e\x1e\xdf\xd4\xe0\x98\xfc\x53\x03\xb3\xf9\xa8\x7f\x27\x87\xc2\xff\x39\x8c\xaf\xb5\x2b\xcb\x07\x79\x01\x65\x94\xf1\x51\xd3\x32\x13\x6e\xe1\x43\xf2\x59\x23\xb6\x0d\xf4\x1b\x5f\x0f\x63\x2d\x5f\x8f\xf2\x51\xcf\x66\xf2\x6c\x26\x46\x1f\x45\x8c\xa3\xc7\x47\x35\x38\x26\x1f\xd5\xc0\x6c\x3e\xea\xbf\xd1\xab\x2d\x3e\x61\xeb\x23\x9f\x2f\x86\xda\x5f\xbf\xf9\x5d\x6b\x7d\x6e\x9f\xf9\xb9\x63\xec\x6f\xf8\x1e\xa4\x01\x3b\xa5\xfa\x18\x7b\x1a\x37\xf5\x6c\x29\xcf\x96\x62\xf3\x54\xd4\x3e\x7a\x5c\x15\x41\x32\xf9\x2a\x02\xb4\x39\xab\x9f\x8a\x7f\x1e\xfb\xf3\x27\xfd\x93\xf9\x6b\xe7\xf2\x6e\xd8\x37\xff\x0e\xfd\xe1\xb3\xf9\xbe\xc9\xfc\x98\xb9\xbc\xdb\x77\xf0\xc6\x36\x9b\x97\x51\x07\xdc\x02\x0e\x78\xb1\x67\x13\x7a\x36\xa1\x51\x17\xc9\x0b\x86\xd3\xe3\xdb\x7e\x2a\x4c\x8e\xed\xa7\xc2\xec\xd5\x7e\x3c\xd5\x86\x9d\xa8\xe3\x32\x8b\x73\xff\xc5\x64\x3e\x1f\x9a\x5d\x1c\x9e\xf5\x14\xb2\x81\x8f\x4f\xc6\xea\x23\xf2\x5f\xab\xfb\xd6\x43\xe8\x82\xc9\xfc\x78\x32\x04\xc9\x1f\x4f\x96\x00\xf9\xe3\xa9\x26\x29\x0d\x58\x9e\xd7\x8d\x48\x72\x60\xb5\x47\xae\xd7\x7a\x8e\x1e\xd9\xca\xb5\xc2\x5e\x57\xd7\x62\xc0\x66\xf6\x2c\x1a\xd1\xa1\x71\x81\xf4\x99\xa1\x39\xff\xc5\x80\x56\x73\x24\xab\xd7\x70\xcc\x1a\xbf\x67\xb6\xdb\xc2\xc7\x48\xc8\x0d\xfb\x93\x12\x02\x0a\x6c\x3e\x9f\x69\x57\x3c\xb9\x03\x7d\xea\x36\xa7\x12\x18\xd0\xaa\x6e\xba\x04\x18\x23\x24\xb7\x4f\x4a\xee\x55\x62\xea\x97\x52\xaf\xbe\x3f\xd7\xbe\x78\x4a\x0f\xfa\x34\x6e\x59\x91\x71\xa8\x55\xe7\x3f\x15\x83\x9c\xea\xf0\x4f\x02\xe3\xdd\x6a\x9f\x57\xbd\xca\xa9\xba\xfd\x5e\xd5\xed\x89\x38\xcf\xa2\x51\x2c\xb2\x6f\x0e\x4d\x50\x8c\xb6\x08\xcf\xa2\x77\x28\xe6\x7b\x1a\xc4\x2e\x1c\x2b\x75\x96\xf6\xd2\xf7\x56\x73\xe8\x6e\x08\x11\x0a\x96\x2a\x5f\xc4\x01\xd2\x81\x07\xde\x3a\x21\x00\xa1\x42\xf9\x36\x85\xcf\xb9\x1f\x1e\xe3\xde\xa0\x5d\x0a\xd5\x6e\x77\x20\xa5\x66\x9d\xb6\xdf\x6e\xc7\x98\xe6\xbc\xcf\x30\xe7\xba\xc5\x43\xc3\xa8\x2f\x2b\xfa\xa9\xb2\xe8\x09\x8c\x59\xb5\x01\x4d\xec\x3a\x88\x5d\x2b\xdf\x26\xfb\xd1\xbd\x1e\xe5\x33\x9e\x4c\x39\x9f\x24\xa7\x9e\xcc\x5f\xaf\x9a\xbe\x4d\xb4\xe3\x8c\x12\xd0\xac\xac\xf6\xd3\xe2\xf0\x09\xe6\xbc\x6f\x12\x33\x87\x26\x31\xd7\x6b\xe9\xd3\x63\xd1\x13\x18\xb3\xea\x06\x9a\x2c\x77\x10\xbb\x56\x46\x1b\xe6\xd8\x99\xff\x93\x29\xe7\x93\xe4\xd4\x93\xf9\xeb\x55\x93\x71\x08\x31\xa0\x59\x59\xdd\x67\xaf\xc1\x02\xe8\xb3\xcf\x27\x1e\x41\x9f\x1c\x87\x9e\xc8\x97\x55\x35\xe0\xe2\x43\x00\xf5\xa8\x65\xb4\x69\x8e\x5b\x4b\x3d\x9d\x76\x3e\x41\x46\x3d\x85\xbd\x7e\x3d\x19\xc7\x10\x87\x9a\xb5\xc5\xbe\xba\x08\xdd\x37\xbf\xd0\x6b\x0a\xba\xb3\x9e\xa0\x3c\x7b\xca\xb9\xc3\x07\x66\x58\x20\xce\x6e\xdb\xdd\x5c\xab\x50\xf3\x1a\x8b\xc3\x61\x25\xda\x56\x57\x3f\x15\x7f\xc6\xd9\xe9\xf1\x12\xb9\x62\x35\x1a\x6c\x00\xd9\x5c\xaf\xd5\x0f\xde\x8f\x27\xd5\x2c\xe1\xbe\x47\xbb\x0d\x8e\x49\xc3\x0d\xcc\xa6\xe5\x2b\x66\xcb\x63\x72\xcf\x4f\x34\x32\x3f\x41\x2e\x3d\x91\xb7\x1e\x05\x19\xdd\x28\x01\x99\xd4\xf3\xe3\x49\x09\xf1\x81\x94\xb3\xd1\x04\xd5\x8b\xef\x71\x2c\x0b\xbb\xc0\x67\x28\x56\x6c\x61\x53\x5f\x13\x07\xe3\xd2\x4b\x43\xfd\x26\xd0\xe5\x0f\xd7\xb6\x27\xb6\x68\x17\xa1\x69\xa5\x6d\xf9\x80\x22\x80\x35\x6b\x1f\xd9\xa3\x6b\xbf\x9b\x7d\x2c\x16\x3c\xa5\xe1\x7e\xd9\x1a\x06\x54\x07\xb5\x48\x58\x5f\x7d\x8e\xea\xdb\x98\xa7\xf3\x01\xe1\x7e\xc8\xd6\x3d\xb1\x4d\xbb\x50\x4d\xeb\x5a\xcb\x27\x20\x01\xfc\x38\x6b\x79\xcc\xb7\xba\x8f\xc7\x84\xa7\x34\xdd\x2f\x5f\xb3\xd1\xf6\xac\x48\xdb\x0f\x3b\xd7\x77\xaf\xcf\x6c\xac\x36\xfb\x01\x1b\xf7\xa4\x26\xed\x32\x35\xae\x24\x6d\x1f\xb1\x44\xf8\xe3\x2c\xe6\xfa\x0f\x8e\x1f\x8d\x07\x4f\x6d\x79\x80\x80\xcd\x56\xdb\xb7\x06\xa4\x5f\x7f\x1e\x13\x45\x98\x33\xb3\x7e\x26\x23\x08\x90\x78\x3f\x5c\xdb\x5e\xd7\xa2\x5d\xa0\xf0\x42\xcc\xfa\x9d\x8b\x00\x1f\x1b\x8d\xaf\xff\xb0\xf9\xb1\x58\xf0\xa4\x86\xfb\xa4\x6a\xb6\x51\xf3\x04\x3b\x4d\x0a\xd3\x35\x49\x05\x2e\xab\x02\x93\x37\xb5\x5f\xce\xc8\xc3\x49\xc2\xb5\x37\xc1\xc4\x9f\xb8\xd3\x85\x7a\xeb\xe1\xf0\x3a\x7a\x67\xd4\x7d\xa3\x18\x55\xd8\xcd\xa5\x89\xb8\x09\xc5\x70\x42\x59\xe7\x46\x16\xb5\x3f\x09\xe6\x10\x8f\xc1\xaa\xbf\x5f\xe3\x28\x3d\x6d\x6f\xe1\x8b\x92\xaf\xe6\x71\xf9\x64\xbd\x5d\x8e\xea\x6d\x92\xf5\x75\x36\xc9\x0c\xa7\xbb\x75\x0e\xc5\xeb\x9b\xd9\x7f\xec\x5d\x02\x2b\x3c\x25\xe7\xe0\x36\x5c\x9d\x0f\x2b\x93\x4f\xca\x90\xfc\x84\xc1\xf3\xc0\x7f\x1e\xf8\xcf\x03\xff\x5f\x63\xe0\xcb\x8f\x75\xb5\xdc\x6d\x51\xf4\x6e\x87\x22\xec\x02\xb9\x5a\x1b\xcc\x34\x11\x49\x13\x7d\x66\x97\x26\xf0\xa4\x2e\x4d\x8a\x1f\xb2\xbf\x5e\xe1\x82\x1a\x83\xf3\x27\x03\x06\x2a\x5c\xe3\x09\xe5\xba\xe9\x92\x8a\x43\xdd\x90\xc2\x93\x1b\x8e\xee\x06\xaf\xf2\x94\xf6\x01\x5f\xcf\xd8\xcb\x8a\x76\xa9\xf7\xd0\x1a\xdd\xe4\x79\xe8\x20\x57\x85\xa0\x5e\x85\x35\xb0\xc6\x93\x0c\x4d\x2d\x8e\x3e\xdb\xf1\xb3\x1d\x7f\x96\x76\xec\x71\xeb\x1d\x10\x10\xba\x97\x4a\x6d\xa1\x41\xc0\xb2\x04\x89\x1f\xb2\xbf\x42\x71\xe2\x87\xec\xaf\xe6\x50\xf1\xb7\xab\x67\xab\x63\x86\x98\x54\xe3\x13\x19\x62\x6c\x8e\x35\x66\x88\xc9\x55\x3e\xea\x10\xa3\xac\x8c\x19\x62\x52\x8d\x47\x0c\x31\x26\x84\x11\x43\x4c\xac\xf1\xbe\x42\xc5\xb3\x1d\x3f\xdb\xf1\x67\x68\xc7\x1e\xb7\xde\x0f\x1e\x2a\xfe\x06\x87\x8a\xbf\x99\x42\xc5\x8f\xa7\x7a\xc4\x74\xcc\xde\x6d\xf8\x7e\xf6\xf7\x39\x1d\x92\xf2\xca\x1f\x72\x3e\x69\xd8\x50\xf1\x2c\xd0\x27\x10\x68\xfb\x6a\xb6\x31\x85\xcf\xe0\x90\xa9\x93\xf2\xf7\x30\xea\x2c\xe3\x67\x44\x8c\x7a\x62\x75\xf3\x7c\xd2\x78\x67\xc7\xaa\x5c\xaf\xee\x47\x06\x59\xeb\xf8\x79\x16\xe8\xa3\x04\xaa\x3f\x31\xff\x81\xa2\x4f\xd3\xa6\x61\x4c\x82\xf1\x27\x4d\xf6\x87\xfa\x3f\x0a\x8c\x63\x7e\xa0\x6d\xe0\x96\x00\x7e\xe5\xba\x2a\xac\x01\xc8\x9d\x9c\xe0\x39\x0d\xc5\xd6\x1c\xa8\x54\xdc\x37\x3b\x61\x2d\x1a\x2e\x20\x1f\x64\x28\xc0\xee\x41\xa1\x8a\x38\x66\x9e\x85\x78\xad\x10\x3d\x49\x74\x06\xbb\x16\x71\x54\xdb\x96\x60\x4f\xfb\xe9\xc2\x3a\x5a\xe0\x3d\x9b\xa3\xd4\x3e\x46\xeb\x9a\xd2\x61\xf3\xfb\xe8\x5c\x79\x32\x2f\xbd\x0a\x05\x76\xad\xca\xc0\xa7\x5c\x41\x41\xef\x53\x13\x47\x6e\x1c\xb5\xc3\xde\x0e\x00\xf6\x50\xa8\xcf\xed\x84\x7e\xdf\x73\x92\x1c\xa3\x13\x26\xa4\xb9\xab\x19\x1a\xee\xcc\x9e\x45\xc2\x5c\x53\x2b\x08\x83\x15\x73\xb8\xf6\x7e\x31\x2b\xb7\xd9\xdb\x1f\xf3\x3b\xe1\x34\xa5\xb1\x4f\x29\xde\xd5\xce\x36\xaf\xeb\xfc\xa8\x77\x4c\x04\xf6\x8b\x7b\xd6\xf7\x70\xe8\x6c\x3e\x42\xd8\x8f\x60\x6c\xbc\x25\x3e\x0b\xab\xd7\x46\x5b\x11\xf5\xd8\x2a\xc7\x33\xd9\x2c\x87\xf7\xd9\xae\xb0\xb3\xd4\xd8\xed\xb2\xc1\x31\xf6\x5b\x82\xf6\x6a\xa4\x4f\x21\xa3\xf4\xf1\x28\xc6\xae\x33\xdf\x67\x79\x0d\xb1\x60\xeb\xe6\x61\x0d\xd1\x66\xc3\xc6\x6d\xc4\x1c\xe9\xa7\xe2\x83\x7a\x94\x27\xd5\xc7\x07\x75\xbe\xcf\x82\xb2\x9a\x2d\x13\x4f\x8f\xcd\x52\x2c\x93\xc1\x52\xa8\xdd\x5a\x3f\xb4\x03\x71\xb5\x2c\x88\x01\xe1\xe3\xbb\x10\xd0\x68\x9f\xe5\x35\xc4\x76\x07\x39\x5c\x86\x66\xb6\xde\x1e\x67\xdb\x2e\x4a\xaf\x9d\xba\xdb\x17\xb3\x4f\xb5\x20\xe9\x5d\x8f\xe8\xcb\x11\xdd\xf4\xfe\x89\xfb\xea\x75\x3d\xb4\x1a\x0c\xb0\xa4\x6f\x01\x56\x23\x79\xea\x69\xfe\x30\x51\x7e\xc4\xd0\x05\x9a\xcf\xbf\x9e\x14\x3c\xbd\xef\x7d\x06\x66\x5f\xc6\x08\x08\xbd\x06\xf7\xc4\x71\x62\x98\xb4\x9f\x34\xf0\x8c\x5f\xab\x1a\xed\xee\x5f\x52\x18\x1e\x20\x82\x21\xf6\x67\x09\x8a\x22\x86\xd5\x02\x9f\x76\x72\xfd\xa1\x87\xfa\x53\x99\xde\xbf\x9e\x14\x3c\xb5\xef\x7d\x06\x67\x5b\x40\xb4\xe0\x1e\x53\xfb\xec\x47\x77\xdf\x14\xdb\xfa\x5d\xfb\x5f\x5b\x10\x9e\xd6\xfd\x7e\x8b\xb3\x3b\x38\xcb\xb4\xff\x90\x64\x7b\x7c\x86\xbe\x28\xf2\xee\xd6\x79\xe1\x34\x83\x4c\x17\x44\x0b\x19\xfc\xe1\x67\xc8\xe7\x3c\x8a\x75\x09\xe9\x1b\xba\xc0\x07\x31\x45\x80\x37\x3d\x02\xbe\x91\xb7\xf7\x7d\x2a\xfd\x9b\xd1\xf7\x81\xfb\xfb\xa7\x1d\x86\x83\xe1\x9f\x58\xff\xfa\xbe\x35\x93\x5f\xed\xc9\xaf\x65\xdf\xb1\xe5\x16\x01\x76\x18\xcf\x56\xfc\x6c\xc5\x9f\xa9\x15\x7b\xd4\x76\x0d\x2e\x9e\x00\x55\xbf\x4e\x0a\xe1\x09\x44\x9a\x02\x77\x5d\x5b\xd9\xee\xee\xb2\x51\xa7\x42\x81\xb6\x21\x65\x54\xbd\xc7\x5e\x4b\xf6\xf9\x77\xc6\x63\x5d\x30\x86\xef\x06\xaa\x07\xed\xa6\xd4\xa4\xdd\x9e\xeb\xc7\x86\xde\x11\xa3\xf4\xd2\x2e\x9c\x9e\x5a\x9a\xd2\x3e\x49\x1e\x3d\xce\x99\x45\x19\x60\x36\x8c\x14\x43\xea\xf8\x2d\xcf\x8f\x43\xec\x73\xdc\x53\x46\x73\xf1\x61\x0c\x49\xb4\x1f\xa4\x3d\x8f\xb5\x62\x90\x12\x85\xaa\x42\xa2\xa5\x66\x19\x0d\xbb\xcd\xbd\xe5\x2d\x98\x90\xff\x57\x0e\x87\x37\x43\x54\x73\xaf\xc3\xeb\xf4\x07\x07\xe5\x21\xb9\xf9\xdc\x9f\xf8\x9e\x3f\x27\xcf\xc9\x2d\x9b\xff\x0e\x56\x63\x1e\xa2\x83\xeb\xf7\xbe\x16\xd7\xf6\x68\xb6\x9c\x4f\xda\xff\x52\xfa\xb5\x30\x0b\x62\x48\xb5\xd1\xb2\x08\x08\xff\x37\x37\xcd\x7f\x4f\x43\x7f\x12\x8c\x90\x83\x5e\x17\xb0\xea\x67\x0b\x79\xb6\x10\xc9\x42\x3c\xc1\x2e\xac\xbe\x08\xba\x04\xb2\x83\x98\x7d\xd2\xb0\xeb\xf1\xad\xd6\xd3\xda\xce\x08\x8b\x93\xea\xfc\x13\x59\x1c\xf4\x9a\xee\xa8\x6a\x1f\xdd\xe2\x34\x9f\xf4\x6c\x21\xcf\x16\x02\xf9\x24\x5b\x0e\xb8\xc3\x80\x7d\x92\x29\xf3\x4b\xa1\x03\x1f\x1c\xb0\x9a\xcf\x15\x16\xf7\x4f\x6a\x70\xee\x95\x16\xe7\x7e\x42\x26\xa7\x39\xa5\x67\x13\x79\x36\x11\xd0\x2b\x59\x3f\x14\x08\x28\xb0\x5f\x32\x7e\x1e\xa0\x60\xfd\xd5\x86\xd1\x93\xf3\x2b\xe6\xe6\xff\xa4\x53\x73\xf7\xca\xb9\xb9\xfb\xc9\x4c\xce\x35\xaf\xf4\x6c\x1f\xcf\xf6\xa1\xbb\x24\xf3\x4d\xbd\x1c\x0e\x3b\x23\xf8\x9e\xde\x06\x06\x64\x16\xc5\xfc\xd5\xe3\xb3\x61\xc6\xa7\x1f\x3e\x42\xeb\x1e\x6f\xd3\x22\x44\x20\x63\xc9\x8a\x2d\x22\x24\x8b\xea\xd9\xe7\x69\xaa\xef\x69\xe0\x0e\x7d\x8d\x1e\x76\x44\xd0\xad\xcb\x83\xab\xf4\xec\x1b\x35\xee\x42\x90\xc1\x1f\x7d\xcc\xeb\x63\xe5\xd9\xcc\x9e\xcd\xec\xfd\x84\x96\x9e\xe7\x61\x04\x14\x83\x73\xb4\xa5\x06\xf9\x53\x1e\x4f\x60\xb9\xb3\xf0\xaa\xd5\x45\x5b\x6d\x90\xbd\xbc\x54\xf3\x47\xf0\x73\x05\xfd\xb8\xf6\xed\x77\xa6\x5d\xec\x02\x10\x72\x02\xcf\xa2\xbc\x52\x94\x9e\x28\x40\xbb\xa1\x9b\xd2\x4d\x96\x67\x65\x18\x98\x2e\x1a\x9f\x40\x3d\xee\x95\xfa\x71\x1f\xa7\xa0\x11\xfa\x19\xa4\x1e\xba\xb3\xcf\xa4\x1f\x11\x0a\xd9\xfa\xb3\x34\xaf\x97\xa6\x27\xc9\xd0\x6e\xef\xc6\x3c\x86\xed\x49\x1a\x06\xff\xa9\x78\x9a\x29\xc9\x87\xfe\xbe\xf6\x49\x4e\x48\xc0\xe7\x46\x86\xd7\xf9\x27\x99\x92\xe8\x8e\xe0\xd9\xc8\x9e\x8d\xec\x3d\xcd\x7b\xed\x39\x15\xf0\xf5\xa3\x16\x00\xb9\xc5\x2a\x4d\xf8\x83\xf7\x43\x2e\xc3\x1a\xf1\x62\x13\xf0\xbe\xec\x90\x3d\x94\x96\x57\xb6\x7c\xfd\x91\xaf\xcf\x91\x7d\x4f\x64\xda\xa0\x4c\x01\x45\x55\xa7\x00\xb2\x28\xd4\x72\x48\xe7\xda\xa7\x0e\x3f\xa4\x42\x3f\x2b\xf6\x3d\x91\x69\xbb\x42\xa1\xa9\xba\x00\xb2\x28\xd4\x76\x0e\xe6\xba\x77\x00\x3f\xa4\x3e\x3f\x27\xee\x3d\x89\x67\xbb\x3e\xc1\xa9\xa8\x08\xb3\x68\xf4\x27\xe3\x0b\x49\x32\x57\x7d\x1e\xeb\x23\xf8\xdb\xcf\x86\x75\xaf\x63\xd8\xae\x48\x3d\x6c\xb6\x00\xa3\x0a\xa5\x77\x91\x1f\xcf\xac\xfc\xa8\xf9\xc0\x17\xd3\x07\x4a\x58\x57\xe2\x67\xc5\xbc\x27\xb1\x6c\xd3\xa4\x21\xef\x27\xc2\x6c\xfa\x1c\x1a\x77\xde\x93\x48\xae\x7d\xf6\xf8\x73\x64\xdf\x93\x98\xee\xd1\xa9\x31\x6e\x5a\x72\x5c\x1c\x3e\x38\xf6\xbc\x27\xa9\x5c\xf7\x2a\xf0\x67\xc8\xbd\x27\xf3\xdc\xa3\x52\x73\xe8\xb4\xa5\x71\x38\xc2\xd0\x08\xf4\x9e\x3c\xd7\x75\x6f\xe6\x7e\x7e\xcc\x7b\x02\xcb\x3d\xfa\x34\x44\x50\xba\xf2\xdc\xe6\xf1\xc3\x79\x97\x67\xb5\xbb\x43\xc7\x24\x7d\x58\xe7\x05\xce\x9c\x0a\x65\xd5\xe4\x9b\x32\x41\xe9\xa4\xf9\xe9\x56\xb8\x4c\x76\x9b\x34\xc9\xb0\x7b\xc0\x8d\x05\xac\x03\x6f\xbe\x21\xd5\xaa\xe4\x37\xbc\x0e\x16\xc5\xfd\x26\xca\xd3\xbc\x5c\x7f\x79\x33\x6b\xfe\x91\x3b\xb8\xf7\x65\x7e\xca\x62\x97\x01\x76\x7e\xf3\x8f\xb4\xe8\x55\xf5\x43\x8a\xdd\xf0\x0c\x60\xed\x76\x62\x5d\x42\x3e\xca\x6f\x71\x29\x96\x16\x79\x95\x90\x05\xba\x3b\xf5\x5f\x88\x80\x12\x17\x18\xd5\xeb\x2c\x67\xbf\x44\x58\x72\x44\x7b\xbc\x3e\x95\xe9\x4b\xcf\x7b\x43\xfe\xa8\xde\x6c\xf7\xff\x2b\xf4\x7e\x2d\xf6\xaf\x36\xbc\x5f\xbe\xff\x42\x64\x71\x2a\xb0\x48\x98\x73\x64\x02\x7b\x9c\x1f\x71\x5d\x3e\x84\x5e\x91\xed\x5f\xd1\x46\x2f\xe8\xcc\x3a\x33\x8d\xa2\x8d\x7b\xcc\x7f\xa3\x1a\xa7\x2c\xa3\x34\x75\xbc\x69\xe5\x60\x54\xe1\x8d\x9b\x9b\x41\xa2\xb1\x40\xf0\x63\x65\x84\x19\xca\x2f\x68\x7d\x68\x44\xc9\xd9\x0b\x57\x68\x8a\xa6\x17\xef\x88\xb3\xd3\xb9\x40\x71\x9c\x64\xfb\xb5\xbf\x39\xa2\x72\x9f\x64\xeb\xa9\x5f\xdc\x3b\xbe\xe3\x53\xb8\x93\x26\xe7\x34\xa9\x6a\x97\xc8\x85\x1e\xab\xa3\x88\x2e\x4d\xc5\xac\x03\xbf\xb8\xdf\xc4\x49\x55\xa4\xe8\x61\x4d\x7a\x9d\x64\xc4\x64\xaa\x1a\x45\xef\x5a\x08\x2b\xdc\xa6\x79\xf4\x6e\xf3\x5b\xde\x54\xdc\x7c\x2d\x03\xdb\x16\x1d\xd4\xb2\x35\x2f\xee\xdb\x62\x0f\x91\x6b\xe4\x9d\x56\xce\xdb\x69\xf3\xef\xe2\xed\x0e\xf3\x28\x77\x9b\x81\xd3\xd6\x6b\x7a\xc1\x19\xad\xf3\x62\x3d\xc3\x5d\xd2\x68\x9b\xdf\xbb\xd5\x01\xc5\xf9\xdd\xda\x9d\x15\xf7\xce\xb2\xb8\x77\x66\x8b\xe2\xde\x09\x8b\x7b\xa7\xdc\x6f\x11\x1d\xcd\x13\x2f\x78\x45\xd5\x38\xaa\x42\x3e\x0a\x7d\x14\xae\x6c\x92\x17\x3e\x9c\x1c\x51\x00\x9f\x79\x27\x2f\x7f\x38\xe2\x38\x41\x4e\x15\x95\x18\x67\x0e\xca\x62\xe7\xe5\x11\xdd\xbb\x77\x49\x5c\x1f\xd6\xcb\xc5\x4d\x71\xff\xea\x0c\x29\x3c\x68\x2c\x45\x34\x05\xe7\x10\x9e\x6b\x7c\x2f\xba\xdd\x53\x51\xe0\x32\x6a\x46\x4a\x8a\xeb\x1a\x97\x6e\x55\xa0\xa8\xa9\x1c\x16\xf7\x82\x5b\x0b\x3b\xdb\x59\xfb\x8e\xef\x10\x5b\x62\x26\xe7\xfb\xbe\xd4\x88\x47\x72\x94\x8d\x56\x8a\xb3\x3c\x2e\x9a\x5a\x26\x54\xa7\x38\x0b\x5e\x74\xd6\x91\x5f\xed\x9a\x7f\x94\x97\x3b\xea\x9a\xa6\xe6\x16\x9d\xa2\x1b\x0b\x2a\x63\x29\xda\xe2\xf4\xac\x10\xda\x28\xad\xf6\xb7\x13\xe5\x59\x5d\xe6\xe9\x59\x71\xfa\x2a\x5d\xe6\x46\xe7\x8d\xa4\x98\x46\xdc\x14\xef\xea\xb5\xdf\xfe\x49\xbe\x2f\xad\xfd\xcd\x36\x2f\x63\x5c\x52\x4f\x42\x7f\xb7\x9e\xa4\xb8\x77\xaa\x3c\x4d\x62\xcd\xdc\x74\x9b\x26\xd5\x55\xbb\xa5\x85\xb9\x56\xa4\xa1\xb4\xf4\x48\xf3\x25\x8a\x93\x53\xb5\xf6\x39\x3d\xb5\xb0\xd2\xca\xc0\x8a\x9f\x88\xb3\x37\xea\x70\xbd\xe6\xcd\x25\x59\x71\xaa\xdd\x22\x45\x11\x3e\xe4\x69\xdc\x46\x06\x51\xec\xd3\x57\x1b\xd3\xe8\xb1\x36\xd1\x48\xe2\x7d\x50\x6e\x44\xf1\x68\xbe\xa3\xbc\x78\x20\x76\x58\x51\xd7\x90\x64\x31\xce\xea\xb5\xbb\x5a\xad\x56\xc5\x3d\xb7\x62\x5f\x9a\xf2\x88\x83\xc6\xdf\x34\x71\x74\x97\xe6\x77\x6c\x6e\x67\x65\xf8\x3d\x49\x62\x97\x47\xa7\x6a\x62\x86\xd3\x28\x79\x1e\x32\xb6\x66\xaf\x2e\xde\xb6\xce\xdc\xa2\x4c\x8e\xa8\x7c\x38\x43\xc3\x98\x8e\xdb\x50\x1b\xd9\xa4\x44\x1a\xcc\x42\x78\x6a\x66\x40\xc2\xcc\x0e\x0a\x4a\x8d\xef\x6f\xe6\x0e\x4e\x43\xc8\x71\x03\x1e\x0a\xe6\xc1\x24\xf4\x67\xe4\x3f\xde\x0c\x88\x4d\x43\xeb\xe5\xd7\xd4\x1a\x5f\x45\x12\x20\x9d\x67\x4d\xa4\x22\xa6\x2e\xb1\x88\x69\x08\x9c\xfa\xae\xbf\x9c\x2d\xe3\x20\x0e\x84\x17\x6b\xf2\x53\xdd\x18\x24\xbd\xc4\x80\x8c\x81\x49\x63\x36\xa8\xc4\xb2\xf7\xd7\x8d\xed\x4b\x84\xd0\xc5\xfb\xb5\x72\xf8\x8b\xd0\x8d\x4c\x84\x3d\xad\x5f\x16\xa8\xac\x93\x28\xc5\x95\xfb\x6b\x75\x6e\xa7\xd7\x68\x5b\xe5\xe9\xa9\xc6\x1b\x1a\x75\x9b\xc9\xb1\x38\x51\x36\x4c\xd4\x9b\x69\x96\xbf\x61\x5e\xff\x37\x32\xb6\xee\xd7\x6e\x40\xd7\x1a\x5d\x5f\x95\x07\x7b\xe4\x65\x40\x18\x34\xff\x84\x57\xab\xfe\x6f\x00\x00\x00\xff\xff\x71\x15\x71\x5b\x22\xdb\x02\x00") func assetsLoginDistAllMinCssBytes() ([]byte, error) { return bindataRead( _assetsLoginDistAllMinCss, "assets/login/dist/all.min.css", ) } func assetsLoginDistAllMinCss() (*asset, error) { bytes, err := assetsLoginDistAllMinCssBytes() if err != nil { return nil, err } info := bindataFileInfo{name: "assets/login/dist/all.min.css", size: 187170, mode: os.FileMode(420), modTime: time.Unix(1570965576, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _assetsLoginDistAllMinJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\xfd\x0b\x97\xa3\x36\xb6\x30\x0c\xff\x95\x32\xd3\x87\xa0\xf6\xb6\xcb\xee\x24\xf3\x3d\x83\x5b\xc5\xca\x75\x92\x49\xe7\x72\xd2\x3d\x93\xcc\xc1\xf4\x2c\x01\x02\x53\x85\xc1\x85\xa9\xae\xea\x18\xe6\xb7\x7f\x4b\x5b\x12\x08\x8c\x3b\x99\xf3\xbc\xef\x5a\xef\xea\xd5\x65\x10\xba\x6b\x6b\xdf\xb4\xf7\xd6\xf5\xf3\xd9\xed\x7f\x3f\xf0\xea\xfd\xd5\xbb\x17\xcb\xf5\xf2\x93\xab\xe6\xca\x89\xc8\xd5\x8b\xd5\xea\x53\xb8\x7a\xb1\x5a\x7f\x7a\xa5\x3e\x7f\x5d\x3e\x14\x31\xab\xb3\xb2\x80\xab\x6f\x8b\x68\x79\xd5\x5c\xdd\xde\x8b\x2f\xcb\xb2\x4a\xaf\xf3\x2c\xe2\xc5\x91\x3f\xbf\x9e\x25\x0f\x45\x24\x72\x39\x0c\x42\x72\xb2\xca\xf0\x96\x47\xb5\x45\x69\xfd\xfe\xc0\xcb\xe4\x6a\x5f\xc6\x0f\x39\xb7\xed\x0b\x1f\x96\xfc\xe9\x50\x56\xf5\xd1\x1b\xbe\x52\xb6\x8c\xcb\xe8\x61\xcf\x8b\xda\x0b\x1d\x06\xb3\x15\x71\xfb\x86\xc8\x29\x4b\x9c\x59\x9f\x85\xd4\xbb\xaa\x7c\xbc\x2a\xf8\xe3\xd5\x57\x55\x55\x56\x8e\xa5\xc6\x50\xf1\xfb\x87\xac\xe2\xc7\x2b\x76\xf5\x98\x15\x71\xf9\x78\xf5\x98\xd5\xbb\x2b\x76\xa5\x4b\x5a\x64\x53\xf1\xfa\xa1\x2a\xae\x42\x87\x91\xd6\xc5\xbf\x8e\xf5\x50\xc4\x3c\xc9\x0a\x1e\x5b\x33\xdd\x5d\x59\xde\x93\x3f\x6e\xbd\xcb\x8e\x30\x1c\xf9\x3b\x56\x5d\x45\xd4\x0f\x20\xa6\xd1\xf2\x28\xe6\x07\x38\x8d\x96\x51\x59\x44\xac\x86\x84\x46\xcb\xc3\xc3\x71\x07\x29\x8d\x96\x59\x11\xf3\xa7\x1f\x13\xd8\xd1\x53\x0b\x19\xdd\x2d\xeb\xf2\x75\x5d\x65\x45\x0a\xb7\x74\xb7\xdc\xb1\xe3\x8f\x8f\xc5\x4f\x55\x79\xe0\x55\xfd\x1e\xee\x44\xa6\xdc\x98\x10\xd8\x53\x0b\x97\xce\x82\x82\x0e\xfb\xa0\xc6\x22\x26\xa2\x58\x26\xc5\x32\x2b\xb2\x1a\xbf\xb4\x50\xd2\xeb\xb7\xfe\xf6\xb8\x7d\xf8\xfa\xab\xaf\xbf\xde\x3e\x7d\xb6\x0a\xe6\xcd\xe8\xfd\xd9\x75\x0a\x07\x7a\xfd\x76\xb1\x3f\x2e\xae\xe1\x9e\x5e\x2f\x1c\x7f\x1b\xb3\xc5\x6f\x01\xb9\x4e\x33\xa8\xa6\x1b\x0b\x97\x75\xf9\xf7\xc3\x81\x57\x5f\xb0\x23\x77\x48\xbb\x11\x2d\xd3\x62\x79\xa8\xca\xba\x14\x93\x47\x4f\x12\x6e\xdc\x3d\x44\x65\x71\xac\xab\x87\xa8\x2e\x2b\xb7\x80\x23\xcf\x39\x3e\x5a\x16\xe4\xbc\x48\xeb\x9d\xbb\x82\xba\xfc\xac\xaa\xd8\xfb\x7e\xb5\xbb\x86\xe2\x65\xc4\xf2\xdc\x11\x53\x4f\x5a\x48\x79\x3d\x80\x08\x3d\xf4\x87\x3c\x9f\x51\xe6\xad\x6e\x98\x27\x72\xfa\x6c\x2e\x7e\x96\xb2\xfe\xc0\x95\x69\x81\x3b\xac\x4c\xac\xcc\xeb\x9a\x45\x77\x83\x2a\xc5\x8a\x86\xb4\x58\xee\x79\x95\x72\xcc\xba\x34\x06\xe0\x10\x60\x3d\xf4\x2c\x0f\x15\x7f\xf7\x23\x82\x38\x45\xe0\x08\x45\xde\x9a\x3f\xc9\x57\xfd\x02\x61\x0b\x9c\x45\x3b\x77\x7a\xdd\x96\xe2\x1b\xb6\x04\x72\xd5\xf6\xec\x30\x35\x4a\xac\xb2\xeb\xb4\x53\x2c\xf7\xec\xe0\x0c\x61\x32\x84\xa8\xcb\xce\xe4\x60\x43\x88\x44\xa5\x84\xb4\x80\xf0\x39\x31\xc7\xa3\x8a\xe3\x25\x3b\x1c\xf2\xf7\xaa\x47\x55\x8a\xf0\x77\x14\x15\x24\x59\x75\xac\x2f\x55\xc0\xef\x9d\x15\x69\x21\x67\x1f\xcc\xb2\x58\x93\x16\xf8\xfd\xc4\x94\x1b\x2b\x06\x11\x9d\xb3\xb9\x23\x96\x33\x74\x57\xdd\x7c\x8f\xfa\x19\xdd\xd0\x95\x6d\x87\x37\x91\xe7\xe3\x02\x47\x41\xe0\xfa\x81\xa8\xbe\x88\x2f\x8e\xb2\x5b\xb0\xa6\x39\x5b\x5b\x01\x46\x0a\x2e\xdc\x04\x8e\x65\x55\xbb\xd1\x52\xfc\xc0\xf1\x80\x53\x17\x2d\xe5\x43\x0b\xc5\x92\x3f\xd5\xbc\x88\x29\xee\x38\xf5\x6c\xb4\x29\x86\xc4\x40\xcc\x7d\x0c\x1c\x12\x48\x69\x37\x91\xfe\x2a\x68\x9a\x53\x0b\x3b\xba\x86\xac\x4f\xd6\x43\xbf\xa5\xb3\xf5\x26\x11\xe8\x2c\x2c\xcb\x9c\xb3\xa2\x47\x9e\xa9\x6d\x3b\xb7\x34\x1d\x54\xb6\x53\x95\xcd\xe7\x04\xce\xb0\x6d\xda\x34\xc5\x32\x3b\x7e\xad\xfb\x95\x92\xa6\x71\x52\x7a\x6a\x09\xec\x28\xa5\x99\x6d\x3b\xa9\x04\xdc\xdd\x62\x41\x36\xd9\xcd\x6e\x23\x2a\xca\x12\x47\xee\x28\x87\x0d\x5a\x22\x44\xf4\x2b\xbc\xca\x8a\x2b\x46\x22\x9a\xfa\xa1\xc0\x7b\x4c\xfc\xa4\x33\x4a\x63\xd1\x3d\xdb\x16\x3f\xa2\xd5\x9f\x72\x96\x15\x72\xae\x9d\x58\x34\xcc\xa9\x48\xc6\x8d\xee\xc4\x84\x10\xcf\xe1\x9e\xc3\xe9\x6c\x2d\xf0\xa4\x6d\xf7\x1f\x23\xe2\x45\x62\x25\xdd\x2e\xdd\xac\x0b\xbf\x9e\x5a\x10\xcd\x53\x3d\xf7\xce\x2d\x24\x10\x13\xe2\xbe\x2b\xb3\xf8\x6a\xa5\x7a\x83\x59\x62\xd2\x01\x50\xda\x2f\x9c\x73\xe2\x4f\x07\x56\xc4\xa5\xab\xc8\x86\x35\x77\xf6\xf3\xef\x59\xbd\x5b\x56\x22\x79\xef\x10\xb2\xac\xf8\x21\x67\x11\x77\xae\xb7\x5f\x5e\xa7\x60\x59\x04\xb2\xe3\xcf\x9c\xc5\xef\xdd\xd9\x0a\xb8\x20\x3a\x03\x38\x1e\x13\x24\x46\x5a\x28\xca\xf2\x60\x02\x63\x0b\xfd\x7a\x4c\x6c\x72\x4b\x27\x59\x94\xd2\x62\x29\xd6\x11\xab\x51\x53\xe3\xe2\x5f\x3d\x51\x90\x1d\x7f\x91\x94\xe9\x32\x4e\xb4\x6d\x46\x29\x65\x4b\x49\xc2\x44\x45\x3f\x3c\xec\x79\x95\x45\x13\x65\x66\xfd\x12\x30\x62\xdb\x6c\x71\x60\xd5\x91\x7f\x9d\x97\xac\x76\x18\x99\xaf\x6f\xe8\x4a\x54\x60\x2c\xc6\xd4\x08\x14\x10\xce\x8c\xfe\x37\x0d\x5b\x16\x65\xcc\xdf\xbc\x3f\x70\x09\x92\xb2\xdf\x0e\x23\xde\x6c\xed\x32\x73\x17\xda\xf6\xec\x56\x62\xae\x41\x72\x4f\x59\xc0\xca\x8e\x3f\xe9\x97\x1f\x13\x0b\xab\x98\x61\xcf\xbe\xda\x1f\xea\xf7\x13\x3d\x43\x04\xb3\x31\x80\x57\x8d\x77\xad\x00\x43\x94\x16\xb5\x5d\x9a\x47\x4a\x99\xc7\xe6\x96\xe5\x9e\xed\x30\xd6\x34\xe6\x92\xe9\x54\x6f\xe7\x67\x6a\x10\x24\x68\x1a\x5d\xcc\xd5\xdf\x5b\x48\xf3\x32\x64\xf9\x57\xef\x58\x7e\xde\x53\x88\x28\x7f\xc7\xf2\x0d\x13\x33\x58\x65\x7b\x87\x11\x60\xb6\xed\xac\x71\x25\x15\x1f\xe1\x58\x0f\x47\x7e\x75\xac\xab\x2c\xaa\x2d\xe2\x39\x21\xcd\x97\x51\xc5\x59\xcd\xbf\xca\xb9\xd8\xb1\x8e\x75\x8c\xaa\xec\x50\x5b\x04\xc2\x25\xd2\x24\x06\xf9\x72\xc7\x19\xe2\x77\x5e\xc4\x5f\xec\xb2\x3c\x76\x42\xb2\x3c\xb0\x8a\x17\xf5\x0f\x65\xcc\x97\x15\xdf\x97\xef\xb8\xfe\x42\xdc\xc8\x61\x02\xf1\x47\x6c\xcf\x73\x41\xea\xa7\x66\x88\x75\xfb\xe4\x00\xd6\xfe\xb8\xb0\xfa\x8d\x73\x0f\x15\xee\x81\x98\xff\xc0\xf6\x7c\x9a\xfe\x49\xd0\x10\xdf\x6d\xbb\x7f\x5e\xd6\xe5\xab\xf2\x51\xf3\x17\x94\xd2\x70\x98\x32\x41\x51\x05\xed\x13\xf3\x17\x03\xa7\x2b\x48\x28\xd3\x28\x35\xa5\x47\x87\x91\x4d\x96\x38\x11\x32\x91\x29\x39\x09\x58\xd8\x24\x37\x7c\xc3\x25\xbe\x8b\x69\xa8\xa8\x1e\xf3\x79\x00\x11\x81\x98\x52\x3a\x5b\x93\xb0\xe2\xec\xae\xe5\xf9\x91\x5f\x89\x32\x5c\xc2\xcf\x1f\x2c\x71\xb9\x2d\x09\x1b\xa2\x20\x07\xf1\xf3\xc7\xda\xfb\x70\x29\x8d\xe5\x58\x0b\x02\x6a\x3e\x04\xcc\x96\xe5\x3a\x02\xa0\xfb\x95\x2a\x05\x7a\x13\xac\xc7\x1d\x1f\xb1\x62\x06\x9f\x1b\x36\x8d\x1f\x6c\xc6\x08\xc6\x39\x3a\x0a\x35\x33\x42\x3c\xcd\x39\x45\x60\x1d\x91\xbd\x35\xb7\x85\x60\xc2\x18\x71\x13\x39\x92\x08\x18\x21\x10\xb5\x90\x15\xe7\x6d\x1a\x9c\x8c\xec\x75\xe8\x2d\xd6\x6e\xaa\x99\x1a\x06\x91\xe8\xae\x68\x6a\xd4\x55\x31\x6d\xb2\xbb\xf3\x50\x43\x40\x4c\x57\xc0\x3b\x80\xd8\x44\x37\xf1\x26\x9e\xcf\x09\xf3\xf9\x7c\x1e\xd0\xd0\x8f\xbb\x51\xe9\x3c\x94\x83\xd8\xa5\x15\x3f\x9c\xf5\x4a\x37\x20\xe0\xcc\x0f\x20\xa1\x2b\x41\x91\x75\x53\x3b\x3a\x8b\x36\xe9\x4d\xb2\x49\xe6\x73\x12\xd3\x59\xe8\x30\x3f\x09\x20\x21\x10\xcf\x28\xdd\xd9\x36\x47\x16\x06\x53\x3b\xc2\xc4\xc7\x4c\x9f\x09\xcd\x67\x0d\x08\x68\x86\x8c\xfa\x81\x00\xe9\x1d\x12\x65\xa3\x45\xdd\xa0\x00\x49\xb9\x46\xb1\x6d\x67\xb2\xd1\x98\x6c\x3a\xd0\x4a\x24\x68\xfd\x6e\x01\xdd\x45\x05\xed\x7e\x00\x99\xe0\xc4\x1f\xb2\xd8\x5d\xc3\xa1\x2a\x9f\x26\x61\x45\x70\x3d\xaa\xe8\x19\x1c\x84\xb6\xed\x44\x92\x6f\x08\x29\x03\x46\x45\xc3\x26\x9f\xc2\x04\x6f\x40\x15\xb7\xde\x71\x20\xf0\x82\x40\x42\xcf\x19\x3b\xa6\x7a\x16\x4a\x96\x0e\xb8\x12\xbf\x9c\x71\x05\x04\x79\xd8\xa5\xe8\x3a\x65\xe6\x8f\xa0\x49\xe2\x77\x3e\x87\x44\xb3\x10\x02\x6d\x3d\xba\x5f\xb2\x9a\x2f\x8b\xf2\x11\x8e\x0f\x07\x21\xa3\xba\x77\xad\xe8\x2b\x72\xec\xd6\xe7\x92\x41\xbb\xfa\xe1\x61\x1f\xf2\xea\x4a\x4a\x73\x57\x7a\x14\x57\x08\xd3\x57\xa2\x86\xab\x9f\x79\xfa\xd5\xd3\xe1\x4a\x6e\x13\xc9\x1d\x58\xc8\x4b\xd6\x8e\x75\x65\x91\x91\x50\xb9\xf3\x2d\x5f\x52\x8c\x2b\x6b\x1e\xce\xad\xc0\x0a\xce\xd0\x1f\xd9\xe8\x32\x57\xc7\x9e\x87\xb6\x24\x8c\x58\x62\x65\x05\x36\xed\xd8\xe9\x8e\x14\x6f\x26\xf8\x8c\x68\x82\x26\x4b\x5a\xa3\x89\xb6\x6d\x87\xde\x6c\xe5\x5a\x4c\x0c\x49\x15\x59\x09\xa4\xdc\x34\x56\x81\xa3\x1f\xac\x6e\x78\x23\x18\xf3\xc5\x1a\x21\xac\x15\x5d\xab\xe9\x04\x95\xd3\xbc\x31\xec\x20\x83\x5b\xb8\x83\x1c\xf6\x50\x40\x09\x07\xb8\x87\x0a\x8e\x50\xc3\x03\xb5\x8e\xd9\x6f\xbf\xe5\xdc\x9a\xaf\x9f\x0b\xce\x4a\x4c\x27\xbc\x33\x05\xe3\x47\xba\x82\x27\xba\x82\xf7\x74\xc7\x1c\x02\xbf\xc9\x9f\xcf\xe4\xcf\xe7\xd3\xe2\xab\xe0\x89\x04\x14\xe6\x74\xb6\x22\xb0\x6a\xe1\x0b\xba\x7e\xf9\xf2\xe3\x35\x7c\x49\x4f\xed\x58\x16\xff\x4a\xec\xf2\xaf\xe9\x57\xcb\x43\x79\x80\xbf\x8a\x5f\x21\xd2\x7f\xa3\x1f\xbe\xa5\x5f\x29\xc9\xff\x6f\xf4\x12\x26\x5a\x09\x3e\x59\x63\x9f\xf8\x26\xda\x44\x92\x14\x30\x3f\x0a\x44\x57\x14\x43\x72\x15\xa9\xe5\x59\xac\x5b\xf8\x8e\x5a\xd1\x8e\x47\x77\x3c\x6e\xa4\xcc\xcc\xe3\x86\x1d\xdf\x17\x51\xc3\x1e\xea\x32\x29\xa3\x87\x23\x3e\x1d\x72\xf6\xbe\x11\x92\x66\x55\xe6\xc7\x26\xe6\x09\xaf\x9a\x38\x3b\xb2\x30\xe7\x71\xb3\xcb\xe2\x98\x17\x4d\x76\xdc\xb3\x43\x93\x97\xe5\xa1\xd9\x3f\xe4\x75\x76\xc8\x79\x53\x1e\x78\xd1\x54\x9c\xc5\x65\x91\xbf\x6f\x94\xd2\x24\x6e\x8e\x51\x79\xe0\xb1\x05\xaf\xa8\xe5\x6f\xb7\x4f\x2f\x56\xdb\x6d\xbd\xdd\x56\xdb\x6d\xb1\xdd\x26\x81\x05\xdf\x53\xcb\xf1\xdc\xed\x76\xbb\x5d\x36\xfe\x76\xfb\xb8\x08\x1a\xff\xed\x76\xfb\xb4\x5a\x2d\xb6\xdb\x27\xb6\x0a\xc8\xdc\x82\x1f\xe8\xf7\x1d\x65\xb1\x1e\x2d\xb0\x1e\xff\x64\x11\xf8\x91\x5a\xdb\xad\x6f\xcd\x5f\xcd\xad\xe7\x8e\x35\xff\x7e\x6e\x11\xc7\x73\xd5\xbb\xff\xfc\xed\xb3\x66\xf6\xef\xc0\xa3\x44\xa5\x78\xee\x47\x4e\xdf\xd4\x5b\xf1\xfb\x51\x40\x9e\x93\x8f\x9a\xad\x35\xfe\xb0\xb5\xc4\x97\xad\xd5\x38\xd6\xfc\x87\xb9\x45\x48\xa3\x6a\xd9\x6e\x03\x0b\x7e\xa2\x96\xdb\x37\xb8\xdd\x3a\x8e\xf3\x9f\x57\x4d\x9a\xf1\x17\x87\xf8\xdb\x6d\x10\x34\xd6\xfc\xc7\xb9\x45\x9e\x93\x66\xf9\x9c\x6c\xb7\xa2\x69\xf8\x6f\x2a\x80\x55\x6e\x7b\xe7\xd5\xdc\x9a\x5b\x60\xa5\x16\x81\x9f\xcd\x74\xeb\x2d\xf6\x71\x8e\x15\xbf\x55\x95\x06\x44\xb7\x42\x9e\xcb\x31\xcc\x9f\xa9\xc2\xaf\x27\x0a\x3f\x07\xf9\x63\x11\x78\x33\xf5\xd9\xf1\x6f\xe6\xff\x16\x5d\x7c\x35\xb7\x48\x97\xf5\xef\x83\xac\x54\x67\x7d\xbb\xdd\x06\x1f\x6d\xad\xe0\xb9\x67\xce\x1e\xb6\xfd\x0f\xb3\xc4\x4f\x04\x7e\x19\x37\xf6\xc3\xdc\x7a\x66\x11\xf8\x95\x9e\xbe\xfd\xd2\x1d\x7c\xfb\x93\x9a\x7a\x8b\xc0\x17\xaf\x3e\x7b\xfd\x7a\xf8\x75\xbb\x5d\xf6\xdf\xdf\x7c\xf6\xd7\xe1\x57\xf1\x69\x04\x49\xcf\x2d\x22\x33\x7f\xf6\xe6\xcd\xcf\xee\xa8\x17\x3f\x12\xf8\xe9\xf5\x57\x7f\xff\xf2\xc7\xf1\x87\x9f\x08\x7c\xf1\xcd\xb7\xaf\x46\x5d\x73\x1d\x04\x7e\xd4\x6b\x34\x39\x3b\xd6\x4d\x51\xef\xc4\xff\x85\x78\x21\x0b\x27\x12\x9c\x70\x53\x26\x0b\x81\xdc\x14\xf0\xa8\xd9\xe2\xef\x78\xd1\x94\x71\xdc\x38\x8e\x3f\x5f\x04\x0d\x71\xb6\xdb\xf8\x39\x29\x9a\x1e\x7e\xd5\x07\xf5\xbe\xdd\xc6\x73\xd2\x90\x6e\x6a\x11\x50\xac\x4c\xf0\xe7\x65\x99\x8f\xc6\x2d\xf6\xc5\x77\x73\x8b\x3c\x53\x59\x0a\xce\xe3\xe3\x17\x52\x9f\x34\x1e\x9b\xa8\x4e\x2e\xb3\xdb\xf7\x8a\xdf\x37\x69\xdd\xe4\x72\x44\xfd\x00\x87\x63\x70\x3c\x77\xb1\xdd\xc6\xc4\xc3\xae\x1b\x1d\x73\x3c\xea\xbf\x5d\x04\xcd\x33\xd5\xc5\x16\xfe\x49\xaf\x45\xaf\xb2\xe2\xf0\x50\x2b\x84\xd4\x88\xce\xb0\x8a\xb3\x26\x7c\xa8\xeb\xb2\x20\xcf\xae\x33\xf8\x1f\x7a\xfd\x76\xb7\x8d\xc5\xe3\x33\x7a\xfd\xd6\x7f\x7b\x0a\xe6\xdb\xd3\xf6\xf8\x7c\xeb\x17\xac\xce\xde\xf1\xab\xed\xe3\x35\xfc\x4b\xd6\xf6\x27\xc7\x17\x18\x64\x4e\x1a\x67\xfb\x38\x27\xcd\x76\xa9\x13\xc8\xb3\x6b\x60\x8c\x5e\xfb\xf3\x7f\x07\xd7\x10\x32\x7a\xfd\x51\xb3\xdd\x5e\xa7\x10\xb1\x01\xe4\xe1\x3e\xf4\xb7\xdb\x98\x2d\x92\xe0\xb4\x86\x3f\xb7\x38\x0a\xaf\x91\x43\x24\xcd\x12\x47\x20\x40\x38\x66\x74\x92\xc1\xa2\xd6\xea\xc9\x9a\x87\x8b\x3f\x7f\xfa\xe9\xc7\x7f\xd6\xec\x8e\x60\xd6\xe2\xa6\x89\xbc\xd0\x5d\xdd\xc4\x9e\xa4\xed\xcb\xa4\x2a\xf7\x5f\xec\x58\xf5\x45\x19\x73\x27\x9e\x63\x09\xe2\x4e\x7e\xbc\xb9\x59\xaf\x9a\x4f\x3f\x7d\xf1\x97\x3f\xc3\x7a\xf5\xe2\x63\x3b\x6e\x3e\xfd\xf3\xc7\x2f\x56\x28\xb8\x98\x4c\xcc\xde\x21\xed\xa6\xae\xde\x9f\xbe\x51\x6c\xcc\x57\xf4\x5b\xc9\xb7\xbc\x5b\x22\xf4\x09\xb9\xec\x48\x60\xf8\xf6\x95\x6f\xbe\x6b\x45\x67\x47\xaf\xdb\x88\xd5\xd1\xce\x49\x18\x39\x7d\x43\x4f\x58\xaf\xfb\x95\xca\xe5\x0d\x89\xd4\x5f\xb5\x14\x03\xaa\xd9\x90\x90\x76\x92\xfb\x67\x06\x37\xbd\x79\xdc\x65\x39\x17\xf4\x4b\x31\xd0\xf3\x79\x40\x36\x1d\xf3\x1c\x2d\xd6\x6d\xdb\x76\x1c\x4a\xca\x70\xc2\x63\xe0\xb2\xae\x04\x76\x8a\xde\x97\x48\xe7\x1f\xe1\x49\xb0\xb2\x4e\xe8\x85\xcb\xf2\xb1\xe0\xd5\x97\x8a\xb8\x37\x4d\xe8\xbe\x23\x33\x4a\x0b\xdb\xde\x3b\x21\x81\x50\xb0\x1c\x05\xc4\x62\x6d\xfc\x00\xee\x68\xd8\x8d\xb9\x93\x37\x66\x86\x70\x3e\x63\x4d\xb3\x9e\x51\x7a\x67\xdb\x7f\x91\x3f\x6b\x7c\xd5\x04\x37\x16\xed\xce\xb8\x6d\x1f\x50\x32\x5c\xab\xbc\x4e\x42\xff\xb5\xe4\x4f\x1c\xc5\x5f\x41\xa8\x6f\x69\xe2\xaf\x03\xcc\xf3\x17\x2a\xca\x8b\xa7\x1d\x0d\x97\x29\xaf\x95\xbc\xfd\xf9\xfb\x6f\x63\xe7\x96\xc0\x6c\xd7\x34\xb3\x9d\x21\x54\x0f\xda\xda\x2d\x33\x21\xb3\xdd\x76\x89\x92\xcf\xde\x11\x88\x3b\x99\x71\x34\x09\xb6\x8d\x2d\x0d\xd2\xce\xdb\x25\xb6\x5d\x3b\x21\xec\x88\x6d\xff\x5e\x1b\xa2\xef\x89\xff\x22\xd0\xdf\x35\xe4\xc5\x60\x8e\xe7\xf8\xf9\xfb\x37\x2c\x15\xb2\xb8\x98\x04\xc0\xde\xe3\x3c\x7c\x1c\x10\xdb\x8e\x86\x39\xbf\xc8\xd9\xf1\x28\xf2\xfe\x6e\x9d\x5d\x4e\xd1\x67\x88\x5b\x21\x95\x2f\xef\x8f\x42\x8e\x9c\xdd\x37\xcd\xec\x7e\x59\xf3\x23\x8a\x92\x38\xc7\x47\x5a\xd1\x07\x78\xa4\x21\x3c\x51\xb5\x38\x0c\x04\x73\x7a\xd7\x9f\x2e\xcd\xa8\x02\x83\x73\xc5\x01\x39\x95\x34\x15\xe2\x92\x53\xc9\xc5\xfa\xac\xae\xab\x2c\x7c\xa8\xb9\x63\x65\xb1\x45\x88\x77\xa4\x55\x47\x60\x42\x06\xd6\x76\xfb\xcc\xb6\x88\x1b\x2e\x8f\xe3\xcc\x70\x24\x70\xa4\x96\x9f\xc5\xf4\x23\x6b\x7e\x9c\x5b\x1f\x05\x57\x16\xe4\xb4\xd4\x8c\x9d\xdc\x13\xf9\x62\x41\x4a\x3f\x0f\xe8\x71\x5e\x31\x47\x3c\x91\xcd\x23\x65\x4c\x8f\xcb\xb6\x0f\xcc\x09\x4d\xf8\x68\x1a\x31\xba\x72\x79\x5b\x66\x85\x63\x81\x45\xc4\xa4\x3c\x11\x81\x14\xce\x66\xf3\x71\x89\xc7\x2a\xaf\xd5\x29\xca\x67\x79\xee\x3c\xe1\x3c\xca\x1d\xff\x9e\x9c\xda\x24\x2b\x58\x9e\xbf\x3f\x55\x4d\x13\x2a\x85\xce\x68\xd4\x6d\xdb\xaa\x8a\x33\xa7\xd7\xde\xfc\x0c\xd6\xb3\xb5\xa0\x46\xb8\x51\xfb\xdd\x2b\x18\x69\xa9\xd0\x16\x22\x67\x97\x1c\x3a\x91\xd8\xcf\x9d\x10\x86\x30\x16\xcd\x85\x3c\x73\x23\x24\xaf\x68\xc7\x5f\xe1\xbc\xd8\x76\xcc\x73\x5e\xf3\xab\xd0\x67\xcb\xe3\x2e\x4b\x6a\x87\x04\x10\xfa\x98\x37\xa0\x5c\xf7\x25\xec\x9b\xcc\x98\xa9\x5f\xf2\x1f\x02\x3a\x5b\x01\xeb\xbf\xdf\x32\xf3\xa8\x66\xa4\xf6\x8a\xb3\x77\x16\xd9\xf4\xb3\x37\x9b\x31\x27\x24\x6a\x82\x3a\xad\xc2\x6c\xdd\x4d\x94\xb9\x18\xb6\x1d\x5e\xd6\x87\x41\x48\x85\x80\x6c\x60\xb6\x3b\x36\xc4\x90\x4a\xa6\x6b\x2c\x62\xea\x1b\x24\x60\xf0\xc5\x82\xc4\x4b\x56\xd7\xd5\x37\xac\x88\x73\xee\x47\x3e\x0f\x02\x6a\x0c\x3b\x1f\xd4\x16\x0a\x50\x8f\x69\x64\xdb\x63\x61\x6c\x4d\xa9\x81\xf8\x6c\xdb\xf9\x77\xb8\x3c\x96\x0f\x55\xc4\xbf\x2d\x62\xfe\xd4\x34\x5f\x90\x85\xf3\x6f\x36\x4e\x13\x3b\x38\x1e\x60\xa3\x88\xc8\xae\x45\x34\x5a\x16\xfc\xa9\x7e\x9d\x85\x79\x56\xa4\x02\xe3\x45\x86\x5c\xb2\x58\x77\xea\x11\x6f\xed\x2e\xd6\x7d\x8f\xf7\xe6\x42\xf5\xc7\x50\xdd\x10\x2e\x6c\x4b\x2d\x85\x22\x37\x81\xf2\xa4\x98\x77\x3c\x37\xa4\x94\x19\xf3\x5b\xfc\x5f\xd5\xef\x18\x0d\x34\x8d\x25\xb9\x14\x7c\x23\x17\xda\x2b\xcd\xf6\x32\xe6\x98\x4d\x6a\x30\xa5\xf3\x10\xcc\x4f\x11\xc4\xb2\x3f\x1c\x12\xca\x1c\x3f\x80\x48\x53\xca\x90\x40\x4a\x93\x21\x18\xa4\x8b\x05\x89\x7c\x4e\x13\x3f\x0d\x02\xdb\x76\x04\x14\xd0\x99\x13\x8b\x1f\xf1\x4c\x48\x2b\xfe\x75\x5d\x3a\x0c\xf6\x82\x6d\x4f\x9d\x53\xb3\x49\xbc\x6d\xdb\xac\x8d\x68\xca\x96\x4a\x79\x41\x4f\x2d\x24\xe2\x3d\x3b\xfe\xfa\xfd\xab\x73\x89\x1c\x95\x79\x6c\x4c\x81\x19\xe9\x64\x6d\xd5\x42\x77\xfe\xe9\x59\xdf\xbc\xf9\xfe\xd5\x10\xff\xba\xb3\x75\x0b\x7b\x6c\x95\xd7\xba\x96\x09\xe9\x9f\x43\x4a\x99\x77\xde\x9a\xfb\xae\x3b\xad\x91\x74\x5f\xd0\xdb\xd4\x00\xf6\x74\xdc\x1d\xcf\x29\x68\x0a\x25\x3d\xfb\x00\x5c\xa4\xf1\x84\x3d\xe4\xf5\x3f\x32\xfe\x08\xdc\xb6\xf9\x8c\x52\x01\x2c\x07\xdb\x76\xf8\x92\xc5\xf1\x57\xef\x78\x51\xbf\xca\x8e\x35\x2f\x78\xe5\x9d\x27\x39\xd6\x43\x91\x97\x2c\xb6\x80\x33\x98\xad\x89\xcb\xc5\x16\x66\xd1\x0e\x73\xd9\xf6\xe0\xd5\xb1\xca\xa2\xcf\x4e\x08\x1c\xe8\x2c\x71\x52\x02\x11\xee\x7b\x44\xc1\x47\x7a\x6b\x00\x8f\xa9\x46\x8f\x34\x69\xa4\x56\x66\xc1\x8c\x8d\xe8\x55\xf7\xd9\x22\xad\xa8\x71\x6a\xc9\x2f\xd6\x6d\xaa\xfc\x53\x85\x31\xbf\x28\xf7\x12\x63\x5a\x84\xa8\xe6\xce\x69\xbf\x90\x17\x15\x00\x9f\xb7\xda\x11\x73\xfa\x4c\x92\xb7\xf4\x12\x5b\x20\x4b\x0a\x5e\xe5\x42\x17\xcb\x41\x17\x19\x11\x3c\xcc\x03\xcc\x46\x15\x8a\xba\x9a\x66\x2a\xd5\x79\x18\x77\x53\x34\xe6\x39\xf1\x32\xc9\x8a\x78\xf9\xed\x97\x23\xe5\x4c\x96\x4c\x5a\x7c\x8c\x39\x3a\xe4\x0c\x35\xb2\x19\x31\x5d\xbd\x25\x40\x24\x18\xa2\x9e\x6c\x78\x7e\x14\xb8\x7e\xd0\xb6\x20\x5a\xcf\x6b\x5e\x0d\xdb\xef\xf6\x5b\x47\x7b\x23\x06\x71\x5f\xdd\xe4\x0a\x9e\x33\x2f\x02\x43\xb7\x2d\x71\x1d\x45\x5f\xbb\xa1\xfe\x3f\xd0\xac\x1c\xf2\x45\x5c\xd3\xf5\x44\xd2\xcc\xf3\x34\xd9\xc3\xc1\xfc\xbc\x63\xf9\x03\x57\x7d\x06\xd5\xd7\x37\x9f\xfd\x95\x4e\x43\xb2\x37\xa5\xb8\xfb\xbd\x15\x33\x8a\x5f\x64\x65\x5d\x64\x37\xbd\xf0\x9c\x91\x62\x9d\xee\x77\x52\xa3\x1d\x53\x3f\x50\x47\x4b\x17\x2b\x17\x44\xd5\x7a\x2e\x48\x0c\x23\x27\x4d\x5b\x13\x3c\x66\x20\x82\x6a\x47\x06\x22\x53\x6c\x79\xd4\xcd\x52\xac\x39\xa1\xa4\xd5\xf3\x83\x0a\x93\xf1\x0c\x75\xbb\xca\xb6\x27\xb5\x9b\x87\xf1\xe0\x7b\x9e\xbb\x1f\x22\x54\x62\x38\xf7\xe2\x8f\x64\xc0\xfb\x2d\x3c\x9e\x18\x21\x5b\x38\xa3\x5d\x7b\xbe\x5d\x8b\x82\x57\x82\x1c\x50\xeb\x25\xbb\x92\x3c\xf2\xc3\xdc\xfa\xe8\xe6\xe5\x35\xbb\x79\x29\x15\x06\x7d\xf2\x62\x9b\x04\x1f\x5d\xed\x8f\x2c\xcf\xcb\xc7\x88\x1d\xea\x87\x8a\xd3\x8f\x3e\xba\x79\x59\x1e\xa4\x4e\x5b\x69\x3c\x31\xed\x5a\x26\xde\xbc\xbc\x96\xc9\x37\x16\xb0\xf3\xd5\xb3\xfc\x61\x75\x6f\xe9\x47\x1f\x05\x1d\xee\xb2\xed\x7b\x39\xdd\x96\xff\xfc\xed\xb3\x80\xf6\x3a\xc6\x8f\x9a\xad\xb5\x45\x85\xd2\x64\xa5\xba\x27\x7d\x55\x4d\xa3\xab\xea\xb5\x99\x9e\x8b\xd0\xdd\x48\xa5\xcd\xa5\xba\xb2\xf8\xdf\x54\x0e\x7f\xaa\xb6\x7f\xd3\x0b\xe5\x5c\xa5\x07\x9e\x28\xd3\x7f\x9a\x2c\xc9\xfe\x84\xcd\xcd\x9f\x4f\x14\x5d\xfe\x69\x39\xf7\xe7\xff\x0e\x90\x9a\x8c\x56\x57\xe2\x89\x74\xcc\x59\x4b\x6e\x8a\x6c\xc6\xc2\x91\xd8\x89\x16\x58\x52\xd9\x8c\x5d\x19\x9d\x30\x0f\xb3\x17\x82\x86\x81\xf5\xe5\xa5\x69\x12\xdf\x69\x3c\xb5\x76\x58\x52\xea\xbb\x3a\x75\xf1\xa5\x49\xe3\x05\xaa\xc0\xa7\x26\x4d\x7f\x02\xcb\xd5\x9a\xf2\x0b\xb5\x3c\x07\xf7\xc9\x22\xa0\x4b\xc2\xf2\xb9\x2b\xe6\x8b\x88\x3d\xb3\x17\x02\x05\x3f\xea\xfc\x7a\xff\x1c\x69\xa9\x3f\x35\x4d\xb9\x7c\xe4\xe1\x5d\x56\x7f\x3f\xcc\x2b\x3e\xec\xcb\xdf\x26\x52\xcb\xa9\x9c\xc7\x51\xa2\xd8\x90\xa3\x15\x8b\x96\x71\x76\x8c\xca\xa2\x40\x60\xc5\xfc\xf4\xa8\xce\xbf\x40\x8a\x44\xd0\xbf\xfb\xc7\x99\xd8\x1d\x38\xb6\x4a\x8d\x6d\x46\x2d\xf8\x49\xc0\xc2\x3d\xbd\xef\x26\xde\x50\xb5\xdd\x2b\xf9\xb4\x11\xdc\x42\x45\xab\xa9\x3c\x95\x99\x27\xd4\x33\x52\x2e\xa3\x72\x2f\xa8\xa3\x66\xf3\x7e\x2a\x8f\x99\xe8\x38\x81\x9a\x86\x4d\x63\x64\x2b\x6a\x96\x15\x47\xe2\x4d\xe9\x9f\xfe\x32\x90\x82\x3c\x36\x66\xf7\x5c\x21\x2d\x85\x43\x01\x6e\x63\x1c\xf8\xc4\x4d\x33\x73\x66\xb1\x54\x08\xc5\x86\x41\xca\xcc\x89\xba\xa6\xbd\xfe\xd1\x89\x09\x9a\xa6\x4c\x76\xdd\xb6\xd7\x7f\xb6\x2f\x7e\x45\xfb\xa6\x31\x15\xc9\x12\x27\x54\xf2\x56\x48\x07\x0a\x00\xf1\x05\x49\x86\x36\x47\xd9\x74\x32\x2a\x7c\x4e\x43\xef\xac\x1e\x66\x1e\x1a\xe5\x42\x38\x5e\x6d\xa4\x2e\x73\x76\xb1\x4f\x8b\x59\x78\xe9\x53\x47\x80\xbc\xd8\x75\x62\x3a\x25\x03\x50\x4a\xc7\x7a\xa9\xa6\x09\x89\x77\x79\x0a\x42\xe2\xae\x61\x6d\x8b\x59\x97\x56\x74\x5f\x72\xc1\x27\xf3\x58\xac\xd0\xa5\x42\xd8\x50\xec\x89\xf1\xa5\x4d\x33\xea\x07\xa5\xf4\x9d\x6d\xd7\xce\x3b\x60\xc4\x5b\xac\xdd\x50\xe6\x0a\x2f\xe5\x0a\x89\xb7\x76\xef\xbc\xbf\x39\x77\xc0\xc8\x42\xfc\x84\xc4\x5d\xb9\x9f\xd8\xb1\x28\xbd\x9e\x5a\xa0\x4b\x13\x1b\x75\x26\x04\xfd\xb2\x21\x1f\x60\xbc\xee\xa8\xcf\x02\xc8\xa8\x1f\x06\x52\xab\xd8\x34\xb3\x84\x18\x00\x98\x76\x9d\xf6\xd6\x2e\x17\x2f\xc9\x54\x07\x45\x61\xc1\x27\x75\x65\x95\x5a\x60\x13\x51\xb6\xe9\xe5\x75\x03\x7e\x76\xcb\x87\x42\x2a\x56\x22\x91\x2b\x9c\xce\x95\x99\xb9\x64\x8e\x9d\x1f\x07\x94\xd2\xcc\x8f\x03\x12\xcf\xe7\x3d\x1c\xe4\x0c\xbf\x01\x7e\x71\x55\xb6\x77\xa2\xcb\x99\x7e\x5e\xbb\xab\x16\x52\xe2\x16\x2d\xa4\x4c\x63\xbc\xe9\xe3\x56\xd4\xff\x16\x0f\x79\x2e\xff\x84\xc4\x2c\xd2\xe1\xcf\xb3\xc5\x98\x82\x43\xad\x0b\x66\xa8\x0b\xee\x18\xd9\xbf\x83\x45\x3f\x7a\xb6\x16\x04\x1f\x66\xce\xec\x0c\x39\x37\xcd\xec\xd0\x34\x95\x6d\x57\x12\xd7\x84\xa4\x69\xee\x05\x5d\x51\x6f\x04\xb5\x6d\x72\x0b\x75\x68\x32\x94\x1a\x93\xa6\x99\x40\xae\x02\x38\xe3\x4e\x41\x8b\x7a\xe3\x3e\xa1\xc3\x2d\x9d\xb2\x45\x69\x9f\x38\x39\xb5\xfd\x9c\x84\x50\xc8\x09\xf1\x59\xa0\xa9\xd4\xcd\x0a\xe7\x46\xe3\xa0\xc9\xf9\xfc\x9d\x79\xd1\xc6\xdf\x29\x43\xa1\x73\x54\xc5\x87\x0b\x23\xb0\x73\x3a\x50\x53\x8d\x4c\x0f\x02\x48\x28\xb7\xed\x2f\xe5\x2c\x99\x39\x61\x94\x93\x78\x1c\xf5\xfe\xb3\x83\xe6\x3a\x35\x80\x75\x56\x9a\x89\x97\xb8\xa6\x6c\x2c\xd6\xc9\x1b\xc9\x3a\x21\x71\x9d\x84\x4e\x88\x18\xa1\xa0\x83\xc9\xf2\x78\xe0\x51\x96\x64\x3c\xf6\x12\x29\x63\xb8\xa8\xa4\x13\xe3\x47\x1b\x4d\xfa\x21\x1b\x4d\xeb\xf5\xfb\xa2\x66\x4f\x57\x98\x13\xae\x1e\x8a\x8a\x47\x65\x5a\x64\xbf\xf1\xf8\x8a\x3f\x1d\x2a\x7e\x3c\x66\x65\xe1\x5e\x59\x73\x26\xa7\xf4\xa1\xc8\xee\x1f\xf8\xeb\xb2\x9a\x52\x6a\x18\x22\x02\x6e\xe3\x9c\xce\xa2\x65\xcc\x6b\x1e\xd5\x5f\x3e\x1c\xf2\x2c\x62\x35\x3f\xc2\x1d\x55\x18\xf1\x75\x2d\x78\x0f\x21\x3e\xa1\x01\x81\xb3\x12\x4c\x88\xf8\xe0\x7c\x4e\x20\xd7\x02\x44\x48\x99\x9f\x08\x01\x02\x69\x84\x9f\x04\xb6\x8d\xd6\x31\x48\xb6\x13\x42\x0c\xf5\x22\x53\x06\xca\xa8\x4d\x82\x35\xd1\xc0\x76\x87\x7a\x4b\x60\x2d\x70\x9a\xe2\x4c\xbe\xe1\x4f\x93\x36\x19\xd4\xb2\x10\xd5\x25\x06\xa9\x15\x23\x49\xe4\xf9\x88\x40\x4b\x4d\xf3\x17\xf9\xb3\xc6\x57\x29\x4a\x9f\xd9\x7a\xa1\xc9\x21\x1e\x58\x16\x75\x87\x04\xcd\x44\xb4\xc7\x64\x94\x2d\xf1\x70\x12\x59\xc5\x0d\xdb\x88\x04\x53\x13\x19\xcd\x29\x5a\xc0\xea\xb3\x91\x8f\x65\xd3\x9f\x98\xf8\x51\xf6\xf4\x1f\x62\xe9\x65\xbe\x7e\xde\xf0\x5c\x0a\xeb\x08\x7b\x61\xb4\x85\x58\xea\xa7\x24\x6e\x38\xd2\x93\xa1\xad\x76\x3f\x5d\x81\x64\x7b\x7f\x3a\xf2\x87\xb8\x74\x33\x06\x88\x4c\xdc\x5f\xa1\x07\x75\xf7\xd4\x82\x10\xd0\xc4\x6f\xc5\x73\x3c\xd8\x74\x4f\xd6\x8d\xe5\x9e\xe2\xac\x72\xad\x1e\xed\x5a\xca\x6a\x7e\xb6\x6a\xc1\xba\x9a\xf8\xde\x82\x35\xef\x92\x2b\xfe\x2e\x2b\x1f\x8e\x6a\xf4\x83\xb2\xff\xbe\x94\xa9\x6d\xe1\x50\xf1\xaf\x51\xe0\x77\x4f\x78\x2a\x3e\xa5\x40\xf0\xd7\x01\x15\x7f\x46\xc2\x3f\x30\xff\xe3\x80\x3a\xe2\x6f\xd3\x30\xff\x13\xfc\xfb\x69\xd0\x34\xa6\x75\xa0\xca\x2a\x44\x14\x84\xc1\x17\x02\x06\xb1\xa0\x25\x76\x86\xff\x71\x80\x7a\x7f\xe8\x00\x19\x3e\x21\xad\x3a\x70\xff\x60\x5f\x06\xf8\x02\xac\xa2\xde\xc9\x06\xd6\x41\x57\xd3\xc7\xc4\x53\xbd\xd3\x1b\xda\x61\xfe\x2a\x10\x1d\xff\x24\xa0\x73\x47\xfc\x78\xa2\xcb\xe2\xf1\xcf\x41\xd3\xac\x89\xfb\xe2\xb9\x63\xf1\x77\xbc\x90\x95\x7d\x8c\x26\xb8\x71\xac\xdf\x88\x28\xfb\xa9\x2c\xfb\xff\x0b\xe6\xcc\xff\x3f\x67\x19\x5c\xf1\x63\xdb\xe3\x16\x5b\x6d\x5d\x30\xb5\x73\x66\xa2\x79\xdb\x16\xb3\xa3\x41\xed\xd7\x25\xce\x81\x3a\xfa\x11\x75\x78\x62\x23\xba\x38\x20\x4f\xe4\xa4\xc3\x29\x77\x23\xdb\xfe\x87\xcc\x1e\x09\xa9\x3b\xa4\xa9\x13\xc1\x6c\x45\xe4\x4b\xd4\x5b\xff\x12\xab\x53\x33\x2f\x42\xb2\xd0\xcf\x04\x17\x66\x25\xea\x5d\xf5\x73\x18\x8a\x11\xbf\x08\xb4\x8f\x12\xa6\x98\xab\xf5\x31\x21\xad\x00\x68\x09\x42\x6f\x3e\xfb\xeb\x84\x7f\xc6\x58\x6b\x34\xad\xd1\x97\xba\x0f\xef\xcc\x4a\x6f\x36\x50\xaa\xfc\xc7\xc6\xbf\x6d\xab\x6c\x47\xce\xfb\xf5\xde\x67\x78\x90\xd4\x69\xa5\x9b\xc6\x09\x07\x36\x02\xce\xdb\xce\xfe\x85\xcd\x2d\x69\x18\xd0\x3c\x23\x96\x98\xd4\xf7\x0e\x83\x89\x7e\x85\x72\x0d\x26\xd0\x5a\xd4\x2b\x5f\x8c\x97\xa6\xf9\x7d\x55\xd9\x58\x4d\xa6\x34\xba\x16\xc1\xbd\xd6\x92\x16\x46\x7b\x77\x60\x04\xdb\x25\xeb\xc3\x06\xaa\xe8\xbb\x13\x1b\x2e\x49\xd2\x54\x96\x7b\x42\x9a\x13\xf3\xe6\x86\x9e\xc3\xe7\x02\xa9\x5b\x32\xc1\x13\x9c\x65\xe4\xea\xef\x1e\x9f\xe1\xeb\x5b\xf5\x1a\xd9\xf6\x8a\x52\xca\x3b\x38\x8b\x88\x6b\x3d\xef\x3f\x9a\x1f\x6e\x16\x6b\xd7\x7a\x66\x7e\x93\xe0\xd4\xc3\xa2\x6c\xea\xdf\x2a\x8b\x23\x70\x05\xef\xa0\xe8\xbf\x05\x3a\x24\x88\x37\xc6\x95\x36\x66\x5f\x9b\x86\x77\x70\xaa\x6b\x9e\xaf\xb1\xee\xb9\xb5\xb0\xdc\xd9\x9a\x08\x04\x79\x8e\x6e\xb4\xfb\x8d\xb2\x39\xa0\x88\x5d\x90\x4f\xeb\xc1\x1e\x52\x6a\xe5\xec\x58\x9b\xe9\x8b\x4f\x08\xec\xa8\xa5\x8c\x7e\xb0\x27\x7a\x7a\x05\xc1\x8b\xd5\x14\x79\x13\x0e\x14\x33\x53\x3e\x30\x00\x5e\xf4\x24\x93\xfd\x18\xd8\x39\xd2\x64\x26\xa4\x01\xcb\xa0\x78\xd6\x04\x15\xb8\x1f\x0a\x1a\x15\xdd\x09\x19\x6a\x7a\xb7\xc0\x91\xce\x32\xdb\x9e\xed\x04\xd5\xbe\x47\xe2\x9c\x68\x4e\xe2\x40\x4e\x79\x27\x1d\xe4\x34\xf7\x0f\x81\x90\x3d\x77\x5e\x7e\x79\xeb\x55\x68\x0a\x9a\x8f\x59\xda\xd9\x7a\x53\xd2\x03\xb5\xca\x22\x47\x83\x50\x66\xdb\xb3\xd2\xb6\x07\x23\x69\xbb\xad\x9f\x25\x4e\x49\xfd\xd4\xbb\x37\x88\xbd\x7b\xbf\x14\x33\x8f\xcf\x01\xa4\xb6\x7d\x24\xa7\x3b\x7a\xef\x3f\x04\x4d\xe3\x88\x1f\xf4\x53\xba\xa5\x77\x3e\x0b\xd0\xd8\xa3\xa0\xb7\x02\xb1\x51\xfa\x68\xdb\xb7\xfe\x3a\x80\xfd\x20\xe1\x45\x00\xb9\x60\x63\xef\x0d\xc3\x18\xbf\x08\xba\xd1\xce\xe7\x85\x6d\xe7\xb6\x2d\x46\xdd\x34\xce\x9e\x16\x74\x45\x9a\xa6\x5c\x1e\xca\x83\x83\x46\x1e\xc3\x81\xda\xf6\x7c\xbe\xb7\xed\x1c\x25\xc2\x93\xe8\x05\xf5\x1f\xa1\x80\x7d\xb0\x91\x46\xfa\x1d\x4f\x72\x44\xbf\x2c\x27\x94\x5d\x0f\x55\xd7\x89\xe0\xea\x45\xc7\x64\x17\x89\xe8\xed\x3a\xd8\x18\x0c\xca\x1f\xe9\xd3\x7f\xb8\x38\xaa\xd3\xd8\x25\x27\x97\x1d\xca\x8d\x0e\x89\x21\xec\x03\x02\x72\x54\x43\xbf\x81\xfd\x82\x72\xd8\x4b\x45\xc9\xfe\xbf\x62\x4a\xe9\xca\xb6\xf7\xd7\xf1\x0d\x5d\xb5\xed\x04\xe5\x33\x6c\xbd\x05\x37\x8a\xdc\xd2\x11\x17\x2b\x5e\x1e\x79\x2d\x19\x92\xa3\xcf\x46\xe2\x83\x41\xc7\xad\x87\x42\x1d\x4d\xf2\xf8\x4a\x56\x20\x39\xed\xce\xe8\xdc\x7f\x08\x3c\x94\x00\xb8\x96\x8f\xd6\x9e\x13\x51\x9f\x01\x03\xcb\x82\x30\x00\xb3\xad\x91\xe5\xae\xc3\xc6\xf2\x88\x79\x6c\xcb\x4c\x0b\x7b\x14\x54\x2e\x1c\xd6\xc6\xf4\x6f\x82\x48\xf8\x29\xf2\x1c\x71\x40\x67\x4e\x24\x7e\x30\xa5\x25\x53\x64\x4d\x54\xb7\x82\x48\x7c\xe5\x82\x3d\x93\x73\xe3\x9e\x8a\xb2\x76\xb3\x29\x55\xab\x1f\x80\x72\x23\xde\x9d\x5b\x64\xf4\x07\x04\x62\x3a\x86\x63\x10\x98\xa5\xb3\xaa\x4a\x69\xac\x05\x6d\x0e\x7e\x20\xd0\xd8\xc8\x06\x61\xb7\x58\x10\x27\xa1\xa9\xbf\x0b\x24\xa7\xb0\x13\xc3\x09\xc5\x4f\x42\x86\x83\x01\x0e\x49\x4f\x0f\x91\xa5\x80\x58\xc8\xac\xa2\x7a\x74\x16\xc0\x44\x7c\x9d\x45\x12\x62\xdb\x96\xc0\x8e\x1d\xc7\x63\x9c\x38\xbf\x37\x35\x03\xa1\x21\xfc\xb6\x04\xb4\xec\x7b\xa1\x16\x76\xc6\x89\xc0\x79\xc5\x4e\x68\x8a\x1a\x4d\x13\xca\xf3\x09\x21\xf5\x34\x0d\x4a\x8e\x1d\xcd\x61\x82\xe6\x88\x76\x73\x56\xa4\x17\xda\xfc\x45\x71\x70\x48\xa9\x2f\x01\x30\x96\x47\xf0\x85\xf3\x3e\x8e\x90\xf4\x99\x29\xc3\x26\x2e\xaf\xd0\xea\xe2\xe0\x85\x4b\xac\x69\x6c\xae\xf4\xb4\xcf\x5d\xf1\x41\x74\x60\xfc\x4d\xa6\x77\x56\xe4\x34\x1a\x35\x17\x09\x0c\x2d\x4d\xf6\x7b\x16\x92\x09\xf2\xa9\xa5\xc7\xb1\x4a\x72\x6c\x64\x42\x7a\x95\x64\x4b\xa0\x66\xd5\xc0\x15\xdb\xb4\x11\x2c\x23\x26\x15\xa4\xfd\xb3\xd8\x97\xbb\xc1\x59\xa0\xa4\xb4\x6b\xe9\xd8\x95\xc5\x2d\x54\x65\x39\xe9\xda\xcd\x28\xa5\x65\x0b\x68\xee\x7e\xe9\x7b\xb1\x64\x91\x10\xc0\x94\x1e\xd8\xb6\x9d\x19\x36\xf9\x35\xda\xc8\x37\xfd\xb3\x23\x38\xbe\xd9\x4c\xe0\x05\x54\xfc\xb2\xe5\xae\xe2\x49\xd3\xfc\x9b\x2d\x6b\x16\xa2\x9d\x0c\xba\x0f\xe3\x89\xc0\x34\xbb\xaa\xcf\x0b\xd0\xef\xaa\x05\xfd\xfa\xfb\x99\x57\x2d\xa8\xb3\x9a\x49\xde\xfa\x0f\xda\xc9\x84\xa2\xff\x6c\xa9\x1d\x03\x1a\x4b\x1e\x8d\x19\x9f\xf4\x79\x55\x0b\xfa\x69\xba\x6f\xa6\xc9\x93\xf9\xd6\x55\x80\xd3\x01\x7d\x85\x6a\x10\x7c\x7f\xa8\xdf\x0f\xaa\xfc\x43\x72\x7c\x96\x38\xbd\x42\xe1\xe5\x9f\xa7\x3c\x30\x65\x1f\xa6\xfc\x52\x3b\xea\xb2\xc4\xd6\xd1\x23\x76\xc7\x59\xcc\xab\xa9\xb1\xfd\x8f\xda\xac\xdd\x9c\x92\x16\x70\x02\xa7\x32\xff\x73\x22\xb3\xb4\x13\xfa\xbf\x5c\x26\xc3\xda\x48\x83\x9b\x91\x14\xb6\x80\x96\xdc\xe7\x5e\xaa\xe3\xaa\x2e\xb5\x69\xdb\x96\xa8\xa1\xaf\xdf\xb6\x1d\xc9\xfd\x3b\x21\x1d\x0b\x1a\xc8\xc8\x12\x21\x68\xe8\x32\x63\x55\x9d\x76\xee\x2f\x0d\xfc\xa7\x27\xc9\x5f\x05\x88\x1e\x47\x9f\x0d\x8d\xa4\x1f\x2e\xd6\x22\x0f\xbf\x1f\xe7\xe8\x25\x18\x7f\x75\x13\x79\xd1\x3c\x74\x23\xcc\xf9\x8e\x17\xe7\xb5\x19\x1e\x33\x9b\x10\xdd\x64\xe8\x0b\xc2\xc6\xe7\xe4\xac\x25\x50\xc6\xf1\x87\x8a\xaf\x7f\xa7\x78\x7e\x36\x94\x81\x67\x1f\xed\xfa\xba\x59\x2c\x04\x03\xb4\xd1\xd5\xc4\x83\x6a\xd2\x3f\x5c\xcd\x7c\x1e\xbf\x0c\xa7\x6b\x41\x33\x11\x0d\xe0\x45\xbd\xa3\x06\xb8\xdf\x77\x5e\xcb\xa7\x8a\xc5\x59\xe9\xce\x56\x12\x8d\x84\xe5\x93\x78\x4e\xb2\x9c\x8b\xdf\x03\x3b\x1e\x1f\xcb\x2a\x16\xcf\xd9\x9e\xa5\x22\xb1\x25\x3d\x57\x16\x06\x74\xcf\x9c\x90\xf4\xd5\x1d\x1f\xc2\x7d\x56\x8b\xfc\x15\x3f\xf2\xfa\x3c\x7f\x21\xf3\x6b\x33\xb4\x7b\xe6\x90\x53\x7b\xcf\x8c\x10\x1f\xda\xca\xe4\xd8\xf7\x78\xc0\x8e\xa1\x10\x7e\xcf\x20\x15\xa2\x6a\x5d\xde\xf1\x22\xfb\x8d\xd3\x0b\xce\x82\xbd\x1b\x18\xfd\x4d\x4b\xf4\x59\xe2\x74\x96\xda\xa1\xb7\x72\xef\x3a\x3d\xe9\x66\x47\x19\xba\x40\xc2\xad\x68\x5c\xab\xbf\x34\x97\x43\x4e\xce\x2c\xc2\x90\x03\xaf\xa5\x19\xf7\x8e\xa0\x06\x85\xa3\x2d\xf5\x4e\x55\xc3\xfd\x55\xa0\x45\xd5\xa6\xd9\x11\x50\x4e\x8f\x09\xf5\x03\x22\x88\xe6\x6c\x0d\x0e\xa7\x6f\xba\x2a\xd0\x6f\x91\x6b\x1b\x56\x48\x64\xf6\x93\x54\x3a\x47\xd2\x85\x1c\x2b\x35\x18\xb8\x2b\x3c\x5f\xef\x1b\xed\x84\x63\xb9\x16\xe9\x55\x56\x5c\xe9\x89\x24\x33\x87\xd3\x5f\xfd\x34\xe8\x5a\x6c\x9a\x5b\x3f\x0d\x6c\x5b\x7c\x10\x4f\x0e\x17\x69\xbf\xdf\x8b\x14\xd4\x01\x88\xcb\x2f\xb5\x9e\x25\xce\x2c\x52\xfe\xc6\xdd\x1c\xef\xd4\x77\x77\xe7\xf5\xba\x2f\xe2\xfe\xe6\x30\xc8\x48\x37\xfb\x6d\x0f\x16\x15\xd3\x24\x40\xa2\xc8\x15\x0c\x1c\x05\x2c\x6b\x13\xdd\x84\x9b\x70\x3e\x27\xf1\x1c\x5d\x3e\xa5\x8a\xbe\x37\x79\xe9\xdd\x18\xd9\xd0\x2b\x23\x5c\xc6\x59\x05\x9c\x46\xb6\x6d\xaa\x4b\x85\x7c\x02\x09\x7d\xea\x4f\xab\x42\x49\x79\xbc\x81\xb4\x9d\xf4\xda\xf3\xd0\x8f\x03\x2d\xde\x85\xc6\xb1\x6f\x77\x3a\xc3\x54\x89\x91\xc0\x9e\xca\x9e\x20\x54\x0a\xb9\x29\x41\x80\x4c\xcf\x2b\x9e\xa8\xd9\xb6\x99\xaa\xa3\x3b\xd3\x1d\xaa\xa6\x2f\x77\x4a\x48\xec\x19\x1d\x09\x93\xe0\xec\xe4\x29\x9d\x6d\xef\x3a\x99\x77\xe7\xaf\x03\x53\x0f\x2e\x64\x60\xba\xf3\x5f\x60\x3f\xf1\x9c\xee\x16\x30\xed\xbc\x2f\x86\xc9\x6b\x3d\xb0\x2f\xed\xc5\xac\xc1\x5c\x74\x4a\xa7\x09\x9b\x66\x0c\xcb\xe4\xf3\x40\x65\x9c\x20\xed\x2e\x13\x24\xa4\x6b\xf1\x81\x4d\x60\x4a\xe0\x54\xbb\x6b\x6f\xb8\xf2\xcf\x96\xd2\x81\x1f\x07\x10\x19\xda\xfb\xae\x9e\x77\xcc\x54\xf2\xe8\xba\x84\x18\xe4\x07\xb0\xa3\x2b\xc8\x7a\x50\xbc\xa5\xd2\xb5\x39\xec\xa2\x9c\x38\x09\x65\x4a\x0c\x12\xb8\x22\x72\x12\xac\x47\xbc\xa7\xfa\x6c\x05\x6e\xd1\x9c\x40\x7a\x4f\x18\x61\x44\xba\x2e\x3c\x1a\x5d\x30\xc4\xa5\xd8\xb6\x67\x42\x58\xb3\x6d\x27\xa6\x8f\xcc\x89\x09\x01\x6e\xdb\x33\x2e\xd3\xb8\x48\x13\xf9\xc9\xc0\x90\x58\xe1\xc0\x81\x9e\x88\xa2\xe2\xc3\x0f\xd0\xbe\x55\x8d\xe5\x40\x93\xa6\x79\x60\x4e\xd8\x34\xd6\x73\x0b\x76\xbd\x4d\x84\xbf\x0b\xdc\x1d\x4a\x7e\xf7\x74\xc6\x9a\x66\x96\xd8\x76\xe8\x1d\xdc\x77\xcc\x39\xc0\x1e\x18\x56\x0f\x15\x8d\x3c\xde\x34\x4e\xe2\x31\xb7\x6c\x9a\x98\x78\x7e\xe0\xa6\xee\x3d\x5a\x84\xdb\x76\xe4\xdc\x43\x25\x73\xc6\xe4\x74\x4b\xdf\x31\xa7\x82\x82\x40\xec\xdc\x82\x98\x58\xf1\xe1\x8e\xde\x0e\x01\xe1\x4e\x08\x96\x39\xbd\xf5\xef\x70\x46\x2b\xbf\xf0\xef\x02\x21\x5b\xde\xab\xa7\x9c\xa0\x5b\x83\x3c\x2e\x12\xbc\xb7\x7c\x10\x0d\xa0\x23\x4f\x35\x59\x5f\x25\xeb\xbb\x95\x6b\x70\xef\xdf\x89\x8a\x36\x1c\x39\x1d\x69\xc1\x76\x0b\x19\x69\x7f\xa7\xb8\x73\x4b\xb9\xf7\x37\x27\x81\x9c\xb8\x7b\x91\x74\xb3\x58\xdb\xb6\x93\xf8\xb7\xa2\x87\xa9\xf8\x11\xdd\x93\x3b\xb4\xc2\x01\xe3\x29\x7d\xa5\x8f\xd3\x4a\xd0\xf5\x13\xb7\x22\xc0\x3d\xd5\x83\x14\x2a\xc8\x88\xab\xdd\x33\x52\xa8\x06\xa6\xdb\x4f\x43\xe4\x08\x48\xe8\xcc\xb8\x14\xf1\x52\x1f\x1e\xf9\xa8\xaf\x17\xb8\x5b\x80\x6e\xda\x34\xc6\x27\x41\x0b\x21\x43\xab\x81\x15\xdc\xd1\xe3\x05\xb1\x18\xb9\xca\x1d\xcc\x56\x04\xf2\x0b\x99\xfe\xe6\x84\x20\xe5\x5d\x95\x71\x4f\x7d\x53\x21\xd2\xef\xf3\x59\x2a\x60\xb7\x69\xa2\x19\xa5\xb7\x82\xe4\x38\x21\x8d\x48\x0f\x69\x77\x2a\xbb\x9b\xab\x87\x3e\x2a\x96\x54\x09\xf0\x36\xd8\x24\x37\xd9\x26\x93\x9e\xce\xd1\x70\xac\x99\x1a\x2b\xd9\x53\xff\xc8\x9c\x9a\x39\x7b\x02\x11\x91\xea\xb1\x93\xca\x2f\x89\xa2\x91\x5b\x4d\xb3\x3c\xcb\x14\xa9\x8a\xc8\x11\x88\xfc\x87\x40\xce\x34\xa7\xf3\x79\x36\x08\xb7\x61\xb6\xcb\x75\xbb\x03\xcd\xd7\x23\x73\xb2\x9b\xb5\x6d\xcb\x6e\xe0\xa3\xa0\x6b\x9d\x9e\x38\x5b\xac\x89\x0e\x2a\xa0\xe8\xac\x75\x25\x0f\x8b\xb2\xc5\x0b\x59\xa5\x67\x3d\xb7\x5c\xcb\x6a\x8d\xb0\x41\xda\xa1\x26\x02\x7e\x93\xd9\xf6\x53\x5f\x65\x26\x10\x0d\x24\x37\x5c\xa6\x76\xaa\xe7\x2e\x15\xc9\x2a\x69\xf7\x9a\x77\xd5\x14\x1a\x7b\xd8\x03\xd8\xfb\xa1\xc3\x48\xa7\x46\x31\x9c\x4f\x6e\x56\x66\xd0\x04\xcd\x66\xdd\xc9\x32\x39\xec\x51\x0d\xbd\x82\x7b\x6a\xad\x2c\xa8\x68\x62\xdb\x7e\x00\x47\xb1\xb3\x6a\x7a\x0b\x0f\x02\xd5\xa0\xad\xaa\x36\xd7\x75\x04\xca\xb9\x23\xf0\x8e\x3e\xce\xa9\x14\x38\x6a\x6f\xed\x0e\x22\x27\x35\xcd\x72\x0d\x4f\xf4\x41\xef\x49\xb1\x2e\x77\x32\x78\x95\x34\x35\x48\xc9\xe6\x7e\x46\xe9\x93\x6d\xab\x40\x53\x39\x7d\xf0\xef\x03\xb2\xb9\x9f\xcf\x25\x5e\xb0\xed\x9c\x9c\xf6\x9d\xa3\x61\x49\x99\xbf\x9f\xcf\x91\x64\x96\x8e\xd8\x78\x3b\x42\x4e\x8a\x5f\xcb\x89\xd2\xc8\x8a\x36\x1e\xe9\x3b\xd2\x46\xa8\xfe\xa4\xb3\x52\x54\x63\xdb\x87\xc5\x02\x12\xdb\xae\x74\x76\xc4\x44\x87\x39\xbd\x87\xc8\xb6\x45\x47\x0e\xc3\xb6\x42\xd9\x56\xe9\x54\x70\xc4\xa6\xfa\x13\xf0\xc3\xcd\x4a\xd9\x70\xdd\x2f\x16\xa4\xf2\xef\x83\xa6\x39\xe2\x5f\x47\xfc\xd0\xaf\xa5\x59\x44\x46\xc8\xe6\x28\x10\xc9\x91\xb4\x1a\x3b\x64\x70\x24\x70\x67\xdb\x02\x29\x1f\xbb\xd5\xb1\xed\x43\x17\xa7\x44\x00\xde\xc0\xc4\xc0\xc9\xfa\x23\x7c\x39\x36\xb8\xa5\x35\x81\xaa\xed\xc8\x21\xea\x03\x89\x9b\xe8\x7c\x3b\x9a\x4a\x9b\xac\x2c\x9f\xe6\xb5\x95\x8d\x02\x46\x2e\xf9\xcc\xe0\xb4\x67\x09\x39\xc9\xb3\xb3\x14\x1d\xfe\x7a\x78\xd2\xe6\x44\x8b\x05\x49\xe8\x13\x73\x42\x3f\x0a\x08\x24\xfe\x43\xe0\x75\x56\x08\x2e\xd7\x4f\x9b\x84\x7e\xe6\x30\x78\x2f\x28\x9c\xa0\x7b\x49\x77\xd0\x4e\x99\x61\xe0\x9c\xf5\x47\xf0\x43\xb7\x5c\xa4\xa3\xa2\xab\x46\x4c\x08\x3a\x15\x64\xc9\xb6\x19\x94\x54\xcc\x66\xea\x30\x5a\x74\xcd\x08\xda\x22\x6d\xa8\x38\x9e\x1b\x08\x16\x4b\xfb\xe8\xe1\x1a\xde\xd2\x52\xf0\x50\xa5\x71\x42\x4a\x40\xd3\xb3\x9b\x17\xb6\x6d\x7d\xfb\xa5\xd8\xdd\xce\x1d\x1e\x30\x10\x25\x5e\x77\x4e\x05\xd2\x27\xc5\x74\xc0\x3a\x88\x1d\xd2\xa1\x99\x5b\x3c\xd9\x46\x34\x83\x46\x7f\xb4\x77\x42\x70\xee\x34\xce\x32\xc5\x04\xa5\xc6\x0c\x89\xe8\x2f\xf1\x57\x01\xcc\x3a\x23\x34\xbe\x29\xf0\xe8\x77\xa0\x9d\x83\x1e\x65\xdc\x6a\x41\x40\x32\xd6\x7a\x9c\x6d\x46\x7f\x5d\x9a\x4e\xe3\xda\xfd\xd0\x5b\xb9\x23\xd2\x9d\x2d\x16\xd8\x4f\x31\xda\x2c\x00\x63\x20\x39\xbd\x1b\xa0\x4b\xc1\xeb\xee\xa9\x1c\x8c\x9f\x23\x65\x4d\xe8\xfe\x83\x63\xd2\x7e\x8f\xb7\x9a\xbc\x4d\xfb\x3f\x2a\x6f\xcf\x5b\x4d\x70\x33\x58\x8b\x41\x26\x9d\x91\x69\xc5\xd0\xb7\x96\x8d\xfd\x4b\x05\xb4\x00\xd7\x27\x32\x0a\xbe\x9c\xa2\x69\x76\x0e\x83\x92\x10\x27\x41\x03\x24\xe0\xf0\x3b\x1e\x98\x04\x78\x0b\xa6\x59\x0e\x7d\xd0\xde\x7c\x16\xd1\x46\x39\xca\xbc\x15\x5d\x2f\x1e\xe0\xdc\xb4\x87\xce\x66\x39\xec\x1d\x02\x43\x8b\xc7\x0b\x2e\x2f\xeb\x0f\x18\x90\x4e\x7b\x35\x4e\x98\x6a\x77\x8c\xfb\xd0\x00\x7f\x57\xf1\x84\x7e\xf4\x27\x69\x7e\x6f\x81\xf5\x27\xa9\x28\xea\x75\x74\x23\x0d\x91\xc8\x2f\x24\xd5\xa6\xb9\x63\x52\x5f\xd4\xa0\x6e\x74\xc7\xb3\x74\x57\x37\x8f\x59\x5c\xef\x2c\xb8\x70\x36\x1d\x79\xd2\xa0\xcb\x1d\x5b\x6e\x81\xd5\x1d\xa1\x0e\xf5\x4d\xde\xda\x7d\x21\xbd\x98\x7a\xdb\xaf\x33\x9b\xe6\xc9\xa1\xa1\x62\xec\x1a\x5d\x00\x8c\xc1\x0c\x0d\xcc\x71\x27\x58\x18\xb0\xcf\xfa\x9d\x71\xcb\xac\xdd\xc0\x55\xc9\x4b\xe3\x6c\x1a\xa5\x98\x9b\x5d\x56\xcc\xf5\x73\xa1\x5d\xcf\xd0\x30\xe9\xd2\xc2\xa9\x90\x5c\xa3\x6e\xf5\x66\xe9\xaa\x67\xdf\x9d\xf5\x09\xe5\xa6\xcd\xd9\x0a\xf8\x61\x80\x9a\x5a\x6f\x34\xe3\xae\x13\x5f\xb4\xa1\x8b\x0d\x1b\xba\xd8\xb4\xa1\x23\x90\xb2\xd6\x61\x64\x53\xe0\x9e\xa7\x35\xc6\x4f\x3c\x54\xb4\xee\xad\xa7\x54\x92\x6f\xb9\x96\x8c\xc7\x78\xa8\x3a\x6d\x50\xa1\x68\x19\xad\x0d\xa2\x06\x85\x0c\x47\x57\x6b\x3b\x34\x0c\xfe\xf4\xeb\xf7\xaf\xbe\x2c\x23\x5a\xcb\x47\x28\x7a\x13\xc8\xba\x7b\x44\xeb\xc4\x07\xdd\x08\x22\x9d\x01\x8e\x83\x77\xf4\xfa\xed\x4b\x0c\x25\xb1\x3d\x3e\xdf\x5e\x7b\x37\x8e\xe7\xbe\xdc\x5e\x6f\xd7\x37\x0d\x79\x76\x0d\x8f\xf4\xfa\xed\xd2\x7f\xeb\xfe\x69\xeb\x6f\x97\x10\x3c\x7f\x76\xdd\x2b\x32\x9e\xf4\xbc\x66\x89\x33\x08\x46\x15\x76\xe7\x2a\xc5\x32\xad\xf8\x61\x60\x30\x22\x18\x66\x7d\xf6\xaf\xe3\xb3\x41\x0c\x68\x52\x19\xb5\x48\x86\xc2\x33\x6b\xd0\x89\x7a\x86\x6c\x7c\x5f\xf8\x3c\x76\x16\x76\xf0\xb1\xb3\x5b\xed\xaa\x94\xcc\xb2\x8a\x8c\xb6\x09\xa9\x99\xd2\x31\x11\x1f\x6a\xb9\x0f\xad\x46\x6e\xe8\x4a\x76\xa1\xd5\xb5\x5c\x88\x9c\x11\xfa\xab\xc0\x38\xd7\x71\x18\xb5\xdc\xa2\xac\x1d\x34\xb4\x21\x16\x01\xa9\xde\xd0\x48\x1c\xcd\x27\x7a\x19\x42\x02\xd5\xd8\x54\x17\xed\x59\x3c\x3f\x0e\x5c\x3f\x70\x87\x59\x1c\x06\x6a\x04\xe1\xd4\x08\x86\x6e\xd2\x18\xf2\xd6\x08\xcf\xea\x9c\xd0\x60\x6f\xca\x72\xcb\x0c\x3d\xab\xd8\x23\x91\x64\x2e\x40\x6f\xd3\xa3\xa7\x7c\x1c\x8e\xd7\x61\x44\x4f\xb9\xa1\x41\x47\x7d\x2b\x5d\x75\x5a\x30\x84\xae\xce\xc3\x80\xfb\x61\x00\x18\x8e\xb8\x57\xcd\x28\xc5\xa0\x59\x48\xce\x82\xc3\x00\xf3\xf7\xca\xe3\x98\x9e\x85\xc4\x5d\x7b\x7a\xcf\x39\x31\x71\x63\x82\x0a\x59\xc5\x7e\x61\x66\xfd\xe6\x0d\xde\xe6\x68\xc7\xe7\x32\x88\x3b\x33\xb0\x89\x09\x1e\xb5\xf6\xa4\x42\x04\x23\x97\x35\x5b\xe3\x7c\x4f\x9f\xe2\x7d\xb0\xe0\x8a\x60\x80\xd3\xa9\x83\x9f\x99\xca\x79\x6e\x87\x65\xdb\x0f\x1d\x47\x23\x4a\xb8\x5d\x2f\xb4\x17\x68\x2b\x8d\x99\xdf\xc3\x6f\x32\xd6\xcc\xf6\xf8\xdc\x79\xe9\x6f\x1f\xb7\xbf\x04\xf3\x1b\xe2\xbf\xbd\x09\x9e\x37\x2a\xfe\xcc\x73\x0c\x37\xf3\x19\xed\xc2\x67\x4f\x33\xce\xc8\x25\x0f\xd6\x7f\x72\x8b\x4a\xcd\x46\x44\xad\x97\x52\x44\x5c\x05\xb6\x6d\xdd\xc8\x67\x2d\x95\x2d\xd6\x41\x1f\x9f\xed\x86\x7e\xec\xf9\x52\xa8\xc5\xd3\xf5\xc0\xfd\x4d\x07\x1f\x81\x59\xd4\x34\xb3\xc8\x17\xd9\x35\x4b\x38\x0b\x9b\x26\x5c\xca\xf0\xda\x9e\x13\x36\xcd\x7b\xa2\xe0\x83\xb8\x67\x31\x8d\xc3\xee\x1b\x6a\x77\x74\x10\x93\x90\x86\x57\x59\x71\xac\x59\x11\x89\x2e\x17\x9e\xd8\xc9\x6e\x08\x66\xdc\x6b\x28\x96\x18\x00\x56\x10\x5e\x2c\x09\xa1\x36\x3b\xc2\xed\x3b\x11\xab\x25\xc7\xd5\x84\x77\xca\x82\x51\xb4\x76\x1e\xc0\x37\x94\x71\x84\xa3\xab\xac\xb8\x0a\xc9\x00\xd7\xaa\x38\xce\xc4\x53\x0f\x52\xd4\x90\xa3\x42\x5b\xb7\x08\x30\xc5\x8c\x08\xdd\x76\x9b\x21\x1f\x3b\xe8\x46\xfe\x8b\x80\x40\x8c\xae\x96\xc6\x71\xa7\x63\xec\x77\xba\xc6\xfd\x27\xe4\x81\x98\x80\x19\xb5\x9b\xe6\x30\xd8\x22\x94\x81\xd9\x9c\xe1\x89\xe4\x0c\x8a\xe9\xea\x64\xf6\x61\x33\xc4\x1d\xc7\x39\x9c\x32\x1b\x7c\xbf\xac\x38\x8b\xdf\x7b\xea\x17\xa1\xdb\x29\x88\xeb\x74\x66\xf3\xbd\xf1\xb2\x1e\x4d\xdf\xcb\xee\x71\x38\x1a\xa6\x9f\x88\x58\x64\x1d\xe6\xd3\x61\x0a\xfd\xb4\x9b\xcf\x8c\x93\x1d\xb1\x11\xe0\x3d\x2d\x84\x68\x2d\x80\xff\x73\xb9\x85\xe4\x24\x1e\x9b\x43\xc5\xdf\x39\x9e\xfb\xf7\xa2\xce\xf2\x06\x1d\x44\xaf\xe1\x0b\x7a\x42\xbb\xab\x8a\x17\x78\x48\x25\x2d\x2f\x8e\xe2\xb9\xe0\x4f\x78\xd0\x24\x8a\xb9\xb3\x55\xbb\xe9\x51\x72\x9c\x55\xd3\x51\x2f\x25\x16\xee\x06\x1c\x69\x33\x05\x86\x87\x08\x44\x86\xf3\xe9\xd7\x40\xab\xd2\x8d\x14\xa5\x46\x40\xbc\x9c\x1d\x9d\x48\x5b\x3b\x29\x91\xb5\x27\x8a\x71\x0b\x47\x79\x4a\x7d\x31\x92\xa8\x1f\x4c\x1c\x69\x8f\xa3\x72\xb0\x19\x1e\xfc\x46\xba\xfe\x5e\x63\x8d\x31\x23\x0d\x42\xb4\x63\xc7\xa9\x98\xf3\x7a\x31\x4c\xd1\xdb\x44\xa0\xd3\xd4\x45\x46\x66\x11\xc4\x82\x6d\xd8\x19\x85\x91\x61\xe9\x7d\x16\x98\x14\xa6\x85\x28\x2f\x8f\xdc\x0c\xd4\x3e\x1c\xb0\xf2\x76\x32\xe9\x62\x22\x56\x24\xa5\x1d\xd6\x6d\x9a\x73\xd2\xe8\x61\x3d\x7d\x64\x75\x04\x37\x77\xd5\xe9\xf3\x71\xdb\xcb\x0d\x12\x07\x9b\xc8\xb6\x23\x31\x65\x9b\xb1\x9f\x52\xe2\xf4\x6e\xd2\x2f\xd7\x6b\xdb\x76\x52\x2f\x95\x66\x2b\xca\x42\x74\xec\x4a\x7d\x81\x93\xc0\x00\xb3\xe4\x94\x74\x27\xc0\x83\xd3\xae\x11\x51\x4a\xfa\xa3\x8f\x8e\x84\x26\xc4\x4d\xd0\x7a\x20\xe6\x4f\x93\x66\x14\xde\x44\x90\x5b\xc5\x48\x15\xe8\x8b\x23\x91\x01\xd1\x81\x6b\x25\xdd\xd3\xc8\x5b\xd0\x06\x57\x61\x6d\x24\x13\xea\xc1\x0c\x25\xa0\x56\xbe\x3a\x0a\x11\x5f\xec\xa0\xcf\xf2\xdc\xd1\x44\xce\x5d\xac\x5b\x60\x71\x3c\x1d\x59\xf9\xec\xc2\x00\x35\xaa\xc1\xe5\x06\x29\xaf\x1d\x02\xb2\x20\x06\x48\x65\x71\xfc\xf9\xf8\x52\x04\xb3\x42\x16\xc7\x8e\x8e\x23\x3c\x8a\xa9\xef\x8e\xde\x35\xc4\x32\x42\x5a\x33\x62\xe9\x97\xb2\x9b\xe3\x2d\xbd\x1e\x6e\xe9\xfe\x88\x5c\x05\x5c\x3d\x4d\x58\x88\x68\xc3\x8c\x73\x97\xcf\x50\xb9\x65\x99\x14\x4b\x79\x06\x29\x3c\x36\x19\x21\x79\x19\x67\x95\xc3\xc0\x3c\x72\x24\x5d\x09\xc4\x78\x17\xc3\x14\x4f\x14\xc5\x28\xc5\xc5\xd8\xd2\x43\x15\x10\xd3\x30\x30\x98\x25\xad\xc4\x91\x97\xf2\x8e\x0d\x83\x55\xdd\x9f\xe5\xf9\x07\x87\x32\xd1\xc4\xef\x15\xb9\xd0\xd2\x1f\x1b\xbf\xd9\x1e\x4e\x80\xa8\xed\x0f\x4e\xdd\xd8\xf4\x59\x14\x57\xd8\xf9\xc2\x7a\xa9\xaf\x8e\x63\x02\x41\xd3\x9c\x5a\x62\x48\xfd\x42\x06\x82\x8e\x3e\x7d\xb0\x1e\x53\x59\x20\x0a\x69\x42\x36\xa9\x99\x50\x5f\x7b\x1e\x48\xef\x2d\x3f\x00\x66\x46\xec\x6b\xdb\x51\x90\x5f\x41\x10\x7c\x16\xf4\x9c\xa6\x71\xf8\x62\x5c\xed\x11\xf6\x47\x9f\x16\x4e\xe1\xc0\x52\xfd\x53\x82\x27\x8c\x11\x32\x39\x67\xa8\x28\xc6\xa3\xc6\x4e\x10\xc4\xd3\x4d\x93\x29\xb9\x11\xa8\xf5\x0b\xb4\xd8\xed\x70\x03\x27\xf0\x79\xaf\x27\xe3\xcb\x8a\xbf\xe3\x15\x5a\x08\xc1\x08\x9d\x70\xa2\x59\xec\xaf\xe8\xf5\xf6\xf5\xfc\x3a\x85\xaf\xe9\xc9\x30\x0d\xf8\x6b\xbf\x3f\xbf\x16\x23\x3d\x75\x4a\x6b\xb5\x9f\x95\x0b\xa8\xf3\x15\xea\x3d\x61\x68\x99\x2b\xf8\x3c\x2a\x88\x15\x84\x6d\xb1\xfc\x82\xe5\x79\xc8\xa2\xbb\xe3\xc0\x67\x8d\xd1\x09\xf4\xfb\x35\x0e\x48\x34\xee\xf6\x14\xb7\x05\xe5\xdb\x38\x08\x3b\x2c\x48\x5a\x46\x67\x6c\x59\x16\x11\xc7\x83\x8f\xdb\xbe\xfe\x5c\x0b\x6f\x6c\xb9\xe7\xfb\xb2\x7a\x6f\xdb\x39\x44\x74\xb6\x82\x94\xf2\xa6\x59\x29\x3f\xbf\x5d\x2f\x38\xce\x56\x9b\x9d\x6d\x27\x37\xe9\x26\x95\x74\x78\xe7\xa7\xfa\xcc\x2a\xf7\x57\x01\xe4\x82\x21\x46\xcb\x41\xf4\xf9\xab\xcb\xc3\x8f\xc5\xd7\x2c\x3f\x72\x72\x0a\xe9\x6c\xad\xc8\x53\x4c\x67\x6b\xd8\xd9\xb6\x93\x79\x59\x27\x3a\xdf\x3a\x99\x56\xf4\x12\x37\xf4\x44\xd7\xdd\x3b\x6d\x60\x88\xf6\x5b\x77\xf4\x34\xa0\x04\x32\x44\xa1\x3e\x1b\xd2\xdd\xdc\x74\x57\x37\x5d\xa5\x0e\x82\x21\x2e\x45\x38\xba\x43\x46\xf2\x60\x2a\x6a\x74\x44\x36\x83\x78\xd1\xb1\xa7\xcf\x28\x6c\xfb\x6e\xb9\x63\x82\xb9\x6a\x9a\x9d\xa6\xb2\x2e\x5a\x78\xea\x8e\xf7\x5c\x02\x8d\x6d\x3b\x75\x22\xd2\x92\xd6\x88\xc9\x0d\xb1\xd7\x4f\xa2\x1b\x22\xc8\x46\x70\x8b\x61\x28\x4d\x2e\x1f\x64\x28\xb6\x89\x8b\x5d\x76\x82\xfe\x4b\x80\xea\x42\x85\x4f\xc8\x6f\x9a\x83\x8c\xa8\x90\xf1\x24\xf7\x1b\xc2\x0e\x22\x22\x58\x0a\xb2\xd3\xaa\xe7\x08\xd6\xb8\x9d\x9c\xe4\x86\x46\xb6\x9d\x2c\x16\x90\xe2\x53\xba\x58\x90\x56\x6e\x83\x16\xc6\x2c\x5c\xc7\x10\xf4\x95\x33\xd8\x21\xb3\x32\x73\x54\x48\x48\xad\x9a\x1f\xdb\x50\xf6\x23\xd1\xf1\xe4\x65\x1b\x6a\x75\x27\x33\x66\x34\x54\xdc\xf1\x30\xf3\xc4\xcd\x37\xb3\x5d\x0b\x79\x69\x52\xf4\x3e\xc2\x99\xae\x23\x6c\x1a\x03\x9a\x54\x95\xa2\xd0\x64\x85\x19\x5a\x0b\xf2\x5f\xb2\x7a\xfa\x4e\x23\x31\xde\xc8\xb6\x67\x19\x1e\x27\xe1\xad\x01\x10\x52\x9f\x41\x28\x11\x97\xa7\x7e\x1d\xe2\x86\x01\xc4\x9e\x3a\xc7\x0b\x89\x8b\xeb\xae\x9a\x17\x4d\x4c\xf4\xf9\x6e\xa9\xdb\x1e\xdf\x50\x64\x94\x9b\xea\xf5\x2c\x6a\x3b\x0c\x74\x67\xde\x04\xf3\x25\x4f\x78\x55\x4d\x1a\xe6\xfa\xbe\x55\xf1\x63\x99\xbf\xe3\x16\x58\x71\x59\x70\x0b\x0c\x64\xe4\x58\x02\x71\x5c\x49\xf4\x60\x11\xd0\x79\x63\x2b\x00\x51\x10\xa3\x53\x82\x95\xb0\x2c\xff\xbd\x72\xb7\x68\x63\x8b\xe5\x8a\xb2\xce\x92\xf7\x96\x20\x86\x65\x5a\xf1\xe3\x71\x54\x56\x17\x0b\x02\x88\xa8\x75\xe0\x45\x8c\x94\x32\xa6\xa7\x63\xcd\xea\xa9\x29\x8b\x5a\x60\xf9\x23\x7b\x7f\x9c\xf8\xc6\x97\x62\x58\xc6\x86\x5c\x8a\xee\x3a\x67\xb3\x5a\xef\x4c\xc2\xa9\x03\x42\x76\xd9\x7a\xd4\xae\x67\xd3\x08\x90\x37\x8d\x66\xd4\x31\x5f\x4a\x87\x32\xb1\xe4\x05\xc5\xcf\x86\xfb\x89\xbf\x0e\x02\xe7\xac\xd9\xd4\xb6\xd3\xe9\x5b\xaa\x36\x4c\x2a\x1c\xfa\xfa\x84\x58\xbb\xcf\x8e\x9c\x78\xdd\xa3\x43\xe4\xa0\xa3\xa5\x5a\x30\x35\x68\xf1\x2e\x16\x42\x30\xda\x72\xea\x51\x12\x11\xcb\x41\xdc\xc8\x4f\xfc\x55\x30\xb7\x04\xe4\x59\x01\xb6\x8b\xb8\x30\xea\x6b\x95\x37\xc4\xa5\xf2\x9a\x8b\xae\x4b\xad\xc0\x1a\x4c\x46\x8e\x24\x7d\x66\xc1\x16\xe1\xe3\x87\x6e\x34\xeb\x80\x94\x41\x4c\xdc\xb8\x6d\x81\x1b\x74\x34\x5e\x1e\x32\xb4\xc3\x14\x8b\x03\xe7\x73\xcc\xfa\x39\x4e\xfc\x17\x01\xec\x30\x7a\xeb\x26\x96\xd3\x4a\x53\xc1\xcb\x0b\x4a\x83\x0f\xe6\x2c\x47\x74\xd7\x42\xe8\xaf\xdf\xb2\xc0\x7f\x11\x68\xc4\x00\xa1\xff\x02\xdf\x05\x62\x20\xc0\x71\x42\x82\x89\x1b\x19\xf8\xe4\x54\x71\x2f\x76\xa7\x77\xec\x30\x3f\x4d\xbb\x1d\x8e\x81\xc2\xf4\x8c\x71\xbc\x05\x47\x5d\x6b\xc6\x81\xe3\x89\xdd\xe3\x8e\x4f\x59\x6a\xaf\x20\x3a\xbb\x3f\x82\xe0\xd5\x7c\x9d\x38\x2b\x64\x03\xde\x34\x1f\x80\x17\xee\x0a\x5a\x8f\x4e\xee\x1e\x73\x0d\xc8\x26\x62\x26\xa7\x39\xd9\x2e\x59\xd0\x74\xc1\xf5\xe0\x88\x23\xf1\x34\xbe\xea\xeb\x66\xed\x9d\x75\xd1\xe5\xe8\xab\x91\x79\xa9\x82\x3b\xc4\x73\xa2\x01\x77\xb1\x48\x9a\x26\xd5\x10\xdb\xa5\xb7\xad\xb4\x9a\xc5\x13\xef\x9b\x35\xca\xd8\x19\x5a\xde\x4a\x2a\xc4\x09\xdc\x0e\x5f\xef\x06\xaf\x1b\xae\x94\xcc\x91\x1f\x06\xa3\xb9\x10\x49\xfd\x74\x98\x6f\x7a\x07\x89\x3e\xdc\x09\x12\x2a\x37\x50\x7a\xbe\x81\x44\x8e\x5b\xc8\x08\x0e\xa0\x8b\x34\x37\x1e\x89\xa8\x03\x52\x63\x73\x28\xd6\xf2\x1b\xbc\x58\x50\xea\xc1\xe8\x24\xdb\x8e\x9f\xc6\xdd\x62\x1a\xb2\x7a\x24\xdf\xdd\xdc\xb5\x06\x2c\xf2\x0b\xcb\x6a\x77\x0d\xbb\x32\x8f\xe5\x87\x01\x63\xe9\xa9\x8a\x45\xae\xf9\xdc\x55\x6f\xce\x6c\x45\x5a\x59\x7c\x90\x1d\xc3\xc6\xcc\x56\xde\x62\x61\x14\x43\x55\x1f\x56\x4d\x9a\xc6\xe9\x5e\x30\x92\xed\x4c\x64\xb7\xed\x41\xfe\x9b\x55\xd3\x38\xdf\x0c\x66\x25\x07\xbf\x08\x94\xee\xa8\xae\xb2\x34\xe5\x2a\xfc\x40\x65\xdb\x8e\xe0\x50\x47\xa9\x8e\x85\xb5\x59\x42\x9e\xcf\xc9\xb2\x4c\x92\x2e\x85\x8c\x44\xf0\x6f\x1d\x72\xca\x55\x78\xdb\x51\xbc\xcb\x2f\x7f\xfc\x5e\xf9\x4d\xbd\x2a\x59\xcc\x63\x0b\xbe\x85\xd9\x9a\x00\x9b\xce\x2e\xa3\x5d\xca\x2c\x7a\x9e\x48\x3b\x5a\x18\x3a\xe1\xfb\xf5\x8d\x18\x2f\x1d\x6c\x2b\x2b\x2a\xf7\x87\x9c\xd7\x78\x64\x9c\xcb\x2a\x5e\x0b\xa2\xe6\x1d\x79\xfd\x26\xdb\xf3\xf2\xa1\x76\x54\xd5\xc4\x75\xf2\x89\x68\x9d\x97\x7b\x7f\x9e\xd7\xe8\x3a\x21\xf0\x4d\x07\x45\x21\x9e\x1c\x8d\x20\x0b\xe1\xf1\x6f\xe8\x6c\x14\xf1\xe3\x71\x84\x00\xb4\x50\xa1\x6c\x86\xa7\x8c\x4f\x29\x8d\xf0\xbc\xa0\xbb\x43\xac\xe7\xaf\xc9\x89\x0b\xe9\x41\xec\xdd\xdd\x55\x56\x5c\x45\x44\x37\x83\xb5\xef\x20\xf2\x77\x01\xcc\x56\xd8\x42\xe7\x77\x3a\xb8\xeb\x4e\x54\x30\xbc\x45\x27\x96\xb7\xfd\xcd\x56\x68\xc6\xea\xa4\x9e\xd3\x9f\x50\xea\x50\xc6\xc4\x75\x6e\x69\x08\xe1\x25\x74\x76\x6b\xe8\xb2\x22\x0c\x7c\xa6\xb4\xf7\x9d\x19\x6d\x88\x4e\x84\x10\x41\xea\xc5\xfa\x82\x4d\x4c\xd9\x81\xfe\x44\x7a\xe3\x40\xee\x31\xf7\xd6\xd3\xfd\x20\x6e\xe6\x85\x18\xae\x40\x20\xb8\xa4\xdd\xc8\x51\x1f\xea\x2f\x59\xcd\xa6\xb6\xfb\x50\xe5\x2a\x03\x91\x98\xef\xb3\xb9\x71\xfe\xd7\x03\xfb\x77\x0e\x39\x29\x8d\x94\x54\xb6\x77\x1e\xa2\x52\x53\xc9\xa2\x9d\x20\xab\xb0\x82\xd3\xc0\xad\x4d\xb7\x7b\x6a\x5b\xc5\xf8\x2f\xd5\xad\x81\xf2\x0c\x5a\x3c\xcd\xbf\x5b\xe2\xcd\x41\x2d\xfe\xd2\x35\x7c\xa7\xc6\x70\xa4\xe6\x68\xe0\x3b\xf3\x6e\xd4\x3b\xfe\xfe\xec\x66\xdb\xae\x9c\xc3\xba\x63\x5d\x19\x7c\x2a\x14\x7d\x8b\x28\xf3\xcd\x1e\x04\xca\x80\xff\x14\x51\xd5\x03\x0c\x79\x1d\x0e\x33\x51\xed\x16\xd0\xc2\xd4\x04\x64\x78\xa6\xda\x05\xc7\x8e\xc9\x59\xf9\x08\x0c\x16\x24\x24\xed\x40\x79\x8a\x13\xe7\x47\x41\xd3\x38\x83\x77\xb4\x58\x8f\x5a\x38\xf2\xfa\xe2\x0d\x6d\x58\xe0\x8e\xbf\x17\x90\x95\x50\xa3\x38\x0f\x2e\x1c\x7c\x27\x7e\x18\xd0\x68\xa3\xa1\x5f\xc0\xba\x71\xe1\x9f\x93\x10\xd2\x75\x75\x50\x1d\x84\xc6\xad\x57\xb1\x3c\x75\x4a\xfc\x78\x78\xef\x57\x32\xbe\x5c\xb6\x37\xab\x34\x2a\x33\x3a\x1d\x0c\x63\x19\xc9\x20\x08\xae\xa0\x91\x2d\xc8\xad\x3b\x3d\xf4\xf3\x62\x4d\x13\x4e\x28\x6f\x42\xdb\xee\xb2\x44\x9e\xa3\x8e\x7a\x53\x2e\xa3\x3b\x41\xbf\xf7\x15\x57\xa5\x3e\x15\xcb\xee\xae\x3e\x0c\x6b\xe5\xea\xe3\xa1\x5a\xf5\xa2\x2f\x19\x79\x91\x1b\x92\x73\xc1\xda\x3c\xf2\x44\x83\x65\x73\xa9\x52\x73\x3a\xa4\x47\x44\x3f\x12\x32\xf8\x26\x18\x55\x34\xe7\xed\xaf\x95\x0c\x89\x87\xf7\xd8\x49\x53\xda\x10\xd5\x5c\x46\x8f\x45\x77\x39\x1d\x0e\x01\xf0\xca\xc6\xd4\x8b\xa9\x1f\x02\x0f\x5c\x27\xa6\x1c\x62\x1a\xcb\x54\x3f\x0e\xdc\x78\xa0\x46\x42\xcb\xc5\xf8\xdc\x72\x51\xc5\xc8\x4d\xfd\xd8\x8f\x82\xa0\x45\x09\x5e\x6c\xcc\x4b\xf7\x60\x9a\xa0\x65\x0c\x6b\xb4\x09\xf1\xf6\x55\x82\xd2\x77\xc4\xaa\xa1\x04\x39\xca\xda\x85\xc1\xff\x40\x6d\x6d\x8b\x1b\xfe\x15\x72\x68\xdf\xc1\xf7\xea\xf7\x07\x75\x82\x7d\x92\xc7\xd7\xcf\xb7\x6d\xb3\xf5\xf5\x73\x40\x9e\x5d\xc3\x8f\xf4\xda\xf1\x3f\x5b\xfc\x4f\x40\xae\xd3\x1e\xef\xfd\x34\x84\x3c\x73\xad\xce\xa2\xca\xcb\x3b\x06\xad\x98\xd5\x6c\x61\xcd\xfb\xc8\x6a\x3f\x82\xb5\x78\xb6\xb6\xc6\x0e\xcc\xd1\xd8\x64\x29\x26\xe7\xa7\xf4\x11\x39\x09\x9c\x14\x51\xab\xae\x1e\x90\xa6\x47\x78\x8d\x58\xc2\xf2\xa3\x7e\x5d\xbb\x96\x20\x44\xf2\x0d\x83\xe3\xcc\xa3\xb9\x25\x5f\xe7\x91\xfb\x83\x0e\x86\xe3\xa9\xd3\xe8\xbf\xbd\xfe\xf1\x07\x54\x32\x19\x21\xd5\xbe\x37\xe0\x5b\x52\xc7\x88\x0e\x03\x8e\x45\xed\xe0\xf4\xed\xc2\xc2\x5f\x7d\xbf\x54\x1f\xf1\x80\xeb\x95\xf1\xd6\x42\x3c\x2c\x33\x20\x93\xdf\x9b\xd4\x3a\xea\xf6\xd4\x97\xe3\x22\xe4\xf4\xbd\x62\xa2\x54\x8c\xb6\x7f\x7d\xa8\xd6\x57\xe3\x5a\xff\x75\xb1\xda\x57\x83\x6a\xc7\xe7\x8d\x67\x8d\x9c\xef\x6f\x41\x83\x53\x9a\xd8\x76\x62\x58\xe4\x0d\x20\x46\x92\x29\x43\x7d\x8c\x4c\xc7\xf7\x88\x77\x12\x69\xe9\x93\x18\x47\x72\xb3\x57\xf2\x0b\x58\x6a\x12\x05\xa8\x1c\x05\x23\x7a\x8a\x3a\x57\x16\x63\x7f\xa6\x7e\x24\xdd\x65\xc4\xc3\xb2\x60\x7b\x0e\x2b\x34\x17\xea\x22\x1e\x49\xd0\x94\x1a\x6f\x13\x47\xc4\x4a\x99\xf4\x29\x21\xf0\x93\xf4\xe2\xf1\xe3\x40\x30\x1d\xaf\x10\x2e\xc6\x5d\x00\xc1\xc5\x6b\x7e\x44\x3d\x9c\x5f\xec\x2a\xcf\xb6\x50\xa2\x36\xf8\x01\x09\x69\x52\x8a\x25\x2d\x71\xff\x36\xbe\x80\xbb\xb7\xb2\x36\xbb\x28\xad\x2f\x12\x03\xa5\x87\xca\x48\x44\xcd\x1f\x30\x13\x31\xf7\xd7\xc1\x0d\xf2\xc4\x1f\xc8\x23\x07\x2e\x3f\x4f\x66\x93\xfb\x62\x72\x50\x92\xcc\xc9\x56\x70\x38\x31\xd9\x18\x03\x8d\x05\xbd\x59\xc8\xc3\xb9\x6e\x31\x70\x21\xfa\x66\x6c\xdb\x9c\x19\xbc\x70\xbc\x55\xc1\x1e\xe1\x5c\xee\x95\x5f\x94\x30\x35\x01\xd1\xa3\x5b\xc3\xcf\xd6\x40\xc1\x7a\xb7\x0c\x12\xe0\x35\xb4\xdf\x3f\xf0\x07\xfe\x61\xe2\xcb\x3c\x27\xa4\xe8\x3f\x95\x3c\x59\x64\x6e\x61\x11\x0b\x62\xfa\xaa\xa7\xb0\x91\x6d\x63\xb4\xd8\xc1\xbd\xd4\x22\x87\xb1\x29\x4d\x4b\x8a\x88\x10\xb7\x0b\xe9\x4d\x00\x2f\x28\xea\xa3\x6d\xc7\xfc\xbc\x5b\xe4\x84\xca\x51\xd1\x07\x19\x64\x94\x16\x4b\xcc\x25\x3b\x10\xf7\xda\x0a\x4e\xa3\xde\xdf\x93\x16\xcb\x7f\x61\xb6\x6f\xca\xf2\xee\xd8\x05\x2e\xe9\x27\xa8\x58\xaa\xd6\x24\x36\xd8\x58\x59\xd1\xa9\x12\x29\xa5\x5c\xea\xd8\xbb\x0a\xe3\xc5\x02\xbd\xd3\x1c\xd1\x11\xaa\x6c\x18\x74\xa8\x50\xb3\x2c\x01\x45\xc1\x12\x3c\xbb\x00\xae\xc5\x89\x14\x5d\xd9\x66\xb1\x6d\x23\x02\x41\xf5\x36\xea\x70\x1c\x81\xb4\xfa\xbe\x4e\x5f\x2a\xab\xa6\x1f\x73\x58\x9b\x0e\xf7\xc9\x85\x88\x10\x0f\x77\x53\x1e\xc1\x49\x2a\xcf\x2f\x6b\x53\xc7\xba\x2c\x03\x35\xfa\x61\xb7\xd4\x51\x20\xaf\xd9\x18\xa3\xca\xa9\x55\x92\xfd\x7c\x31\xba\xce\x74\x66\xd8\xa2\x39\xf2\x1e\x53\x31\x81\x20\x90\xd9\x19\xcc\xbf\x8c\x3c\xbd\xb6\x1a\xdb\x76\xa1\xd8\x91\x75\x14\xa9\xee\x07\x76\xa7\x59\x1a\x37\xd8\x66\x08\x05\x6a\x2f\x80\x5a\x43\x66\xdb\xe6\xca\x89\x2d\x8a\x06\x06\x3d\x68\xf4\x9b\x67\x02\x36\x3f\xbc\x01\x27\x2b\x89\x72\xce\xaa\xff\xfe\x60\x3d\x0a\x26\x25\xc4\x03\x5e\xd5\x7f\xae\x02\x35\x1d\x55\xd6\xc0\x87\xfa\x01\x49\xab\x34\x13\xda\x5d\x88\x6b\xf4\x6d\xb1\x88\x9b\x86\x0f\xb4\x28\x09\xf8\x49\x20\xb6\xc1\xe5\x85\xd3\x78\x93\x51\xd5\x3b\xf3\xae\x16\x85\x14\x12\x3f\x0d\x80\x0d\x80\x15\x91\x44\x24\xe1\x5d\x90\xa5\xf9\x1c\xd4\x1b\x02\xa1\xe1\x32\xba\x73\x08\x70\x53\xbf\xa0\xf4\x5b\xff\x4d\xaf\xfd\xf9\x22\xf0\x04\x77\x17\x3f\xdf\x2e\x1b\xb2\x8d\xe7\x8e\xe7\xfa\xfc\xab\x00\x3f\x6c\xe3\x79\x43\xae\xd5\x4d\x3e\xf0\x33\xf5\xad\x37\xe5\xc1\x02\xeb\xe7\x2c\xdd\xd5\x16\x58\x9f\x97\x75\x5d\xee\x2d\xb0\x5e\xf1\xa4\xb6\x02\x78\x7d\xe9\xc2\xd3\xb0\x69\x18\x58\x45\x59\x70\xa9\x79\x88\x70\x3f\x59\x71\x76\x3c\xe4\xec\xbd\x45\x9a\x66\x66\x98\x0d\x8d\x82\xc4\xe2\xf1\xf9\x1b\xc9\x85\xea\xf0\x03\x0d\x06\x24\x20\xcf\xae\xb3\xfe\x4c\xb1\x53\xd0\xeb\xbb\xc8\x75\x05\x5f\x57\x2c\x45\x3f\x06\x02\x21\x1d\x86\x87\x3f\xbb\xb6\x5c\x7a\x3a\x40\x74\x7e\xa1\xb9\x8e\x3f\x1f\x4d\xc7\x9f\xc7\x0e\x59\xe8\x7c\x31\x0c\xb3\xa7\x62\xe4\x83\xd5\x47\xcb\x1f\xe7\x51\x31\xe9\xe5\x6d\xe9\x66\xf7\x22\x02\x77\x32\xde\xca\x17\x79\x59\x70\x21\xbd\x88\x5f\x34\x9e\x9f\xad\xc8\xe8\xad\x8b\x68\xa6\x43\xb4\x40\x38\xf0\x5e\xd0\x37\x26\xde\x3c\xbd\xbc\xee\x9e\x2d\xb8\x5b\x16\x25\x56\xff\x85\x2c\x45\xd1\x9a\xfc\x42\xcd\x03\xb7\x02\xa5\x97\xfa\xbb\x79\x55\xc7\xe6\x6e\x89\xf1\x72\xb2\xe2\xf3\x87\x30\xcc\xf9\x91\x5a\x65\xa1\x52\xf0\x6a\x60\x2c\xf2\x0f\x7a\xfd\xf6\x8e\xbf\xbf\x86\x5f\xe4\xba\xee\xcb\x87\x23\x6f\x0e\x65\x56\xd4\xbc\x6a\x94\xf5\xd6\x9e\x17\x0f\xa4\x89\xf2\x2c\xba\xbb\x86\x5f\x65\x46\x55\x93\xbc\x81\x16\xff\x96\x0f\x75\x98\x3f\x54\x42\x10\xc1\x6b\x22\xfd\xb7\xcb\xe0\x39\xde\x34\xb9\x74\x96\x73\xd2\x10\xd3\xd0\xfe\x7f\xcc\x98\x90\x5d\xea\x33\xc7\xbc\x98\x4b\xa7\xfe\xcb\x91\x12\x84\x82\xe2\x7c\x18\xe8\x47\x49\x00\x8c\x9c\x5a\xc1\xde\xbf\xe3\x45\x4d\x4f\xf2\x62\x7d\xf7\x74\x6e\x17\x35\x88\x06\x38\xba\x75\x58\xdd\x39\xac\xe9\x3f\xb2\x6b\x15\x39\x45\xcb\x5d\xa7\x6f\x4d\x68\x04\x11\x4d\x74\x0a\x70\xda\x7b\xb6\xe1\x8d\x33\x78\x91\xb4\x23\x1f\xa8\xbe\x50\x9a\x80\x93\xd1\x4a\x76\xee\x48\x9a\xc6\x78\x93\x7e\xfd\x29\xad\x54\x95\x52\x5d\xa7\xdf\xa6\x34\xa6\x0a\x6f\x15\x33\x4a\xff\x8e\x87\xde\xa2\x1e\xad\x03\xe6\x31\x1a\x3b\xd5\xd2\xb2\x5e\x7e\x12\xbb\x1b\xbd\x24\xf4\x1d\x8f\xc6\x49\x83\xe2\x4c\xc4\x86\x44\x4e\xc8\x22\xa6\x1c\x6d\x59\x01\xdc\x8e\x3d\x00\x6f\x17\x0b\xb2\xa3\xff\x94\xc6\xc9\xa1\x7f\x1b\x48\xc3\x8d\x92\xde\xd3\x9d\xbf\x0e\xe0\x40\x9d\x9d\xff\x42\xc5\x8e\x55\xce\x53\x4b\xed\x3d\x45\xa0\xc4\x1b\x97\x75\xdf\xd0\xe5\x84\xe5\x7e\x89\x32\x34\x94\xd4\xe1\x5e\xbe\x14\x1c\x46\xca\x6a\x14\x22\xdc\x7c\x19\x66\x45\x8c\xd2\x69\xd3\x94\x70\xb1\xec\x1d\xed\x09\x38\x86\xbf\x28\xa1\xac\xb2\x14\xeb\xb8\x97\x82\x5b\x0c\x6a\xdd\xdc\x48\xde\x5d\x2e\xd7\x09\xf4\x0a\xba\x7c\x78\xc5\x2a\x1a\x15\x5e\x70\x33\x91\x22\x29\x27\x20\x90\xc6\xf1\xc0\x22\xee\x1e\x94\x67\xd8\xd2\x22\x2d\x24\x04\x9c\x3d\xcd\xfc\x52\xcc\x8f\x7a\xa2\x7e\x00\xfb\x6e\x74\x5f\x94\x0f\x45\x4d\x57\x90\x0b\x2c\xf4\x70\xb0\x6d\xf5\xd0\x7b\x90\x1c\x20\x25\x33\x4a\x67\xeb\xa6\x39\xd7\x5c\xdb\xf6\x84\x36\xbb\x84\x14\x15\xd9\x80\x5a\x71\x31\xd5\xe2\x57\xd7\x78\x27\xd0\x98\x9a\x02\x0d\xaa\xc3\x04\x2a\x67\x84\x10\xe0\xde\x5e\x1b\x43\x8c\xba\x3c\x9f\xc3\x0a\xee\x88\xab\xfc\x92\xef\x90\xed\xc6\x15\x91\xdb\x4e\x0c\x54\xb0\xf5\x93\x4a\xa5\x3f\xb6\xff\x7a\x91\xdb\xb6\x07\xbb\xd1\xb6\xcd\x9d\x24\x78\xe7\xff\x04\x6c\xf1\xba\xce\xff\x3d\xe4\x92\xd3\x87\x00\x37\xfe\x1d\xc0\x95\x20\x80\x2d\xee\x30\x40\xc7\xe0\xd2\x0c\xcb\x79\xdb\x6c\xb7\x4b\x62\xcd\x35\x14\x6d\xb7\x4b\xc7\x73\x97\xcf\xb7\x82\x21\x10\xf2\x89\x23\x9e\x9e\x11\x0b\x19\x7d\xba\x1f\x0e\x2f\x59\x2c\xc8\x1d\xdd\xfb\x49\x00\x33\x2e\xfd\x99\xef\x96\x1a\xfe\xd1\x10\x43\xae\x2c\xa6\xcb\xa5\xdf\xd9\xf6\x6c\x27\xc1\xf8\x6e\xd9\x41\x31\x69\x9a\xd8\xb6\x65\x3e\xc3\xbe\xdc\x7a\xfe\xdc\x92\xb7\xe1\xce\xfa\x74\x84\x6c\x0d\x25\x09\xac\x05\x78\xf5\x65\x46\x60\xb3\x58\x80\x3e\x6b\x12\xa0\x2e\x9f\x7a\xc8\x24\x9b\xd4\xb6\x67\xfb\x5e\xad\x90\x2f\x6b\xce\xaa\xb8\x7c\x2c\x44\x76\xfd\xac\x0b\x1c\xa0\xc3\x98\x6a\x87\x14\xe6\xc9\x94\xc3\xa0\xec\x73\x68\x91\x05\x77\x63\xdb\xa9\x81\xcb\xab\xac\xb8\xca\x88\x5e\xd2\x4e\x42\x28\xe7\x02\x38\x10\x52\x67\x2b\xc1\x63\x0f\x15\x81\x19\x6a\x1f\x64\x8d\xba\x09\x30\x04\x0c\x4b\x42\xa7\x85\xe1\x94\x15\x5e\x1e\x06\x95\x39\xdb\x01\x77\xca\x05\xdf\x8f\x9b\x26\x0f\xe0\x9e\xde\x6a\x3f\x2c\x15\xb5\xcb\x93\x38\xdd\x0d\xa1\x32\xbe\x75\x8b\x86\x19\xba\x37\x03\x76\x5d\x5f\xc6\xab\xa1\x3b\x8a\xd7\xe5\xe6\xf0\xf1\xe0\xde\x13\xdb\xfe\x3f\xa3\xf7\xd9\xaf\x12\x24\xee\xe7\x67\xa4\x45\x8c\xfb\xbe\x97\xfe\x97\x16\xb9\xa1\x2b\xdb\x76\x2a\x7a\x6f\x34\x09\xf7\xb4\xea\xc4\xca\x4a\x6d\x1e\x02\x77\xd4\x28\xea\x5a\xe4\xe5\xca\xb6\xad\xb2\xb0\xe6\xf7\x10\xd2\xd0\xef\x8e\x52\x02\x2f\xc4\xab\xad\x8b\xa5\x5c\xc8\x7b\x38\x53\xcb\x84\xb6\x1d\x0a\x0e\x2d\x3b\xbe\x91\x5d\xa3\xdc\x7b\xe1\x7e\x0c\xc6\x14\xd0\xaa\xc7\xc5\x66\xfa\xbf\x2a\xc1\xbc\x75\xaf\xde\xe4\x0e\xac\x7e\x77\x07\xba\x52\xab\x21\x24\x8c\x87\xbc\xee\xec\xa7\x96\x32\x24\x62\xd3\x38\xfa\x91\xc6\x82\x87\x55\x07\x7f\x9e\x1f\x06\xee\x40\x5b\x00\x7e\x18\x10\x28\xcf\xb0\xca\xbd\xc4\x2a\xbc\x69\x66\xa5\x9e\xff\xa6\xe9\x1e\xbb\x8b\x60\x23\x09\xfc\xd2\x6f\x5a\xec\xfb\x59\xb9\x2c\x4a\xc9\xf0\xd9\x36\xaa\xb0\x7f\xc9\x8a\xb8\x7c\x74\x62\x22\x2d\x19\x33\x5a\x0e\xb0\x54\xd3\xdc\x83\x5a\xf1\x6c\x7e\x2f\xb9\x8f\xd4\x34\xc4\xdf\xa4\x9b\x51\xca\x41\xe2\xfd\x94\xc0\x8e\xa6\x9b\x1d\xa5\xd4\x89\xc7\x5e\x40\x18\x70\x41\xc5\xcc\x31\x6f\x5f\x44\x0b\x41\xac\x4a\xf6\xab\x69\x18\x69\x93\x2e\xea\x82\x93\xd2\x83\xbc\xe6\xc0\xb6\x67\x62\x81\x7f\xaa\xca\x03\x4b\x31\x7e\xe4\xeb\xba\x3c\x1c\x84\x00\x48\xd4\xa5\x9d\xc9\xcd\xda\xcb\xdc\xb2\xc3\xb2\x62\x28\x7b\xea\x48\x7a\x91\xf6\xdb\x10\xb5\xf3\xbe\x2c\x14\x68\x7a\x92\x82\x25\x77\xae\x45\x60\x2f\x70\x95\x0e\xde\x12\x11\xd8\xd3\x3b\xdb\x4e\xfd\xbb\xc0\xf8\x22\x38\x81\xfe\x20\xcf\x49\x31\x14\xbb\x5e\xff\x41\xe9\x2e\x55\x9a\x78\x86\x68\x0a\xcf\x8b\xfa\x4b\x39\x0b\x8e\x11\x24\x45\x8e\xe3\x5e\xac\xb3\x18\xac\xca\xf1\x93\xcc\x2f\x86\x2a\xd6\xfc\x5f\x6a\xfa\x6c\xbb\x7f\x56\xed\x1d\x64\xc0\x55\x0d\x06\x28\xbd\x19\x9d\x8c\x49\xd3\xdc\x8d\xac\x39\x62\xff\x1e\x27\x77\x00\x1a\x18\x10\x2d\x16\x03\x16\x88\x57\x3c\xc8\x73\x61\x38\x43\x01\xf4\x1e\x44\x0d\xce\xd4\x27\xb5\x0b\xba\x2a\x76\xa4\x9f\x8c\x16\x4f\x47\x90\x0d\x1d\x1e\x8f\x74\xa0\x9f\x64\x4f\x8e\x61\x9e\x3b\x30\xce\x3d\x37\xe2\xb9\xd5\xeb\x2c\x3d\x03\x87\x4b\x2d\x43\x21\x06\xea\x72\xf0\xf1\xde\xea\xbe\x9e\x5a\x19\x22\x0b\xdd\xb4\x58\xbf\x2b\xe4\xc6\xc5\x8a\x67\x77\x62\xf5\xbe\x54\x3d\x6f\x9a\xc1\xab\xe9\xcc\xa1\xf6\xe1\x69\xd7\x35\xa7\xb8\xaa\xa3\x99\x0b\x6e\x05\xa3\xdd\x01\x7b\x42\x77\x7e\xa8\x80\x9d\x5d\x02\xf6\x13\x5b\x46\x0f\x95\xd8\x31\xaa\x63\xc9\x92\xe7\x7c\x0f\x91\xb9\x69\x3a\x81\xe4\x88\x77\xb1\xeb\x0a\xbf\xdd\xef\x79\x9c\xb1\x9a\x4f\xd6\xec\xcc\xd8\x00\x31\x0a\x26\xd3\x7c\xd7\x37\x01\xf6\xac\x01\x46\x0b\x56\x4d\xfd\x18\xde\xd2\x54\x4c\x1b\xab\x19\x4d\xf1\x07\x38\x75\x9c\xf1\x74\xa7\x1d\x17\x22\x8f\xc9\x54\xf1\xa6\x49\x75\x9f\x89\x82\x66\x35\xb0\xcc\xd0\x5c\x73\x6c\x50\xed\x27\xae\xad\xa6\xd1\x3c\x6b\xb8\xa7\x40\x5a\x52\x1b\xe3\x74\x48\x6f\x3b\x7c\xb7\x3c\x94\xc7\x5a\xaf\x9b\x6d\x0f\xdf\x07\xeb\x08\xac\x87\x58\x3d\xa7\x97\x4f\x4d\x74\x94\xb1\x70\xc8\xea\xa0\xd9\x87\x24\x00\x78\xdd\xbb\x6d\x67\xe6\x45\xcd\x33\xb6\x94\x41\x40\x9b\xc6\x42\xa9\x5a\x9a\xf3\x63\x60\x0c\x65\x57\x31\xa3\xca\xf9\x98\x66\x03\x87\x06\x74\x0d\x13\x50\xdb\x85\x95\x45\x2b\xa2\x89\x8a\x10\xdb\xc7\x32\xa6\xf4\x6a\xb3\xc3\x40\x98\x73\x92\xd0\xd0\x8f\x82\x81\xd8\x3a\xb7\xae\x2c\xe8\x94\x90\xb1\xcf\xf1\x04\xc6\xe7\x01\x4d\x06\x02\x8f\x57\x38\x5c\xba\xa6\x29\x2f\xac\x4c\x90\x7f\xe5\x9c\xad\x3e\xa9\x9b\x8c\xb2\xee\x26\x23\x02\xb2\xc2\x2e\x44\xcc\x26\xee\x38\x3c\x15\x60\xed\x24\x56\xdd\xcd\xfa\xd9\x8e\xdb\x6e\xe1\x76\x2f\xc3\xe9\xec\xd8\x58\x57\x42\x5b\x12\xef\x48\x4b\x20\x45\x85\xe2\xe1\xe8\x5a\x2c\xaf\xbf\xe3\xef\xaf\x42\xa9\xff\xb8\x8a\x58\x11\xf1\x5c\x4c\xda\x55\x54\x57\xb9\xf8\x34\xd8\x59\x57\x08\x52\x3f\xed\xd8\x91\x5f\xed\x79\xcd\x44\x06\x8c\x82\xc2\x63\x95\x01\xb9\x1a\x91\x2c\xd7\xf6\xaa\xce\xf6\xfc\x75\xcd\xf6\x87\xab\x77\x19\x7f\xbc\x7a\xdc\x65\xd1\xce\xd2\xac\xd0\x95\x45\x20\xc9\x9e\xa4\xce\x5b\xc8\xa7\xfc\xbd\x7a\x56\xdd\x8b\x76\x02\x90\x76\xac\xfa\xa2\x8c\xf9\xd5\x1d\x7f\x2f\xfe\x8b\xe7\x51\x15\x23\x47\x6c\x43\xa1\xa7\xc3\x46\x60\xc3\xb8\x2f\xf0\x49\x47\xb9\x5b\xea\xca\xbd\xfe\xd1\x0d\x97\xaa\x15\x02\xac\x6d\x01\x15\x3e\xc3\x7e\x49\xd8\xbc\x92\x3f\xc7\xab\x28\xcf\x78\x51\xff\xaa\x7e\xff\x79\x55\x26\xc9\x91\xd7\xbf\xaa\xdf\x7f\x5e\x1d\x58\xca\x7f\xc5\xbf\xff\xbc\x3a\x46\x15\xe7\xc5\xaf\xea\xf7\x9f\x57\x75\xa9\xb4\x34\xbf\x3f\x24\xf3\x2c\x32\x54\xfb\x63\x33\x1a\x27\x36\xa5\xc3\x45\x85\x4b\xd5\x33\x0c\xc8\xa9\xf7\xdb\x19\x23\x82\x27\x28\xe7\x77\x42\x47\xcb\xb0\x8c\xdf\x83\xaa\xb3\xaf\x6c\xee\xa0\xa7\xf0\x31\xaa\xca\x3c\x7f\xc5\x93\x1a\x23\x5f\xf1\x41\xc2\x8a\x2c\x64\x2e\x59\xc6\xc8\x65\x26\xe0\x3d\x4e\x38\x2d\x5d\xed\xff\x1c\xd4\xfe\xa6\x3c\x0c\x2a\xc7\xf7\x51\xdd\x7d\x1e\xe3\x7d\x85\xd7\xb6\xe0\x52\x37\x4d\xb7\x73\x93\xa6\xe9\x00\x60\x6d\x27\xde\xda\x7d\x61\x27\xde\xc7\xee\x27\x76\xe2\xbd\x70\x57\x72\xb9\x93\xec\x69\x6c\x73\xc4\x0c\xde\xbb\x0b\x86\x69\xba\xc9\x28\x8c\x02\x09\x65\x5a\xe9\xae\xe1\xda\xe7\xc1\x26\xd5\x86\x3f\x46\x22\x4d\xe9\x2f\x5a\x41\x22\xcf\x50\x0d\x38\xfb\xc7\xf0\x4b\xbf\x2f\x5a\x02\x31\x45\xfb\xcf\xc3\x51\x7b\x15\x96\x87\xa3\xb6\x14\x51\x5f\x88\xdb\x7f\x02\x46\x4d\x59\x21\x11\xe4\x75\x64\xf6\x11\xa2\xf6\x3e\xf6\xc3\x00\x98\x1f\x05\x34\xf1\xa3\xce\x6a\x87\xf5\x0c\xbb\x7e\xa4\x39\x81\x8f\x65\x38\x65\x09\x4f\x06\xde\xee\xf2\x74\x1f\xcd\x68\x4c\xa9\x72\xb1\xf2\xd2\xce\xe3\x11\x12\xe2\xb2\x16\x14\x29\x74\x4f\x79\xc9\x62\xf7\xa4\x19\x74\xbc\xd1\x49\xc6\x34\x3f\x9d\x89\x89\x83\x43\x93\x19\xa5\xff\x72\x88\xf4\x0c\x95\x5a\x5d\xe5\x6e\x9e\xc8\x80\xe6\x78\x25\x79\x7f\xc8\x68\xe8\x20\x2c\xad\xf1\x6d\x21\xcc\x1f\xaa\xdf\x6b\x88\x9a\x0d\x89\x02\xaa\x1d\xf1\xf8\xfb\xcd\x94\x0f\xb5\xd5\x02\x12\xa2\x0f\x34\x64\xe9\xb3\x03\x8b\x4a\x22\xa7\x22\x6b\x49\x8b\x18\x51\x58\xb0\xac\x3a\xac\x8e\x62\xf0\x94\xd2\x5f\x7b\xd9\x8b\x5c\xa3\xfe\x68\xd6\x78\xda\xaf\xaf\xab\x4e\x2f\x1d\x58\xcc\x12\xf2\x79\xc8\x93\xb2\xe2\xf2\xba\x76\xf7\x64\xb2\x05\x43\x83\xf2\xde\xe9\x5e\xb2\x07\xb6\xcd\x90\xb1\xc9\x0a\x96\xab\x4b\xe0\x9d\x51\xca\x52\xb6\x8e\x2a\xfa\xae\x1c\x69\xdb\x16\x8e\xd9\xfe\x21\x1f\x78\x69\x28\xcd\x58\xef\xfb\xa7\x34\x99\x06\x74\x43\x04\x52\xaf\xc9\x20\x3b\xbe\x56\x35\x60\xac\xe7\x41\xab\xee\xa9\x6d\xc9\x26\xf6\x46\xfc\xb9\xc3\xf5\xb5\x8b\xee\x99\x5e\x58\xa9\x13\x38\x01\x3e\x29\x85\xa0\x3b\xfb\x88\xe1\x6a\xa5\x71\x6c\xa7\x70\x39\xb3\x1d\x9d\x34\x14\x16\xb3\x36\x65\x3f\x2c\x06\x3f\x5b\xa3\xc1\xed\x79\x6d\x03\x08\x1d\x04\xac\x90\x99\x3d\x07\x3d\x02\xea\x3e\x0a\xc3\x60\x42\x74\x0c\x06\x94\xb5\x14\x2a\xc3\x84\xf3\xa1\xd2\x2e\x5c\x53\x97\x64\x20\xd8\xf3\x8f\x72\x38\xfd\x22\x0b\xf6\xd4\xfb\x1f\xf7\x99\x42\x51\xb2\x45\x08\xa5\x16\xb9\xb3\x49\x84\x50\x99\x91\x76\xec\x03\x95\x03\xd0\xaf\x4d\x23\x00\xf6\xd1\x91\x8c\xb0\x3c\x2b\xee\x71\x34\x9d\xad\x08\x19\xa8\x48\xa4\x15\x91\x7a\x33\x2d\x4c\xcf\x47\xe8\x3e\x83\x29\x39\x03\x93\x3f\x20\x2d\xb8\xcf\x60\x08\x00\xe7\x4e\x40\xe7\x13\xbf\xb9\x34\xcb\xff\x23\x5d\x38\x86\x35\x9e\xa7\x38\xa4\x85\x11\x53\xff\x9f\x34\x7b\x3e\x0a\xdd\xf0\xa8\xd2\x89\x24\xdd\xf4\xd4\x94\xfc\x27\x7d\xf8\xc0\x94\x9a\x9d\x99\xca\xf6\xa1\x6f\xca\x39\x6f\xa2\xd7\xad\x76\x00\x3a\x21\xc1\x15\xf3\x5d\xb9\x16\x3e\x97\xef\x78\x65\x49\x7e\x2f\xe7\xec\x1d\xd7\xc9\x0f\xb5\x05\xea\xc0\x4f\x65\x57\x6f\xb2\x80\x7a\x51\x45\xf4\x27\xc4\xf4\x63\x5f\xe6\x91\x9c\x1d\xd0\xd3\x80\x48\x84\xa0\x35\x35\x6e\xa8\x78\xf7\x33\xa7\x9d\x08\xa4\x8d\x2b\x48\x8c\x69\x30\xdf\x18\x33\xb7\x13\x3d\x15\x05\xc7\xfb\x75\xb9\x34\x7e\x37\x4f\xae\x75\x0c\x67\xa6\x34\x45\x9d\x0c\x6a\x1e\xde\x4d\xfb\x8e\x81\x2a\x13\x12\x88\xd0\xe2\x7b\x7c\x8e\x2a\x76\xa7\x9c\x62\x49\xbb\x3b\x12\x2b\x29\xac\x49\x0a\xa7\x2c\x48\xcc\x11\x77\x53\xa6\xb0\xb9\x13\x42\x47\x9f\x86\x7a\x11\xb4\x93\xda\x8c\xa7\x38\x0c\xe8\x09\x8f\x8c\xc6\x30\xa9\x0c\x85\x47\xbc\xb0\x9a\xd8\xce\x92\x26\x46\xa3\xe8\xa6\x89\xcf\xcf\x91\x18\xe0\x85\x83\x60\xe6\x05\x87\x0b\xde\x73\x2e\xf0\xb4\x56\xc7\xff\xef\x1b\x5e\xac\x37\xdc\x1b\x54\xcf\x89\x8b\x71\x7a\xcf\xc9\x43\xdf\x1b\xa5\x64\x17\x15\x90\xf6\xcc\x6e\x67\x70\x5f\xc7\xd9\x59\xd3\xd0\xef\xa2\x8f\xd3\x74\x66\x12\x12\xa2\x44\x11\x35\x4d\x08\xda\xbf\xd6\x88\xd3\xcf\xa4\x81\x73\x59\x38\x29\x36\xc1\xfc\x34\x00\x3e\x8c\x46\x94\x25\x2a\x3a\x46\x24\xa5\x15\x4a\x63\xcf\x89\x69\x08\x51\xe7\xb1\x2b\x75\xc8\xd2\x6d\xe3\xdc\xee\x5b\xe4\x8e\x20\xea\xf2\xaa\x57\xa3\x43\x82\x57\x46\x9d\x53\x4c\x9f\x75\xe6\xf0\xb3\x78\x10\x98\xca\x70\x98\xe0\x78\x78\x1d\x43\x3c\xe9\x40\xe5\x48\x3f\x21\x46\x20\x99\xde\x15\x2d\xc4\xf2\x7c\x30\xd1\xe7\x86\xc9\xe8\x88\x5b\xbb\x46\x9c\x99\x09\x49\x90\x65\x71\xac\x95\x60\x31\x44\xca\x36\xb0\x2c\xa6\x58\x20\xd3\x5a\xc8\x58\x48\x01\x76\x65\x92\x5c\xf2\x25\x10\xab\x7b\x81\xac\x74\x58\xa3\xbb\x89\xd9\x44\x25\x50\x38\x63\xe5\x9f\x9c\x8d\xd8\x38\x27\x88\x3b\x0c\x32\xb7\x96\xd6\xdc\xf8\xe4\xf6\x9f\x8c\x30\x6b\x10\x77\xda\x2d\xa8\x75\x8c\xb0\x09\xd8\xc3\x60\xd5\x26\x54\x25\x89\xc3\x21\x04\xe6\xf3\xc9\x00\x57\x78\x45\xfc\x6c\xdd\x34\x13\xb1\x70\x43\x79\x35\x85\x01\x23\xe8\x46\x88\x1a\xb3\x88\x3e\xfb\x9d\x05\x1a\x98\x53\x76\x2b\x74\xc6\xc5\x9f\x85\x96\xb9\x54\x9f\xe6\x3b\xc5\x2a\xa1\xd6\xc8\xa8\x4e\x79\xaa\x5d\x74\xb4\x30\x03\x0a\x9e\x31\xb2\x12\x1e\x66\xab\x8e\xf5\x57\x56\x54\x8c\xd1\xeb\x97\x8e\x37\x63\x15\x67\x4d\x58\x35\x51\x99\x37\x7c\x1f\xf2\xb8\xd9\x55\x4d\xb6\x4f\x1b\x94\x21\x9a\x3c\x2b\xee\x9a\x3d\xaf\x59\x73\x60\x15\xdb\x13\xc7\xf1\xb7\x8f\x6e\x30\x97\xc1\xe0\xc8\xf6\xfa\xe6\x3a\xcd\x20\xc4\xca\xd4\x97\x6b\x88\xc4\x6b\x63\xff\xc9\xdb\x3e\xce\x37\xd7\x10\xcb\xa6\xdc\x63\x54\x65\x87\xba\x39\xd6\xef\x73\x8e\x15\x93\xeb\x0c\x38\xa3\xd7\xca\xee\x67\x7b\x7c\xee\x78\xae\xff\x96\x06\x0d\xdd\x1e\x9f\x6b\x73\xa0\xa5\xc8\x96\x30\x7a\xfd\xf6\x59\xb3\xbd\x76\x3c\xf7\x96\xbd\x63\x0d\x8f\xf6\x8c\xc8\x1a\xaf\x33\x48\xc5\xe7\xba\x7a\xe0\xdb\x6b\x67\xf9\x9c\x5c\xc3\x4e\x24\x6c\x8f\xcf\x5f\xce\x1c\xcf\xdd\xfa\x5f\x7c\xf9\xd9\x9b\xcf\xb6\x7e\xb3\x58\x90\x46\x24\x04\xdb\x40\x3c\xdf\x6c\x8f\xcf\x9f\x5d\xa7\x90\x31\x7a\x92\xb7\x42\xb9\xfe\x1a\xac\x97\x12\x2e\xaf\xf6\x0f\x79\x9d\x1d\x72\x4e\x3f\xd2\x4f\x1f\xdd\x58\x60\xbd\xbc\x96\xdf\x6f\xac\x00\xea\x1d\x67\xb1\x2c\x84\x11\x70\xe5\x77\xf5\x18\x40\x54\xe6\xae\xff\xa2\xfb\xf8\x32\x2a\xf3\xb4\x2a\x1f\x0e\x32\x5b\xf7\x66\x94\xa8\xab\x41\x81\x3a\x2c\xe3\xf7\xaa\x52\x7c\x34\xb3\xc6\xae\xff\xf1\x38\xeb\xcb\xba\x52\xd9\xab\x9b\x89\x32\x9d\xdc\xe7\xaf\xc0\xb2\xc0\xb2\x82\x76\x93\xb1\x65\x79\xa8\xb1\x27\x54\x3e\x67\x65\x01\x19\x5b\x62\x69\x91\x54\x27\x65\x59\x8b\x07\xdd\x63\x7c\x66\x98\x11\xbf\x8b\x59\xc0\x12\x3b\x7c\x8d\x7b\xd3\xa5\x5b\x36\xd4\xc1\x19\xb2\x25\x58\xd8\x2d\x8b\x0c\x24\xd8\xf3\x00\x44\xa1\x19\x94\xc6\xaa\x2b\x8b\xc8\xeb\xce\x95\x7a\xea\xf8\xf9\xfb\x37\x2c\xc5\xb2\x16\xf6\xd8\x22\xfe\x2a\x40\x1b\x10\xc3\x26\x6d\x64\x9d\x37\x36\x93\x53\x05\x89\xcb\x7a\x4b\xaa\xbb\xe1\x2d\x1f\xc8\xe7\x38\x52\x9b\x76\xe9\xb6\xa8\xb9\x75\x6d\xcd\x95\xd4\x64\xd4\x94\xb3\xde\xcd\x3a\x65\x2a\x50\xa1\x54\x3c\x77\xa7\x5b\x9e\xe6\xa4\xfc\x75\xe0\x6a\xb9\xef\xac\x05\xb3\xd6\x3d\x3b\xbb\x01\x0a\xe2\xfe\xb6\x91\x58\x29\xb1\xa5\x45\x3f\xf3\xa3\x00\x2c\x69\x72\xf2\xd5\x3b\x96\x5b\x30\x0b\x9b\x46\x9e\x0a\x85\xe3\x6f\xc4\x88\x97\x5f\xb0\x09\x3d\xbe\x34\x44\xd9\x9c\x5d\xc6\x82\x2a\xb2\xa1\x41\x8a\x93\x18\xf6\xdf\x04\x52\x2a\xfb\x13\x42\x42\xe0\x96\x26\xbd\x71\x8a\xf6\x36\xd2\x36\x02\x69\x6f\xf3\xb5\xe9\x10\xff\xad\x0a\x88\x26\x46\x7a\xeb\xf3\x60\x3c\x58\x93\x80\x86\xc0\x41\xe4\xf1\xa3\x80\xb4\xdf\x0f\x3b\xb5\xa3\xdf\x1b\x9d\xca\xa8\x19\xf6\x66\x47\xe0\x7b\xd5\xc7\x4c\xf0\x4d\xdd\x54\x94\x83\xab\x03\xa6\x61\xf0\x12\x68\xca\x8b\x47\x88\xcb\x96\x18\xc7\x4c\xc7\x5b\xfb\x2c\xcf\xbd\xf3\xa4\x2e\xb7\x3f\xe1\x32\x87\xbe\x6f\x83\x7d\x14\x12\xaf\x8b\xa1\xc4\xd0\x2f\xd4\xb8\xf1\xe5\x30\xba\xef\xe0\xc2\x75\x6c\xfd\xed\x69\x91\x6d\xbf\xd1\x37\xbc\x21\x88\xa2\x3e\x5c\xda\x58\x76\xd7\xe8\xb9\x8e\x51\x40\xdd\x91\x26\x48\x09\xbe\xcb\xd3\x5e\xd3\xe6\x92\x0e\x23\x3b\x13\xc3\xb5\x08\x4d\x36\x2f\xb1\x29\xea\x58\x93\x0d\x0d\x3b\x71\xbd\x3e\x60\x77\x8b\x6e\x9e\xce\xd8\x40\xb4\x69\x86\xc1\xd2\x54\xac\x33\xd3\x17\xb6\x0f\xaa\xec\x30\x22\x0f\x97\x52\x5a\x32\x67\x47\x20\x11\xbf\x8c\xa8\x28\x7f\xc9\xf8\xda\x9d\x03\x73\x12\x3f\x0e\x20\xf5\xe3\x40\x86\x30\xc6\x98\x7c\x58\x45\x42\x93\xa6\x91\xa5\x53\x9a\xe2\xe3\xee\x62\x45\xc5\xa0\x22\xe4\x54\x71\x07\xee\xfa\xab\x74\xb0\x47\x60\x49\xe2\x67\x11\x48\x8d\x8b\x11\xf6\xcc\x49\x61\x96\xd9\x36\xc2\x6a\x97\x87\xc0\xae\x85\xf0\x21\xcb\x63\x6d\x55\x3c\xc1\x49\x6a\x3c\x32\xbc\x59\x2c\xbc\x6c\x96\x9c\xa3\x85\x1e\x5d\x41\xd9\x63\x9d\xf2\x66\xbf\xd9\xcb\x50\x4e\x9c\x32\x7f\x1f\x00\x97\x97\x68\xa2\xb7\xdc\xb9\x23\x37\x27\x44\xc3\x6e\x0e\xdc\xb8\x96\x87\x07\x2e\x27\x1d\xab\x1e\x31\xad\x06\x27\x27\x9c\xcf\xbb\x01\x76\x0f\x2f\x18\x44\xa7\xd4\x09\x15\xbe\xe5\xd2\xd6\x4d\x90\x3c\x72\x7e\x8d\xbe\xa0\x5b\x7e\x1a\x34\x4d\xc6\x3a\xb3\x01\x48\x0c\x3b\xe4\x9d\xbf\x0e\x8c\x9b\xb8\x19\x03\xeb\xe5\xb3\xf5\xcd\xcb\xeb\x67\x2f\x6e\x2c\x32\xdf\xf9\x2f\x02\xb8\xa5\x3b\xc1\x8b\xf5\x16\x74\x89\x58\x5f\x6d\x84\xbc\xe9\xc7\x99\x98\x61\xce\x20\xa1\x77\x26\x85\x4b\xcc\x6b\x58\xa9\x65\x49\x0b\xac\x5c\xc5\xfb\x51\x03\x7d\xc3\x9f\x50\x91\x2e\x26\x64\x73\x37\x2a\x01\xfd\xc5\x1c\x9c\xe6\xdd\x25\x20\xe8\x9a\xb3\x58\xe3\xdc\xeb\x80\x4b\x78\xdf\x04\x9a\x09\x9a\x21\x96\x47\x3b\x8a\x2b\xf0\x1f\xce\x39\x27\x06\x0c\x66\x08\x7a\x09\x81\x88\x90\xd3\xad\xd1\x7c\xe2\xdf\x8a\xe6\x13\xbd\x7e\xfa\x5e\x47\x8b\x74\x61\x3f\x79\x7f\xf2\x2c\x7d\x22\x8a\x33\xdf\x26\xf3\x3e\x20\x79\xe8\x35\x12\xee\x21\xa5\xab\x4d\xa7\x76\x76\x22\x2a\x56\x93\x60\x50\x31\x19\x9d\xdc\x30\xf4\x40\xfc\xc4\x69\xe4\xbf\xea\xb4\x84\xe8\xcb\x13\xd2\x57\x9d\x03\xb4\xba\x5c\x21\xd4\xe4\xa9\xf7\x83\xee\x52\xfc\x38\xf0\x46\xe2\x00\xde\xee\x33\xb4\xac\x13\xfd\x0d\xb5\x65\xdd\xa6\x6f\xa0\x73\x6d\xed\x93\x5a\x95\xf2\xbd\x76\x0a\xf7\xbf\x37\xdd\x5c\xc7\xe2\xfb\xd9\x65\x98\x6a\x12\xc7\xfe\x75\xfd\x97\x5e\x37\xeb\xc9\x78\xf2\x98\x53\xa9\x5f\xe5\x35\xa1\xe4\x4c\x42\x41\x0a\x8f\x39\x7a\x3c\xb9\x9e\x48\xfb\xcb\x38\x89\xe8\x38\xbb\x26\x70\xb2\xde\xcb\x8d\x9d\x79\xfc\x90\x16\x24\x80\x5d\x38\x6f\x59\xc6\xe5\xfe\x7b\x56\x64\x87\xc9\xa8\x65\xb8\x60\xff\xeb\xce\x2a\xee\xec\x96\x69\xd3\x86\xcd\xd0\xa7\x81\x91\xb6\x95\x61\x19\xff\x3f\xd4\xc1\xac\x38\xf2\xaa\xfe\x1c\x0f\x65\x04\x1e\x1f\x84\x61\x14\xdd\x95\xe7\x35\xff\xcb\xde\xca\x83\x43\x23\x08\xf4\x28\x61\xdc\x7c\x27\xb7\xb2\xa4\xbe\x78\x66\xf6\xff\x46\xa3\x83\x10\xc3\xed\x25\xf7\x7c\x33\x52\x2f\xf3\x8a\xfe\xd8\xb1\xdf\x04\xc0\xe9\x6a\xa3\xae\x57\x8a\xd0\xb8\x83\xe0\x95\x58\xa1\xe4\x1d\xa2\x01\xab\xd0\x61\x2a\xa7\x64\xe8\xbe\x18\x0d\x23\x66\x23\x97\xd6\xe1\xd4\x68\x84\x53\x05\x12\xda\xcb\xa2\x26\x99\x36\xeb\x50\x78\x44\xfb\xd4\x0c\x15\x1c\xe7\x01\xf1\xba\xc0\xc6\x68\x34\xa5\x46\x21\xd5\xed\x7e\x18\x10\x0c\x58\x34\x8e\xbf\xec\x8c\x86\xc1\xa4\x39\x3c\x1b\x11\x94\x51\xd3\xe7\x2c\x9b\xe1\x34\xa5\xe3\xdc\xce\xd6\x2e\x53\x11\x53\x28\x0d\x3d\xe6\x4a\xc5\x06\xc6\x2f\x38\x07\x8d\x42\x72\x78\x43\x67\xd8\x5d\xbd\x9f\x0c\xb9\x3a\x81\xe1\xe4\xe6\x50\xda\x10\xb4\x06\x95\x32\x82\xe1\xf4\x36\xf4\xcc\x3e\xbb\xac\xbb\xb3\x32\xec\x68\xfe\x74\xa4\x7a\xdb\x9e\xc5\xc6\xb5\x38\xb3\x8c\xf9\x1d\x8f\xc1\x3e\xc4\x63\x04\xe4\x64\xde\x71\x3e\xe2\x20\x30\x12\x09\x5a\x33\x69\x51\x46\x0d\x27\x92\xc3\x59\x8f\xae\x4f\x1a\xaf\x5c\x28\x57\xce\x74\x9d\x12\x28\x82\xae\x0c\x9f\xff\x36\x54\xdb\x49\xe3\x7a\x89\xe0\xd0\x55\xff\x32\x4a\x56\x1d\x1e\x46\x2e\x3c\x0b\x66\x67\x28\xa1\x7e\x77\x9b\x87\x62\x26\x46\xfb\x1a\x46\xe3\xc1\x4d\xa9\xa2\x97\xa9\x1e\x28\x56\x4f\xe3\x19\xf1\xcd\xd1\x7c\x27\x5a\xe3\xe9\xa5\x34\x3c\x43\x15\x61\x46\x8f\xcd\x9a\x8d\x8e\xa9\xcd\xfe\x76\xf6\xe8\xe8\x62\xad\x7b\x3f\x02\x72\x46\xb9\x52\xf8\xfa\x81\x8e\x8e\x2a\x08\x7c\xc7\x2f\xd3\x15\xe4\x03\x47\xcb\xbd\x3c\x9f\x29\x69\xbe\x58\xc3\x01\x6f\x36\x80\xfb\x61\xf4\xbe\x03\xca\x0b\xf7\x4d\x93\xdf\xac\x27\x82\x9a\x1c\x6c\x7b\x66\x7a\xd3\xd9\x36\x57\xe0\x77\x20\xe4\xb2\x6a\xb1\x0b\x48\xba\x5f\xf2\x7b\x27\x22\x9b\x7b\x31\x5b\xfe\x2a\xa0\x07\xc3\x82\x2f\x82\x78\x29\x76\x99\x43\x08\x81\xd8\x58\x34\xdc\x81\xa2\x5f\x39\xaa\x43\x8b\xe5\x40\x78\x50\x48\xd3\x5f\x05\x23\xac\x36\x53\x31\xfb\xd1\x8c\xc8\xe0\x69\x65\xf0\xf1\x9e\xe9\xed\xfd\x16\x22\x1a\x13\xd0\xe6\xd6\x89\x0a\xe3\x3b\xc4\x8a\x70\x87\x92\x53\x27\x2a\xe5\x37\xb7\x9b\xdb\xf9\x9c\xec\x68\x04\xb7\x33\x4a\x4b\x94\xe7\x35\x06\xd9\xc1\x6c\x85\xc7\x1f\xa9\xc0\xbf\x92\xe3\x4e\x60\x28\x32\xe1\x46\xe9\x66\xc1\xbf\x0d\x60\x07\xb7\x44\x5e\x55\x2b\xcd\xbe\x13\x3f\xe9\xaf\x9d\x18\x0d\x52\xf6\x31\x81\x9c\x11\xb1\xe2\x9b\xb4\xeb\x4f\x22\xaa\xd2\xac\xee\xce\x64\x75\x67\x9d\x0e\x64\x37\xd4\xb4\x0c\x88\x44\x06\x3b\x54\x4e\x2c\x8f\x55\xe4\x15\xcb\x7f\xf1\x77\x2c\xff\x7b\x95\x8b\x3c\xfa\x59\x7e\x14\x5c\x66\x5f\x8b\x68\xaa\xc7\xd7\x1d\x86\xd9\x31\xb0\x2c\x32\x8a\x09\x2b\xdd\xfe\xf1\x40\x4e\xee\xfe\x37\xa5\x6b\xc9\x27\x4b\x73\x37\x22\x49\x3d\x5a\x60\xd2\x5b\xd7\x92\x0c\x85\x4e\xfd\x0c\x09\xbd\x85\xf4\xde\xd2\x88\xe2\xb3\x3c\x77\x2d\x03\x69\x4c\x1c\x7d\x8e\xc2\x38\xb3\x21\x71\xc6\x6b\x0c\x0a\x29\x2e\xf3\x6e\x15\x60\x87\x53\x4d\x65\x08\xad\x88\xee\xf0\xba\xd1\x7e\xa7\xcb\xd5\x17\x0b\x5f\x38\xdc\xdf\x05\xc4\x0f\x03\x27\xea\x8f\x68\x62\x88\x64\xe0\xf6\x01\x31\x33\x82\x33\xc7\x9d\x87\xf1\x3d\x83\x8a\x0d\xe2\x32\x1f\x99\x33\x88\xc4\x54\x38\xd1\x48\xe2\x0c\x89\x46\xa7\x6f\x4a\x47\x9a\xcb\x11\x3c\x84\x4d\xb9\x3e\x5c\xf9\xa2\xdc\x1f\x1e\x6a\x1e\xbf\xae\xdf\xe7\x1c\x43\x72\x5c\xfc\x8a\xf7\x6c\x13\xe2\xc5\x4b\xe5\x6c\xec\x4a\xef\x63\x91\x6c\x38\x20\x6f\xfa\x80\xa4\x88\xdd\x1c\x02\xc9\xf8\x96\x62\x49\x19\x73\x88\x68\xc5\x7c\xd6\x9f\x14\xe0\x95\xd8\xf2\x02\x69\xa2\x9c\x9c\x65\x54\x0a\xf1\xe5\x9e\x51\xe7\x9e\x35\x4d\xe1\x58\x2f\xb3\xa4\x62\x7b\x7e\x85\x7f\xc3\xb2\x8a\x79\x45\x3f\x5a\x7d\x74\x85\xd7\x9b\xe1\x93\xbc\xef\x4c\x3c\x5e\xdf\x58\xe6\x34\x84\x63\x4b\x42\x02\x21\xbd\xc7\x5b\x5b\x47\x41\xc0\x21\x5c\x3e\x56\x59\x2d\x24\x71\x74\xe2\x55\xf1\x72\x74\xf7\xee\x59\x37\x40\x02\x38\x0c\x1a\x11\x88\x5a\xbc\xdb\x8a\xd1\xeb\xb7\x7b\x56\xa5\x59\x71\x0d\xef\xa4\x85\x9b\xf6\x51\x79\xeb\x58\xf3\xff\x9e\x5b\xc4\xf1\x66\x87\x27\xe2\xb3\xc5\x6f\xff\x15\xcc\x9f\x59\x60\x65\x16\x81\x47\x36\xe5\x2f\x3a\xba\xa1\xc5\xf4\xc6\x58\x96\x07\x5e\xf0\x6a\x7c\x89\xcb\x20\x4b\xca\x47\x0b\x19\x82\x8c\x19\xc7\x2e\x7e\x32\xc0\xec\x89\x5d\xd2\x7f\xe1\xa1\x49\xb7\x76\x34\x6a\x9a\x47\x54\x28\x45\xb6\xed\xa4\x14\x21\x5b\x07\x68\x43\x0d\x9b\x13\x92\xa6\x89\xd0\x5f\x46\x64\xb1\xc4\xda\xa6\xc8\xb5\x5e\x56\x9b\xa1\x37\x4b\x21\x9b\x92\x77\x1b\xc0\x3b\x85\xcb\x52\x62\xdb\x0f\x4c\xdf\xa0\x85\xb0\xbb\x5b\x22\x04\x00\xa7\xbb\xe5\x3e\x2b\x7e\xc1\x97\x44\xbc\xb0\x27\xf9\xd2\xa7\x1b\xa9\xba\x1c\x4d\x41\xf4\xfb\x51\xe5\x94\x69\xb1\x59\x86\x83\x51\x2a\x21\x86\x9d\x7b\xea\xa5\x73\xcb\x72\xd3\xf3\x4b\x5d\x55\xec\xb9\xc9\x88\x74\x57\x4c\x5f\x34\x67\x06\x95\x12\x59\xbb\x5b\x1d\x68\x48\x2e\x1c\xe8\xb6\xed\xd8\x61\x1f\x55\x11\x34\x9f\x30\x96\x9d\xf6\xce\x87\xe4\xc2\x07\x0c\x73\x23\x67\x9d\x9c\xd4\xc3\x32\x64\xd1\x5d\x5a\x95\x0f\x45\xfc\x45\x9e\x1d\xa8\xa5\xf6\xcb\x22\x2c\x9f\x2c\x48\x46\x7e\xee\xd3\x45\x2c\xb8\x43\x96\xaa\x42\xb6\x01\x41\x6e\x58\x0f\x46\x1f\x9a\x2a\x0b\x5c\x25\x47\xc7\xe3\x1b\xfe\x54\x53\x4b\xee\x7b\x77\xb5\xc1\x75\x72\x57\x1b\xb9\xe7\xdd\xd5\xa6\x2e\x0f\xee\x6a\x93\xf3\xa4\x76\x17\x7f\xf9\xcb\x5f\xfe\x72\x78\xda\xc8\xcd\xb8\x10\x5f\xd6\x87\xa7\xcd\x41\xdd\xcf\xe8\xb2\xf0\x58\xe6\x0f\x35\xb7\x80\x0f\x44\xeb\xc4\x88\xb1\x99\x3a\xfd\x1c\x74\xad\x2f\x1e\x79\x78\x97\x61\xa7\x17\xc7\xec\xb7\xac\x48\x5d\xd9\x21\x91\xb2\x59\xec\xcb\xdf\x2e\x7c\x9a\x4e\xd5\x28\x35\xcc\xcb\xe8\x6e\xd0\xdb\xff\xda\xa8\x1f\x35\x5e\xec\x3e\x8b\x63\x51\x81\x78\x96\xa3\xff\x64\x7a\x50\xa6\xb6\xd0\xb2\x20\x1e\x29\xcb\x36\x32\xa8\xf0\x04\x1e\x48\x24\x1e\xd8\x84\xd4\x5a\xff\x17\x6e\xd4\x65\x5d\x1e\x20\xa2\xd6\x27\x07\x5c\xa5\x54\x6d\x93\x78\x20\x11\x72\xd2\x9e\x57\x66\x18\xcf\xdd\xc1\xe9\x90\x3d\xf1\x5c\xdf\x8f\x39\xb1\x23\x52\x81\x6f\x5b\x08\xcb\xa7\xd7\x38\x4b\x3f\xf3\x3c\xbb\x10\x3e\xbd\x33\xd0\x10\x65\x22\x21\x15\xc8\xac\xdf\xe3\xf4\x61\x68\x8d\xb1\x74\x10\xa2\xf9\xd0\x1f\x88\x5b\xd1\xe1\xb5\xd1\xc2\xff\x11\x40\x30\x00\xfa\x0c\x12\xcc\x6f\x17\x92\xa7\x60\xc1\x5d\x6d\x3a\x78\xd7\xab\xbf\xb2\x40\xf7\x6e\xdf\x8f\x98\xea\x34\x89\xbe\xac\x95\x80\x82\x41\xca\xfa\xf0\x74\x0e\x0a\x10\xd2\x19\x06\x66\xfb\x3a\x2f\x59\xed\x4c\x80\x44\x24\x41\xc2\x6c\x8b\x9c\x2d\x3f\x24\x23\x0d\x01\x84\x6d\x4b\xda\x16\xdd\xcd\x8e\x8f\xec\x70\x16\x6f\x55\x19\xcc\xa2\x27\x8e\x3a\x55\x4b\x64\x70\xc7\xd4\x4f\x02\x4d\x66\xfc\x24\x80\xfe\x91\x86\x7e\x12\x6c\x38\x8d\xba\x80\x08\x32\x4c\x93\x59\xda\xc8\x2d\x2a\xea\xd8\x12\x19\x9a\xef\x37\x41\xa1\x1d\xc1\x61\x34\x78\xe0\xeb\x78\xb3\x45\xe4\x73\x16\x90\xe5\x9c\x5c\xc3\x67\x17\x68\xf6\xf2\x39\xd1\xa4\xfa\xf3\x71\x16\x7f\xbe\x08\x08\x55\x39\x55\xa6\x2f\x18\x3d\x75\xdb\xd2\xea\xf7\xe5\xbb\xec\x98\x85\x59\x9e\xd5\xef\x5d\x6b\x97\xc5\x31\x2f\x2c\xd0\xcb\x6e\xe1\xba\x5b\x2d\x7c\xc9\xe8\x29\xe7\x75\xcd\xab\xd7\x07\x16\x89\x15\xc7\xc5\x2c\x8b\xfa\x17\x89\xe9\xac\x4f\x56\x2b\xab\x85\xaf\x18\xf5\xad\x5f\x10\x0a\x2d\xb0\x7e\xb4\xc0\xfa\xbe\xfc\xcd\x02\x6b\x7f\xb4\x82\x1e\x8b\x7d\xad\xc8\x51\x96\x38\xa1\x34\x57\xd1\xdc\x85\x0a\x5a\x15\xe2\xd5\xbe\xe5\xdf\x0f\x07\xad\x1d\x98\x6b\xaf\x9c\xb5\x10\x9e\x42\xe0\xf4\x2b\x36\x34\xcd\xe7\xd2\x25\x3f\xa4\x5f\x31\x9f\x07\xf3\x08\xc6\x55\x6b\x73\x9d\x9e\x2c\xfe\x75\xc8\x4f\xd0\xcf\x94\x9e\x22\xec\xaf\x43\xf4\xf0\x16\xf2\x3d\x7b\x72\x56\x10\xfb\xeb\x60\xe1\x44\xe8\x32\x31\x77\x62\xe9\xdc\x7f\x78\xb2\x88\x1b\xf6\x75\x7e\xc3\x4c\x63\x31\xcd\xb7\x27\x34\x42\xcf\x56\x4f\x91\x0a\xcb\xd5\xa4\xc6\x22\xde\x27\xae\x25\x2f\xc3\xc5\xb0\x4d\x6b\x0c\x11\xbe\xda\x7c\x72\x93\x6c\x92\x39\x7d\x41\x2c\x09\xe5\xea\xec\xd1\x49\xe7\x5d\xa8\x9d\x68\xfe\x33\xba\xe8\xaf\xf0\x1a\x96\xd8\x73\xba\x4a\x75\xde\x45\x1f\x96\x47\x6d\x55\x6b\x50\x46\xd7\x3d\x3b\xcf\xaf\x3a\x8a\xd9\xe7\xd6\x2f\xf2\xb6\x5e\x59\x8c\xb8\x66\x2f\xa6\x6a\xee\x13\x67\x67\xbd\xfe\x60\xcd\xdd\x29\x5e\x3f\xa3\xdf\x8e\x56\x49\xe4\xa4\xe6\x8c\xb1\xa5\xf4\x1e\xc2\x9a\x5c\xfd\xf6\x0d\x02\x26\x24\xf4\x51\x1d\x2d\x5a\x3d\x8d\x1b\xc4\x2b\xea\xd0\xbb\x25\xe4\xf3\x04\x19\x8e\xd5\x0d\xe5\x4d\x23\x91\xba\xba\xf7\x8d\x2a\xee\x33\x21\xe0\xac\x6e\x8c\xaf\x78\x5a\xa2\xb7\xb8\xe0\x28\xdf\xf5\x87\x71\x7a\xa7\x6f\x62\x9a\xda\xb6\x73\xb7\x3c\xa3\x25\x0e\x69\x1a\x8e\x6a\xc7\xbe\x02\x4e\x0d\xf4\xc7\x49\xd3\xac\xba\xe0\x82\x73\x0d\x5f\x82\x1b\x9d\x82\x26\x88\x21\x21\x73\x01\x96\xfd\x0c\xfe\x6d\x6c\x09\xa1\x0e\x89\xf0\xfa\xb5\x15\x32\xd0\x6a\x2b\xed\xd4\x4d\x33\x31\x1e\x10\x41\x2c\x3b\x65\xdb\x18\xaa\x4a\x85\xb2\x89\xc1\x2a\xf3\xb8\x13\xb2\x30\x36\xaa\x44\xea\x2a\x0d\x42\x0f\xf3\x37\x4d\x2f\x37\x35\x8d\x33\xca\x45\xbb\xbb\x94\x47\x1f\x6c\xfb\xb5\xf4\x22\x56\x6d\x76\x46\x9d\x66\xb3\x50\x33\x27\xee\x0e\xeb\x09\x91\x71\x5e\x5f\x63\xcc\x50\x1d\x91\x2a\xb2\x6d\xde\x34\xd2\x9e\x62\x54\x9a\x7b\x91\x12\x19\x63\x43\x5e\x24\xea\xa2\xd4\x14\x7d\x1c\x2f\xcc\x44\x68\xdb\xdd\xb0\xce\x7a\x6e\x4d\xa4\x4e\x0c\x3d\xf4\xd4\xfc\x58\xae\xac\x8b\x0c\xaf\x26\xd3\x67\xff\xc7\xa3\x72\x66\x2a\x05\xd6\xad\xdf\xbb\xa7\xf3\x88\xc2\x78\x98\xae\xcc\x17\x10\x44\x2d\x95\xb9\x93\x7f\x55\xe8\x53\x6b\x6d\xb9\x51\xdb\xb6\x2d\x44\xc7\xe3\x0f\x0f\xfb\x90\x57\xee\x29\x2a\xf3\x87\x7d\x81\x7e\xa6\xee\x6c\x05\x49\x96\xe7\x3f\xaa\xb6\xc4\x6b\xce\x9f\xfe\x5a\x95\x8f\xfa\xf9\xf5\xae\xca\x8a\x3b\x7c\xeb\x51\xff\x6c\x05\x79\x56\xf0\x6f\xba\xb7\xb2\xaf\x40\xf2\x09\xf8\x70\xd8\xb1\x02\xef\x6e\x7c\xcc\xe2\xf2\x11\x9f\x7e\xfb\x16\x6f\xc1\x13\x4f\x65\xb9\x47\x0f\xa6\xe8\x88\xa6\xf6\x47\xf7\x64\x25\x02\xfc\x05\x68\x1f\x8f\xb8\x13\xac\x16\x70\x16\x27\x8e\xe6\xa5\xb5\xe6\xc7\x23\xfb\x85\xff\x33\x7a\x67\x5a\x8a\x30\x4e\xf1\xc7\xa1\x81\xb3\xb1\x30\x19\x4a\x44\x81\x9d\xf2\x77\x01\xc6\xdd\x37\xde\xe9\xd7\x0c\xd5\x52\x02\xc1\xe0\x07\xe9\xb4\x16\xe2\x05\x58\xdd\xeb\x2e\x00\x23\xf2\x72\x6a\xdb\x56\xca\x6b\x2b\x2b\xae\x52\x23\xe2\xa5\xc3\x69\xaa\x42\x14\xce\xd6\x10\x13\xe2\x71\x37\xf3\xc3\xc0\x75\x92\x2e\xfa\xad\x11\x10\x97\x26\x88\x78\x3e\x57\x34\x2b\x22\xd2\x60\xd3\xe1\xfe\x3a\x98\xaf\xc9\x73\xee\xbf\x08\xe6\x06\x1e\xd1\xf8\x4e\xc8\xad\x09\xb5\x0a\x04\x00\x8b\x80\x3c\x09\x89\x6c\x3b\x52\x44\x43\x7f\x9a\xa1\x17\x20\x16\x93\xd0\x22\x87\x1f\xcd\x29\x12\xbd\x73\xf1\x49\xc0\xb3\xdc\xeb\x2b\xb4\x51\xeb\x02\x74\xf4\xe2\x93\x85\xf1\xaa\xfc\x30\xa0\x56\x56\xec\x78\x95\xa1\x81\x86\x6d\x5b\xc7\xd1\x7c\x50\x3c\xa5\x4e\x55\x14\x5e\xb1\xc8\x5d\xc9\xa8\x93\x75\x89\x84\xe5\x4b\x8e\x4f\x93\x2b\xfc\x1f\xac\xab\x82\x84\x3f\xb2\xba\xc3\x25\x35\x57\x72\x05\x7d\x7f\xbb\x48\x99\x8a\x94\xc4\x04\xb1\x55\xb5\x67\xb9\x8a\xa2\x89\x3c\xcb\x97\x0c\x33\x7d\x89\xf7\xd6\x48\x14\x19\x35\x4d\xe4\x39\xc9\x90\x2e\x48\x83\xdc\x95\xb4\xcb\xf9\xe1\x61\xcf\xab\x2c\x72\x12\xe2\x25\x4d\xb3\x72\x39\x71\xb9\xa1\xcd\xf4\x2d\x29\x92\x5a\xa0\x28\x67\x70\xa6\x75\x34\x86\x47\xc7\x78\xc6\x34\xa5\x8e\xbc\xdf\x14\x81\x3b\x0f\xf9\x47\x6c\x5b\x3a\x37\x19\x14\xd9\x93\xdc\xb6\xc3\xe0\x0b\xe3\x96\xf0\xae\xba\x6f\xf5\x5c\xb4\xc4\xed\x9e\x3b\x47\xbc\xe3\x44\x3f\xa4\x57\x5b\x6c\xdb\x48\xd9\xf5\x82\x22\x33\x17\x41\xec\x29\x0a\x19\xc3\x1f\x23\xf8\x9c\x00\x27\xee\x4a\x3b\x00\xe8\x59\x18\xc8\x31\xef\x99\x73\xb7\x9c\x10\xe9\x60\xf2\x90\x2f\xec\x47\x7c\xea\x38\xe9\xac\x10\x48\x72\xa1\x19\xea\x27\x06\x3e\xd3\xec\x97\x8c\xbc\x18\x18\x01\xd4\x3a\xbf\x1b\x29\x71\x59\x16\x68\x49\xcb\xb2\x40\x49\x5f\x8a\x73\x3a\x57\x1f\x77\x0b\xc9\xe6\x62\x29\xa5\x8d\x84\x6b\x1e\x7d\x68\x46\x40\x1a\x59\x9d\x5a\x81\x10\xce\x22\x6d\x7b\x91\xe1\x66\xed\xfa\x51\xb0\xf9\x44\x19\x61\x71\x9f\xcd\x7f\xf6\xe3\x40\x54\x9f\xf8\x71\xd0\x34\x89\x1f\x2f\x5e\xe0\xef\xca\x10\x6f\x5a\x78\x60\xfd\xe5\xae\xce\xa8\x67\x62\x6f\xd3\xbf\x32\x32\x36\xdc\x18\xef\xe8\xcb\xe7\x9a\x23\x5d\xa0\x18\x88\x20\xdd\x2a\x92\xbf\x8e\x0f\xaf\x83\x17\x48\x3e\x90\xf7\xa1\xbc\xb8\x22\xf1\x89\x1f\xfa\x69\x10\x74\x00\x22\xde\x24\x0a\xee\x43\xf9\x0f\x4c\x44\x30\xd2\xbd\xa1\x09\x04\x3c\x70\xd0\xe8\xb5\x05\x36\x19\xa2\x98\xb4\x70\xdc\x95\x8f\x13\xca\x83\xbf\x29\xa3\x05\x3c\x5b\xdb\x65\xf1\x94\x82\x41\xe5\x21\x2d\xd4\x65\x9a\xe6\x53\x21\x51\xad\xb0\x2c\x73\xce\x0a\x33\xe4\xb4\x0a\x3a\x2d\x1a\x56\x97\x49\x2d\x45\x03\xfa\x79\x6c\xcd\xf2\x5a\x36\xe2\xc9\x7b\xb3\x89\x2e\xa7\x5f\x65\xd1\x76\x78\xef\xcb\x77\x03\x89\x47\xeb\x43\xf8\xe3\xd5\x77\xac\x77\x1f\xc4\x3b\xd0\x8d\x7c\x6d\xb1\x7c\xf3\xc8\x79\x41\xbf\x63\x60\xe6\xa3\x27\xe3\xaa\x71\xf7\x3b\x06\xa2\xdc\x84\x1f\x0e\x24\xca\x16\x82\xe7\x7c\xaf\x9d\x32\x0f\x55\x79\xa0\x91\xf6\x4c\x38\x66\x05\x5e\xab\x68\x1d\x1f\x71\xaf\x4b\x97\x08\x34\xca\x3e\xd2\x50\xfb\xbc\xb1\xaa\xd6\x96\x24\x8f\xea\x22\x02\xf4\x4e\x96\x95\x14\x31\x8d\xe5\xe3\x03\xde\xe1\xae\xa1\x58\x11\xc4\x28\xf0\x04\x0b\x27\xc8\x61\x0b\xd1\x43\x75\x7e\x00\x2c\xc7\x76\x90\x50\xdf\x75\xb2\xf7\x19\x17\x5c\x49\xca\x6b\x69\x16\xab\xec\x8d\xcc\x32\x7d\x90\x9e\xee\x7b\x0b\xd5\xc3\xc4\x05\x55\x10\xfd\x5e\x63\xe6\x04\x2c\xe3\x87\x0a\xdd\xfc\x94\x6b\x7c\x79\xa4\x82\x22\xca\x59\xf3\x8d\x19\x0c\xb4\x11\xc9\xb8\xe0\x73\x06\x2b\x58\x4f\x7f\xd3\x5e\xf5\x58\xab\x36\x42\x29\x1f\xa9\xa3\x67\x75\xd1\xcf\x3e\x79\x1e\xce\xfb\xb7\x61\x7d\xc7\x9a\x1f\xd4\x99\xbc\x99\xd4\x9f\x4d\xca\x20\x2f\xba\x7e\x7d\xd7\xb5\x6d\x63\x2c\x56\x2f\xea\x02\x88\x5f\x9a\xd4\xee\xbb\xbc\xdc\xa9\x85\x33\x98\x35\x40\xd3\xfc\x06\x66\x7d\xf4\xd4\xf9\x0d\x8c\x08\xa7\x5a\x9b\x71\xe8\x09\xd1\x6b\x5f\x56\x80\x96\xf8\xe2\x5d\x0b\x18\xea\x9e\x36\x23\x4d\xe7\xf4\x9c\x50\xe3\x28\x39\x6e\x99\x0e\x42\x90\x12\x52\x09\x7b\xa8\x4b\xc1\x80\x85\x5e\xe8\xae\x88\x3b\x6c\x66\x4c\x4a\xf1\x9c\xf1\x09\xa7\xb3\xab\xff\x2c\x05\xef\x89\x1f\xf4\xce\x99\xe8\x9e\xc1\x38\xa9\x72\x43\xfe\x48\x25\x92\x1e\x65\x0e\xba\x2f\x58\xf4\xc7\x39\xde\xff\x59\x8f\x7b\x8d\xfc\xfb\x63\xdb\x2d\x8c\x5a\xbf\x2e\xc4\x05\x9d\x48\x7e\xc5\x93\x1a\x3d\x19\x87\xb1\xa1\x64\x8f\x4d\x69\x00\x13\x06\x36\x49\x53\x8d\x6b\x37\x58\x44\x27\x27\x41\xc4\x59\x35\x79\x4f\x67\x0b\x88\x68\x26\xbe\x2d\x3f\x5d\xa0\x1a\x29\x2a\x8f\x0e\x7b\x8e\x8f\x3f\x7d\x4b\xae\x5f\x60\xcd\xc9\x13\x3d\x03\x3a\xe8\x56\x82\x9e\xd4\xfd\x1d\x0c\xbe\x67\xf0\x03\x93\xf1\x72\x25\x09\x68\x04\x76\x6e\x04\x4e\xc6\xfb\x3a\xc6\x4a\x40\xcf\x55\x7a\xc0\x86\x68\x9d\xa1\x3c\xe2\xeb\x15\x87\x3f\x31\x7a\xdd\x07\x9f\x7e\x76\x0d\xff\xcd\xa8\xff\x0f\x16\xc0\xcf\x8c\x9e\xac\xe7\x96\xeb\x5f\x72\xaa\xd2\x76\xb6\x02\x87\xf7\xb1\xe5\x25\xea\xe4\xf4\xc7\x4e\x91\x06\x89\x60\x6b\xb9\xff\x71\x30\x42\x9d\xac\x47\x9d\x90\xd2\xd1\x27\xa9\x57\x9b\xa1\x8c\x33\x8f\x89\x6d\xeb\x0a\x25\xf8\x47\x0a\x7e\x08\x81\x1d\x5d\x43\x46\x5f\x20\xd1\x4f\x6d\x3b\xf5\x3f\x0e\x44\x31\x65\x05\x2d\x5e\x81\x0b\x22\x80\xaa\x8e\x79\xdc\x34\xeb\x4d\x5c\x5e\xed\xe8\xae\x69\xac\xe5\xa7\x16\xa4\xd7\x74\x07\x1a\x2e\x75\xbd\x90\xce\x13\xa2\xd4\x8a\x3b\x21\x99\xed\xf4\xd8\xae\x63\x75\xa9\xf8\xce\xb6\x17\x8b\xac\xbf\xf4\x41\x9d\x33\x4a\x7a\x32\x4f\x9b\x46\xb4\xb5\x82\x48\xd1\x0d\x88\x90\x96\x08\xd9\xcc\x4b\xe7\x03\x19\xcd\x9d\x8b\xbf\x04\xa2\x36\x30\x8e\x3a\x5f\xb3\x9e\xf4\x1b\x17\x95\x99\x41\xe8\x75\x8c\xf1\x96\xc0\x2b\x46\x95\x93\x7f\xaf\xf4\x79\x33\x74\x4c\x91\x9c\x9e\x3a\x97\x62\x52\xb9\x1d\x4a\x75\xa3\xe2\xeb\xe8\x8b\x45\x48\x22\x2a\x18\x3b\xe0\xbe\xd6\x0c\xce\xa3\x80\x72\xbf\xd7\xf1\x45\x01\x65\xc6\x7d\xe8\x0e\x5f\x2a\x71\x9f\x6a\xa5\xbe\x60\xb2\xfa\x6e\xfc\xbd\xd3\xde\x75\x4c\x27\x70\xea\xfc\xcc\x50\x8a\xf2\x03\xa2\x03\xb2\xfc\xcc\x7c\xeb\xb9\x15\x10\xbc\xad\xb6\xb7\x6c\xd8\xa4\xa8\x07\x9d\xcb\xcb\x64\xb8\x9f\x04\x12\xfb\x47\x82\xc7\xea\x14\x6c\x86\x52\xf7\x1f\xd3\x87\xc4\x3a\x32\xac\x34\x38\xda\x53\x0c\xb3\xaa\x25\xbc\xc3\x40\x4f\xf0\x5a\xf0\x89\xf7\xdd\xc5\x0d\x56\xf2\x24\x36\x1a\x06\x09\xc7\xcd\xd2\x34\x68\x4f\x33\xbc\x31\x01\xaf\x7d\x00\x89\xe0\x77\xcb\x87\x02\x3f\xc6\x68\xad\xa2\x5f\xf0\x06\xb7\x9d\x71\x97\x01\x98\x2f\x66\xc8\xf9\xbe\x4c\xd3\x64\x82\xe1\x82\x3e\x65\x3e\x87\x7c\x29\xef\x5e\x35\xc1\x61\x2a\xad\x2f\xb4\x58\x40\x7f\x11\x04\x76\xb5\x33\x0c\xdb\x0d\x2f\x57\xc0\x1b\xd9\xce\xec\x20\xb5\xf4\x98\x15\x57\x61\xd3\x28\x11\x12\xcf\x36\x6c\xdb\x89\x96\xe5\x3b\x5e\x25\x79\xf9\x48\xfd\xb2\x7b\x86\xfe\xf1\x57\xe3\xf9\x9f\x01\xdc\x4e\xc4\x8a\x87\x3b\xda\xe9\xed\x6e\xbd\x6e\xea\x4d\x45\x63\xd3\xd4\x42\x26\xef\x74\x7e\xee\x2d\x28\xa9\x4a\x14\xba\xd3\x6a\x39\x53\xd2\x93\x2a\x24\xd1\xc7\xb2\x57\x3b\x0e\x24\x31\xb4\x29\xd5\x7d\xc3\x7c\xdd\x58\xba\xd3\x90\xa9\xa9\x35\xf2\xf5\xe5\xfd\x55\x60\x8e\xda\xfc\xb2\x36\xbf\xfc\xd3\xfc\xf2\x22\x68\x95\xda\x51\x5d\x24\x86\xca\xe6\x50\xec\xc2\x1f\x3a\xdf\x0c\x54\x71\xa9\x73\x79\xfc\x84\xe8\xcd\x92\x74\x00\x75\x07\xc0\x29\xa5\xce\xc1\x13\xbd\xe6\x96\x6b\x49\x90\xc5\x72\xf2\x59\xde\x4d\x3a\xbb\x37\x62\x90\xdc\xfb\x71\x40\xa2\xb2\xa8\xb3\xe2\x81\x6f\x0e\x74\xb6\x6a\xf7\x7e\x1c\xd0\x7b\xdb\xbe\x47\xb1\xae\x97\x71\x62\x15\xe9\xf6\x56\xdf\x82\x34\x71\x5d\xda\x9e\x10\x63\x41\x1c\x63\x3d\xc7\x0b\x37\x5c\x91\x5b\xe9\xc7\x72\xba\xf7\xf4\x94\x67\xc5\xd5\xbd\x6d\x3b\x07\x7a\xbf\x94\x29\xc4\xbd\x37\xaf\x49\xd1\x5b\x12\x4e\x2d\x81\x04\x03\xc9\xca\x7c\x74\x76\x20\xf0\xff\xe7\xee\x4f\xdb\x1c\xb7\xb1\x43\x71\xfc\x7d\x3e\x85\x44\x3b\x32\x51\x82\x54\x52\xb5\xc7\x99\x50\xcd\xd2\xdf\xeb\x4c\xcf\xf5\x16\x77\x3b\xf1\x44\xd6\xf4\x05\x49\x50\x62\x95\x8a\x94\x49\xd6\x36\x25\xdd\xcf\xfe\x7f\x70\x0e\x56\x2e\xaa\x6a\x4f\x92\x27\xcf\xef\x45\x77\x89\x20\x00\x62\x39\x38\x38\xfb\xd9\x2f\xc5\xdd\xab\x78\x97\x1d\xe6\xef\xb4\x9d\x8a\xc5\x5b\xc5\xca\xd0\xf6\x7b\x24\xd9\xec\x18\xbc\x1a\x03\x00\xd6\x14\xdb\x74\x43\x6c\xfe\xef\x66\x15\xad\xc9\xd1\xda\xc5\x1b\xb2\x09\x7f\x66\xfe\x7e\x29\xd6\x31\x98\xd1\x84\xee\x08\x85\x37\xbf\x1d\x0e\xbe\x28\x0c\x37\x92\xe0\xdd\x8b\xab\x03\x6e\x07\x55\x22\xff\x5a\x3a\x8e\xe4\x70\x50\x27\x10\x12\x04\xcf\x83\x99\xe3\x79\xf7\x1f\x5d\x4e\x88\x30\x9a\x18\x95\x60\x80\x3c\x6d\x41\x58\x0c\x9c\x30\x42\x12\xf8\x3e\x1a\x8e\x39\x45\x8d\x46\x2a\x60\x16\x5f\x86\x82\xad\x27\x34\x96\x79\x21\x99\x18\x7e\xaa\xc2\x20\x8b\x0a\x0d\xf9\x58\x82\x02\x31\x14\x3c\x80\x4c\x4c\xdc\xc7\x1b\xe9\xad\xe1\xa7\xc4\xb4\x4d\xd6\x66\x98\x29\xc1\xd1\x1e\x0e\xbe\x0e\xae\x45\x21\x69\x3f\x97\xd0\x27\x06\x1c\x5a\x97\xcb\x2f\x6d\x5c\x0f\x97\xc7\xbf\x31\x93\xc9\xc3\xce\xf6\xd1\x71\x90\x55\x30\x67\xb8\xfa\x8f\x84\x66\x36\x1e\x16\x47\x91\xa8\x1c\x02\x0b\xed\x65\x13\x7e\xcb\x0e\x07\x71\x43\xd3\x38\xb4\xf4\x83\x57\xb8\x6f\xe2\xae\x1e\x5f\x69\x5e\x68\x82\xb4\xd1\xb9\x29\x11\x84\x41\x1a\xce\x27\x09\x68\x5f\xb2\xf0\x6a\x5a\x0b\x32\xca\x18\x62\x4b\xb9\x84\x2a\x5f\x6d\xd6\xd3\xf2\x36\xf7\x53\x93\xfb\xc3\x4e\xe5\xcb\xe8\xea\x8a\xa6\x54\xec\xc2\xfc\x32\x1d\x8d\xb2\x65\x1c\xf8\x5b\x27\x5f\x89\xa8\xb2\x26\x18\x14\xe9\x2a\xdc\xea\xac\x21\x18\xfe\x90\xc9\x10\x87\xb6\x93\x67\x44\x68\xb1\xaf\xad\xb2\xe1\x8c\x3e\x49\x67\xa2\xaf\x81\x16\x0e\x9e\x8e\x47\x1a\x13\x1d\x2f\xca\xe4\x7f\x0c\x22\x5d\xf8\x03\x72\x6d\x41\x4c\xf5\xd2\x04\x7a\xf1\xd4\x7a\x04\xb1\x5e\x1a\x8a\x33\x0e\x56\x6b\x6a\x11\x98\x4e\xbc\x6b\xa5\x06\x94\x02\x04\x9f\xd1\x2b\xc1\x1c\x56\x20\x19\xc0\x9f\x53\x67\xa0\x40\x68\xc8\x17\x48\xc6\xeb\x75\xd4\x2b\x0f\x8e\x56\x09\xa1\x09\x46\xea\x09\x6c\xcb\x37\xe3\x3b\x1c\x2d\x1b\x5b\x15\x00\x1e\xe4\x4e\x98\x0c\xf0\xc5\x0d\x87\x33\x6d\xa8\xae\xb7\x31\xc6\x6d\x9c\x5b\x4e\xcd\xed\x6d\xa2\xd1\x9a\x04\x5b\x99\xf4\xd8\x29\xa5\xca\x40\xf5\x3a\xbc\xc2\x80\x75\xf0\xad\xff\x60\xfe\x75\xe7\xbc\x89\x4b\x3a\xfd\x1b\xd3\xb4\xd3\x15\x65\x54\xb5\x31\x24\x94\xc9\xb7\x7e\xc3\xf6\xfe\x35\xfd\x19\x22\xcc\x3a\xb6\xd8\xea\x33\xc0\xb7\x8f\x46\xf6\xa3\x0a\xa5\x0e\x4d\xd2\x07\x88\x3f\x55\xfa\x1a\x7c\x32\xaa\x60\x8d\xe5\xd9\x4d\x70\x45\x31\x3f\x90\xec\x01\x1e\x04\xe1\x71\x65\xb2\x3c\xcb\x57\xea\x59\xa6\x61\x96\xa5\xe2\xb7\x9a\xb4\x4a\xf0\x2b\x13\x46\xcb\x52\xf1\x5b\x9f\x77\x59\x86\x4f\xe4\x98\x4f\x3f\xcf\xb3\x1b\x00\x38\xe3\xd9\xfc\x0b\xa3\x4f\xb0\x51\xad\x50\x12\x6e\x32\x6f\xb2\x94\x19\x7e\x90\x5c\x0d\x98\xa0\x22\xb5\x9c\x74\x61\x5b\xea\xce\x20\xf0\x50\xc3\x83\x35\x0e\x05\xd6\xa3\x3f\x01\x8a\x83\xff\x81\x3b\x81\x5f\x3a\x47\x56\x84\xbe\x54\x9d\xb1\x2d\xa3\xe5\xbf\x31\x5d\x91\x91\xe0\xdf\x18\x82\x2f\x93\xa9\xa7\xaa\x3d\xe7\x49\x2b\x82\x1a\x1e\x1a\x36\x1a\x75\xe4\xa5\xb3\x0f\x3e\x23\xc1\x93\x5a\xd1\x20\x3e\x1c\x86\xf1\x68\x14\xa1\x8a\xc1\x5a\x83\xd1\x88\x99\xe3\xcb\x28\x1e\xab\x00\xab\x46\x32\x20\xf4\x37\xe6\x0c\x8d\x46\x91\x95\x61\x5e\x35\x0c\x01\x50\x8a\x34\x5d\xce\x02\xa5\x74\xd2\xa3\x32\xd5\x96\xe6\x67\x60\x7e\x8a\x9b\x02\xb9\x64\x31\xdd\x6a\x69\xfd\x5e\x99\x5a\xeb\xc0\x2a\x37\x9e\xab\x32\x9e\x4e\xa2\xe8\x79\xf9\x03\xd4\x29\x60\xbe\x29\x9f\x91\xa8\x4f\xa6\xc5\x2e\x09\x13\x0d\x68\xd4\xfc\x74\x73\xa4\xd9\x91\xb1\x45\x1b\x32\x1a\xc1\x5f\x23\xaf\x12\x9d\x41\xd7\xad\xbc\x59\xb2\x9c\x1c\x05\x0e\x72\xe4\xe1\x29\x4b\xf8\xbb\xe2\x99\xd0\x36\xd2\x5b\xeb\x2d\x01\xd2\x57\xab\x80\xe9\x4c\xd1\x41\x82\xc2\x10\x17\x20\x00\x3e\xf7\xb5\x46\x39\x3a\x52\x54\xab\x1c\xa9\x7c\x77\x22\x8e\xa0\x4b\xef\x31\xcc\x1c\x07\x8b\x8b\x99\x08\x1a\x59\xe3\xf0\xb2\xfc\x45\x4a\xb7\x5d\x28\xa3\x29\x59\xf8\x5c\x85\x58\x80\x0a\x5e\x9a\xe5\x59\xb5\x05\x2d\x52\x04\xe1\xc8\x20\x3b\xba\x36\x09\x99\xe2\xfb\x70\x43\xf9\xe1\x90\x9a\x2d\x9b\x5b\x89\x15\x37\x52\xf4\x88\x2b\x2b\x2b\xd1\x0d\x69\xe2\x75\xe7\x54\xb4\x3d\xa5\x30\x5a\xda\x42\x91\x29\x98\x9c\x2e\xf2\x63\x3d\x9a\xce\xcc\x5f\x18\x2e\xc7\xce\xfe\x15\x8d\x46\x90\x99\x7d\x2e\xa5\x98\xad\x7c\x65\xdd\x61\x74\x70\x10\x60\xe8\x22\xe5\x6d\xa3\x91\x9b\x27\x0c\x56\x1e\x70\x6c\x05\x31\x23\xb4\x74\x18\x2f\xa4\x0d\xb8\xd0\x8a\xff\x61\xe8\xa3\x51\xe2\x6f\xd0\x5d\x4f\xa5\xab\x80\x70\x11\x9b\x76\xc5\x1f\xb5\xf1\x8a\x69\x84\x57\x9a\xf1\xc5\x9f\x4c\x16\x24\x15\x4d\x04\x4a\x97\xc1\xa5\xd1\x1e\x06\x46\x0a\xaf\x60\xac\xc3\x30\x14\xd4\x1c\x14\x08\xe8\xc2\x4d\x8d\xc1\xc2\x6f\x4e\x53\x95\xec\x83\xd3\x39\x21\x0b\x3f\x12\xd8\x86\xf4\x64\x94\xc3\xbd\xef\x14\xbc\x0d\x55\x20\x6f\x95\x6a\xed\xd4\xaa\xd2\xd8\x5e\x2d\x41\x99\xad\xd4\xca\x7a\x6b\xca\xad\x47\x5c\xe8\xb5\xbb\xd2\xc9\x32\x31\x77\x3f\x50\xae\x0a\x2a\x21\x57\xba\x93\x51\x4f\x6c\x2f\x46\xe4\x85\x95\xc5\xbf\x96\x77\xd1\x50\x00\x88\x59\xd6\x08\x97\x35\xc2\x65\x95\x0e\xae\x62\x35\xa3\xb5\x86\x75\x06\x66\x31\x91\xbd\x9a\xa2\x17\xbd\x92\x11\xac\x24\xca\x76\x66\x8b\xcd\x65\x04\x6e\x8d\xc9\x2a\x5a\x8f\x46\xe2\x7f\x39\x58\xe7\xc1\xc2\x4e\x0a\xe0\xd5\xa4\x74\x1e\x4c\x54\x21\x4b\x76\x93\x22\x43\x49\x91\xd5\x6c\x2a\x92\x55\x72\xc1\x34\x5f\x45\xeb\x85\xfc\x6b\x5f\x47\x8e\x9a\x08\x05\xe2\x87\x43\x97\xee\x2a\xee\x36\x36\xc7\x03\xae\x10\xd9\x3b\xf0\xed\x9b\x11\x8a\x1d\xdb\x0e\x3c\xd5\x2e\x4b\xf8\x57\xc5\x7d\x1e\xbc\x63\x92\x09\x26\x14\x0a\x7f\xde\x43\x11\x8c\x5f\x16\xbd\x43\xad\x9a\x28\x96\xd3\x24\x54\x60\xde\x37\xb9\xb1\xbe\xc1\x3e\x8e\x50\xfe\xc3\x6d\x6d\xbd\x80\x9e\xf0\x85\xec\xc8\xbc\x93\xdd\x1d\x9f\xf7\xf3\x69\xa3\x75\x35\xcb\x48\x21\x69\x98\x1e\x42\x63\xb8\x5a\x2b\x52\x2b\xbe\x6e\xa2\x5d\xf0\x72\xa5\xb1\x06\x5d\x80\x09\x23\x26\x5c\x44\xaf\x63\x0d\x77\xe3\x31\x61\x61\x0c\x31\x8d\x7d\xe9\x16\x81\x07\x37\xd6\x60\x35\x99\xd0\x39\x59\xc4\x5a\x68\x24\xe5\xd3\x90\x2f\xc2\x08\x22\x2d\xca\xaf\x11\x99\x10\x07\xa1\xe8\x14\xf1\x1d\xa5\x6c\x60\x65\xed\x93\xc0\xd4\x10\x5d\xca\x8e\x20\x38\xe4\x1d\xdb\x85\xf3\x57\xd4\xd4\xb6\x67\xfa\x9d\xc0\x2e\xdf\xb1\xb0\xe2\xf5\x1b\x59\xd9\xd7\x4b\xe2\x76\x42\x54\xaf\x62\xd4\x76\x1f\x60\xc4\xa2\x5b\x7f\xc7\x08\xfd\x0e\xbd\x74\x55\x7d\xa0\x1d\xc2\xa7\x6a\x57\xdc\x07\x9f\xcd\x66\x34\x65\x55\x1d\x5c\xcc\x66\x26\x58\xd4\xa7\xb3\x99\xbc\xb3\x13\xbe\x63\x8f\x7d\xf9\x12\x45\x77\x0e\x9d\xc2\xd6\x87\x03\x03\x37\x60\x99\xb3\x95\x5a\x97\x44\x44\xbb\xb8\x1e\x4b\x16\x1c\x51\x06\x79\x0b\xbb\xe6\xa3\xea\x48\x3f\xf7\x96\x5a\xb2\x2f\x0f\x22\x8d\xda\xaf\x30\x9a\x17\x18\xfa\x45\xa7\xcd\xd5\x51\x47\xe7\x11\xb2\x90\xc1\x9a\x4c\x74\x66\x95\xf1\xf0\x87\x3c\xf4\x30\xaf\xc0\x1d\xdb\xdd\x72\x7a\x2d\x28\x73\x0c\xed\xc3\x93\x30\x96\x21\xef\x20\xc9\xa1\xca\x49\x20\x30\x2b\x54\xfb\x4a\x17\xc4\xfa\x25\x3d\x31\x17\xf9\x8d\xd0\xab\x3d\x15\x87\x53\x26\x74\xa4\xd7\x53\xf8\xf1\xef\xea\x7d\xa8\x47\xa4\xd2\x1f\xfe\x95\xd1\xff\x64\xf4\x63\x48\x29\xf2\xb0\x2f\x21\x85\x35\x46\x9a\x5b\x38\xd4\x99\x28\x3f\x69\xae\x90\x43\xd3\x7e\x9b\x00\x13\xc9\xea\x03\xb2\xa5\x9a\x46\x7d\x29\x8b\x5b\xe3\x72\xa5\x24\x46\xba\xbb\x30\xc6\x73\x29\xda\xcc\xa5\xa3\xd1\x05\x28\x51\xdc\x1c\x81\x6e\x4c\xaf\x30\x0c\x7f\x5e\xe6\xc0\x87\x2a\x13\x08\x08\xde\x90\x62\x8a\x18\x1d\x26\xe8\x70\xf0\xa3\x30\x6a\x84\x93\x11\xdc\x3b\x2c\xa8\x36\xa7\xf2\x9d\xd4\x78\xe2\x32\x50\xde\x54\xcb\xff\x64\xc1\x5f\x99\x6d\x43\x15\x2f\x13\x63\x6e\x95\x28\x8d\x69\xe8\xf3\x30\xd1\xb9\x96\xc9\x92\x63\xe2\xff\x34\xcb\x13\xf8\x16\x6a\xa9\xa4\xd1\x2e\x3a\x3a\x81\x95\x94\x6c\x8d\x9d\x56\xba\x53\xdb\x2c\x2f\xd1\x66\x68\xb2\x63\xe6\xa6\xfa\x8c\x68\x3c\xf6\xc4\x01\x91\x16\x3c\xce\xfe\xc0\x68\x7a\xb6\xd9\x91\xd9\x85\x33\x9a\x86\x91\x20\x7d\x55\xf6\x39\x99\xe1\xbb\x91\x55\x5f\x26\x38\x0f\xd3\x15\x1f\x8f\xd7\x44\xac\xa5\xd8\x85\x6f\xb2\x07\xe0\x25\x63\xda\xb3\x94\x10\xd7\x05\x64\x77\xc3\x39\x66\x26\x71\x43\xa8\xc5\x82\x05\x50\x9b\x12\x60\x74\xf0\x86\x1a\x55\xda\x9b\x0e\xed\xe3\x33\x1a\xc9\x43\x85\x79\x9e\xdd\x08\x76\xf2\x28\x9a\x98\x60\x70\xc6\x4c\xc4\xfc\xae\xa4\xab\x32\x51\xb6\x3a\xbd\xe8\xb7\x01\xd6\x59\xff\xc9\x9a\x7a\x5d\x27\xb9\x3d\x46\xb3\x5c\x36\x56\x3f\x26\x41\xe3\x3b\x31\x05\xef\x48\x1d\xdd\xb8\xbd\x5e\x98\x1b\x57\xee\xc3\xf9\xaf\xf7\xe3\xf3\x0d\xe9\x24\x73\x3e\x66\xd2\x18\x50\x83\xd9\x02\x8a\x5c\xf6\xdb\x18\x24\x6a\x26\x58\x50\xc5\xd8\x9a\x62\x03\xae\x69\xfd\x58\xb6\x59\x36\x4e\x0d\xa6\x09\x93\xdd\x13\xca\x95\x3b\xee\x7b\xa9\x14\xc6\x88\x94\x88\x40\x0f\x2a\xe0\xd8\x01\x73\x5f\x40\x4e\x5d\x07\x6f\x09\x90\x79\x06\x6f\xa1\x76\xfe\x34\xde\xfa\xd1\xed\xe6\x34\xde\xb2\x1c\x0b\x57\x06\x68\xe1\x16\x5c\x37\xf1\x97\x7c\x1b\x3c\x79\x69\x51\x7a\x81\xb7\xad\x6f\x76\xdf\x14\xa5\x47\xbd\x78\xc7\xaa\xca\x0b\xf0\xaf\x00\x34\x0f\x73\xb4\x9c\x0a\x92\xd6\x8d\xef\x36\x88\xef\x36\x88\xef\x36\x0a\xdf\xa5\xe1\x1c\xdd\x41\x87\x0e\x26\x03\x45\x43\x64\x9d\x36\xb1\xf3\x11\xe4\x93\x36\x56\x37\x60\xff\x6f\x8c\xc4\xb8\xc1\x29\xdc\xc6\x29\x49\xc8\x1d\x9c\x92\x04\xb0\xad\x71\xc0\x0d\x66\xe3\x06\xb3\x89\xea\x06\xb3\x61\x65\x9c\xb4\x3a\xac\x2c\x42\x5b\xea\x96\xfd\x89\x3e\x6a\x5b\x56\xd9\x47\x8d\x45\x60\x9e\xeb\x91\xc3\xe1\xbd\x32\xd2\x33\x2a\x9a\xc3\x81\x4d\xb7\x25\x4f\x97\x6c\xaa\xbb\x9e\xcc\x8f\x32\x84\xb5\x75\x65\x03\xe6\xb6\x2c\x30\xd4\x4d\xde\x6d\x07\x03\x59\x57\x94\xbd\x85\xa5\x45\x8e\x1c\x33\x0c\xfb\x49\xf7\x08\x63\x00\xf4\xed\xb2\x24\x72\x74\x1e\xf5\x4a\xce\x92\x1f\xf2\xdd\xa3\x47\xbd\x1b\xf6\xf0\x2d\x40\xaa\x00\x17\xbe\xdb\x49\xa7\x25\xf9\xf4\xa3\xd4\x65\x53\xaf\x2c\xee\xdf\xee\x59\x2e\xca\x8b\x9d\xfc\x75\x5b\xf1\xef\xd8\xde\xa3\x1e\x78\x74\x7f\x81\x0e\x16\x54\x39\x58\x7c\x9d\x64\x18\x95\x73\x4d\x9d\x0b\x59\xc1\x04\x46\x74\x72\xe2\x9a\x00\x1f\xa7\xc2\xca\x46\xe1\xf9\xea\xd7\xfa\xd7\xf2\xd7\xfc\xd7\x74\x7d\xbe\x69\xd0\x12\x49\xf2\xa5\x00\xea\x2e\xe3\x2e\x13\x5a\xb2\x6d\xaa\xc9\x46\x23\x46\xb3\x70\x46\xaf\x9a\x01\x5d\x1a\x62\xbb\x13\x01\x31\x04\x43\x22\xad\xfc\xd4\x30\x7c\x66\x31\xab\xd2\x60\x4e\x1f\x3a\x22\x03\x60\x6c\x09\x72\x9b\x20\xd4\x70\x33\xa7\xae\x17\x57\x97\xd9\x22\x43\x01\xb4\x8c\xc5\x9b\xad\x69\x12\x62\xb8\x0b\x4b\xbd\x1c\x9b\x7e\x97\xbe\x37\xf0\xc6\x56\xc1\xd8\x1b\x78\xc4\x84\x85\x89\x28\x98\xa3\x8a\xff\xc8\x53\x6a\x45\x52\x8b\x30\xd5\x5f\x62\xcc\xce\x07\xde\x18\x5b\xbf\x9e\x41\x2a\xf5\x10\x9f\x16\x1b\xc1\x15\x95\xd9\x8d\x9f\x10\x6a\x7d\x08\x31\x81\x3d\x96\x70\xe3\x06\x87\x90\x38\xef\x25\x7b\x04\x56\xd0\x0d\xb4\x79\x38\xfc\x77\xef\x9c\x35\xbe\xff\xd5\x9b\xd7\xb3\x77\xf8\xd8\xb5\x83\x97\xe1\x8c\x24\x61\xa2\x7b\xd2\x6f\xa8\xdc\x51\x08\xd9\x86\x7b\x1a\x78\xde\x07\x6e\x2b\x72\xe8\xcd\x6d\xb5\x0c\x9e\xe4\x66\x2d\xfa\xec\x6c\x23\x3b\x30\x4d\x18\x2f\x23\x94\x48\x9a\x83\x44\xec\x70\x3b\x6e\x99\x24\x41\x5c\x15\x83\x6d\xac\xad\x36\xd7\x1a\xa5\xb3\xb9\x71\x63\x73\x05\x01\x15\x91\x63\xe0\xea\x31\xed\xf1\x29\x80\x45\x0d\x85\xec\x1f\x98\x02\x07\x00\x64\xca\xa3\x30\x5d\x25\x62\x77\xb8\xb8\x42\xf0\xf3\x11\x59\x72\x67\x32\x11\x09\xb8\x99\x6e\x84\xea\x5a\x3f\x16\x4c\x82\x23\xdb\xc1\xe0\xa7\xee\x78\x47\xa3\x6f\xb5\x1d\x26\xf5\xde\xbf\xd7\x2f\xde\xbf\xf7\x9a\x70\xdb\x78\x0e\xdd\xc7\xc3\x81\x21\x09\xe8\x79\x81\x2d\x57\x76\xfb\x24\x00\xeb\x10\x40\x4b\xce\xa7\x3b\x96\x62\x28\x80\x8c\x01\x90\xb5\x83\x65\x29\xe5\x9e\x15\xb2\x6e\x15\xaf\x1d\x93\x99\x81\x37\x56\xc5\xa7\xcf\x83\x86\xf7\x08\xe0\x5c\x65\xb2\x5f\xe8\xe4\xf5\xf2\xf2\x88\xa2\xf0\xfc\xd7\xb2\x79\x69\xdc\xb1\x5d\x1f\x2e\xd2\xe1\xcf\xc1\x41\xaa\x19\xba\x4a\x87\xaf\x6f\x00\x5f\x97\xf0\x54\x82\x0c\x5f\xb4\x62\xf1\x81\xad\x40\xb2\x74\x01\x52\x81\xec\x1d\xdb\xf9\x84\x04\x4c\xb3\x5d\x3c\x04\x97\xb7\x86\xae\x87\x2f\xf9\x58\xbc\x30\x36\x08\xd2\xab\x12\x55\x91\xbc\x2b\x58\xa3\x8a\xa3\xe6\x79\x01\x1b\x7b\xde\x91\x10\x2a\x68\xb3\x3b\xb6\xb3\xcc\x9f\x65\x6e\xce\x66\x71\x77\x8c\xdf\x35\x18\xd1\x4a\x6a\x2d\xb2\xa8\xb5\xc8\x80\x27\xa7\x1e\x70\x25\xe0\xc7\x04\x7d\x21\x93\xa2\x31\xaa\x09\x94\x66\x0f\x86\x77\x8c\x84\x9f\x1c\xc6\xa6\x3d\x0c\x3f\x0e\x23\x00\x6a\x33\x08\xb2\x8c\x03\x3f\x0e\xb9\x14\xa6\x74\xfa\x70\x28\x60\x8b\x22\xea\x79\x2a\x4f\x44\x2c\xd6\x2d\x56\x3e\x2f\x16\x28\x69\x7f\x43\x50\xb7\xf5\x50\x71\x2e\x57\xad\x06\x63\x1b\x39\x0f\xc1\x08\x59\xa2\x64\x19\x4c\x93\x41\x0a\x6b\xa4\xe7\xda\x3d\x3b\x21\x4c\x43\x15\x66\x1d\x53\xb7\xb8\x34\x60\x1a\x4a\x91\xd4\x44\xda\x17\x31\x19\x49\x6a\x76\xc9\xe9\x26\x4c\x97\x62\x00\x01\x64\xd2\x4c\x97\x7c\x3c\x0f\x94\xc4\x5e\x5c\xb4\x97\x7c\xb9\x0d\xd2\x25\x0f\x66\x8b\xad\x7d\xbf\x25\xe2\x72\x1b\xfa\x43\x23\x81\x1a\x8d\x32\x34\x99\xf2\x1d\xe1\xd3\xd2\xc8\x9e\xb4\xe8\xa0\x11\xec\x5c\xbd\xf7\x08\x39\x1c\x9c\x88\x85\xea\x8d\xc3\x26\xdb\x35\xa8\xa7\x42\xcd\x7b\x2a\xc4\x6a\x28\x4e\x1f\x9e\x24\x9a\x1a\x6f\x76\x99\xc0\x32\xd2\x57\xd9\xa6\xe5\x2c\xe5\x08\x17\xcc\x8a\x62\x14\x31\x95\x35\x3a\xb2\xc3\x48\x49\x94\xbf\x99\x4c\x48\x12\xf2\xd5\x66\x4d\xfd\xc4\xd0\xf4\x26\x2c\x6e\x22\x01\x2e\x05\x84\x05\x9a\xaf\xe1\x8c\xd8\xb1\x93\x1a\x9b\x16\x4e\xe6\x84\xa6\xc7\xa3\x43\xbb\x4b\x59\x9c\x11\x12\x36\x68\x6a\xe7\xd0\xae\xdb\xac\xbf\x15\x1d\xd1\x78\xfb\x2c\x75\x0c\x6e\x6b\xbc\x60\xf1\x85\x4b\x08\x38\x56\x27\x7b\x30\x62\x49\x60\x64\xdc\x2f\x42\xc8\x9b\x5e\xd4\xd3\x8a\x71\x2f\x8f\xc1\xd2\x2b\x72\x2f\x50\xd2\x44\x62\x26\xec\x45\xbb\xdb\x72\x00\x09\x7d\x06\x32\xcb\xcf\x40\xa5\xf7\x19\xec\x0a\x96\x0c\x4a\x5e\x65\x7f\xe7\x03\x34\x63\x1f\x60\x1a\xb9\x01\xa4\xa7\x1b\x24\xd1\x0e\x7f\x40\x9a\xa5\xa4\xb8\xcf\xf1\xd7\xed\x1e\xff\x8a\xab\x78\xa0\x33\x33\x0d\x54\x32\xa6\x81\x49\xdc\x34\x30\xc9\x9a\x06\xf1\x96\xe5\x1b\x3e\x90\x79\x1c\xaa\xdb\xe8\x26\xab\x07\xd7\xfc\x11\xfa\xbd\xe6\x8f\xfb\x92\x57\x95\xf8\x71\xbb\x1f\xf0\xb2\x2c\xca\x41\x8c\x69\x5b\x6f\x78\x7e\xeb\x66\xdf\x6c\xab\x34\x5c\xe9\x87\x11\xcf\xb4\xa4\x08\x33\xa4\x92\x40\xc0\x2d\xe3\x2b\xc6\x2a\xd9\x99\x4c\xcf\x11\x91\x56\x5c\xdf\xad\x98\xe0\x89\x14\x22\x66\xc6\x62\xd3\xcd\xa4\xfd\x08\xd2\x83\x43\xda\xa8\x3e\x09\x52\xad\xb3\xc4\x60\x7a\x3b\x1a\x93\x23\xbd\xcd\x5b\x4d\x1a\x0d\xd2\x54\xb7\x20\x26\x97\xe1\xf3\xc9\x68\xb4\x56\x87\xde\xe6\x3d\xad\x74\x9b\x79\x07\x43\xb1\xb4\x3e\xef\x9d\x9d\x79\x72\xf1\x44\x41\x44\x05\x49\x7f\x76\xe6\x89\x29\x48\xfa\x21\x8e\x94\xfa\x87\x26\x82\x94\x58\x9e\x2f\xf2\x29\x78\x94\xfe\xe5\xed\x0f\xdf\x77\x41\xba\x28\xc7\x1a\xbe\xb8\x64\x41\x85\x02\x8f\xbf\x7c\xf7\x6d\x5b\x6b\x4e\x63\x88\x2c\xcf\x0c\x9f\x63\xb4\xe3\xc4\x3a\x3b\x10\xcb\x33\x06\x6f\x85\xaf\x7e\xf8\xee\x47\xd1\x5f\x49\xa3\x30\xc6\xae\xbf\x29\x8b\x9b\xb7\xd0\x1c\x52\x60\xf0\x87\xfa\xfc\xe1\x66\xe7\x11\x19\xa8\x33\x21\x4f\x2a\x23\x8d\xca\x62\x33\x8c\x0e\x87\xa8\x27\xe3\x05\x74\x59\x02\x0c\x6b\x9b\x67\x50\x31\x43\x91\xef\xbd\xc9\xef\xd8\x2e\x4b\x06\xbf\x7c\xf7\x6d\x20\xc8\x3d\x42\x23\x74\xb8\xe0\x51\x78\xfe\xd1\xf4\xec\xe3\x73\x9a\x46\xe1\xb9\xbf\x5a\x8e\xd6\xe4\x7d\xb8\xfa\xdb\x68\x7d\x76\x4e\x37\x51\x78\xfe\x37\x7f\x7a\xb6\x24\xc1\x6a\xf0\x6b\xbd\x3e\xf3\x57\x7f\x13\x3c\xfd\xfa\x8c\x7c\x7c\xbe\xb9\xa1\xdb\x08\x45\x72\x2c\x2a\x6e\xeb\x03\xdb\xef\xc5\xbf\x49\x55\x17\x25\xdb\xf0\xc3\x74\x3c\x01\x60\xae\xb2\x22\x3f\xa4\xd9\x8e\x1f\x4a\x5e\x1d\xee\xb3\x64\xc3\x6b\x12\x7c\x7c\x4e\x33\xd9\xfc\x4f\x5f\xbf\x3b\xfc\xf9\xeb\xcf\xbf\x22\x1f\x9f\xd3\x2b\x51\xf6\xeb\xf9\xaf\xe7\xe7\xf4\x1a\x5e\xaf\x7e\xbd\x9f\x8e\x27\xeb\x71\x40\xfc\x65\x20\x5e\x40\x72\x98\x5f\xcf\x97\x1f\xad\xcf\xfe\x7f\x07\xe2\xe3\xef\x60\x7d\x26\xde\x07\xfe\xaf\xc9\x98\x1c\xc8\x81\x9c\xd3\x5d\x14\x3e\x1d\xe9\x0d\xfc\x9f\x47\xa1\x77\x76\xee\x29\x1b\x7c\xef\xcc\x23\xb4\x88\x42\x36\xdd\x15\x31\x18\xd0\x80\x14\x88\xee\xa3\xf0\x3a\x42\x5b\xe4\xa2\x21\x95\x44\x56\x41\x5b\x64\xfe\x16\x59\xe0\xe3\x2a\xb0\x7a\x32\x63\x45\x54\x8c\xc1\x43\x10\xd5\x62\x70\xf7\x23\x2e\x5f\xd2\xe4\x8e\x63\xa2\x38\x47\x25\x13\xf7\xc6\x60\x27\xbb\x9a\xad\x97\xbe\x60\x1b\x55\xe8\x18\x48\x1b\x41\x51\x08\xce\xc0\xc2\x79\xb5\x26\xda\x96\x2a\x26\x24\x68\xbe\x83\x4b\x36\xb6\x6d\x6d\xcb\xa8\x69\x17\x03\xfe\xb3\x82\xf3\xb8\x89\xec\x48\x5d\x5b\x7c\x9f\x69\x7f\xd8\xd5\x76\x8d\x56\x02\x70\x1d\x30\xf0\x3a\x5f\x39\xea\x73\xd9\xe4\x2a\xdc\x4a\x7b\x9a\x3e\x6b\x93\xab\xc3\x21\x3d\x1c\xf8\xea\x6a\xbd\x4c\x97\x43\x3f\x0b\xaf\x94\xf3\x70\xe0\x47\x90\x3e\x5d\xd0\xe6\x95\x9e\xda\x15\xa1\x1b\xf1\xdf\x70\x2e\x2e\xa4\x4c\xd3\x0c\x76\xe5\xd5\x6c\x4d\x0e\x87\x21\x07\xbb\xb6\xd1\x68\x03\xd0\x60\xe6\x5d\x45\x4d\x92\x22\x9f\xb2\x2b\xf6\xf0\x96\xd7\x75\x96\x6f\xaa\x69\xba\x63\xb5\xb4\xf7\x84\x74\xf8\xda\xae\x37\x22\x86\x94\x5e\xc5\xeb\xd1\xc8\xf7\xf9\x2a\x5e\x2f\x59\x90\x1c\x0e\x7e\x12\x3e\x1d\x09\x59\xc5\x6b\x78\x69\x22\xef\x58\xa1\xba\x86\x33\xca\x68\xe2\x24\x77\xa9\xa3\xde\x54\x18\x28\xa8\xab\x20\x94\x83\x9e\x9c\xa4\x6c\xbc\x33\x01\x18\x99\x98\x6a\x36\xc5\xa5\xb1\x14\x4b\x89\x8c\x3a\x79\x93\xdd\xc8\x30\xd6\x80\x56\x7e\xe2\xd5\xbe\xc8\x2b\xfe\x67\xce\x12\x5e\xfa\x9e\x0c\x24\x3a\x79\x87\x49\x6d\x04\x3c\x26\x44\xdb\xd4\x6c\x05\x41\xb9\x05\xb3\x1a\xf1\x3f\x8a\x56\x13\x41\xcc\xe9\xdd\xe0\x64\x11\x95\x9c\x5d\x1f\xb3\xd4\x17\x63\xc9\xf2\x41\x4c\x52\x18\x16\x5a\xc2\xeb\xce\x62\xd4\xb7\x64\x32\x63\x4f\x5c\xe4\x77\xbc\xac\x79\x59\xad\x80\x95\x1c\x8b\x17\x6b\xf2\x94\x86\x5c\xf6\xb8\x81\x28\x85\x9c\x1c\xd1\xff\x49\x6d\x74\xba\xf4\xd3\x21\x4e\x7c\x34\x32\x03\x49\x09\x8d\x57\xa9\x71\x3c\xd7\xcb\x7b\xdb\x04\x72\x2b\x86\xef\xd3\x91\x5e\xdb\x4b\x2b\x4f\x17\xac\xc3\xf5\x6a\xbe\x26\x26\xb9\x9d\x35\x60\x72\xb5\xda\x34\x05\xa3\xce\x84\x36\xeb\x45\x1a\x5e\xab\x4d\x91\xfb\x95\x8a\xc5\x84\x6c\xb7\xb0\x03\xdf\x64\x7c\x97\x54\xab\x54\xc0\x50\xbc\xea\x28\x5f\x87\x11\x81\xfc\x1e\x90\x4d\x55\x0c\xf1\x1b\x30\x8c\x03\xc9\xbd\x5d\x00\xc9\x11\xd5\x14\x08\x98\x7d\x53\xeb\xf3\x90\x8c\x03\x60\x25\x15\x1b\xa3\xf3\x6c\x78\x67\x9e\x58\x46\xe4\x0d\x52\xd8\x9c\x4d\x78\xb5\xca\x60\x33\xd2\xf5\xe1\x70\xb5\xf2\xce\xe0\x27\x1d\x6e\x88\x95\x96\x47\xc0\x44\xc8\x6d\xca\x69\xbb\x9a\xaf\x65\x14\x0f\xd3\xc5\x56\xec\xa7\xee\x05\x9e\x08\x79\xda\x80\x61\xe2\x72\x03\x29\x7d\x02\xf1\x1f\xe4\xe9\x87\xe4\x41\xa2\x0e\xbd\xd6\x3b\x2a\x7a\x25\x16\x78\x6d\xa0\x26\x41\xef\x38\xb6\xf2\xea\x6d\x59\xdc\x57\xde\x9a\x44\xe1\xc6\x8f\xa4\x3d\x98\xb8\x8f\xf1\x59\x5e\xb2\x3b\x1d\x2a\xb2\xaa\x05\x4d\xe2\x5c\xa3\x14\xfe\x04\x9b\xe5\x2e\xf0\xbe\x2f\x06\xb8\x85\xe2\x2e\x1b\xa4\x65\x71\x23\x80\x72\xec\x0d\xea\x42\xac\xc2\xf1\x78\x74\xfb\xa9\x6e\xc1\x85\xc3\xa3\x62\xe9\x83\xe8\x68\x05\xbb\x61\x71\x9d\xdd\xf1\x60\x46\x77\xac\xaa\xbf\x2b\x92\x2c\xcd\x78\x12\x3c\x1d\x29\xaf\xd9\x46\xfc\xb5\x91\x4d\xf0\x74\x5b\xee\x82\x22\xa2\xa0\xa5\xf4\xfe\xf4\xf5\x3b\x8f\x66\xd5\xb7\x45\xcc\x76\xc1\x36\x92\xf1\x9f\x23\xb1\x16\x14\xe3\x00\x07\xc3\x19\xdd\x97\x85\xf8\x38\x64\xcf\x10\x28\xa5\x7a\xcc\x63\xf1\x43\x62\x0c\xcc\x3d\xcd\xf6\xfb\x5d\x86\x77\xdf\xf9\xc3\xe4\xfe\xfe\x7e\x92\x16\xe5\xcd\xe4\xb6\xdc\xf1\x3c\x2e\x12\x9e\x2c\x20\xcb\x7e\xc5\xeb\xf0\xe7\x77\xdf\x4c\xfe\xe8\x51\x4c\x9d\x51\x05\xe0\x30\x99\x47\x14\x12\x4f\x20\xe1\xb2\xdf\xb1\x2c\xf7\x30\x50\x3b\x96\x88\x9f\x1e\x7d\x10\xcf\xce\x97\x6e\x76\x74\xa0\x69\x1d\x7a\x55\x41\x8c\x36\xab\x82\x28\x91\x35\xae\xd8\x1d\x93\x91\x9a\x8f\x6a\xec\x55\xf0\x24\xfa\x14\xad\xcf\xf1\x73\xf0\xa5\x73\xec\x09\x5a\x9f\x1f\xa9\x7b\x5c\xb0\x89\xa7\x0a\x7f\xf9\xee\x5b\x4f\x8e\x5d\x15\xbd\xe3\x0f\xb5\x1a\x8c\x2a\x13\x24\x21\x7e\x57\x1e\x5c\x31\x6f\x18\x98\x17\x20\xd9\x86\x44\xdb\x00\x66\x2a\x96\x17\x1f\x45\x2f\x5e\x60\xd1\x9b\xb2\x5c\xcc\x37\x30\x54\xe5\x91\x5a\xd7\x08\xee\xb2\xda\xa1\x87\x3a\x18\x0a\x96\x4d\xc2\xc1\x6d\x8f\xfa\x32\x5a\x56\x91\x0f\x97\x95\x7b\x3f\x09\xd6\x2f\xa8\x22\xdf\x2d\xa5\x82\x25\x10\x05\x3f\x6a\x6b\xeb\xdf\x22\x7f\x17\x11\x28\x7c\x57\xb2\xbc\xda\x17\x65\x2d\x0a\x6f\x64\x61\xe3\xb3\x6d\x7b\x6a\x44\x36\xb6\x15\x68\x18\xc1\x8d\xd8\x91\x23\x8c\x5e\x9b\x6b\xf4\x76\x2f\x3d\x2f\x76\xe1\xf5\x54\x4e\xf9\x70\xb8\xa6\x37\xe6\x71\x34\xf2\x77\x56\x96\x85\xdd\xf4\x0a\x72\x63\x91\x65\xee\xef\x74\x2e\x6e\x5a\x38\x4e\x2f\x74\x1f\xe6\xd3\x2f\xd9\x6e\x17\xb1\xf8\xba\xf2\xbd\x22\x8f\xf9\xe0\x86\xdf\x14\xe5\xa3\x47\xe8\x6f\x02\xe9\xd5\xac\xbe\xad\xbe\x2c\x12\x0e\xb1\xf4\x4b\x81\xe2\x2b\xf1\x5f\x1d\xce\xe8\x6d\xe8\xc5\x2c\x8f\xf9\x8e\x27\x1e\xbd\x0b\x9f\x4a\xce\x92\xc7\xb7\x70\x9c\x67\xb4\x75\x3b\x76\xf8\xbe\x67\xa9\x7f\x11\x86\x61\x8d\x57\x19\xb8\xe6\x3e\x1d\xb5\x70\x79\x13\x69\x1f\xb7\x74\x15\xb5\xb3\x02\x84\xd1\xea\x62\x7d\x8c\xc2\x74\xc5\x1a\x6f\x8e\x0e\x3b\x1e\xa1\xd8\x27\x3a\x8a\x31\x7d\xbe\xdb\xb9\xc3\xaa\x3a\x22\x6a\xc0\xa0\x96\x3c\x40\x5b\xaf\x4a\xcc\xe4\xb7\x5b\x5e\xd5\xad\x89\xd8\x39\xcd\xdc\xac\x60\x8a\x9f\x3b\x1c\x7c\x16\x56\x82\x86\xc1\x84\x04\x8c\x96\x2b\x06\x77\x11\x2a\x18\x04\xcb\x5a\x66\x09\xff\x4e\x12\x16\x9d\x1a\x73\x90\x34\x29\xd2\x23\x64\xaa\xad\xd9\x9c\xee\xb5\x05\xe7\xae\x8b\xcb\x9a\x68\xdf\x34\x46\x7e\x13\x4c\xf8\xea\x37\x30\xe9\x5b\x45\x6b\xa4\x2a\x06\x77\xca\x1d\x82\xad\xee\xe4\x9e\x37\xd2\x82\x52\x16\x09\x60\xef\xd0\xdb\x1e\x0e\xb7\x5a\xbc\x33\x1a\xc5\x53\xa8\xe8\x47\x84\x3e\xf8\x33\x95\x82\xfc\x78\x14\xe3\x29\xb4\x77\xd1\x1d\x31\x76\xf2\xfb\x29\x4b\x12\x7a\x37\x95\x17\x40\x78\x87\x2e\x1c\x77\xc8\x87\x85\x77\xe0\xaf\x21\xee\xb1\x72\x17\xfa\x3e\x3b\x1c\xe0\xe7\xe1\x50\x44\x44\x30\x9e\x5a\x8a\xc9\x41\x8a\xa9\x1f\xaf\x22\x0a\x68\x7e\xec\x9d\x9f\x43\x48\x2a\xcc\x11\x38\xbd\xe1\xf5\xb6\x48\x04\xfd\x86\xa2\xc1\x6b\x5d\x82\x55\xe8\xb5\xa1\x5f\x94\x36\xd0\x14\x61\x76\xb9\x7e\x16\xc4\xf3\xd6\x52\xa2\x7d\x3d\x8d\xcb\xa2\xaa\xbe\x2a\x6e\x58\x96\x43\x9c\x7d\xc5\x27\xc1\xf8\x1b\xac\x12\x75\xaa\x87\x43\x7f\xb8\x3d\x1c\x24\x1d\x00\xd3\x10\x24\xe3\x85\x7c\xba\x10\x44\xce\x16\x1d\xe7\xbd\x6d\x5d\xef\x03\x41\x8e\x88\xda\x4b\xef\x8f\x33\x2f\xf0\x3e\xfd\xf4\x95\x47\x08\x78\x7d\x46\xcd\x6a\xd0\x9b\x53\x0f\xbe\x2e\x26\x38\x1a\x5d\x4f\xad\x9b\xd0\x68\xae\x34\x73\xa1\xea\xc9\x15\x09\x01\x3b\x33\xb5\x40\x62\x91\x4b\x96\x40\x1c\x51\xb6\x23\x84\x96\x02\x5f\xd2\x6b\x1a\xd1\x3b\x42\xf1\xa4\xab\x68\x39\x8b\x4c\x25\xa2\x12\x5f\xc5\x9b\x98\x66\x18\x23\x2a\x9f\xe2\x8d\x3f\x1e\x03\xa5\xef\x64\x65\xf5\x00\x23\xd6\xac\xac\xcd\xa6\xe2\x1f\x37\x2a\x28\xbd\x06\x9d\x94\x4c\xc4\x32\xcc\xe4\xcd\x8f\x55\x09\x4d\x42\xd8\x05\xa7\x16\x9c\x32\x39\x3f\xf9\x7e\x1c\xfa\x49\xa4\xe8\xf4\xa5\x37\xf2\x02\x6f\xe9\x91\xb1\x9c\xae\x34\x5a\xc1\x27\xd8\x42\x16\x6f\xb9\x4a\x85\x8b\x10\x9b\x9a\xe6\x46\x47\x99\x46\xd4\xfb\x78\xfe\x3e\xf4\xc6\x71\x34\x1e\x93\x20\x19\x77\x7e\xc6\xd3\x35\x44\xe7\x59\xaa\x48\x1f\xc8\x61\x62\xd3\x42\xab\x64\x3d\x1a\xdd\x4d\x9b\x88\xca\xf7\xde\xa4\x13\x55\x67\xf2\x36\xcb\x63\xee\xd1\x56\x4b\x90\x42\xd6\x6c\x73\xaa\x93\xef\x8b\x9c\x4f\xbe\x13\x60\xee\x99\xda\x84\x50\xdf\x00\x8e\x59\x47\xf1\x64\x11\x4e\x43\x4c\x24\x1c\xd9\x65\xa4\xfb\x4b\x0e\xfb\x44\x9d\x5e\x08\xed\x6a\xf0\x39\x10\x58\x9e\x7d\x66\x81\x8f\xb9\x96\x59\xcb\xaa\x95\xfb\x66\xbd\xec\x7d\x33\x96\x14\xbc\x5b\xbc\xf4\xe8\xc0\x1b\xe7\xd1\xd8\x5b\x0c\x7e\x0b\x67\xd3\xd9\xdc\x0b\x3c\x8f\x04\xa6\x1b\x70\xf5\x02\x8e\xf6\x4a\x60\xd8\xeb\xe9\x16\xaf\x15\xd2\x31\xde\x2b\xaa\x5f\xaf\xae\x30\xdb\xe1\xf5\x14\x13\x43\xbc\xe5\x79\x82\x61\x40\xf5\x23\xea\xcd\x76\xf4\x8e\x5e\x13\x99\x8d\x19\xcf\x90\x3e\x44\x12\xd7\x92\xc5\x6d\xe8\xc1\x4f\x4f\x0f\xe4\x49\xa2\xd3\x60\x2e\x89\xf2\x39\xd5\xbe\x5b\xf3\x23\xb9\x5b\x5d\xad\xfd\x6b\x35\x88\x38\x2c\x05\x11\x23\x4f\x2a\x79\xba\x9b\x9a\xab\x3c\x9c\x43\x8a\xba\xc6\x01\x84\x04\x17\xab\x3b\x7a\xbd\x16\xa0\x09\xf4\xb2\x58\xf5\x1a\x8d\x8b\x2f\x67\xc0\xba\x74\x47\xa7\x50\xa3\xf6\x64\x65\x8f\x1c\xa9\x6e\x49\x30\x9d\x4f\x1d\xce\x69\x3c\xad\x04\xf5\x5f\xd2\x07\xc5\x7b\xdc\x23\x9d\x00\x57\x1a\x01\x76\x65\x70\xbf\x78\xf0\x27\x73\x7a\x4f\x8e\xe8\x06\x0c\x4f\x82\xf7\xd0\xf4\x99\x67\xc5\xa3\x7a\xc0\x30\xad\x5a\x98\x42\x4b\x5a\xd1\x5b\x7a\x4f\x1f\xc2\x68\x71\x31\x0c\x43\x41\x45\xd5\xe1\x05\xdd\x8c\x46\x8e\xb1\xf4\x86\xe8\x1c\xe9\x94\x43\x84\x10\x8f\x3a\x8b\xc4\x2e\x67\xcb\x4f\x83\x19\xbd\x0a\xd9\x65\x78\x31\x9b\x8d\x46\xaf\x66\xb3\x4b\x76\x38\xbc\x9a\x7d\x1a\x86\x21\x03\x0b\xb1\xdb\xb0\x8e\xfc\x6b\x7a\x47\x53\x42\xe8\x6d\x78\x2b\x1e\x6e\xe9\x1d\xbd\x22\xf4\x6a\xe9\x37\x4e\xf8\x7d\x78\xd7\x25\x61\xf8\x96\x55\xb5\x3e\xd3\x1e\xa1\xf7\x5d\xc8\x20\xbc\x27\xb4\xa7\xbd\x38\xbb\xba\x99\x3c\xc8\xe1\x3d\x21\xf4\x02\x07\x7a\x38\x78\x7f\xfe\xfa\xf3\xaf\x20\x6e\x02\xe0\xca\xe5\x43\xe8\xe5\x85\x0a\x22\x1b\xc8\xf9\x60\x69\x7d\xa3\x06\x12\xf8\x0f\xe1\x2d\x50\x0e\x9c\x96\xe1\x2d\xe2\xc7\x2a\xbc\xc5\x4b\x9c\x5e\x85\xc3\x8a\x90\xc0\xaf\xc2\x07\x2a\xae\xf0\xe1\x03\x19\x8d\xfc\x87\xd0\x93\x7c\xe3\xec\x12\x52\x12\x85\x33\x71\x19\x29\x0a\x24\x64\xfa\x27\x04\x31\xf7\xa3\xc3\xe1\x41\xdc\xf9\xf4\x6a\x59\x38\xde\xb1\x3b\xba\x2a\xe9\x03\xbd\x5b\x93\xa0\xb0\xfd\x63\x77\x02\x44\x1f\x68\xb5\x36\x9d\x0a\x6a\xc9\xff\x4d\x10\xb7\x72\x3b\x1d\xe0\xbe\x5a\x22\x78\x4b\x5e\x34\x80\xa7\xaf\x71\x8c\x02\xda\xe9\xd5\xb2\x0c\x44\x77\x7b\x08\x8a\x61\x7d\x64\x0d\x99\x1c\xfd\xc6\x39\xf9\x52\x1e\x39\x7d\x56\x26\x13\x75\xb9\x1d\x0e\x3d\x57\x5b\xb1\xb7\x53\xcf\xdc\x01\xd5\x2a\xb8\xa2\x3e\xf1\x7f\xae\xec\xff\x68\x4c\x3d\xe0\xa5\x08\xb4\x79\x0b\x8c\x60\x9f\x5a\x0c\xdb\xc8\x35\x88\x4c\x82\x1f\x47\x0d\xb7\xe1\xb5\x47\xbd\x7d\x51\xd5\xed\xa0\x90\x4d\x65\x8e\xeb\xbc\xe3\x0a\x61\x41\x63\xcf\x0f\x87\x84\x26\x61\xac\x4f\x12\x91\x6c\x98\x0f\xbc\x1c\x43\x86\x3d\xa2\x0a\xfd\x06\x1c\x45\x01\x31\x55\xa8\x2c\x51\x96\xa0\x2a\xa5\x4f\xa7\x0a\xae\xdd\x27\x0a\x01\x74\xbf\x6a\xae\x8a\xcd\x9f\x6b\x41\xc0\x9c\x2a\x29\x88\xe0\x27\x49\xc3\xdb\xf2\xbe\x64\xfb\xcf\x77\x1d\x26\x15\x8b\xae\x59\x33\xb2\x3c\x6d\x91\x25\xbb\x73\xad\xb1\x08\x39\x12\xcc\xaa\x01\xf7\x18\xe8\x78\x7b\x52\x46\x91\x29\xff\xcd\x9f\x11\x2b\x7d\x8f\xaa\xe6\x5a\x4c\x3a\x69\xff\x64\x15\x42\xa3\x66\x3a\x39\xf4\xfe\x00\x3f\x75\x64\xc0\x18\xa6\xa1\x92\x9a\x13\x4c\x8d\xc8\xc2\x8e\x52\x13\x9f\x58\xe7\x45\xab\x31\x07\x99\x0c\x4a\x27\x66\xfa\x26\xcf\xf9\x33\x6e\x0c\xbd\x96\x4e\x8d\x45\x83\xae\x5a\xcb\xd6\xca\xa1\xa0\xad\x97\xe2\x50\xd3\x1e\x95\x6f\x5c\x95\x96\xb1\xd9\x02\x12\x44\x56\x4a\x37\x39\xe4\x4e\xf3\x06\x67\x88\x8b\x93\x59\xc4\x9a\x1b\x1d\xb9\xa6\x30\x24\xc0\x4f\xdd\xe6\xee\xc7\xdc\x95\xc1\xbd\xec\xc8\x2e\x6a\x99\x09\xa0\x29\x13\xe6\x61\x3f\x1c\x8c\xc5\x9f\x4e\x24\x25\xcd\xaa\x4c\xe6\xdc\xa3\x74\xfa\x55\x46\x1e\xfb\x52\xba\x09\x57\x2a\x5a\x4a\xa7\xa1\xb0\x15\xba\xf5\x75\x38\x1b\x8d\xdc\x80\xea\xaf\x43\xf0\x75\x72\x7a\x83\x14\x02\x3b\xde\xd1\xdd\xb0\xf3\xbb\x62\xf9\x41\x18\x72\x17\x85\xe7\xff\x7c\x31\x3b\xdf\xd0\xfb\x28\x3c\xff\x75\xf5\xeb\xfa\xe3\x73\xfa\x00\x66\x4e\xcb\x5f\xf3\xf3\x0d\x7d\x94\x9a\x30\x54\x51\x4b\x63\xf6\x43\x76\xc3\x36\xa0\x34\xe3\x35\xe8\xcf\xc8\xc7\xe7\x19\xfd\x7b\x74\xca\x0c\xfe\x9a\x3f\x6e\x78\x4e\xce\x33\x43\x27\x7c\xde\x94\x71\xb7\x02\x87\x4a\x14\xe9\x78\x62\x71\xf2\x14\x1f\x0e\xf7\x91\x8a\x6b\xba\x4c\x7c\x46\x39\x09\x44\x6f\x63\x6f\xe5\x8d\xfd\x96\x40\x88\x2f\x23\x41\x4e\x8e\xbd\xb5\x47\x39\x2a\x7c\xad\xcc\xcd\x87\x83\x6a\x30\xd4\x59\x9f\x23\x42\x12\xc0\xc0\x0d\x7f\xdd\x88\xe8\xcf\x70\xe8\x2e\x5a\xf1\x35\xf6\x28\x99\xb4\xb0\xd3\xfe\x03\x73\x86\x35\xc2\x08\x84\x0d\x27\xfd\x65\xe4\x2b\xf3\xa0\x68\xe9\x79\x02\x49\xaf\x94\xe9\xcc\x3a\x44\xe9\xe7\xcf\x3f\xbd\x11\xb7\x5d\x91\x43\x96\x3b\x32\xf6\x42\x6f\xdc\xf1\x26\x22\x47\x27\x9d\x64\x24\x2d\xe7\x6d\xc9\x9b\xe0\xfa\x1c\xfd\x91\xcd\x55\x5a\xe1\x68\x18\x18\xa3\xa3\x9c\x4b\x46\x16\xf8\x71\xc7\xb2\x5c\x3b\xa1\xab\x6d\x72\x82\x0b\xe3\x79\x99\xe6\xec\x86\x53\x63\xa7\xa5\x17\xde\x0a\x8d\xf3\x79\xe4\xc7\x14\x42\xe0\x88\xcd\x35\x51\x0a\xae\x8a\x2c\xf7\xbd\x91\x25\x6c\xb8\x8b\xa8\x37\xf6\x9a\x17\x46\xc5\xcb\x8c\xed\xb2\xbf\x77\x66\x85\x91\x9c\x33\xc6\xb7\x54\x15\x71\x5e\x84\x1c\xa9\x5b\xd4\x87\x1d\x3a\x71\xb8\x74\xbd\x42\xac\xc0\xa5\xe2\xdb\x18\x61\xb1\xa5\x6d\xe4\x23\x6d\x4d\x8f\x44\xc5\x09\xe8\xbc\x12\x00\xf6\x1c\x6c\x97\x83\x79\xe6\x50\x21\x9b\xac\xf2\xbd\xc0\x58\x37\x8d\x46\x7f\x97\xc7\xc0\xb1\xaa\x23\xa3\xd1\xf0\x31\x32\x29\x40\x15\x5e\x92\x59\xe6\x87\x2a\x7b\xbe\xb8\x05\xdd\xb9\xd9\xfe\xc3\xb6\x05\xa1\x1b\x3e\x33\x46\x49\x9f\x81\x90\x18\xf2\xfb\xb3\xbd\x1f\x77\x18\x0a\x3e\x89\x39\x04\x11\x42\x02\x00\x41\x60\x92\x8c\x3e\x44\xd4\xfb\xb5\xfc\x35\x07\x8a\x28\xe8\xa8\x1a\x77\x57\xc5\x4c\x79\x88\x57\x1d\x18\x7e\xd8\x96\xb6\x2f\xa6\xe0\x72\xac\x80\xb8\xbf\x7c\xf7\xed\x9f\xeb\x7a\x2f\xd9\x45\xc9\xef\x30\xf2\x74\x44\x6c\xf8\x45\x14\xce\xe8\x97\xa0\x97\xff\x2a\x0a\x9f\x66\xe0\x64\x3a\xbf\xb8\x78\x15\x5c\xcc\x3e\x3d\xd2\xaf\x9b\x27\x48\x7c\xcd\x27\x0b\x36\x65\x75\xcd\xe2\xed\xd7\x28\x67\x71\x1e\x7d\xaf\xc8\xd1\x8e\xc8\xb3\x4f\x87\xce\x85\x2b\x8e\xc0\x97\x11\xf9\x32\x5a\xb1\x35\x44\xc3\x12\xec\x78\x59\x85\xc3\xe1\xd7\xd1\x68\xe4\xdd\x67\xf5\xf6\xcb\x92\x27\x3c\xaf\x33\xb6\xab\xbc\x2c\x1f\x7c\x1d\x09\x56\xf0\x8a\x3d\x84\x5f\x47\x50\x4d\x2e\x81\x66\xc5\xfc\x5e\xca\x09\xfb\x3e\x1c\x44\xd7\x43\x66\x8b\xc2\x96\x4f\x95\x93\x35\xda\xd6\x3b\x86\x0c\xe7\x49\x37\xe1\x78\xfc\x45\x84\xe9\xc0\x8a\xbd\xb8\x45\x50\x94\xc7\x40\xc6\xc3\x90\x3f\x15\x4f\x15\x2f\x61\x0b\xd9\x74\xcf\xaa\xea\xbe\x28\x13\x42\xa1\x13\xd4\x7b\x18\xb5\x9c\x53\xb8\xe2\xeb\xd0\x2a\x58\xf1\xf5\xc2\x68\x82\x47\xa3\x74\xda\x14\xe2\x76\x95\xf9\xa6\x89\xf8\xa6\x35\xc5\xc3\x21\x5e\x79\xbf\x4c\xe4\xde\xf3\x64\x02\xb9\x1f\x21\xa0\x7e\x57\x79\xe8\xb9\xc0\x22\x23\xcb\x48\xa5\x70\xda\x96\x3a\x70\x1a\x43\xac\x86\xa8\xeb\x52\xb7\xb6\x5e\xa0\x62\x29\xd2\xfa\x12\x02\x5d\x47\x61\x3a\x2d\x00\x44\xe0\x07\xca\x63\xc1\x98\x49\x4a\x1b\x80\x13\x4c\x95\x14\x22\x90\xdc\x1c\x94\x26\x90\x99\x4d\x70\x5c\x34\xb5\x98\x38\x12\x24\xfe\x57\xd1\x4a\x15\xad\x0f\x87\xce\x6a\x6d\x7b\xd5\x74\x6a\xab\x9e\x96\x32\x87\xbb\x53\x78\x94\xba\x6a\x9a\x4e\x3b\x05\xfd\x3e\x01\x33\x53\x3d\xa7\xc8\x27\xd4\xcc\x2b\xf2\xe5\xf0\x09\x8d\x42\x98\xbf\x28\xc2\x79\xca\x1c\xc3\x28\x90\x60\x8e\xa8\x0b\x55\xc5\x18\xe2\x42\xc9\x29\xb6\x32\xf5\x06\x8a\x28\xb6\xc7\x96\xf0\x1c\xd6\x3a\x12\x68\xc2\x8e\xeb\x6e\xe9\x7a\xb4\xe2\x10\x59\x15\xa9\x21\x34\xea\x3d\x3a\x70\x34\x80\x3d\xe5\x3c\xbe\xe9\x2c\x7f\x98\x98\x37\x8e\xa2\x50\x7e\xed\xdc\x5f\x06\xa2\xcf\x83\xa8\x46\xb0\xf0\xbc\xa1\xd8\x03\x0d\x9d\xec\xa2\x8b\xac\x77\xb2\xac\x32\x42\xd9\xd1\xe0\x44\xad\x50\xf3\x35\x2b\xe6\x60\x06\x9d\x6a\x1a\x05\xaa\xe0\xf1\x89\xa2\x55\x74\x4f\x75\x05\xeb\xca\x7f\x5b\x30\x79\x44\x7f\xc3\x20\x9d\xce\x6f\x80\xed\x80\xd5\x8f\xb1\x53\x53\x5a\x69\x07\xeb\x00\x6f\x2b\x38\x0a\xef\x35\xf6\x76\xe9\x11\xbc\x65\x9f\x8c\xae\x18\x75\xbf\x01\x9b\x62\x95\x2f\xf1\x99\x56\x65\x1c\x00\x22\x3a\x92\x69\x91\xfb\x1e\x98\x6e\x4a\xb9\x47\xec\x1c\xc9\x48\x27\x5d\xa6\x31\x9e\x33\x36\x1a\x71\xdf\x3a\x56\x28\x91\xf9\x74\xf6\x29\x5c\x00\xf8\x88\x91\x0a\xb7\x9c\xb9\xc9\xd2\x22\xc1\xe6\x75\x40\x5e\x3c\x1a\xc5\x02\xf2\x94\xe9\xdf\x37\x91\x20\x01\xff\x14\x85\xe7\x7e\x48\x7e\x5d\xfa\xcb\x70\x74\xf8\x98\x1c\x7e\x5d\xa2\x11\xa0\x05\x94\x57\x55\x91\xef\x03\x2f\x96\xfa\x42\x54\xff\xee\x95\xfa\xb0\x1d\xe0\xfc\x9b\x08\x63\x36\x80\xa4\x03\xe2\xfb\x15\x63\xef\x3d\x4a\xb4\x6d\x5a\x62\xc5\xc0\xf8\x89\x75\x02\x88\xf8\x06\x68\x88\xf7\x9e\x13\xf5\xa0\x99\xca\x23\x9a\x42\x25\x15\xf0\xe5\x4f\x92\xca\x88\xc4\xc2\x93\xa5\x77\x5b\xee\xbc\xa0\x85\x54\x22\x29\xbd\x1e\xfa\x8e\x74\x1a\x3d\x9e\xb4\xab\xd1\xb3\x7a\x7f\x41\xef\x98\x0f\x82\x32\x60\x34\xf2\xc4\x5f\x43\x75\x6d\x0f\x07\x0f\xa7\x01\xe9\xc8\x1d\x19\xb3\xcf\xd5\xf0\xd5\x62\x36\x08\x70\xf7\x25\x59\x36\x0a\x7c\xc1\xbe\x3a\x25\x74\xbb\x8c\x56\xdb\x75\x28\xfe\xd3\x74\xca\x9f\x40\xeb\xe0\x8d\xb9\xae\xae\x56\x2b\x6a\xe8\x3a\xd4\xaa\x29\x45\x84\xac\x8e\x34\x3d\x24\x9a\x35\xc6\x39\xf2\x78\xa1\x16\x7f\x1d\xb6\x09\x55\x48\x9e\x8a\x36\x95\x7c\xec\x0d\xee\x59\x35\xc8\x8b\x7a\x20\xc0\x08\x24\x98\x9b\xd5\x6c\x7d\xa4\xee\x92\x84\x28\xc8\x82\x20\x93\x7c\x4d\xc5\x7f\x76\xcf\x1b\x63\xef\x7a\xa4\x49\x47\xe8\x46\x6c\x00\x3c\x10\x4c\xcf\x5d\xdc\xb8\xb1\x58\x02\x50\x6f\xab\xad\xcf\x89\xcc\x7d\x6d\xad\x7d\x4a\x46\xa3\xd4\xdf\x80\xcc\x64\x13\xa6\x26\xb0\xb2\x96\x98\xd9\x28\x1c\x6c\x15\x20\x8f\x65\x53\x58\xf7\x32\xf3\xd7\x4e\xff\x31\x69\x09\x29\x70\x1f\x98\x0b\xec\xd0\x1e\x32\xbc\x53\xa9\xf3\x29\x0f\x87\xf1\x68\xb4\x5a\x9b\xdc\x74\xab\xa8\x11\xfa\x22\x59\xcd\xd7\x64\x1d\x40\xac\x4f\x37\x23\xf9\x8a\x21\x7f\x83\x01\x89\x54\x7a\xf1\xdc\xe7\xc4\xa0\x23\x95\x0e\x7c\xb5\xa6\x89\x2d\x47\x90\xcc\xfa\x9f\xc1\xf1\x23\x9f\x0a\xd4\xb6\xd0\xbf\xba\xd6\xa0\x2b\x38\xd6\x9f\x23\xb5\x06\x7f\x8e\xba\xe3\xfa\x2c\x6c\x7f\x6d\x78\xb7\x0d\x99\xed\x0b\x68\x8e\xd9\x65\x08\x1e\x9d\x4a\x73\xcb\xa4\x09\xda\x96\x10\x0a\xe1\xf8\xe0\x69\x06\x89\x7b\x9a\x4c\xae\x5c\x67\x29\x9c\x0c\xa2\x8e\x80\x78\x10\xd6\x3a\xf4\x7e\xfc\xe1\xed\x3b\x01\xb9\xda\x5c\x5d\x71\xac\x8e\xd8\x91\x5b\x22\x47\x34\xee\x91\xa6\x4d\xa4\x11\x57\x96\x91\xa7\xd4\x40\x34\xdd\x60\x62\xf9\x64\x29\xae\x9b\x24\xbb\x13\x77\x8d\x14\x4e\x59\x10\x26\xb8\x24\x70\xb6\xf1\x13\x94\x24\x69\x8d\xba\x1f\x8f\x46\x2e\xe3\xb4\x41\x36\x38\xa6\xe9\xe1\x60\xd9\xc6\x01\xa5\x15\x51\xb6\x16\x57\x08\x6a\xf9\xb5\xe8\xd7\xa8\x59\xa9\x91\x4b\xd3\x86\x50\xdb\x16\x8f\x3b\x82\x73\x6a\xb4\x44\xed\x6c\x42\x4d\x47\x80\x2e\xe3\xf7\x2e\xc9\x94\x8c\x78\x94\x74\x4b\x7d\x37\x25\xdf\xfb\x3a\x1c\x97\x2d\x3b\xd4\x51\x76\x04\xe2\xc5\x58\xae\x72\xe3\x10\x7a\xdf\x80\xfd\x9f\xce\x49\xed\x66\x25\x36\x42\xa1\xbf\x44\xce\xf7\xb2\xea\x3f\xb2\x3c\x29\xee\x7d\x46\x96\x2c\xf8\xd7\xb0\x99\x50\xcc\xca\x6d\x7d\xcc\xa5\x9c\x0c\x1c\x55\x7e\x80\x9f\xa7\x42\x12\x58\xf6\x3f\x2a\x8f\xa2\xcc\xce\xe9\x11\xba\xc3\x04\xef\x37\xe1\xd3\x71\xe1\x09\x8a\x39\x8b\x65\x90\x6b\x95\x95\x6a\xaa\x6a\x87\x5e\xc9\x77\xac\xce\xee\xb8\x47\xe8\x36\xdc\xc9\x51\xf8\x18\x9c\x4f\x76\x0d\xfa\x06\x9a\x99\x82\x1d\x4f\x6b\x8f\xd0\xab\xd0\x37\xa9\x40\xc5\x07\x0e\x07\x2f\xcd\x1e\x78\x02\x0f\x90\x84\x6f\x9c\xd9\xb7\xe4\x6d\x5d\x78\xe4\x72\x32\xa7\x57\x4b\x3f\x09\x77\x7a\x14\xc0\x9f\x25\x90\x98\x97\x87\xc9\x54\x74\x4f\x02\x7f\x63\x27\xac\x4a\xc9\xe1\x30\x73\x73\x1b\x66\xa2\xa8\x75\x46\x41\x58\x14\xa9\x80\xa2\x31\x1e\x63\x74\x2a\x9b\x42\x24\x35\xff\x46\xfc\xc5\xa7\xc9\x56\xfc\x3f\xde\x98\x2a\xe2\xdb\x50\x47\xfc\x90\xcf\x93\x2d\xfc\x11\xf7\x9a\x77\x5b\x09\xdc\x94\xe5\x83\x68\x19\x4d\xe1\x41\x7d\xea\x86\x04\x3b\x58\xa0\x1b\x4c\xfa\x60\x49\x79\x8a\xe6\x7e\x92\x53\x3e\x95\x86\xb8\xb5\x32\xf0\xb7\x75\x04\x72\xab\xa6\x1a\x5e\x54\xe4\xb8\x88\x28\x97\x4f\xf0\x86\x93\xf2\x7c\xca\xc3\x27\xc8\x27\x4d\x21\x9f\xf4\xec\x48\xd3\x30\x81\x10\x93\xb6\xc6\x00\x18\x64\xe3\x85\x98\xb6\x32\x70\x5b\x49\xce\x21\xcc\x88\xaf\x23\x6e\x6e\x78\xfd\x45\x71\x9b\x27\x59\xbe\xf9\x72\x97\xf1\xbc\xfe\x89\xc7\xf5\x30\x0c\x7f\x46\x27\xcf\xee\xf7\x3e\x11\x84\xec\x5f\x22\x3f\x25\x14\x86\xc7\x61\x43\xe2\xe9\x9e\x6d\xf8\x5f\x71\x5e\x93\x68\x1a\x43\x83\x77\xc5\x1e\x07\xcf\x71\x3f\xb0\xd6\x2f\x8d\x5a\xdf\xf2\xb4\x3e\x92\x80\x1f\xe9\xbe\x23\x39\x73\x96\x6a\x05\x87\x0a\x75\x46\x63\xbd\x46\x49\x63\x8d\x94\x05\xbd\x86\x6a\x99\x42\xc2\x3e\x6e\xcb\x08\x7d\xf8\xba\x26\x17\xf8\x52\x38\x86\x7b\xf5\xa3\x94\xd4\xd3\xc8\x2e\x85\xcb\xd3\xc4\xbd\x11\xe3\xc0\xcb\x80\x80\x81\x3b\xd3\xd5\x08\x85\x33\xa2\x93\xa1\x42\x4d\xcc\xe7\xf5\xae\xd8\xeb\x54\xa8\xa2\x1a\xac\x4f\x47\x3d\xb1\x38\xa6\xa2\x5c\x73\x3c\x0a\xd0\xf7\x44\x4f\x10\x33\x38\xbc\x13\x28\x5d\x74\x09\x0b\x22\x8f\x03\x76\xdf\xac\x2a\xba\x86\xba\xc7\xe3\x91\xda\xf3\xfd\x20\xc9\x64\x6b\xb5\x0e\x87\x37\x91\x52\x37\x81\x04\xd7\x8e\x10\x84\xcb\x04\x56\x48\x0a\xcb\x75\x20\x44\xd0\x49\xd9\x7d\x6a\x39\xa7\xe8\xfc\xe8\x86\xfd\xd3\x59\x60\x02\xcf\x82\x2e\x8f\xea\xac\x31\x58\x2e\x61\xd3\x4e\xa0\x66\x05\x5a\x73\xaa\x84\x61\x18\xb7\x43\x19\xf2\xde\xcc\x64\x11\x26\xa8\xc2\x94\xe6\x7f\x89\xac\xb4\x83\x1a\x33\xa4\xcb\xcd\x72\xb3\x8a\xd7\x81\x20\x5f\x81\xba\xf4\x37\xcb\x8d\xce\x6c\xe3\x27\x4b\x66\x9f\x8d\x20\xa5\xc9\x32\x0d\x98\x7d\xaa\x08\xb4\x0d\x53\x72\x14\xa4\x5d\x2b\x4a\x0f\xe6\xc8\x6e\x04\x70\x14\xd7\x3b\xe0\xfe\xd3\xf9\xff\x20\xe1\x9d\x93\x1e\x9d\x76\xfa\xf4\xc5\x82\x9e\xc2\x6c\x86\x26\xef\x6d\x4c\x30\x00\xbf\xb9\x1b\x56\xd1\x1a\x52\xd2\x06\xb1\x21\xa4\xad\x1d\x93\xa9\x43\x75\x8a\x42\x4c\xe4\x2b\xc3\xdf\xb7\xc3\x26\x62\x23\x9d\x10\x0f\xd2\xca\x7b\x63\xa6\x44\x1c\x41\x44\x3d\x2f\xf0\x8a\xdb\x1a\x8a\xad\xf6\xc0\x4f\xc2\x36\x26\xd6\x36\x02\xdb\x8f\x49\x9a\x9b\x4b\x28\xc8\x72\x2b\x7e\x81\xa6\x67\x21\xd0\x2d\xe4\xb4\x95\x19\x18\x31\x74\xf0\x52\x25\x4d\x09\x54\x62\x5e\xbd\xef\x6d\x08\xb1\xf4\x4e\x6d\x72\x23\x12\xec\x5f\x1f\xb5\xb2\xf2\x10\x4d\x7a\x63\xb6\x06\x9a\x24\xd2\x34\x09\x72\x99\x4d\x8c\xaf\x63\xd4\x47\xd3\xa8\x48\x1e\x81\x9b\x2b\x76\x3b\xd1\x9e\x72\xe7\x49\x55\xc0\xa3\xa6\x2a\xb8\x4f\xe6\xe3\x44\xed\x26\x24\x25\xc0\x63\x2b\x26\xb6\x21\x81\xca\x8e\x80\x91\x08\x36\x00\xa2\xe9\x32\xd1\xc2\x3b\x0d\x9c\xca\xbd\xb3\xca\xfe\xce\x3b\xf8\x4a\x2b\xe6\x82\xbc\x91\x59\x9e\xbc\xe5\xbb\x14\x79\x11\x96\x24\x5f\x08\xe6\xce\x53\x2d\xad\x00\xd2\x3c\xcd\x72\x3e\x1a\xe1\xdf\x29\xbb\x49\xd4\x6f\xdf\x43\x6d\x92\x47\x57\xeb\x8e\x84\x94\xb9\xbc\x7b\xff\x8f\xa0\x18\xaf\xfe\x4d\xd4\xa4\xdf\x8a\xdf\x1f\x9b\x8d\xca\x8b\x2f\x8b\x3c\xdd\x65\xb1\xe5\x20\x6c\x11\xa1\xd3\x8f\x05\x1a\x03\x62\xed\xe3\xf0\xdb\x08\xe3\x00\xcb\xbe\xf4\x1b\xf9\xf8\x7f\x22\x42\xf3\x23\x55\xbc\x47\x88\xd7\xad\x7e\x2d\x7a\xc8\x45\x0d\xb2\x38\x3f\x1b\xfe\xd3\xd9\xe0\x8b\xa2\xa8\xab\xba\x64\xfb\xc1\xdd\xab\xe9\xab\xe9\xbf\x0c\x7c\xb0\xfa\x3c\x3f\xdf\xf0\x3a\x52\xef\x04\x9b\x40\xfe\xe9\x6c\xf0\x65\xb1\x7f\x2c\xc5\xa1\x1a\x5c\xcc\xe6\xf3\xc9\xc5\x6c\xfe\xd9\xe0\xdd\x7d\x56\xd7\xbc\xa4\x83\x37\x79\x3c\xfd\xa7\xb3\xc1\xb7\x59\xcc\xf3\x8a\x27\x83\xdb\x3c\xe1\xe5\xa0\xde\xf2\xc1\x77\x6f\xde\x0d\x76\x58\xfc\x4f\x67\xe7\x82\xa3\x13\xef\xc4\xda\x25\x66\x81\x71\x80\x52\xfe\x99\xf3\xfb\xc1\xd7\xe8\x52\xa9\x07\xf8\x49\x35\xf8\x0b\xbb\x63\x68\xa2\x32\x28\xf9\x6f\xb7\x59\xc9\x2b\xd9\xce\x23\x8b\xb1\x4d\x4d\x79\xb7\x15\x1f\x08\xbe\x31\xae\xbd\x85\x0a\x16\x95\xe6\x52\xf1\x67\x39\xce\xac\x66\x6b\xf5\x34\xf5\xc0\xb0\x2d\x5a\xcd\xd6\xaf\x2f\x46\xa3\x68\x35\x5f\xbf\xfe\xd7\xc3\x61\x1e\x42\x02\xf9\xd1\xe8\x5f\xc5\x8f\xf9\x5a\xbc\xb9\x58\xbf\x9e\x1f\x0e\xa2\xf8\xf2\xd5\xef\x1d\xf2\x40\xf9\xb9\xcc\xa7\xff\x3a\x9d\x0f\x8a\x72\xb0\xcd\x36\x5b\xb1\x92\x11\x78\x70\xdf\xc3\xea\xb1\x5c\xd7\xfb\xd4\x23\x47\x5f\x2e\x13\xed\x9f\xad\x66\x3e\x22\x7d\x87\xea\xa3\xdf\x08\x6d\xa9\x37\x18\x04\xd8\x4f\x98\x69\x1f\xa4\xa0\x32\xaf\xff\x7d\xa3\xe4\xeb\x3c\xf1\xe8\x77\xc5\xdf\xed\x3a\xb5\xfe\x0d\x06\x7e\x3f\xd8\xef\x0a\xa7\xe9\xa0\x68\xd4\xad\x7b\xbb\x39\x9a\xc8\xf7\x3a\x8d\x8d\x76\xfb\x53\xc9\xcd\xe3\xb5\x24\x4c\x9f\x78\x9e\x04\xd1\x2a\x5e\x1f\x4d\x94\x13\xd8\x6e\x7e\x73\xbb\x63\x35\x77\x46\xe1\x1c\x31\x54\x0f\x0e\xe7\x92\x2c\x5e\xc8\xb4\x98\x53\xc1\x6b\x7b\x51\xd5\x98\xb9\x2d\x12\x0d\x87\x33\x79\xb2\x1d\x44\x13\x1f\x0e\xcc\x4f\x88\x36\xd0\x62\xd3\xea\x76\xbf\x2f\xca\x7a\x6a\x26\x38\xe5\x79\x62\x02\x91\x5b\x16\x8f\x5c\xdb\xbe\x53\xe6\x88\xa6\x3a\x3a\x01\x55\x44\xd7\x0b\x4c\x3c\x07\x56\x62\x32\x81\xc3\xb4\x31\x91\xf0\x29\xca\xf2\x04\x84\x0c\x7d\xc3\xd3\x6e\xe7\xa7\x6b\x6d\x21\x84\xa9\x93\xdf\x42\xf0\x31\x7e\x34\xad\x59\xb9\xe1\x35\x28\x79\xd1\xb0\x47\xb1\x10\x53\x6c\xf3\x43\x74\x25\x7f\x95\xdd\xf2\x1b\x40\xe6\x1f\x08\xef\xd1\xe9\x80\x81\xd2\xeb\x42\x9a\xf8\xf0\x30\x06\xf9\xa1\xd8\xe7\x29\xdb\x71\xd0\xd9\xf0\xc3\xa1\x55\x4a\x39\x38\x97\x6b\x0b\xa5\xb6\x48\x78\x34\xe2\xab\x48\x65\x12\x13\xc3\xc6\x2f\x7d\xb2\x12\x3d\x4d\x92\xac\xba\xc9\xaa\x2a\xf4\xb0\xbb\xf5\x27\xd4\x85\x41\xe6\x47\x28\xe5\x87\x90\x0c\x9e\x89\xc0\x54\x54\x9c\x1c\x17\xc9\xf4\xdf\xbf\xfe\xe9\xed\x9b\x1f\xbe\x0f\x3d\xc0\xd0\x1e\x4d\xa6\xef\x7e\xfa\xfc\xfb\xb7\x6f\xde\xbd\xf9\xe1\xfb\xf7\x5f\xfd\xfc\xd3\xe7\xe2\x47\x38\xff\xc3\x8c\x26\x56\xe6\x3f\x68\xef\x7c\x48\xaf\x54\xec\x93\xa7\xcd\x34\xe1\xb5\x58\x20\x03\xab\x1e\x34\x49\xa6\x66\x3d\xb4\x34\xef\x88\x80\xce\x74\x70\x27\x8e\xf1\x5a\x40\x62\x3d\xc1\xcd\xf6\xc8\x22\x85\x40\x94\xea\xdd\xb6\xe4\xa9\x27\x2a\xa7\xa3\x51\xaa\x45\xca\xe7\xd3\x33\x7f\x19\x7e\xb4\xfa\xdb\xaf\xd5\xfa\xec\x63\x72\x4e\x3d\x8f\xe0\x41\xda\x84\xcc\xf7\x3e\x02\x37\xc9\xe5\x6a\x1d\xa4\x64\x81\xc1\xfc\x4a\x80\xe6\xaf\x50\x38\xe2\x1b\x19\x1a\x3a\xa7\xe2\x44\x2b\x81\xc0\xe5\xa8\x45\x0d\x1d\xf2\x21\x64\x53\xa9\xbb\x86\x7a\xd6\xe4\x08\x8d\xa6\x59\x25\xbb\xfd\x11\x3f\xc2\x13\x5f\x30\x59\x1b\x27\x1c\x95\x97\xe5\x5e\xdf\x59\xdb\x98\x30\x56\x5e\xca\x12\xee\x91\xe5\xa6\x07\x7b\xc4\xa4\x13\x1f\xf9\x9d\xdb\x49\x82\xd8\x57\xa2\x52\x8e\x77\x17\x0c\x7b\x61\x7e\x86\x11\x35\x0f\xd3\x2f\x4d\xa2\xdb\x30\xb1\x5f\x74\x11\x17\x16\x6d\xa1\x7b\xe3\x1a\xf3\x24\xda\x5a\x50\x43\xa5\x5e\x36\x38\x1c\x13\xb6\xcf\x04\x9c\xb6\xc0\xed\xbf\xe1\xc0\x26\xd6\x81\x4d\xcc\xd1\x44\xdb\x2d\x80\xae\x2e\x89\x6b\xb4\x80\x3c\x1c\xcd\xea\xf2\x28\xc7\x92\x7c\x16\x87\x59\x27\x3d\x8b\x96\x5c\x06\x45\xf3\x41\x90\x0b\x21\x35\xc1\x52\xdb\x8f\xcc\x99\xb6\x48\xee\x44\xe6\x0c\xfe\x58\xda\xcb\x84\xe2\x20\xbb\x79\x81\x99\x95\xa4\x22\x9e\x7e\xf5\xf5\x37\x9f\xff\xfc\xed\xbb\xb7\x34\x91\xd5\xb2\xea\xdb\x82\x09\xb6\x23\x1c\xce\x8f\x8b\xb8\x75\xd0\x4d\x93\xf0\x69\x87\x35\xdf\x81\x4b\xa5\x7c\x98\x4e\xa7\x9e\xe8\xd8\xec\x82\x1a\x72\xc7\x25\x67\x02\x09\xa9\xe0\x63\x6a\xe0\xb0\xb2\x59\xa5\x43\x5d\x2f\xbd\x3b\xb6\xf3\x94\x00\x3a\x55\xcb\x4e\x16\xd1\x38\xf4\xd0\x8b\x13\x6d\x67\x40\x97\xce\xeb\x77\xe0\x4a\xa8\x56\x5b\x17\x79\x34\x59\xf1\xb5\x4f\x08\xb5\xae\x38\xc8\x4d\xfa\xf0\xe8\xc4\x71\x15\xb5\x64\x87\xab\x68\xbd\xb4\x57\x70\x15\xad\x83\x14\x13\xd7\x5b\x0b\x00\xbb\xe5\x37\x97\x50\xa0\x3f\x1d\x34\x2e\x26\x88\x84\x62\x71\xec\x40\xeb\x1a\x83\x80\x23\x70\x5b\x29\x7b\x22\x7b\x27\x68\xe2\x9c\xfe\x98\xd8\x11\x80\xad\xde\xe6\x84\x1c\x65\x8e\xe0\x19\x71\xb7\x01\xe1\xa8\x15\x45\x5f\x8c\x31\x72\xd7\x5e\x63\x2f\x79\x59\xc8\x96\x1e\x02\x6c\xe5\xad\x3f\x41\xa2\x54\x89\x04\xed\xa4\xa9\xba\x0f\x10\xe9\xab\xdd\x5b\xe8\x00\xca\x31\x0e\x15\x03\x21\x93\xa5\xaf\x9e\xa5\xf1\x14\x64\x32\x64\xa8\x23\x92\x5d\x48\x3b\x73\xcf\x8d\xfd\xe8\xa9\x52\xea\x7e\x56\x2f\xb6\xae\x40\x02\x13\x7e\xa9\xf9\x7d\x88\x9a\xd8\x18\x80\xcc\xf6\x61\xba\x34\xc8\x54\x75\xa9\xc7\xe8\x56\xb4\xc3\x17\x9a\xcf\xd3\xe6\x17\xe8\x73\xdd\x13\xca\x46\xa3\xd8\xba\x02\x21\x96\x91\x27\x33\xc4\x35\xe6\x0b\xb7\x1a\x2b\x33\x36\x81\x90\x46\xa2\xff\xe1\xf3\x1f\x78\xc1\xc0\x8f\x52\x3d\x07\xe8\x18\xb7\x7e\x61\xfd\x56\x98\x1e\x9f\x1c\x54\x1f\x3b\x6f\x9e\xc7\xf5\xb2\xc3\xe4\x39\x64\x2f\x3b\x34\xd8\xde\x81\xcf\xbf\x29\x00\x15\xd4\x8c\x6d\xbf\xac\x30\x76\xac\x09\x40\x73\x3b\x47\x75\xee\x91\x85\x94\xc4\x27\xd4\x24\xc6\xb0\xab\x67\x95\xff\x09\x00\xf2\xca\x8e\xb0\xbf\xa6\x03\xbb\xd0\x84\xf8\xfa\x44\xdc\xd6\x71\x9b\x44\xb0\xf0\x19\x55\x57\xc5\x32\x31\xdb\x0c\x91\xb2\x3c\x12\x24\xf6\xd9\x09\xa4\xe5\xb1\x6c\xa1\x1e\x3d\x82\xf6\xeb\x36\xa5\x24\xdb\x13\x69\x9f\x01\x8f\x1d\xcb\x36\x88\x76\xb7\xe5\xef\x5d\x4e\x24\x0d\xfb\x16\xd2\x05\x24\x1c\x0f\x3d\xff\x1b\xfc\xf0\xb3\x9c\x2c\x3f\x3e\x57\x8a\x79\xb0\xf8\xf8\x6f\xa1\xa6\x7b\x2e\xe7\x98\x95\x10\x28\xcb\xc3\x30\xa0\xdd\x77\xa0\xbc\x54\x68\xe7\xf5\x4d\xe8\xa6\x1d\x98\x38\x5a\x46\x41\x3a\x85\xfc\x2a\x8d\xeb\x5d\x7f\xb0\xe3\x82\x6f\x86\x87\xc4\x7b\xde\x8f\x48\xb0\x59\xf2\xd5\x66\xed\x93\x20\xd5\x79\x3d\xc4\xb5\xbf\x67\xb7\xe0\xa2\x1b\x3f\xc6\x3b\xcc\x61\xdb\xba\xfa\xe3\xfe\xab\xff\xe3\x2c\x4f\xb2\x98\xd5\x45\x59\x75\x62\x69\x3d\xd6\x89\xa9\xe8\x35\xc8\x06\xc9\x01\xc0\x40\x12\xb4\xea\x41\x9b\xdf\x5d\x06\x77\x94\x29\xd1\x49\x4d\x4c\xd1\xc7\x88\x54\xec\x92\xac\xe6\x37\x95\x55\xa0\xb2\xdf\x5f\xf3\xc7\xa8\x60\x65\x22\xd3\x49\xe9\x91\x0a\x90\x96\xf1\xdb\xa6\xce\xea\xaa\xdb\x1b\xaa\xcb\x1a\x54\xb1\x45\x10\x4a\xcd\x93\x18\x5d\x7d\x02\xe6\x30\x1a\x0d\x7d\xaf\xc8\xeb\xe2\x36\xde\x42\xd6\x15\xc8\x8a\xd0\x23\x8f\x24\x5d\xa3\x31\x61\xd8\x4e\x0c\x08\xbe\x25\x87\x63\x5a\x41\xb8\xb6\x13\xad\x60\x9b\x65\xab\x6e\x22\xac\x8b\xdb\xfa\x6c\x36\x73\xc8\x33\xb5\x11\xc1\x1f\xf8\x2b\x0a\x03\x09\xe4\x82\xa0\x5f\xc8\x70\x46\xd5\x6a\x07\xc3\x99\x4b\x2d\xc8\x85\x0c\x1b\xea\xc0\xe1\x39\x3a\x1f\x28\xaf\x83\xf3\x4c\x05\x56\x47\x94\x30\xad\x31\x2c\x19\x21\x4f\xd5\x7d\x06\xc6\xbf\xd3\xfb\x6d\x16\x6f\xc9\x53\xcc\x2a\x3e\x78\xf5\x2f\x48\xec\x08\xe4\xe8\xcb\x20\x2e\x0b\x7c\xf3\xaf\xf8\x26\xe7\x0f\xb5\x7e\xa3\xd2\xcf\xe0\x99\x3f\xb2\x16\x52\x3d\xba\xa3\x86\x75\xeb\x92\x57\x46\x2a\x98\xa9\x84\x5f\x7d\x79\x9b\x43\xe6\x66\xc9\x71\x5e\xba\x47\xc1\x6a\x33\xb4\xfa\xd4\x64\x9b\x02\x7f\x3b\x65\x8f\xb3\xbb\x62\x8a\x92\x48\xeb\xec\x97\x28\x81\x8b\x3d\xb5\x0d\xaf\xdf\xd4\xfc\x06\x63\x4d\xf6\x19\x1d\xc8\x53\xc5\x8c\xbb\x0d\x18\xb9\x94\x3c\xf7\xbd\xa9\x78\xa7\xe9\x25\xa8\x88\x5a\x6f\x9f\x1d\x0e\xf6\x29\x25\x9d\x1f\xfe\xa6\x28\xbf\xca\x4a\x0e\x9f\xed\x72\xc1\xc0\x23\x66\x8f\xd2\x87\xb4\xb0\x9e\xd8\x32\x0f\xf2\x7a\x41\x66\x93\xc3\xc1\xcb\x91\x5c\x16\x44\x8e\xa2\xb5\x70\x38\x48\x4f\x4e\xe6\x10\x6f\x4a\xad\xae\x5a\x1d\x01\xb2\x26\x38\x28\xf2\xa0\xba\xf3\xe5\x64\x1e\xcc\x69\x1a\xfa\xf1\x98\x93\x7f\x6e\xf7\xb9\x68\xaf\xd2\x94\xff\xe6\xa7\x2d\x1a\xb9\x23\x53\x1e\xba\x39\x75\xcc\xcf\x41\x6d\x9d\x78\x55\x7c\x48\xd3\xaf\x40\x34\x0f\x7d\x76\xd9\x35\xe5\xc3\x81\xbd\x9e\xb9\x31\xd0\x25\x66\x5d\x36\x31\x0f\xf7\x3d\xf1\xca\x45\x1f\xb6\x4d\xae\xb8\x4a\x18\x39\x92\x20\x56\xea\xf9\xe6\xfd\x11\xe8\x0f\x70\x9f\x5d\xc6\x4b\xdc\x92\x00\x97\x93\x36\x16\x89\x91\xc6\x2a\x41\x67\x2f\x3a\x65\xb3\x26\xa5\x29\xd7\x05\x4e\xc0\x00\x4e\xb3\x8e\x59\x38\x1a\xf5\x48\x0e\x1b\xb4\xea\x73\x42\x4c\x6a\x30\xa8\x0f\xea\x63\xf7\x54\x3e\x7b\xcc\xdd\xb9\x8a\x91\x36\xf2\x25\x0f\xed\xdd\x69\xed\x18\xf7\x71\x31\x9b\x6b\x56\xf2\xbb\x0f\xed\x07\x97\xa7\xc1\x4c\x8b\x57\x0d\x8e\x1f\xcf\xc2\xf3\x00\x28\xd8\x66\x79\xd4\x3b\x0e\x35\x78\x7e\x49\xbb\x34\xbd\x24\x74\x1b\xaa\xe3\x1a\x2d\x51\xad\x1a\x78\x25\xea\x30\x33\x14\x4f\x83\xb7\x42\x07\x8f\xd1\x01\xca\xe1\x70\xbe\xc0\xe8\x7f\x29\xc4\xf4\x32\x72\x30\x98\x96\x0b\xd1\x4f\x60\xf4\xc3\x93\x77\x70\xb1\x04\x57\x34\x51\x23\x0d\xb6\x18\x89\xba\x1b\x30\xae\x09\x1d\x5e\x77\x0a\xd1\xb4\x61\x85\x19\xcf\x8c\x6e\xe4\xd5\x2e\x4f\x48\x8b\x60\xd2\x4c\x6e\xeb\xc5\x8b\xd8\x53\x98\xef\x4e\x92\xa4\x4e\x73\x8d\x99\xc9\xaa\x8d\x5a\x52\xb2\x26\x8b\xdd\x68\xb4\xeb\x60\x68\x81\xf4\xbb\x71\xd7\xee\x83\x96\xce\xe4\x26\xea\x38\x6e\x7d\xbc\x23\xec\x90\xe0\xd8\x53\x3b\x0a\x3e\x4d\xc1\x9f\xd7\xf8\x53\x52\x2b\x48\xfe\x96\xd0\xd4\x79\xe2\xcf\xeb\x30\x52\x67\x19\x57\x11\xdd\xae\xa5\x9f\xda\xc0\x23\xa4\x63\x35\xa8\x1b\xa6\x7f\xa5\x5e\xb8\x0d\x69\x66\xc1\x20\xed\x0e\xe8\x90\xb5\x61\xe9\x86\x1c\xe9\x0c\xbc\x4c\xbb\x84\xa4\x9d\x54\x18\x21\x81\xcf\x7b\x44\x15\x69\xd7\xf8\x1b\x07\xa4\xc9\x9a\xeb\x91\x10\x0d\xaa\x12\x89\xab\x88\x44\x16\x9b\xae\x40\x60\xe1\x3c\x29\x56\x5d\x3d\x77\x31\xeb\xfa\xdd\xf3\xec\xba\xee\x56\x32\xec\x4d\x85\x93\x31\x02\xb4\x64\xf3\xcc\xef\x94\xce\x83\x81\x81\x2b\x9b\x87\x94\xc2\x5d\x82\xf9\xb1\x16\xcc\x37\x50\x8e\x61\xed\x94\x41\x8a\xcd\xdf\xa5\x8a\xa9\xe3\xf2\x07\xa1\x5b\x57\x55\x00\xa0\x3d\xa9\x0b\x8f\x2c\xb6\xa3\x91\xbf\x31\x97\x05\xca\xa1\x40\x38\x90\xd2\x0d\xa1\xdb\xd1\x28\xed\x62\x29\xc5\x8d\xbb\x45\x49\x4f\x93\x3e\x5d\xf4\x8a\x33\xf4\x92\x1b\x0e\xdc\x5b\x99\x01\xad\x3d\xca\x3f\xac\xc5\xa4\x2e\xa0\x11\x65\xfe\x3d\x18\x59\x18\x47\x0d\xe7\x8c\x31\x25\xd8\x2b\xc5\x5d\x62\x96\x6f\xfd\x49\xdb\x3d\xdb\xd1\x4f\x29\x41\x49\x4c\x63\xb5\x96\xbf\x4f\x23\xa6\x9c\x76\xa3\x1e\x98\x88\xf5\x1b\x0d\x13\xf1\x49\x98\xd0\x38\xcd\x4f\xac\x80\xae\xf1\x3f\xa0\x7d\x8b\x8b\xdd\x8e\xed\x2b\xde\x92\x17\x24\x46\x5e\x10\x9f\x96\x17\x2c\x86\xe0\x41\x87\x42\x91\xd1\xe8\xbc\xda\x16\xf7\x87\x6d\x96\x70\x25\x05\x01\xeb\x53\x25\x98\x15\xb0\xe6\xaa\xfa\xf4\x10\x1c\x6d\x1f\x4a\x10\x7a\xf4\x7d\x5a\x34\x90\xbc\x50\x34\xd0\xa5\x15\xb0\x67\xa8\x2e\x44\x89\x87\x42\xd6\x14\x0a\xeb\x41\xae\x57\x62\xaf\x42\xef\xa3\x4f\xc6\xd1\x34\x4b\xc6\x9f\x78\x6b\xda\x5b\xd5\xda\x70\xa7\xc5\x27\xf2\x7b\xe6\x46\x72\x65\x0b\x86\x85\x17\xfc\x8d\x24\x8d\xf1\x41\x13\xe8\xca\x80\x51\x66\xd1\x4d\x92\xcf\xcb\x8c\x7d\x9e\x27\x5f\xca\xcf\x4b\x0c\xec\xaa\x1b\x9c\x59\x36\xf8\x32\xb5\x81\x38\x32\xa9\x8e\x79\xb9\x12\xf4\x15\x28\x41\x0d\x5b\x8e\x3d\x00\xc7\x6d\x2b\xab\x92\xec\x06\x03\x66\xb7\x45\xf4\x7d\x77\x32\x9a\x8f\x59\x1e\xd1\xb2\x44\xdb\x99\xb9\x5f\x10\xf0\xd7\x49\x83\x3a\xab\xad\xf8\xae\x8e\xef\x65\xb9\x42\xb1\x11\x55\x04\x27\x2e\xbe\xa2\x1b\xf0\xc9\xe6\x3a\xf7\x2c\x07\x0c\x69\x33\xa2\x39\x1d\x28\xe0\x16\x40\x2c\x19\x23\xc7\x6f\xc3\x8f\x42\xde\x79\x18\x41\xfd\xea\x0c\x98\x10\x6d\xdc\xa6\x49\xa2\x6d\x71\x3f\x75\xda\xf5\xd3\x8b\x29\xa1\xc3\xb4\x87\x5e\x74\x87\x14\x23\xf6\xe3\x54\xa5\x55\x8e\x0e\x87\xae\x41\xa2\xe5\x97\xd2\x1f\xc3\x57\xf5\xe6\xfa\x64\xe1\x0e\xc3\xa1\x14\xcc\x78\x2d\x4a\xc1\x5e\xa9\xd5\x66\xed\xcf\x88\x2d\xf5\x47\x8f\x34\x10\xfb\xcf\x1a\x87\xb5\xbb\xef\xc4\x7b\xae\xbd\x7b\xf8\x90\x64\xdf\x3a\x4e\xdf\xcf\xce\x00\x06\xdb\x9e\x03\x1f\x08\x10\x12\x93\xf0\xbc\xce\x8f\xcd\x7a\xc8\x1f\xd8\xd1\xdc\xdd\xd2\x23\xc6\xe2\xef\xa0\x62\x15\xef\xe1\x24\xfe\x86\x48\xe5\xe0\x8b\x79\xc3\x77\x10\x5c\x4f\xdb\x05\xd2\x8d\xa2\x15\x27\x82\xbc\xe8\x60\xb8\x5b\x24\xab\x12\xe8\x6c\x95\x6c\xef\x03\xd4\xe8\x62\xfe\xce\x37\x56\xb3\xf5\x2a\x5b\x83\x33\xa3\x73\x60\xb7\x0e\xaf\xd7\x7f\x60\x5f\x70\x5e\xcd\xd9\xd8\x2a\x4e\xeb\x05\x67\x23\x22\x74\xd8\x6d\x90\xe0\x48\x7d\x7a\xa1\x7b\x15\x37\x67\x1a\xaf\x7d\x42\x0c\xcf\x80\x76\xb1\xbd\x3a\x3c\x07\x9a\x3a\xa1\x19\x00\xaa\x07\x9e\xe7\xcd\xf3\xd0\x86\xc7\xfe\xc3\x30\x3f\x71\x18\x78\xeb\x30\x9c\x86\xe2\x0f\x39\x21\x9e\xa5\xd1\xc1\x58\x32\x4d\xa8\x3f\xc1\xbe\x61\xd2\xdf\xd6\x8a\xcf\xfa\x8c\xc7\x14\x14\xf3\xdf\x01\xc5\x01\xb7\x4e\x57\x13\x72\xdb\xca\x66\x51\x6d\x75\x0a\x50\x97\x88\x55\x65\x0a\x7a\x41\xc9\x38\x3d\xea\x8b\xbd\x8b\x2d\xf1\x3b\x88\x03\xe9\x55\xd6\x4f\xae\x40\xb9\xa4\x1d\xbc\x4f\xc6\x1d\x5d\x20\x45\x22\x63\xaf\x34\x8d\x04\xac\xf4\x08\x82\xea\x5c\x9c\xa6\x36\x22\x9f\x13\xca\x95\x72\x5e\x85\x2d\x72\x66\xd8\xd7\xb6\x53\xda\xca\x1a\xab\x87\x31\x32\xda\x70\x1c\x0b\x06\xc6\x51\xcb\x19\xd0\xa7\xc3\xb8\x07\xfa\x63\xd7\xca\x47\x35\x59\x38\x4f\x9a\x75\x94\xcf\x5d\xe6\x3e\xfa\xdd\x0b\xd8\x4a\xd5\xed\xb3\x46\x3f\xba\xd3\x1e\xd5\xa5\xbd\xcb\x96\xee\xd2\xda\x2e\xbc\x11\x7a\x38\xd2\xa4\xc5\xc5\x2d\x90\xbc\x80\x3d\xdc\x84\x69\x27\x5d\xb2\x0d\x37\x4b\xa5\x3e\x0e\x14\xab\xb9\x88\x15\xf3\xb8\xfd\xfd\x7c\x52\x37\x97\xb4\x88\x3b\xf8\x24\x1a\x87\xf1\x68\x74\xfe\xd1\xea\xf3\xc9\x7f\xb2\xc9\xdf\xd7\xe7\x26\x2f\x76\x37\xff\xe4\x1a\xbb\x25\xa2\x35\xf3\x63\x3b\x45\x85\x8a\x8f\xb4\x4c\x82\x48\xab\x15\x6c\x16\x2b\x06\x5f\xfc\x57\x90\x33\x13\x54\x3d\x87\x83\xcf\x1c\xaf\x5b\xe6\xa7\xdd\x8c\xa5\xad\xaa\x8d\xfc\x44\x70\x5a\x0d\xd1\x15\x0a\x18\xac\xbc\x8c\x5e\xb1\xe7\x39\x1a\x6e\x8c\x46\xd2\x3a\x51\x7c\xb9\x06\x77\xc5\x1e\xed\x54\xdc\xd4\x4e\x8d\x46\xcc\xb8\x88\xf1\xd5\x6c\x4d\xb5\xb6\xff\x70\xf0\xb9\xc6\xc0\x71\xfb\xda\x4c\xca\x62\x9f\x14\xf7\xb9\x07\x7c\x58\xdc\x67\xad\x97\x74\x1f\x2c\x2f\x65\xbb\xaa\x2d\xb5\x92\xb3\xb2\x84\xdb\xe6\xab\xf2\x06\x70\xbe\x4b\x04\xe3\x6d\xed\x42\xf2\x61\x8c\x6e\x62\x33\xba\xba\x63\xb2\x48\x1c\xf6\xd3\x7c\x31\x01\xf6\x73\x73\xca\xd8\x34\x69\x1b\x9b\xf2\xd0\xd3\x7d\x4c\x22\x16\x5f\x8b\x07\x8f\xa6\x61\xe3\xb0\xea\xef\xac\x3f\x11\xa7\xab\xd7\x0a\xd5\x5d\x05\x8b\x19\x23\xc7\xc5\xa6\xc5\x8b\x6d\x4e\xdc\x46\x2d\x4c\x20\x08\x2b\x0e\xe6\x19\x3a\x81\x1d\x1d\x58\x71\xa0\x14\x83\xa1\x31\x40\x13\x1e\x21\xfa\xac\x4f\xe8\x70\x43\x9e\x5e\xac\x55\x1e\x8d\x86\xa9\x65\x42\x91\xb3\xbb\x88\x95\x93\x9c\x39\x3a\x11\xbf\xcf\x50\x3e\xc9\xee\x5c\x89\x68\x7b\xad\x89\x0c\x9a\xf8\x79\x0a\xb9\xc2\x7c\x4b\x0d\xad\xec\x7a\x89\xa4\xee\x3b\xcf\x1d\xc8\xd9\x14\x4c\x26\x6d\xf6\xca\xec\xc6\x96\xa0\x7d\x4b\x07\xa1\x88\x60\xb9\xe0\x2d\x43\x95\x9e\x13\x52\x97\xb7\x28\x2b\x75\x6e\xad\xbe\x03\xa2\xf9\x02\x67\x2c\x47\x93\x58\xd4\x01\x84\x96\x56\x1b\xbd\xf9\xcf\xfd\x57\x7f\x3c\x7c\x3a\x3b\x5c\xfc\xcb\xe1\xd5\x05\x51\x48\x53\x2a\xae\x47\xa3\x3e\xa5\x77\x0b\xad\x34\xb0\x1a\x00\x45\xdb\x0e\x28\x9e\x56\x75\xb1\xff\xb1\x2c\xf6\x6c\xc3\xf0\x7c\xd2\x61\xf2\x2c\xf4\x49\x14\xb9\x09\xdb\xd8\x10\xe0\x77\x33\x1a\x5d\xfc\xcb\xd0\x20\x61\x78\xd6\x48\x59\xb1\x44\x56\x91\xe0\x6d\x81\x44\x4a\xdb\x46\x44\x34\xb1\x2d\xb0\x05\xa8\x28\x40\xf1\x06\xbb\x2c\xc8\x8b\xda\xd7\x63\x25\xca\x28\x69\xc0\x3c\x9a\x85\x5c\x29\x46\x34\x3c\x42\x4a\xbd\xf1\x16\x86\x99\x39\x46\x83\x57\x61\x26\x75\xd0\x1a\xff\x2e\x5e\xfd\xd1\x1a\xe1\xd5\xe5\x6c\x34\xba\x9a\x4c\xe8\xa7\x33\xbb\xf4\x75\xa6\x15\xa7\xa3\xd1\xd5\x78\x4c\xff\xdf\xd5\xe1\xe0\x5f\x85\x33\x42\xb3\x29\xff\xcd\xbf\x6a\xcf\x48\x30\x57\x72\x0a\x40\x6e\xa8\xd1\x2d\x9c\x27\x45\xb7\xa8\x67\x87\xa6\xd9\x34\xde\x3d\x4f\xd3\xe8\x6e\xb7\xcf\xd1\x34\xba\x53\xcb\x96\xf9\xf9\x2a\x66\x91\x07\x69\x51\xde\xb8\xb1\x81\x58\x1b\xce\x8e\xcf\x77\x99\x76\x60\x4e\xd2\xb4\xbe\x79\xb6\x9d\xac\xfb\x92\x86\x4d\x40\xe9\xec\xe7\x43\x49\xa7\x66\x2a\xc2\xae\xfb\xd0\x75\x1d\xd0\xd7\xde\x4d\x91\xb0\x9d\x27\x0e\x5a\x8f\x95\x18\x7f\x46\xea\x9b\x3a\x52\x21\xec\x8e\xa6\xb6\x0d\xd8\xa6\xf3\x12\x5d\xa6\xab\x68\xed\x27\x24\xd8\x80\xa4\x6e\x34\x4a\xe1\xaf\x9f\x9c\x34\xf7\x6a\xd8\x67\x7d\x1c\x15\xc9\x63\x68\xdd\x1a\xe2\xb9\xa1\x85\xb7\x2d\xc3\x92\x8c\xed\x8a\x4d\xb7\xf2\x18\x86\x3e\xc1\x1a\xda\x70\x44\x5d\x2e\xb6\xc1\x57\xf5\x56\x60\x61\x5b\x4c\x5b\x66\x9b\x2c\x67\xbb\x2f\x8a\xe4\xf1\x47\xe6\x98\x8b\x81\xc4\x25\x62\x25\x68\x0b\x15\xa7\x9c\x6d\xf2\xa2\xe4\x5f\xc8\xae\xbf\x14\xe0\xa9\x55\x61\x8a\x25\x13\xf4\x52\xcd\x9b\xc2\x0e\x67\xa8\x2a\xba\x37\x81\xb8\x2d\x7e\x47\x73\xda\x61\xeb\xdd\x23\x71\x12\x5d\xa0\xe3\x89\x84\x88\xe3\x07\x1b\x64\xbd\x02\x83\xac\x2f\x3e\xff\xf2\xff\x7c\xf5\xd3\x0f\x3f\xbe\xef\xf3\x90\xb1\x6d\xb6\xd4\xf2\x36\x8c\xb3\xa8\x80\x84\x96\x91\x56\x93\xae\x69\x58\x03\xc9\x7d\x41\x29\xb9\xa0\x5f\xb5\xe1\xc7\x16\xe2\x7d\x34\x2c\x0b\x1c\xe9\x70\xa4\xee\x32\x00\x58\xde\xbe\xfb\x25\x5c\x37\xe8\x86\xe8\xd8\x14\x9f\xa9\xf5\xe4\xc4\x01\x16\x71\x46\x7a\x48\x67\x07\xa6\x86\x12\x42\xc0\xbc\xf6\xad\x02\x1e\xa5\xa7\xaf\x20\x3c\xb8\x5b\x06\x27\xc0\x22\x8b\x10\x34\xf0\xa2\x94\x89\xbf\xab\x98\xed\xb5\xae\x1f\x53\xd2\xfa\x4d\x4b\x15\x83\x27\xa5\xaf\x94\x35\xe9\xa6\x13\x15\x16\xaf\x3f\x71\x8d\xf8\xc4\x8a\x2b\x43\x44\xfb\xb0\x19\x33\x40\xc4\x84\xad\xee\x6d\x3f\x84\x86\x1c\x52\x66\xc4\x3d\xd5\xa8\x61\xa2\x9b\x55\xbe\xe9\x44\xf0\x4d\x49\xf7\x69\x9b\x81\x2a\x0f\x07\xaa\x80\xb0\x03\x63\x76\xda\x0c\x24\x5d\x32\x1d\xf4\x3c\x5a\x58\xef\xb4\x51\x9a\x72\x95\xb2\xde\x61\x60\xa0\x77\x85\x18\x2c\xa2\x2c\xeb\x25\xc0\x2b\xd1\x91\x03\xf6\x3e\x84\x8f\x60\xc9\xd5\x6d\x55\x7f\x05\x6b\xea\x43\xd8\xa7\xc4\x96\xa8\x3a\x56\x09\x49\x97\x74\x11\x5c\xa8\x92\x29\xcf\xd3\xa2\x8c\xf9\x37\x60\xa5\xac\x78\xfd\x36\x81\xd9\x0f\xf0\x7c\x99\x58\x7b\xfb\x8c\x81\x43\xd2\x81\x6a\x14\x41\x6c\x54\x12\x1f\x66\x72\x10\xbc\xb4\xd3\xc6\x91\x77\xe5\xcb\x11\x86\x73\x6c\x13\xac\x1d\xc2\x63\x75\x49\xf6\x8a\x8d\xed\x43\x3c\x1a\xf5\x08\x91\x8d\xa7\x8b\x3c\xec\xf3\x93\x07\xd4\x21\x9e\xd2\x54\x4e\x31\xcb\xfb\x07\xd4\xf2\x98\xc3\x76\x3d\xe7\x5a\xbe\xed\x3d\x63\xcd\x63\xac\x2b\x77\x9f\xe3\x3e\xf7\xbc\x3e\x21\xa8\x74\xd5\xfb\x10\xed\x83\xc6\x33\xdf\x89\x2f\x9e\x14\xe2\xf6\x40\x8e\xdb\x83\xdf\x84\x10\xfb\x6c\x84\x8e\x09\xc1\xb3\x5b\x61\x9c\x10\xec\xe2\xf6\x05\xcc\xc8\x93\xea\x0b\x43\x43\xc2\xc1\x52\x26\xa9\xe6\x3c\xf7\xbf\x14\x6b\xa8\x2d\x90\x0d\x76\xe9\xb9\xd7\x15\x3f\xa0\x6e\x73\x77\xbe\x00\x79\x2d\xf1\xbe\x06\x64\x87\xa4\x50\xf7\x73\x6b\xcb\x0c\xc9\xdb\xc6\xd3\x5d\xf3\x17\x4c\x19\x53\xcc\x8d\x75\x5b\xab\x31\x06\xee\xcd\xd9\xf8\x9c\x58\xfe\xde\xef\x35\xe6\x87\x67\xa9\x6f\x7e\x4b\xd7\x70\x04\x2b\x77\x8c\x1d\x87\x08\x9e\xd2\x3f\xef\x13\x56\xab\x6b\x2e\xb0\xda\x8b\x51\x35\x3b\xe8\x40\x3f\x00\x76\xdd\x1a\xef\x06\x21\x81\x4b\xd2\x7f\x41\x31\x79\xf3\x3b\x67\xde\xb9\xfc\x19\xba\x06\x7e\x0e\xf7\xc6\x0d\xa6\x51\x50\x85\x36\x19\xc1\x3a\xa0\xc6\x08\xe2\xd4\x54\x5a\x2b\x2b\x3e\xab\x2e\xd5\xb6\xb6\x54\x0d\x59\x9d\x7f\xf5\x6c\xc4\xa4\x1d\xf4\xb5\xfb\x89\xa8\xd5\x79\x93\x4a\x7b\x06\xb5\xe0\xdf\xc0\xf3\xb4\xc6\xaf\x1b\xb0\xd5\x87\x8c\x5e\xbd\x0b\x8f\x71\xa3\x37\xd4\x23\xfb\x00\x71\x15\x6e\x8d\x6a\x39\xf0\xc6\x9c\x18\x2a\xc0\x50\x72\x1f\x42\x97\x75\x9d\x2d\x87\x20\x6e\x13\x3e\xa0\x31\xf3\x4f\x30\x21\x18\x00\x46\xa3\x17\x0c\xe7\x7b\x5b\x0a\x4a\x06\x49\x80\xd1\xc8\x37\x91\x9d\x3a\x97\x71\xd9\x44\x65\x53\xf4\x88\xb2\xb0\x2f\xc4\x74\x56\xc4\x62\xda\x84\x91\x26\x35\xd3\x80\xa0\x06\x45\x33\x54\x71\x28\x17\xe9\xb2\x51\xb3\xfb\x36\x89\x7a\xaf\x8c\x53\xac\x0b\x09\x22\x5f\xba\x24\x6a\xbd\xb4\x0b\x4e\x1f\x1b\x38\xea\x84\x79\x5b\x7d\x85\xb6\x12\x0e\x9d\xe4\x9e\x28\x1f\x4d\x3f\x7c\x72\x5c\xfc\x03\xd7\xea\x33\x2b\xb1\xf9\x9d\x2b\xb1\x51\x2b\x21\x87\xe8\xa2\x39\x0b\x51\xb6\xf0\x82\x4b\xc4\xba\x0d\xed\x77\xcf\x18\x05\x41\xc8\x18\x40\x61\xa8\x51\xbf\xec\x93\x39\xcb\xf8\x73\x58\xab\x81\x61\xe3\xaa\xd2\x41\xa7\x20\xb8\x18\x6e\xaa\x38\x85\x6f\xaa\x1f\xee\x78\x99\xee\x8a\x7b\x30\x38\x90\x5e\x05\x2e\x33\x1f\x78\x1e\x95\xad\x7f\x82\x68\x57\x7d\xad\x87\x7d\xcd\xdb\x38\xd5\x45\xd7\xfd\x36\x28\xad\xa1\x37\xc7\xd2\xee\xdc\xe5\x28\xdb\xeb\x8b\x37\xd9\x14\x62\x6f\xc1\x00\xd1\xdc\x44\xd9\x53\xf4\x2e\x70\x4f\x94\xbd\x05\x0b\xa3\x29\x58\xce\x4f\x20\x58\x15\x8b\x2a\x1f\x43\xd5\x91\x63\xf7\x42\x85\x8e\x0c\x47\x6e\x1c\x26\xad\x61\x9d\xc2\x14\x28\xbb\xe1\xac\xba\x2d\xb9\x75\x9f\xb5\xbd\xf1\xfb\x27\x0d\x91\x2b\xdf\xe4\xb5\x85\x80\x61\x6d\x3d\xb9\x98\x13\xb4\xfd\x87\x38\x97\xf3\x99\xe4\xf5\x9b\xd2\x1e\x77\xdc\x32\x96\xa7\xb5\x19\x90\x76\xae\x0f\x38\x4e\x7f\x98\xb2\x71\xc7\xcc\xbb\xc0\xa6\x73\x92\xcf\x74\xde\x35\x9b\x46\xdf\xcd\xe5\x6d\x2f\xe1\xc9\x0b\x70\xc1\xa6\xb1\x40\x4b\xdf\xb3\x1b\x2e\xe5\x06\x13\x3d\x97\x89\xec\xdc\x73\x04\x19\x2a\x9d\x93\x0e\x19\x65\xdd\x04\x13\x66\x83\x85\xeb\xe4\x04\x61\xce\x66\x6b\x85\x6b\x21\x98\x3a\x23\x34\x72\x0c\xc6\x61\x04\x0b\xf3\x53\x99\x8a\xc3\x43\x97\x9d\x38\xbe\x78\x5e\xf2\x8d\xbd\x3d\xeb\xd2\x8d\xdd\xf5\xea\xf1\xb5\x60\xa5\xcb\x9f\xbb\xd6\x4e\xbe\x8d\xd0\x2e\x4c\x6b\x5f\x1b\x9a\x7d\x30\xe7\x3b\x69\x5a\xee\xaa\xf7\x25\xa9\x67\xf4\xfa\x46\x22\x8c\xe2\xc4\x60\x78\xfe\x91\x54\x17\x71\x32\x1a\x71\xcb\xda\x5c\xf9\x12\x93\x05\xaa\x76\x98\x07\x4a\xf8\x16\x73\x9d\x4a\x8f\x2e\x57\xac\xe6\xca\xf1\xbb\x05\x65\xb2\x65\x93\x32\x75\x85\x0d\x90\xd0\x46\x3b\x8d\x8f\x46\x6d\x7f\x73\x10\xfb\x18\x23\x77\x99\xec\xec\x7f\xce\x31\xbb\x2e\x8a\x5d\x9d\xed\x4f\x84\x4d\x19\xf2\xd1\xe8\x3c\xe1\x55\x5d\x16\x8f\xae\xfd\xf4\xe1\xe0\xbb\x4e\xd7\xaa\xb3\x0e\x9f\xeb\x5e\x8b\xe9\x0e\xf1\x3a\x18\xda\xa0\x86\xf9\x71\xcf\xdb\xf6\xc7\x56\x09\xcf\x41\x09\x66\x95\xc8\x14\xa0\x56\x09\x38\xdd\x62\x0c\x14\xcb\x03\x5a\x49\xe3\x6d\xcf\xe9\x66\xa5\x2c\xcf\x6a\xdf\xd3\xb3\x82\xb8\xb9\x2f\x16\x3f\x37\x65\xcb\x18\x78\x3a\x2b\xf2\x60\x38\xa3\x70\x08\xc4\xf7\x03\x8c\x99\x89\xe9\xc4\x8a\x32\x18\xce\x69\xcd\x6f\xf6\x82\x08\x0a\x3e\x79\x9d\x64\x77\x03\xc0\x58\xa1\x1e\xc5\xa0\x2c\xc4\xd9\x54\x8f\x97\x1d\x75\x26\xac\x2c\x8b\x7b\xef\xf2\xf5\x79\x92\xdd\x75\x56\xc0\x90\x96\xaa\x02\xfc\xff\x09\x95\xa0\x29\xbd\x94\x07\x32\x80\x40\x9d\xd5\x3b\x2e\x2e\xf4\x84\xef\xd8\x63\x30\xc3\xec\xff\xc3\x39\x95\x16\x1c\x1c\xc6\x7c\x97\xf1\x7b\xc8\x63\xff\xa4\x67\x82\xa9\xe4\x14\x1d\x10\xcc\x1a\xce\xc2\x62\x6d\xc3\x66\xb8\x4a\xc5\xd2\xa8\x6d\x55\xf2\x67\xcc\xba\xdd\xd2\xa3\xc4\x0d\x33\x7a\x78\xd8\x70\x95\xde\xdf\x57\xee\x88\x1f\xab\xe1\xb9\x1c\x82\x2a\x1d\x8d\x98\xcf\xec\x10\xd1\x9d\xb5\xc8\xb2\xb3\xd8\x4a\xc6\xe7\x0c\x4f\xb2\x17\xad\xea\x6a\x7d\xa4\x20\xa1\xf5\x15\x17\x16\x9f\x00\x57\x8b\x15\x86\x4d\x11\x3f\x60\x5f\x82\xe1\xfc\x48\x9b\x34\x68\x96\x57\x35\xcb\x63\x08\x4e\xa9\xaf\x41\x73\x89\x34\x5d\x7a\xd5\x48\xda\xe1\x0a\xff\xaf\x7a\xf5\x7f\x07\x58\x79\x70\x73\x5b\xd5\x83\x88\x0f\x20\x7e\x5c\x9a\xf1\x64\x70\xbf\xe5\xf9\x40\x6c\x22\x24\x18\xcb\xf2\xcd\xc0\x1b\xeb\xbd\x1a\x7b\x83\x22\x87\x48\x8f\x92\x8e\x53\xe3\x19\x20\x8a\x19\xca\x74\x43\x96\xef\xa4\x36\xf7\x97\xd6\xa2\x26\x20\x23\x28\x08\xa5\x23\x71\x3a\x99\x2c\x94\x9b\x11\x5f\xa5\x6b\x41\x15\x6a\x3b\xa4\x0d\xe9\x63\x56\xad\xa1\xd1\xce\x35\x70\x85\x2b\x78\xe1\x48\x86\x50\x67\xd2\xf3\x6e\x58\x7e\xcb\x76\xde\x30\xdc\xe0\x10\xb6\xa1\x8e\x70\xb0\x59\x5a\x01\x09\xbc\x40\x49\xde\x3c\x9a\xb5\xeb\x40\xf8\x01\x55\xa7\xb8\xad\xbd\x96\xc9\xb3\xbf\x1d\x7b\x1f\x3a\x66\xf8\xb2\xab\xf0\xb0\x3a\xcc\x3e\xbc\x43\x18\xa6\x12\xd3\x1d\x3b\x1b\xe0\x89\x78\xdf\xe5\xc5\x62\xd7\xa7\x4f\x1a\xb5\xc8\x25\x34\xf8\x4e\x70\x06\x78\x52\xd2\xec\xe1\x9d\xc0\x35\x4d\x92\x79\xc3\xd5\x7d\x5d\x75\x90\x3b\x06\xc3\xb6\x5a\x49\x2c\xd0\xe9\x2a\xdd\x1e\xab\xf5\x99\x96\x36\x4a\x12\x15\x91\xb8\xa9\x01\x0d\x8e\x46\xed\x20\x22\xea\x8d\x2f\x7f\x85\x4f\xa0\x35\x94\x4f\x54\xdc\x9c\xea\x41\x5c\xf9\x1d\x93\xc4\xf8\x8a\xad\x61\x2b\x9e\xe7\xe9\x68\xf9\xc1\x9b\xb1\x3a\x74\xa7\xda\x8b\xd1\x88\x21\x15\xe0\x94\xda\x91\x8e\x13\xf2\x14\xaf\xd8\x7a\x18\x26\x62\xc8\x2b\xb6\x0e\x13\xd2\x1e\x17\x40\x55\x47\xe8\xb0\x68\x60\x21\x1b\xf8\x86\x85\x68\x96\x51\xc0\xfc\xc8\x95\xd3\x10\x43\x25\x58\x70\xa8\x07\x8f\xe6\x94\x02\x05\x35\x3b\x6b\x76\x64\xed\x96\xb3\x5e\x3e\x21\xf4\x85\x5f\xa5\x31\x21\xd4\x99\x81\xd4\xb0\x80\x97\x89\x44\xbd\x2b\x7d\x86\xc3\x10\x03\xe6\x2c\x25\xcd\xa6\xc2\x78\xac\xc1\xc3\x3e\x9e\xd6\xd9\xde\x27\x0d\x83\xe0\xc3\xc1\x83\x96\xb1\x45\x7d\xa0\xb0\xcb\x2e\x09\xa1\x6e\xe0\x3b\x59\xc2\x63\x9d\xc5\x9c\xb6\xea\xd2\x58\x9f\x41\x09\x6d\x8d\x02\x50\xd6\xa9\x0f\x29\x52\xa8\xdb\xe1\xb6\x3d\x40\xd1\x1b\x2a\xfb\x8e\xcd\x0f\x41\x39\x21\x81\xaa\xd0\x38\xa3\x59\xf5\x06\x57\xed\x5d\x79\xeb\x48\x59\x9c\x44\x80\xf6\xcd\x46\xb4\x0c\x54\x2e\x37\x53\xa1\x5b\x87\x33\x13\xb2\xd5\xf9\x08\x20\xa4\xff\x4e\x58\xc4\x6c\xa9\xff\x3b\xe1\x50\xdc\x13\x27\x00\x71\x4e\xe8\x30\x76\xb7\x41\x1b\xff\x0d\x5e\x06\x5e\xe2\x0b\xcf\xc3\x97\x40\x63\x2f\x84\x2f\x1c\x72\x13\xc0\x94\x6e\xa5\xab\x63\x00\x30\x53\xa1\xdf\x77\xae\xe1\x54\xa3\xd8\xb7\xe6\x6e\x4a\x4d\x89\xca\xb3\xe7\xab\x40\x42\x92\xbc\xec\x33\x3e\x89\x88\x66\xd2\xb5\x99\x72\x4b\xde\xe7\xe4\xc4\x68\x45\x44\x6f\x56\x97\x21\xfb\xba\x59\xc9\x61\xa2\x44\xc6\x86\x1e\xa2\xa9\x4c\x99\x2a\x90\x8b\x8a\x0b\xb1\xe1\xf5\xcf\x6f\xbe\xf2\xad\x49\xa2\x38\x86\xd7\x7a\x86\x34\x95\xcc\x77\x06\x02\xd5\xa6\x6f\x8f\xb1\xf9\x4c\x78\x15\x97\x59\xc4\x93\xe8\xd1\x54\x54\x5b\xa2\x79\x95\xd1\xc8\xf6\x9a\x97\x46\x05\x92\xf6\x69\x87\x44\x77\xfa\xd0\x2c\xce\xb2\xbb\xd8\x22\x9c\x21\x1e\x45\x6b\xc9\x82\xee\x76\x34\x0b\xcf\x7f\xad\x96\xec\xb6\x2e\x96\xbf\x56\xcb\xf3\x8c\x5e\x85\xd2\x24\x74\x4b\x16\x57\xa3\x91\xbf\x0d\xb7\x5a\xce\x90\x51\x0f\xb0\x31\x26\xa8\x49\x4d\x88\x5b\x90\x59\xda\x99\x3c\x68\x92\x55\x7b\xc1\xe2\x78\xd1\xae\x88\xaf\xbd\x23\xb1\xa3\x27\x74\x1f\xe0\xba\x1d\x46\x48\xb3\x45\xcb\xb4\xa1\x50\x69\xd5\xc0\x30\x63\xc6\x44\xd8\xe5\x1f\xfa\x7c\xf1\xb0\x05\xda\x46\x39\x00\x2f\xb6\xe5\xda\xf8\xe1\x9a\xc4\x39\xbb\xb0\x15\x27\xe2\xc6\x2e\x92\xe2\xe8\x2c\xf5\xaf\xf0\x68\xe5\xe1\x96\x16\xed\x9e\x5c\x5e\x8a\x2c\xb6\xa1\x17\x15\x75\x5d\xdc\x78\x61\xb8\x1d\x8d\xae\xa7\xf8\x34\xbe\xb9\x2c\xe4\xcf\x25\xac\x3b\xf2\xb8\xb2\x4e\x5d\xec\x27\x37\xaf\x0b\xf1\x77\xa9\x9a\xab\xa0\x26\xb2\x0a\x3c\x8c\x77\x97\xc5\x14\x1c\x6a\x75\xe4\x13\xf8\x23\xeb\x40\x7a\x91\xdd\xeb\x02\x7e\x2c\x65\xfb\x60\x4b\xdd\x08\x16\xb9\xb3\x87\x20\x67\xd8\xeb\x79\x7d\xc9\x76\x31\x68\x1b\x12\x99\x1c\x67\x4b\xaf\xe9\x8e\xde\x28\x67\xa2\xfd\x7e\xf7\xf8\xa3\x82\x3a\x7f\x4f\xb7\xb8\xc4\xbf\xb5\x85\x8e\xdc\xc2\x71\x0b\x7e\xca\x7f\xd2\x1b\x73\xdc\x2d\xca\x5b\x72\x09\x89\x30\x19\x7a\xbd\xb2\x3b\xee\xf3\x67\xd4\x2d\x75\xb6\x6f\xab\x5a\xd2\x1e\xed\xca\x6f\x1f\x66\x9a\xf0\x5b\x2b\xbc\x97\xbb\x20\x0d\x6b\x48\xa3\x08\x95\x28\x8b\x87\x49\x13\xe8\x52\xbb\x48\xfa\x1e\x6e\x8c\xd0\x3b\x41\xa9\x30\xa6\xb8\x98\xe0\x81\x9d\xcf\x08\xdd\xf6\x55\x91\x39\xa6\xe6\x33\xb2\xc8\xaa\xef\xd9\xf7\xfe\x86\x8c\x46\xfe\x06\xec\x90\xe1\x79\x4b\x00\x1b\xcc\xd0\x0b\x6b\x3f\x0e\x37\x34\x92\x79\x6f\xb6\x94\xb5\xb3\x23\x89\xe1\x51\xc3\x19\x40\xee\x26\x27\x25\x53\x62\xd0\x06\xa8\x11\xca\xe2\x16\x72\xb9\xd6\xc5\x5e\xe6\xbf\x71\x8a\x51\xbf\x20\xd6\x31\x22\x54\x5a\x4d\x25\x4d\xbd\x5b\xd6\x5e\xa8\xab\xf6\x42\x2d\xe4\x19\x8a\x47\xa3\xab\x61\x98\x02\x9b\xa1\x73\x54\x8d\xd3\xc9\x55\xf3\xfc\xff\xbb\x3c\xa6\xa8\xc0\xe1\xc9\x57\x7c\x57\x33\x3f\xa6\x11\xcd\xe8\x15\x59\xe0\x09\x5a\xaa\xe5\xc0\xc7\x40\x2e\x13\x9c\x52\x19\x3b\xe7\xbc\x2e\xf6\x07\x3c\xa7\xda\x9f\x89\xde\x84\xbb\xe5\xc5\x99\x3c\x85\x7c\x9c\x05\xe2\x41\x9c\xec\x74\x7c\x45\xf3\x70\xb7\xf4\xac\xe9\x78\x81\x67\xcf\xc4\x5b\x24\x2a\x5d\x51\xa4\x6d\x8c\x00\x59\x7f\x5e\x96\xc5\xbd\x7f\x43\xc5\xe4\x57\xf9\x9a\xee\x5a\x9a\x05\x53\xad\x95\x16\x10\xcf\x2c\xf4\x80\xc8\x3d\xd6\x78\x03\x24\x6c\x7f\x98\x9d\xf9\xf3\x09\x3b\x8f\xc8\xd8\xfb\x67\x4f\x57\x41\xfc\x04\x15\xc5\x4d\xd1\xd2\xd6\xc8\x8b\xb5\x47\x01\x88\xa0\x1e\xe9\x45\x97\x0c\xec\x82\x29\xcb\x58\x57\xe0\x26\x63\x0d\xa9\x8b\x60\x5b\xdf\xec\x96\x18\x53\x19\x73\xf3\x7a\x6b\xb1\x24\xcc\x55\xd0\x8a\x63\x0d\xd4\x73\xb1\x1f\xe0\x3e\x0c\xc4\x70\x07\x52\x17\xf4\x8c\x4d\x99\xe5\xa4\x84\x24\xff\xd0\xc1\x56\x10\x51\x45\x5e\x89\xd4\x60\x2e\x81\x82\x1a\x66\x5c\x9f\x77\x93\x0e\x9d\xfe\xb2\x06\xcb\x49\x8d\xac\x43\xd7\xa8\x68\x4c\x75\xb6\x47\x3b\xef\x86\x75\x5b\x27\x15\xd7\xc2\xa9\x1b\x42\x87\x9b\x53\x3e\x2f\x83\xf4\xc5\x21\xdb\xd3\x97\x63\xd1\xe4\x03\x4d\x03\x95\x2c\xa1\x4b\x08\xed\x6e\x9d\x92\x7f\x3c\xa3\x6b\x5e\xf8\xca\xd7\x14\x24\xb3\x40\xdc\xb4\xd2\x61\xda\x0a\x18\xa5\x51\x9b\xc8\xfa\x44\xa6\x70\xef\x79\x4f\xdb\xdd\x6b\x67\x21\x59\xa3\x75\x4e\x0c\x89\xdd\x97\x61\xc7\x9c\x8d\x96\xdc\x43\x91\x17\xae\x29\x64\x18\x35\x2c\xad\x16\x92\xd9\xc3\x1c\x6c\xde\x17\x3f\x7c\xf5\x57\x74\x3d\x44\xef\x1f\x08\x1f\xd3\xa7\xfc\xc5\x50\xe2\x1c\xc9\x09\xc8\x35\x67\x8b\x7f\x38\x7d\x82\x17\x01\x97\x1a\x62\xcc\x1d\x47\x31\x8a\x47\xc0\x25\x2d\x33\x81\xbc\x73\x47\xa2\x6c\x54\xa5\x64\xf3\xed\xbf\xff\x49\x3b\x94\xc5\x36\x2f\xd7\x7a\x4f\x37\x61\xb2\x74\x93\xc7\x05\xe9\x52\x8c\x2d\x88\x4c\x9e\xb7\x6d\x28\x13\x8c\x05\xc9\xb2\x57\xcb\xad\x6d\x71\x0f\x87\x86\xba\x57\xa7\x20\x8b\x2c\x83\x5d\x72\xa4\x99\xf8\x36\x4e\xd3\x98\x89\xc1\xb3\xf8\x26\xce\xd4\xbc\xc0\x02\x9f\x1c\x03\x48\x28\xab\x55\x8b\xf6\xa2\x6d\x69\x06\x79\x97\x1a\xdb\xd9\xa4\xaa\x1a\x88\xda\xb8\x86\x18\xda\x91\x2d\x4d\x8e\xb9\x71\x24\x3f\x6e\xa7\x93\x1b\x47\x38\xd4\xf3\x8b\x49\x7c\x7e\x71\x54\xf4\xa4\xdd\x6e\x92\x9c\x6c\x20\x49\xc7\xce\x2f\x9d\x5f\x4c\x92\xf3\x0b\x27\x7d\x5d\x7c\x0c\x5e\x54\x51\x7d\xe7\xd8\x5a\x86\xce\xeb\xb7\x63\x2d\x10\x33\x36\x52\x0a\x6a\x8b\x1e\x43\x6c\xcb\x2d\xe0\x12\xf8\x7a\xf4\x18\xdd\x2a\x07\xa9\x82\x39\x1c\x66\x16\x23\xd9\x4b\xd5\x67\xa9\x7f\x0e\xe7\xe0\x20\x86\x23\xef\x7c\x46\x94\xc8\x1b\x57\x3b\x9d\xa8\x54\x72\x34\xd3\x34\x88\x2a\x1a\x27\x8b\xed\xeb\x0d\x50\xf8\x70\x66\xc2\x0d\x26\xd2\x0c\xb2\xcb\x0d\x26\xd3\x94\x0b\x2a\x8e\xa2\xa9\xa0\x8b\x27\x19\xda\xf3\x48\x27\x35\xb9\x27\x29\xbd\x96\x3f\xc7\xe9\x38\x5e\x5c\xbd\xde\x20\x09\x83\xa7\x35\xc4\xa7\xc9\x55\x70\x7d\xb9\xc1\x73\x0c\xbd\x5b\xef\xc6\x1b\xdc\xac\xc9\xb5\xf2\x50\x1c\xf0\xd6\xbe\x75\xa3\xe0\x66\x8c\x7e\x25\x88\x95\x4b\xad\x0f\x88\xeb\x2c\xde\xc4\xbc\x87\x83\xdf\xc1\x34\xc7\x53\x78\xbd\x94\x7f\x91\x2d\x86\xbc\xeb\x81\x2c\x6a\x1f\xb2\x9f\xdf\x7c\x15\xba\x26\xbc\x03\x36\x0e\xff\xdf\xff\xf3\xe7\xfc\xb3\x33\x24\x41\x59\x9e\x14\x37\x3e\x21\x32\x31\xa2\x46\x13\x1b\xae\xb0\xc8\x17\x8f\x6f\x12\xb1\xb1\x7a\xf4\x0d\xf7\x96\x6c\xdf\x19\xfd\x44\xdc\xdb\x3a\x2e\xa8\xa8\xd4\x88\xff\xa0\xd4\x97\x84\xce\x87\xa1\xe1\x53\xa4\xe3\x61\x4b\xd9\x64\xeb\x8c\xfe\xaf\x6a\xeb\xea\x9d\xe2\x22\xaf\xb2\xaa\x1e\x14\xe9\x80\x3f\xb0\xb8\xde\x3d\x0e\xe6\x82\x1c\x9a\xec\xf8\x1d\xdf\x0d\xe4\x9e\x0c\x3d\x57\x14\x2e\xbe\xda\x60\x60\x5c\xc2\xb1\x11\xbc\x17\xdf\x5a\xbf\xe5\x05\x84\xe2\xdd\x06\x3d\x87\x1a\xd6\x96\xb9\x36\x8b\xda\x61\x37\x2c\x65\xa6\x5b\x5d\x7a\x70\xf6\xd7\x9f\x77\xf9\x1b\x7d\x2d\xdf\xf6\xb6\xb2\x9f\x4e\x3b\x2c\x39\xc1\x83\x17\x98\x23\xfc\xa5\xc2\x52\xfa\x3f\x2e\x29\x25\x34\x5a\x1a\xb1\xe8\x34\x46\x0b\xd1\x46\x01\x6d\x09\x41\x97\x31\x2a\x31\xfc\x58\x9c\x27\xe4\xab\x63\x82\x67\xab\x2d\xb7\x5f\x9a\x2a\x81\x69\xd8\xd8\x37\xb4\x85\xe8\x31\x9b\x76\x84\xad\xb5\x65\x91\xa0\x08\xc1\x2c\xe1\x0d\xc3\x69\xc7\x96\x7c\xea\x8d\x19\x2e\xb1\x24\x5f\xbf\x32\xeb\x21\x5f\x50\x26\x0f\x21\xfe\x35\x04\x3c\x3e\x23\x81\xc9\x14\x44\xab\x27\xad\x03\x57\x05\xb6\x05\xc4\xd1\x4d\x38\x21\xc1\x7c\x61\x3f\x28\xe3\x24\xf9\xd8\x65\x9e\xa4\x5e\x3d\x6f\xa0\xa4\xfa\x94\x26\x4a\xff\x63\xe6\x2e\xfb\x62\x0f\x22\xf3\xff\x12\x73\x17\xd5\xd9\x7f\x99\xb9\x0b\xda\x9b\xe8\x6e\xd1\xde\x04\xc3\x6c\x99\x35\x6b\xab\xeb\x7f\xc4\x06\x26\x9d\xa0\xda\x87\xab\xca\x23\xa7\x93\x08\xd9\x24\x5d\xdf\xee\x1a\xdf\xdb\x27\xcb\x6c\x45\x19\xed\x29\xcd\xae\x0a\x69\x20\x73\xa4\x7a\x5e\x8f\x1d\x8b\x9a\xdd\x29\x3b\x16\xd7\x7e\x65\xfb\xaa\xd1\x56\xde\xa7\x97\xaf\xcf\xb7\xaf\x2e\x3b\xfa\xd6\x9e\xa8\xae\x81\xcb\x91\xd8\xc7\xf8\x65\x53\xd7\xd5\x89\x6b\xbd\xea\xc0\xfe\x3f\xae\xad\xfe\xbd\x82\x06\x4b\x21\xac\x35\x00\x46\xf8\xe0\x2e\xd7\x4b\x85\x0f\x8d\xc6\xc6\xab\xd7\x84\x4c\x36\x52\x74\x08\xa4\xd4\xd5\x71\xf3\x00\xc4\xfa\x5b\x28\x14\x37\x1f\x8d\xbb\x25\x1e\x9d\xe2\x8e\x81\x64\xe2\xbb\x27\x08\x9f\xf6\xc9\xe1\xd0\x5f\xa1\x43\xb7\xf4\x21\xcc\xab\x89\xdf\xad\x97\xbb\xcd\x00\x9d\xdc\x48\x4d\x41\x46\xdd\x14\xa4\x4d\x3f\xea\xa5\xef\x26\x1c\xa3\xa9\xac\xb0\xd4\xbf\x64\xa2\x79\x20\x1e\x75\x61\xd3\xae\xfd\x1f\xa7\x82\x14\xf5\x63\x5f\x19\x72\xa9\x17\xf6\x83\xba\x32\xe4\x63\xd7\x95\xa1\x5e\x3d\x7f\x65\xa8\x3e\x7f\xdf\x95\x11\x9b\xe4\x6c\xa7\x7c\xf4\x91\x81\xf9\x5a\x5b\x98\x31\x3f\x46\x27\x5e\xa7\xf2\x12\xf9\xe4\xa0\x69\x7f\x66\xa3\x94\xa8\x9d\xdc\x4d\x19\xbd\x84\x0d\x82\x59\x7a\xd5\x79\x1e\x19\x7b\x83\x69\xce\xee\x06\xbb\x6c\x70\x39\x60\xca\x24\x1a\xf8\xe8\x2a\x5c\x49\x1d\x19\xd6\x37\xcf\x18\xcb\x1a\xc9\xa7\x96\xaf\x3f\xca\x5c\x75\x4c\x3c\x67\x7e\x60\x20\x85\x25\xd3\x48\x35\xa8\xf6\x8f\xcd\x24\x2a\x65\x11\xf3\xaa\x72\x6c\x8b\x4a\x9e\x96\xbc\xda\x2a\xe9\x96\xac\xd2\x0a\x4d\xf5\x3b\x6f\x69\x33\x92\xce\x7b\x3a\x1e\x8d\xe2\x46\xba\x1f\x6b\xec\x78\x19\x47\x27\x2e\xe3\x58\x5c\xc6\x31\x46\xeb\x8d\x5a\xb7\x63\x64\xd9\x6c\xe2\xd2\x07\xf3\x99\xd8\x4f\xe7\x94\xbf\xb5\x57\xb7\xef\x30\x39\xab\xdd\x74\x12\x39\x1c\x74\xda\x6c\x03\x97\xcd\x4a\xf4\x19\x11\x10\xd6\x22\xee\xf0\xe4\xe6\xb4\x15\xe6\x35\xe6\xd2\x50\xf9\xb6\x69\x12\xce\x16\x2f\x02\x31\x07\x96\x14\x0a\xb4\x97\x00\x88\x4f\x9d\x5d\xbc\x7b\xf6\x18\x5a\xda\x24\xdd\xd7\x49\x07\x5d\xa0\xb4\xc4\x56\x4e\x4c\x01\xc0\x3d\xce\x39\x22\xd3\x1b\xd6\xf2\x92\x8f\xec\xa8\x66\x12\x40\x8c\x0d\x7a\xd4\xb4\x56\x3f\xff\xdb\x47\x53\xcb\x86\x9c\xf9\xc6\x26\x09\x72\x94\xaa\x48\x50\x69\xcb\x96\x7b\xb5\x4a\x01\x88\x40\x74\x91\x50\xbe\x5e\x1f\x0e\x48\x4a\x4f\xab\xa2\xb4\x4c\x21\x80\xbe\x53\x98\x6c\x35\x5b\x4f\x04\x73\x7f\x6c\xc7\x64\x53\x42\xc0\x6a\xba\xbf\xad\xd0\x72\x4b\xac\x1a\x55\xd1\x04\xec\xf2\xf9\x1a\x5c\x20\x23\x27\xc7\x05\x9c\xc1\x7e\xd9\x45\xef\x32\xbb\xc1\x17\x71\x10\x16\x65\xd1\xd8\xe7\x24\xec\xa8\x3e\x8e\x27\x5d\x1f\x51\x72\x44\xe5\x1c\x29\x27\xa8\x8d\x1b\x70\x5e\x4a\x2a\x65\x23\x32\x2d\xf8\xb7\x41\x6f\x18\xc6\x52\xc6\x65\xf0\x4f\x74\x19\x2a\xf3\x89\xc1\x66\x18\xfa\x2c\x4c\x57\xa9\x8e\x4f\xb4\x56\x26\x1f\xd0\x37\xab\xb9\xcf\x40\xc2\xb5\x19\x8d\xa2\xd7\x5c\x2c\xaf\x7d\x60\x7b\x30\x29\xb0\x74\x3e\x5a\xac\x32\x63\x8b\xca\x26\x93\x05\xd9\x0c\xc3\x74\xc5\xd6\xa3\x51\x74\x19\x72\xf8\xe1\xeb\x94\xf5\x7c\xc5\xc6\xf3\xf5\xe1\x20\xbe\x24\x7e\xb5\xc6\x22\x5a\x36\x76\x51\xbd\x73\xb8\xf4\xf6\xe0\x22\x77\x64\x56\x34\x58\x75\x38\xc6\x9f\xb8\x61\xbe\x3f\x19\x47\x10\x14\x5c\x86\xda\xb4\xaa\x61\xe0\x70\xf9\xfe\x13\x0a\xc9\xfa\x88\x0c\x17\x51\xf9\xde\x2e\xf3\xba\x32\x3f\x2c\x12\x15\x51\xa2\x19\x42\xc8\x84\x4f\xf3\x93\x30\x31\x21\xd6\x76\x99\x15\xed\xae\x2b\x55\xa4\x1d\xf6\x4a\xad\x83\x7b\x31\x35\x16\x0b\xa6\xef\x3a\xc6\x37\x10\x84\x9c\xc5\xcf\x79\x9d\xed\xba\x6e\x5d\xfa\x5c\x06\x11\x87\xc6\xd1\x03\x59\xb8\x8f\x8a\x98\xd1\x05\x0e\xa5\x13\x35\x5f\x3e\x4f\xeb\x98\x9e\x8d\x0f\x4f\x33\xa9\x80\xb3\x32\x76\x28\xa8\x8e\x54\x03\xa2\x27\x15\x6e\xb9\x2f\xcf\x80\x46\x9c\x2a\x6c\x66\x44\xa3\x7f\x2c\xcf\xc0\xef\x75\x49\x61\x11\xe6\xdd\x6e\x94\x39\x6c\xf6\x4b\xa2\xf0\xc7\xed\x43\x64\xc7\x60\xfa\x50\x57\x8e\xe7\xcc\xd1\xec\x0f\xd0\x38\x8c\x0c\xe4\xdf\xee\x64\xcc\x36\xfb\x9c\x10\x8f\x40\x0e\x06\xf7\x8a\x82\xe4\x5b\x90\x97\xa3\x71\x55\x25\x61\xd2\x97\x9a\x43\x87\x11\xa5\x43\x1d\x24\x14\x8f\x6d\x47\x62\x20\xa9\x71\x88\xdd\x04\x3a\xc1\x8e\x55\xf5\x80\xc9\x74\x0b\x0d\x85\x2c\x2c\x7e\x33\xf2\x0a\xdc\x61\xb6\xfa\x56\x19\xe1\x75\xd5\xe6\x50\x5b\xcc\x8d\xdb\x91\xdf\xa3\x17\x68\x73\x21\x4c\x63\x7f\x0c\xec\xad\x1d\xfe\x57\xe1\xd5\xc8\x46\x3a\x1e\xd1\x79\x14\x74\x85\x2d\xdd\xea\x78\x38\xf6\x81\x31\xa3\x7b\x12\x1b\x1d\x58\x3a\x6d\x98\x56\xe7\x1a\x44\xcd\x46\xda\xda\xa7\xa3\x0d\xae\xc4\x11\x42\x36\xc7\xa7\xf1\x3e\x4d\x28\xb7\x14\xf8\x29\xa4\x68\xef\x44\x52\x72\x2f\x2f\x07\x2e\x84\x0d\x2e\x07\xcf\x60\x37\xe4\xdf\x3b\x43\x35\x8b\xb1\x0b\x54\xd1\x1b\x9f\x3b\xea\x40\xe1\xbf\xa3\xa7\x19\xa1\xdb\x25\xe8\x3b\x1c\x13\x98\xa8\x61\x2a\x23\xf8\xd9\x96\x90\xc0\x13\xa3\x78\xf6\x16\x8a\x5e\x7e\x05\xfd\xee\xf5\x98\x41\x04\x24\x95\x16\x7f\x13\x26\x66\x4b\x74\xaa\xa1\x6d\xc8\x7b\xb3\xac\x6d\xf4\x68\xdb\xe9\xe3\x0f\x87\xe1\xd0\xea\x0f\x0b\x95\x3e\x65\x61\x5a\x6e\x7b\xf3\xcc\xa7\x1f\x66\xb4\x90\x42\x46\xfd\x96\xf1\x84\x2b\x21\x66\xd1\x42\xfd\xd0\x92\x61\x16\x75\x4a\x85\x59\xf4\x12\x89\x30\x8b\x4e\xa4\x34\xea\x70\xdd\x94\x4e\x93\xea\x0a\xc1\xc0\xe5\xe4\x44\xc6\x1f\x31\x8e\x5e\x5f\x57\xdc\xde\x56\xce\x9f\x93\x6d\xf6\x19\x5c\xa7\xf4\x7f\x30\xc9\x3d\x4b\xd3\xec\xe1\xc5\x39\xee\xb1\xf6\x87\x88\xa7\x4f\x65\xb5\x7f\x61\x0a\xfb\x8f\x25\xc5\xd9\x54\x0b\x4a\xf5\x8e\x2b\x73\x80\x11\x5a\x2b\xec\xe6\x61\xdd\xf2\xf8\x5a\xe9\xa9\x55\x78\x25\x67\x7b\x5e\xde\xfc\x3f\xb2\x7a\x0b\x17\xd5\xb7\x45\xb1\xef\x74\x93\xb2\xe2\x32\x42\xb7\x8e\x57\xe9\x6d\xbe\xcf\xec\x10\x8b\xfb\x2c\xcf\xb5\x85\x83\xc5\x29\xd8\x9f\xf4\x7b\x28\x8c\x9f\xbe\x7e\xfb\xf5\xbb\xd0\x83\x8f\x0c\xe0\xff\x49\x5d\xec\xe5\x2f\x69\x14\xe1\x78\x8e\x4a\x29\xc4\x8c\xe2\x1a\x06\x48\x09\xb6\x04\x8f\x8d\x34\xff\x0d\x13\x03\x7b\x6f\x6c\xe6\x4f\xf1\x62\xb6\x16\x0a\x2d\x51\x36\x6e\x1b\xc5\xcb\x89\x5b\x5c\xcc\x18\x98\x31\x69\x89\x61\xaf\x9a\x36\x55\x78\xad\xde\x83\x93\x9e\xb6\xf6\xe8\xaa\x2b\xfb\x5b\x0e\x7d\x3e\x36\xeb\xfd\x3a\x4c\xc1\xb2\x72\x34\xd2\x86\xc2\xa2\xc2\xe6\x75\xc8\x26\x89\x55\x2a\x0d\xd2\xd1\xca\xc7\xee\x9e\x66\xe1\x76\xc9\x03\xe8\x85\x5e\x85\xdb\xe5\x26\x88\x16\xee\x27\x47\x23\xfe\x3a\x54\x76\x80\x58\x96\x8c\x46\xd9\xf8\xea\x52\x7c\xc4\x7c\xa3\x6d\xb6\x64\x43\x80\xab\x27\x6f\x41\x88\xc3\x64\xda\x2f\x4e\x64\xa3\x91\x70\xe2\xdc\x52\x78\xf8\x17\xb6\x38\xb9\x63\x43\xa3\x9e\x0d\x5d\xf4\x8d\x42\xda\x74\xb0\x8e\x08\x1d\x9d\xc7\xc7\x9e\xae\xe5\xfb\xf1\xdc\xd9\xa5\xf3\xae\x18\x20\x6d\xf3\x2f\xb3\x86\x7a\x0a\xae\xec\xc5\x21\xb8\x4d\xcc\x99\x93\x02\x0a\x40\xa3\x02\x0c\xd2\x30\x91\x06\x5d\x74\x13\x6a\x09\x9c\x7d\x69\xe8\x8e\x9a\x32\x62\xfd\x86\x2c\x14\xf6\xd5\x26\x77\xc9\x68\xe4\xa7\x21\x0f\x13\x42\x3b\x44\xf5\x1c\x8c\xce\x60\x00\x0d\x2b\xff\xce\xea\x29\x74\xa6\xc6\xd9\x6c\x21\xc1\x5d\x8b\x67\xc4\xb1\xf7\x37\x34\xa2\x9c\xa6\xc6\x60\x52\x1e\x81\x61\xb8\x25\x4f\x08\xd7\xe6\x60\x35\xc3\xf5\x80\x51\x35\x58\xc9\x7a\xda\x28\x59\x42\xdb\xd8\xdf\x2e\xbd\x89\x37\xde\x06\x9e\x47\xe8\x95\x26\xf7\xb3\xb1\x37\x35\xf7\x51\xbf\x99\xe6\x15\xa1\x57\x27\x23\x93\x3b\x08\x77\x6b\x63\x5b\xcb\xb9\x60\xa9\x26\x6b\x9f\x3a\x9f\x04\x6d\x7f\xfe\x67\xce\x50\x66\xec\x55\x33\xcd\x4b\xc9\xa9\x52\x4f\x0e\xc3\x23\xce\xe4\x8e\x8e\x97\x43\xe7\xd9\x02\xfb\xad\xcd\x24\x9a\xa4\x82\xb2\xb7\xe9\x24\xe8\x63\x61\x7e\x2a\x5a\x09\x6f\xae\x0e\x6a\x09\x5f\x3c\x4f\x2f\x61\x6f\xfd\xe2\x81\x13\x82\x00\x9c\xd7\xb3\xf9\x06\x4d\xa2\x02\xa2\x4d\xb6\x43\xf5\xe3\x70\x78\x3a\x52\x89\x2f\x65\xd1\x17\xb0\x4a\x10\xe3\x54\x5a\xd6\xe3\xba\x35\x2a\x90\x46\xb3\x77\xc5\xde\x6e\x53\x17\x7b\xfb\x95\xa6\xf3\xc4\x55\xe6\x88\x21\x0c\x41\xb5\xe5\x0f\xef\x8a\x9f\x36\x91\xcf\x95\xaa\xed\xfc\x6f\x1f\x2d\xfd\x15\x9b\xa4\xbf\x26\x6b\xd2\xfe\xf1\xf1\x79\xb6\xe0\xa1\x09\x46\xc2\xcc\x5a\x71\xca\x68\x4d\x33\xb3\xd6\x63\x36\xae\xc7\xf5\x38\x1b\x67\x47\x3c\x1a\xb5\xd3\xfb\xd3\xc5\x91\xf4\xfd\xfe\xf8\x3c\x9b\xf2\x07\x1e\x5b\x32\xe5\x7a\xf9\x54\x06\x26\xcc\xcf\x6a\xbe\xa6\xf3\xcf\x08\xdd\xd8\x65\x17\x58\x16\xd9\x65\xaf\xa0\x0c\xcd\x31\x2d\x1d\xcb\x8e\xdd\xec\x71\xc8\x7a\xc0\x88\xd2\xb2\xdc\xd7\xb8\x8d\x53\x46\x68\x6d\xa9\x66\xb2\xea\x4d\xfe\x79\x59\xb2\x47\x78\x65\xa0\x0a\x62\xc1\xff\x90\xfa\x9c\x5c\x4e\xe6\xe8\x2c\xf3\x97\xb7\xa1\xbd\x34\xb8\xbe\xb5\x89\xb2\xf3\x9b\xd8\x8a\xb7\x52\xdc\xe6\x7b\x1f\x79\x63\x3e\xf6\x04\xdf\xb9\x67\x65\x9d\xc5\x3b\x5e\x4d\xae\xaa\x49\xcc\xf2\x3b\x56\x4d\xf8\xce\x93\x9c\xba\xe8\xf7\x09\x4b\x83\x27\xbe\x0b\x6a\x7a\x1f\xd4\x0e\xff\xb7\xd5\xcf\x28\xfa\x3d\x52\xdd\x63\xf0\x84\xbe\xd7\xc1\xd3\x1d\xdb\xdd\xf2\xe0\xd3\xd9\x8c\x26\x5c\xb0\x35\x8f\xc1\x13\x1a\x3e\x05\xc3\x19\x85\x97\xef\x59\xc9\x59\xf0\xc7\x19\x44\x9f\x28\x76\x85\x6e\xe4\x7d\x94\xa6\xa9\x77\xa4\xd5\x96\xed\x79\x20\x19\xf7\x38\x2b\xe3\x1d\xf7\x68\x55\x97\xc5\x35\x0f\xa4\xbd\xec\x4c\xb6\x14\x4d\x66\xb3\xd9\xcc\x3b\xd2\x7d\xb1\x7b\xdc\x14\x79\xf0\x94\x47\xef\xab\x2c\xe1\x55\xf0\x87\x23\xcd\x6e\xd8\x86\x07\x4f\x55\x19\x07\x9e\x47\xb1\xed\x7c\x36\x53\xd6\xb5\x73\x18\x44\xb1\x67\x31\x0c\x14\x87\x31\xa7\x68\xa8\x17\x0c\xe7\x94\xe5\xd9\x8d\x99\xc0\x9c\x56\x7b\xce\x93\xe0\x42\x35\x79\x7f\x93\xe5\xc1\x8c\x56\x8f\x79\x1c\x40\x6a\x85\x2a\xfb\x3b\x57\xfd\x5c\xcc\x9e\xef\x68\x06\x2d\x5a\xdd\xec\xb2\x9c\xbf\xdf\x65\xf9\x35\x4f\xec\xe5\x4b\x32\xb4\x64\x86\x29\x98\x05\x48\x3d\x3d\x85\xb9\x9a\xe3\x91\x0a\x94\x6b\x37\x56\x43\x37\x99\x8f\xbd\xbc\xc8\xb9\x67\x0d\xb2\xaa\x4b\x06\xeb\x32\x9c\xd3\xe2\xb6\x7e\x7f\x53\x24\x3c\x40\x27\xd4\xa8\xb8\x15\x1f\x16\x33\xa9\xeb\x92\xc5\xb5\x3d\x99\xb2\x10\xf7\xdd\x2f\xc1\x2b\xfe\x4a\xfe\xfe\xab\xf8\x7d\x3c\x52\x26\x40\x3a\x58\xad\x8f\x14\x32\xc8\x02\xdf\x0d\x4b\x9d\xf0\x9a\xc7\xf5\x7b\x31\x0a\x84\x39\x8f\xc2\x35\x54\x05\x4f\x45\x8e\x71\x35\xac\xb1\xe3\x40\x36\x25\x8b\xbc\x23\x2d\x72\x0c\xc0\xd1\x7a\xbf\xbf\xad\xb6\xde\x91\x62\x8c\x4d\x08\x0d\x2e\xca\xab\xe0\x49\x34\x0c\x9e\x9c\xd5\x73\x56\x58\xaf\xde\xf1\x48\xa3\xdb\x48\x74\x6a\x6a\x5f\xcc\x70\x93\x82\x3f\xce\x68\x72\x5b\x62\xb8\x98\xe9\xa7\xe2\x3b\xfb\xdb\x5d\xd5\xac\xea\x54\x11\x23\x0a\x9e\xf4\x29\x79\x9f\x47\x01\x34\xc4\xbd\x71\xca\x2f\x8e\x62\xb8\xb7\xa2\xbf\xa3\xa8\x52\x67\x39\x7b\x8f\xab\x04\x11\x46\xf2\xe0\x49\x2d\x61\xf0\xa4\x67\x76\xa4\x77\x3c\x4f\x8a\xb2\x82\x56\xf5\xcd\x5e\xfc\x95\xd4\x82\x3a\xd5\x0b\x36\x1a\xfd\x00\xa4\xd1\x34\xe1\x7c\xff\x35\x32\x8a\x99\xc0\x40\xd9\xb4\xbe\xd9\x4f\x8b\xe8\x2a\x7c\x02\x38\x44\xc0\xcd\x0c\xa6\x98\x42\xb8\x52\x28\x46\x48\x15\x70\xfc\x1e\x41\xa9\x55\x4d\xbc\x9b\xc2\x3b\x00\xbe\x8e\x6a\xa2\x58\xd6\xb0\x36\xe0\xbd\x5e\x40\xbb\xae\x55\x61\xaa\x2a\x38\xad\x10\xd2\xfb\x9a\xdc\xa3\x4f\x65\x91\xf0\xf7\x62\xfb\xed\x6f\x38\xa0\x38\x85\x95\x9c\x8a\x3a\xe6\x33\xd0\x0c\x21\xe1\xb9\x86\x58\xab\xbb\x29\x80\xcd\xc9\x66\xa2\x06\x36\x91\xd0\xf4\xdc\xe7\x64\x35\xfd\xbd\x23\xcd\x04\xe5\x81\xf0\xf2\xc6\x89\xdf\x43\x9e\xb2\xa9\x03\x47\xa3\x91\x8a\xfc\xc2\xef\xb2\x98\xff\x98\x3d\xf0\xdd\x4f\x02\x58\x2f\xe7\x4b\x3f\x9b\xe2\x39\x9c\xee\x1f\x00\x80\xc3\x9e\xba\x12\x66\xb0\xe3\x70\x38\x23\x41\xbb\xe9\xbc\x51\x69\x2e\x20\x4d\xd6\xb9\x0f\xf5\x4f\xbe\xb3\xaf\x97\xb3\x66\x37\xa6\xcd\xb6\xa3\x0d\x5e\x41\x5d\x8d\xba\x80\x37\xd4\x90\x3e\x35\x80\xfe\x82\xc6\x06\xa4\x9b\x3d\x98\x83\x70\xba\x1b\x03\xf2\x56\x0f\xe6\x78\x9c\x6e\xdc\x75\x06\xac\x6e\xba\xce\x50\x57\x87\xcf\x02\xbc\x33\xb4\xe6\x89\x79\x69\x8f\x8d\x93\xd0\xec\xb3\x71\x9c\x5e\x3e\x71\x38\xc9\x3d\xb3\xbe\xef\x83\x9c\x67\xce\x5c\xcf\xe0\xc4\xab\x97\xf6\xd6\x3c\x89\xcd\x2e\x9b\x07\xba\xd5\xaf\x3c\xba\x58\xd8\x3e\xba\xb2\x72\x5c\x3f\x38\xd0\xaf\xac\xd9\x1e\x6a\xdf\xbb\x48\x3c\xe2\xf4\xf2\xb6\x11\xca\xda\x6e\xa8\x96\x51\x9d\x43\x6a\xbf\x44\x7a\xc8\xbc\xdd\xd2\x6c\x34\x6a\xce\x1b\x2f\x68\x19\x31\x5b\x23\x13\x96\x24\x28\x85\xc8\xaa\x9a\xe7\xbc\x54\x41\xae\x1d\x66\xe7\xf9\xe3\xff\x92\xd3\xee\xa0\x95\xd1\xc8\x20\x9e\xfb\xb3\xf0\x04\xf6\x68\xbf\x24\xf4\x1f\x59\x99\xe6\xe9\x46\x3a\xe4\x70\xf0\x61\x27\xf4\xcb\xaf\x6f\xf6\xf5\xa3\x4f\xa8\x5b\xfa\x25\xc4\xc0\x6c\x15\x7f\x55\xb2\x7b\x55\x28\xaf\xf4\xa9\x24\xa0\x3f\xbf\xad\x8b\x1f\x55\x3d\x9f\xbc\xa8\xd2\xd1\x85\x8b\x1f\x59\x96\xf7\x82\xd7\x34\xcd\x76\x3b\xf0\xca\x9b\xd1\x19\xed\x5a\x86\xad\xdb\xdb\x97\x4d\x15\xbf\xd3\x1b\x18\x00\xbc\xac\x3b\x35\xfb\xd0\x65\xf5\x8c\xb0\xa9\x64\x49\x76\x5b\x85\x7e\x0b\x2f\x23\xcd\xba\x74\xdc\x6a\x82\x39\x39\xeb\x21\x5d\xba\xf1\x3a\xee\x9b\xf2\x9b\x01\xac\x5e\xd5\xac\xbe\xad\x74\xda\x85\xbb\x2a\x3c\x71\x25\x9c\x0b\x42\xb2\xe7\xfd\x63\x1e\xab\xc4\x2d\x77\x32\x08\xde\x5d\xd5\x70\x03\x92\x92\xed\x87\xb0\x5e\xd6\xd3\x87\xc0\x79\x79\x66\x2d\x1c\xd4\x7a\x84\x5a\x8f\x7d\xb5\xa4\x94\xe6\xe1\xd2\xb4\x9b\x5c\x9c\x59\x8b\xb8\x54\xdf\x82\x3f\x13\xeb\x0d\xc6\xf4\x78\x78\xed\x54\x57\xab\xa2\x1a\x8c\xad\x77\x72\xdc\x8f\xe6\x5b\xdb\xae\x6f\x3d\x62\xd3\xc7\xf6\xb7\x1e\xbb\xbf\xa5\x1a\xb8\xdf\x6a\x1d\x37\x64\x45\x04\x7a\xb2\x8e\x01\xc8\x2d\x7f\xb8\xe3\xe5\x8e\xed\x65\xe4\x3f\x39\x4c\xe0\x93\xc2\xa7\x63\x3b\x39\x95\x84\x0e\x02\x2a\x70\xf8\x69\xfb\x8a\x02\x37\x8e\xcc\x75\x15\xca\xf7\x2b\x58\xfd\x74\x57\x14\xa5\xdf\xdc\x08\x33\x4a\xf8\x22\x36\x50\x2a\xc1\xf5\xc2\x8c\x65\x5a\x6e\xa2\x50\xcb\x47\x2a\x19\x27\x1b\x2d\x94\x86\xea\x4b\xd3\x72\x34\x6a\x16\x6d\xda\x45\x91\x5a\x3b\xd3\xf3\x53\x19\xe8\x3e\xe8\x46\xff\xde\xd0\x48\xff\x8e\x8e\x84\x36\x7b\xda\xb6\x3b\xaf\xda\x45\x3b\xf7\x7b\xdb\x6a\x17\x3e\x6d\x75\xbf\x5b\x5a\xe9\xdf\x15\xdd\xe9\xdf\xbb\x23\x46\xec\xf3\x70\xb9\xbc\x50\xf5\xb7\x6c\x8f\xdd\x5a\xe1\x8b\x3f\x34\x1d\xe7\xc6\x33\xba\x79\xb6\x46\xf4\x5c\x8d\x63\xd0\x52\xb6\xc9\xf1\x38\xb3\x93\x69\x77\xbb\x36\xcd\x2a\x47\x10\x52\x71\x9f\x91\x91\x74\x11\x96\x2c\x7c\x11\xce\x52\x75\xdb\x68\x4b\xbd\xe9\xc0\x5c\x4a\x18\xd1\x44\x5e\x45\xd8\xdb\x41\x37\xfe\x72\xab\xd8\x28\x4c\x46\x9e\xb9\x2b\x9a\x28\x6c\x81\xb1\x69\x9e\x8e\x8b\xea\x3e\xab\xe3\xad\xdf\x3a\xae\x5a\xde\x40\x9e\x62\x56\x71\xa9\xd5\x09\x9f\x1e\x82\x19\x7d\x0c\x26\xf3\xe3\x22\x2a\x39\xbb\x5e\xa8\x97\x32\xf4\x34\x56\x99\xfe\x41\xd4\x99\xfe\xc1\xa9\x64\x57\x98\x8b\xf7\x33\xe7\xb5\x74\x0d\x6f\x75\xd3\xe8\x45\xa9\xaf\xf4\x50\xe6\x5d\xbd\x60\xb8\x0a\xa8\x33\x81\x5e\xdc\x5a\xf6\x6b\x31\x94\x59\x6b\x36\xad\x0e\xac\xd9\x24\x28\x81\x37\x43\x98\x1d\x8f\x6d\xde\x41\x0a\x65\x96\x72\x2b\x1e\xc2\x7c\xfa\x20\x77\xf8\x31\xcc\xa7\x8f\x6d\x0c\x89\xdb\xa3\xc0\xe3\x4e\xe2\xf0\xbb\x07\x77\xf3\x74\x1f\xf2\x6f\x73\x6b\x03\xfb\x83\x63\xe7\xa5\x98\x89\x35\x82\xd6\x4b\xd5\xf7\xc3\xfb\x4c\x7d\x5b\xd5\xd7\x25\x8f\x00\x3a\xa5\x7b\xc1\x6e\xd9\x1e\xc3\x54\x80\x7e\xb2\x89\xb0\x4b\xa0\x0c\xca\x1e\x2c\x1d\x87\x65\x3f\x7e\x2e\x1b\x98\x18\xbe\x14\xc6\x47\x44\xbe\x56\x51\x09\x5f\x06\xb9\xa1\x52\x8c\xc2\x0b\xfc\x46\xd1\x1e\x2e\xf6\x97\xdd\x6c\x42\x10\x33\x16\x53\x68\x3b\xad\xca\x98\x02\xad\xa9\x4b\xd0\xfb\x5d\x3d\x6d\xa5\x08\x55\xb5\x9e\x42\x65\x9d\xec\x4d\x15\x84\x73\x42\xbd\xea\x4e\xa0\x2a\x24\x7e\xb3\x9b\xcd\x7b\x4c\xed\xac\x70\x33\x96\x57\xc5\x6d\x19\xf3\xf7\xd5\xdd\x06\x08\x63\xfb\x6a\x04\x8a\xf3\xed\xdd\xe6\xcd\x8d\x4c\x58\x2c\xe9\xe8\xfd\x6d\xb5\x85\x08\xf3\xe6\x9b\x98\xe2\x4f\x70\xec\xe4\xd8\x20\xd2\x6c\x6f\xcb\x92\x39\xb6\x76\x5a\x8a\xcd\x9b\xc4\xa0\xa8\xf9\x46\xcc\xd7\x2f\x29\x13\x64\x07\x65\x82\x20\xa0\x17\x67\xf0\xef\x9c\x99\x99\xa2\x95\x83\xf4\xd8\xcc\x52\x5f\x4d\x8f\x49\x4a\x40\xf2\x68\x04\xa5\xdd\x8d\x52\x0c\x08\xeb\xbe\x72\x3b\x51\x48\xd2\xea\xa5\x6a\x15\x9b\x6e\xac\x77\xa2\x1f\x66\x6e\x01\x82\x18\xcf\x2b\x37\x11\xf3\xbd\xb1\xf5\x66\x5a\x8e\x3d\xea\x96\x6c\x5a\x25\x11\x94\x54\x63\x8f\x78\xe6\x6b\x79\xe8\x6d\xab\x9d\xdd\xdd\xb6\xda\x4d\xb7\x4e\x63\x51\x52\x8d\xbd\x7f\x6e\x14\xed\xb0\x08\x3b\xd4\x38\xb8\x41\xdd\xbf\xad\x1f\x77\x3c\xcc\xa9\xf3\x22\xe2\x9b\x2c\xff\x91\xd5\xe8\xa5\x2a\x81\x1c\xf0\x96\x94\xb9\x07\x4e\x75\x56\xc6\x3e\x9b\x3e\x88\x0d\xa4\x35\x9d\xd1\x0b\xc4\x17\x3f\xbe\xa1\xc3\x39\xb1\xb1\x1e\x4f\x36\xcd\xb6\xe2\x06\xf0\x3b\xf6\xdf\x69\x57\x97\x19\xcb\x37\xf8\x5d\x9b\xc1\x29\xd9\xfd\x5b\x31\x38\x67\x5a\x06\x9a\xc6\xf5\xf9\x7c\xfa\xd9\x67\xd0\xe5\x2b\x7a\xe1\x74\x29\x75\x02\x1f\xd0\xe3\xb9\xdf\xc6\x47\xb2\x97\xa9\x52\x2c\x9c\xbf\x12\x18\x0e\x26\x72\x3e\xfd\x97\xcf\xe8\xc5\xf4\xb3\xcf\xce\x5e\xd8\xd2\xa5\x67\xbb\x6b\x51\x77\x3d\xab\x9a\x95\x2f\x9f\xc1\xc5\x0b\x47\xf2\xa9\x9a\xc1\x7c\xfa\x87\x0b\xb1\x78\x67\x62\x1a\xff\x85\x93\x70\x77\x02\x11\x6a\x20\x70\x6b\x17\x36\x23\x78\x17\x20\x3a\x28\xa2\x2b\x73\x34\x4a\xab\xa6\x78\x51\xa2\x49\x5f\x83\xe5\x2c\x2a\x2e\x21\xb9\x3d\x32\xd4\x1c\x21\xfa\xbd\x9c\xd9\x62\x03\xd1\x16\xdf\xe2\x01\xe9\x6d\x0b\xc7\xcd\x3d\x3d\xbb\x2c\xe7\xff\x21\x05\x07\xa7\xbe\x48\x3b\xbe\x86\x4c\x7c\xe3\x8c\xfa\x4d\xae\x58\x8a\x0a\xba\x42\xb7\xf2\x70\xb6\xe0\xaf\xed\x0f\xa3\xfa\x0d\xe9\xc6\x05\x1f\x8f\x89\xfd\x12\xb4\x30\xe8\xa9\x92\xf3\xfb\x81\xf3\x15\xbf\xc5\xb9\x74\x92\x84\x92\xcc\x6d\x0e\xb1\x9d\xc3\xa7\x7f\x88\x38\x0a\xe9\xa8\x21\x86\x28\x15\xc3\xad\x3a\x2b\xbe\xc6\xc4\xd8\x9d\x72\x16\xa5\xef\xec\x16\xb2\x9e\x5f\x2c\xd8\xf4\x61\x1c\x32\x41\xee\x20\x7e\x10\xbf\x1f\xcf\xea\x63\xa3\xcb\x6e\x82\x7a\x1e\x5a\x97\x02\x12\xd4\x4b\x5f\x97\x5c\x76\x52\xd4\x8a\x75\x68\x36\x04\xc1\xb7\x2e\x84\x71\x14\x24\x30\xd5\x5e\xf7\xd3\xe7\x96\x7e\xb1\xb3\xe3\x99\xd5\xf1\x04\x3b\x36\x05\xaf\x67\x76\x9b\x70\x46\xc8\x73\x02\x10\x98\xb5\x25\x00\x11\x53\xc6\x4b\xf4\xb2\x2d\x00\x31\xd3\x75\x45\x26\xe0\x33\x0c\x8d\x60\xaa\x15\x4c\x15\x0b\x5e\xf7\x89\x51\xa4\xf2\xb3\xdd\xdb\xcc\xf4\x36\xc1\xde\xf4\xb3\x9c\x9e\x94\x0d\x89\xd9\x79\x28\x12\x00\xac\xd2\x00\x0a\xa5\xc6\x94\x17\xfe\xd3\xc3\x7b\x08\xe8\xa3\x9a\xd3\x87\xf7\xc0\x27\x04\x96\xb8\xe5\xf1\x7d\x5d\xec\x4d\x8d\xc7\xf7\xc8\x0a\x98\x2a\xdb\xa3\x4d\x27\xa8\x2e\x27\x27\xfa\x1c\x5b\xbd\x89\xce\x27\xa7\x7a\xd7\x95\x35\x4f\x25\xf0\xba\xde\x10\xd3\xab\xd8\xa5\x87\xb0\x9a\xe2\x00\x04\xac\x87\x7d\xd2\x21\x12\x88\x53\xd1\x58\x41\x6c\x0b\x63\x3d\xdd\x18\x6e\x8a\xf6\x00\xb6\x62\x00\x8f\x61\x35\x85\x49\x89\xdb\xa7\xaf\x8b\x7b\xf1\xfd\xc7\xe6\xf7\xb1\xa9\x34\xfc\x3a\xd9\xba\xcd\xe2\xe8\x7d\x7d\x92\xdc\x1a\x00\x80\x33\x4b\x7b\xa5\x04\x3a\x08\x27\xe2\xff\xc0\x5e\x4c\x39\x10\xf5\x0e\x26\xda\xd1\x7e\x2b\xda\x3f\x42\x9d\xc7\xc0\x5e\x0b\xd5\x5e\xbe\x23\x80\x63\xb4\x25\x07\x2a\xac\x5b\xea\x03\x29\x46\x97\x6a\x6e\x50\x16\x10\x29\xcd\x32\xaa\x19\x25\xcb\xf5\x19\xa1\x76\x97\x48\xa7\xbe\xac\xd3\xc3\xe1\x43\x1a\xa2\x01\x2f\x34\x74\x87\x83\x2d\xfb\x06\x24\xd5\x1c\xbf\x63\x44\xcf\xb7\xec\x1d\x92\x6c\x6a\x8f\xa9\x4f\x7b\xa4\x84\xf3\x2d\x08\x92\x76\x0c\xea\x56\x51\xf7\x56\x1e\xf2\xf1\x7c\x91\xf7\xdf\x5c\xb9\xba\xb9\xca\x8e\x9b\x2b\x5f\x2f\x4e\x0f\x44\x4e\x43\x4d\x58\xd4\xb8\x36\x72\x7b\x46\xcb\x0e\x58\x77\x47\xda\xec\x41\xbe\x7d\xae\x13\x47\x6a\xaa\x1b\x63\xa9\xdb\xf6\xd8\xe4\xfc\x40\x39\xf1\x0f\xc9\xfb\x3b\xa9\x06\xdf\xce\x37\xf2\x0f\x11\x0b\x0c\x08\x62\xbf\xc5\xb2\xa2\x0a\xc6\x1d\x79\xa3\x79\x08\xb6\x29\x4e\xa3\x9f\xda\xae\xda\x31\xcb\x63\xbe\xfb\x89\xff\x76\xcb\xab\xfa\xf3\x3c\xbb\xf9\xa6\x64\x37\x1c\xd9\x6c\x90\x3c\xeb\x32\x42\x4f\xd5\x15\xc3\xb4\xaa\x36\x39\xf7\x10\xd9\x55\xea\x50\xbc\x6e\x61\x5c\xdc\xe6\x35\xd4\x9d\x75\xcd\x55\xa9\x90\x2c\x45\x4d\x53\xab\x24\xd8\x89\x5a\x13\x9b\xdd\x80\xd8\x69\x60\xc6\x01\x71\x3e\xd0\x2a\xe4\x80\x02\x1f\x69\x8e\x18\xbb\xfa\xad\xac\xfd\xfa\xac\x1e\x57\x67\x15\x9a\xa2\xbb\xf7\x7d\x97\x16\xbb\xeb\x08\xd9\xf5\x14\x6d\x93\x9f\xfb\xf3\xf3\x67\x2a\x91\xde\x0a\xea\x6b\x62\x50\xe5\xe5\x4c\xc9\x89\xfa\xaa\x03\xf9\xfb\xbe\xdc\x44\xa2\x80\x2f\x7a\xf9\x04\xc5\xfb\xc7\x92\xe3\x8f\x25\x9f\x1f\x4b\xee\xbe\x14\xcc\xf8\x4b\xd8\x85\xb6\xc1\x4a\x2f\x87\xee\xbc\x10\x27\xfa\x5d\xe1\xf3\xe9\x03\xe5\xd3\x47\xd2\xfe\xd4\xbb\x42\xf1\xea\xa4\x9b\x01\xa1\x7d\x0c\x94\x3e\xfd\xbd\x08\xe6\x7f\x0e\x38\xea\x73\x7f\xce\x5f\x9d\xf5\x22\x44\x69\x77\x46\x68\x1c\x56\x2f\xaa\xfa\x57\xb2\xe0\xd3\xbb\x87\x49\x58\x52\x3e\xbd\x7b\x9c\x80\x81\xef\xdd\xc3\x38\x2c\xc5\xdf\xc7\x71\x18\xb7\x66\xdf\xc0\x90\x27\x27\x9f\xe9\xc9\x57\x8d\xc9\x67\x67\x19\xa1\x79\xc8\x15\x81\xac\x65\x54\xf9\x65\x58\x41\x50\x44\x41\x83\x88\xff\x61\x60\xf0\xf3\x91\x1a\xca\x84\xda\x44\x06\xb5\x6e\x42\xc1\xd4\xf5\x0d\xce\x91\xf2\x85\xc3\x99\x46\xb7\xb5\x40\xb7\x97\xf5\xa2\xfe\x6f\xe2\x13\xe9\xd3\x43\xc0\x96\x6c\xba\x2f\xaa\xf7\x27\xf4\x9a\x8f\xba\x52\xbf\x5a\xf3\x48\x08\xad\xc3\x90\x4f\xe6\xc0\xb8\xf7\x68\xde\x7b\x74\xe9\xce\xf4\xe7\xee\xc2\xa1\x11\x5e\xd7\xd2\x75\xdc\x12\x90\xf9\x2a\xe6\xfe\x8c\xf2\x8e\xab\xf5\xd4\x28\x9c\x6f\xba\x94\x94\xf3\x49\x2d\x42\x65\xe0\xf2\xea\x8a\x25\x43\x5d\x40\xb9\x2b\xf7\xd4\x10\x65\x2c\x89\x6b\x9f\xd1\x9a\x56\x34\xa7\x31\x88\xcb\xd9\x30\xac\x09\xf0\xbe\x62\x39\x94\x15\x8e\xb4\x52\x7c\xcf\x73\x4c\xf1\xa6\x04\xa5\x95\x92\x73\xe7\x93\xfd\x99\x9f\x4f\x98\x40\xae\xa7\xac\x7d\x64\x47\x74\x17\xb2\x49\xb1\x48\x42\x36\xde\x51\x0f\xec\x3f\x20\x30\xba\xdf\x1c\x70\x42\xa8\x27\x27\xa3\x6b\x34\x66\x9b\x90\xa3\xce\xa2\x5c\x0a\x6c\xf1\x02\x6b\xa3\xc6\x24\xc4\x1c\xee\xc2\xca\xf0\x69\x77\x61\x0e\xf2\xe0\x61\xc8\x94\x33\xdf\x07\xce\x70\xf1\x5f\x34\xab\x53\xdd\xe0\x04\x9e\xef\x4b\xd6\x43\x91\xc6\x49\xb2\x5b\xd3\x8c\xbf\x8f\x85\x30\xfa\xef\x87\x49\x7b\x95\x6e\x2b\x8e\x67\x1c\x50\xdb\xe3\x89\x1a\x8f\xb4\xb4\x30\x62\x75\x56\x8d\xf3\xb3\x5c\xe0\xed\xf9\xa4\x7c\x66\xf9\xed\x2b\xfc\x43\x80\x21\xbe\x0c\x67\xa3\x11\xa6\x77\x13\xc7\x14\xa4\x03\x6e\x63\x14\x36\x40\xed\x67\x2d\xc6\x86\x3d\x82\x10\xf2\x92\xc6\x97\x3d\x6d\xe5\x59\xd3\xd7\xc2\xb3\x1d\x9d\xc5\x8b\x02\xe6\xd5\x02\x9d\xc2\x8a\xcf\xbb\xd3\x3d\x76\x6c\x49\xd3\xfa\xd4\x7c\x7e\xb2\x83\xee\x67\xcb\x56\xdf\x41\xb3\x64\xd6\x05\x7a\x4e\xdf\x12\x62\x87\xfd\x12\xb3\x67\x57\x4e\x09\xdd\xfa\x7b\x78\xc2\xa3\xfd\x92\x5e\xce\xe2\xc5\xdd\xa5\x7e\x1a\x8d\xee\x9e\x81\x25\x5d\xb1\xe3\xf4\x59\x4b\x7d\x67\x70\xf3\xa4\x53\xbc\x08\x03\x3d\xbd\x0d\x8a\x8c\x15\x43\x7c\x6d\x0f\xf1\xf2\x1f\x19\xa2\xc4\xa1\xcc\x27\x0b\x3b\xc7\x61\xdf\x29\x18\x8d\x98\x95\xbc\xfe\x19\x96\xfc\xf7\x60\x15\x9b\x99\x7f\x6a\xde\x47\xf0\x32\xcb\x37\xcf\xe3\x1b\xa8\xf9\xfe\x79\xac\x63\xea\xf5\xe0\x9e\x7d\xe8\x03\x95\xf3\x15\xab\x39\xc1\x78\x82\x37\xdc\x27\x27\xbb\xab\xb3\x1b\x4e\xce\xe7\xfc\xd5\x62\x7f\xf9\xa2\x4b\x03\x88\x96\x9e\x7b\x17\x84\x9c\xfb\xcb\x8b\xb3\xdf\xd5\x93\x5a\xb1\x70\xa8\xac\xad\x3b\x3f\x31\x27\xc7\xce\x66\xa3\x91\x5f\x3f\x8f\xb7\x7a\xac\xa9\x9b\x54\x88\x7e\x96\x37\x3f\xa1\xcf\xf4\xad\xa8\x99\x7e\x0a\xb2\x09\xd1\xa6\xc0\x5c\x8e\x46\x47\xdd\x29\x15\xea\xa7\xaf\x50\x94\x80\x49\xe7\x6b\x96\x5f\xf8\x09\xdd\xcb\x48\x28\x77\x0f\xe1\x2d\x2a\x36\xe3\xa2\xf2\x19\x41\x72\x5c\x16\x55\x59\x2e\x8a\x5e\x22\x6e\x96\x9c\xc1\xd3\x43\xc0\xa7\x0f\x63\x20\xec\x1f\x03\x3e\x7d\x14\x3f\x1f\x8f\x8b\x1a\x0a\xdb\x72\x4a\xc3\x07\x04\xf5\xf4\x61\xc2\x6d\x39\xa3\x79\x47\x68\x0d\x3d\xb5\xe5\x94\x86\x79\x08\xea\xe9\x63\xab\xbd\x7c\x47\x8e\xbf\x8f\x72\xf8\x20\x59\xdf\x0b\xef\x5e\xc3\x41\x9d\xa2\x2f\xaa\x67\xe9\x8b\x2e\x76\x93\x96\x62\x03\xea\xf3\x9c\x3e\x06\xd5\x79\x7e\xa4\x71\x0f\x42\x6d\xda\x72\xd3\x22\x04\x27\xa1\x10\xbd\xf9\xe6\xe7\xf1\x99\x3f\x99\x23\x10\xec\x8b\x7b\x3f\x3f\x8f\xe9\x05\x19\xcf\xc9\x59\x7c\x56\xd0\x19\xfd\xc3\x8c\xd0\x3b\xb5\xd9\xe5\xf4\xe1\x6c\x27\x77\xbb\x9c\x3e\x9e\xed\x8e\x8b\x17\x40\xcc\xd2\xbf\xb3\x36\xfc\x72\x36\x1a\xdd\x59\x30\xf2\xda\xc0\x08\xec\xe4\x43\x78\x37\x7d\x20\xf4\xce\xda\x63\x6c\xf2\xd8\xd1\x04\xd2\x6b\x4c\x1f\xc3\xbb\xe9\x23\x21\x81\x6a\x4d\x55\xd1\x3f\x80\xf4\x3f\x4c\x84\xab\x91\xbe\x32\x8d\x4f\xb3\x3c\xab\xb6\x60\x38\x6d\x17\x83\x8c\x6b\x3c\xa6\x1d\xa5\x61\x5b\x00\x68\x22\x9b\x75\x75\x2e\x90\x2c\x69\xf6\xe4\x5c\x36\x71\xa8\xb7\xf5\x65\xc0\x71\xfe\x19\x7d\x25\xae\x8f\x67\xef\xa7\x09\x9f\x3e\xd0\xe4\xd9\x7a\x62\x0b\x1f\xe9\x4d\xb8\x3f\xdb\x8f\x93\xb3\x84\xde\x86\x93\xf8\xfc\xe6\x6c\xbe\x88\x2f\xc3\x1b\xeb\x5a\x9e\x29\xa5\x79\x73\x1e\x0a\x37\x70\x30\xb8\x42\x8c\xc5\xc1\xd4\xca\x65\x3f\x6d\xbd\x82\xcb\xef\xbe\x18\x19\xbc\xf8\x48\xb3\x67\x8f\x74\xfd\xec\x91\xb6\x85\x28\xec\x8c\x8d\xeb\x33\x4c\x85\x51\xf5\x91\x6e\x8e\x4f\x8b\x4a\x9b\x77\xa2\x6a\x97\xc0\xb1\x42\x81\xe3\x87\xb4\xe9\x63\x20\x9d\xe1\x80\xe8\x4b\x89\x20\xfb\xe5\x9e\x1f\x2a\x82\x2c\xa5\x08\xb2\x94\x22\xc8\x52\x8a\x20\xf3\xff\x0d\x22\xc8\x53\xdb\x7f\x62\xe3\x7f\x87\xc8\xf2\xe8\xca\xb8\x11\x7a\x95\x47\x8a\x13\x7f\xd3\x43\xb7\x95\x0e\xf0\xd5\x2e\xa9\xcb\xd6\x61\xd8\x49\x6f\xb8\x96\x53\x1e\xdf\xd9\xce\x2a\xf4\x65\xc7\xe8\x70\x78\x11\xa6\x25\x80\xd2\x9a\xdf\xeb\xf0\xb7\x31\x67\x92\x3e\x77\xaa\x77\xa1\x9c\x09\x51\x87\x34\x86\xa4\x4c\xbf\xc0\x71\xc4\xdf\x7f\x35\x52\x13\x51\x01\x1d\x70\x7e\x39\x1c\xdc\xba\x58\xfc\x57\x53\xfc\xd7\xc5\x89\xed\x0e\xd9\xa9\x0d\x0f\x3b\x3c\x7b\x7a\xbb\xea\x74\xf5\xe9\xed\xba\xdb\xf7\xa7\x0b\x6f\x85\xd6\x3a\x1e\xdb\x95\xfa\x57\x1e\xf9\x2a\x77\xe9\x4f\xac\x04\xc4\xc7\x38\xb5\x18\x9d\x15\x9c\x31\xe2\x17\x8f\xa4\x63\x94\x3d\x57\xf6\x4b\x26\x23\xb3\x05\xb8\x31\x5f\x9e\xbd\xe4\x7a\xae\xb7\x53\x87\xdc\xba\xfa\x4e\xb4\x7e\x3c\xd9\x5a\x70\x62\x61\x17\xff\xf6\xb2\x25\x21\xda\x52\xf2\x79\xba\x05\x2d\x0c\xc0\xb9\xbc\xed\xcc\x8c\xdd\x2d\xfb\x24\xf2\x3d\x24\x85\xa8\x33\xb5\xdd\xbf\xbb\xe7\x4a\x82\x79\x1b\x4d\xf5\xf4\xf0\xdf\x36\x84\x17\x36\xbf\x9c\x3b\x1a\xfa\xdf\x35\x04\xc7\x62\x10\x05\xf4\xd2\xf0\xb1\x53\x66\xdf\x4b\xaf\xc1\xce\xf4\x76\x2c\x25\x15\x41\x0f\x3b\x3d\x73\x07\x81\x04\x6e\xd0\x4d\x79\x85\xc3\x59\x27\x95\xda\x2c\x55\xb4\xe8\x9c\x76\xe7\xe5\xee\xeb\x7d\x7e\xa4\xa8\xd5\x3a\x49\x97\x4a\x86\x9f\x1c\xb5\xd7\xdf\x29\xe7\xc0\xb0\x79\xc0\x5b\x46\x84\xb2\x95\x63\x6f\xc7\xc3\x96\xc7\xe4\x59\xdb\x4d\x12\x44\x23\x0d\x54\xce\xcf\xc3\x8b\x96\xef\xab\x0a\x98\xc5\xcf\xfa\x8c\x18\xcf\x4f\x0c\xcc\x84\x11\xa1\x75\x2f\x43\x30\x61\x8b\xd9\x65\xdd\x7f\x2c\x90\xfd\x8f\x2a\xbf\x26\xe4\x14\x90\xd5\xa4\x49\x5d\xd8\xbe\x66\x0d\x95\x9b\xad\x61\xab\xfb\x0d\x1a\x6a\x65\xd0\x50\x75\x18\x34\xd4\x6b\x10\x6c\x3d\x4c\xaa\xe9\x03\x2d\x81\x4a\xae\xa6\x8f\x34\xb6\xa8\xe1\xfc\x2c\x1f\x97\x67\x25\x59\xc4\xaf\x8d\xf0\xd8\x72\xa7\x13\x2c\x1e\x5b\xb2\x53\x4e\x85\x82\xfb\x13\x55\x4e\x78\x14\xf6\x3b\xd8\x71\xd2\x5e\x14\xcb\xcb\xc0\x61\x2e\x94\xdd\x86\x6b\xea\x40\xeb\xf0\xfc\x23\x7f\x35\x9b\xfc\xeb\xe7\x93\x6f\xd6\x4f\xaf\xe8\x67\x47\x72\xbe\xc9\x68\x15\x32\x1d\x02\xa8\xa6\x56\xe0\xbc\x9a\x66\x14\x45\xf5\xbc\xd7\x16\x9f\xb7\x6c\xf1\x79\xcb\x16\x9f\xb7\x6c\xf1\xb5\x64\xa9\xcf\x26\x9f\xb7\x6c\xf2\x79\xdb\x26\x9f\xb7\x6d\xf2\xdd\x8e\x55\x8c\xbb\x23\xa1\x39\x04\x7f\xfc\x62\x57\x44\xfe\xaa\x5a\x53\x19\xe9\x06\x4c\xa4\xcf\xab\xbb\xcd\xf8\xe1\x66\xb7\x88\xb7\xac\xac\x78\x1d\xde\xd6\xe9\xe4\x8f\x82\x20\x29\x55\x44\x86\x9f\x7f\xfa\xf6\x70\x90\xbf\xef\x79\x74\x9d\xd5\x56\x09\x8d\xc3\x52\xee\x05\xc6\xfc\xf8\xf9\xa7\x6f\xfd\x9c\xd0\x02\x3e\x09\xae\x18\x8b\xa2\xe3\xf2\x6f\x85\xa7\xe2\xca\x14\x3b\x2c\x28\x77\x7c\x43\x66\xb4\x9c\x96\xfc\xae\xb8\xb6\xbe\x10\x93\xa6\x7d\xca\x78\x7c\x24\xb4\x98\x56\x65\x1c\xc6\x2d\xac\x04\x99\x9c\x9c\x40\x46\xca\xc6\xe6\x73\x95\xe5\xbe\xdf\x6a\x46\xc5\x13\xf3\x09\xdd\xff\xe5\xed\x57\xc5\x0d\x66\xcb\xa2\xdd\x16\xf2\x61\x33\x8c\x14\xad\x68\xae\xb8\xb0\xea\x2c\x07\xdb\x81\x9c\x16\xe1\xfc\x8f\xb3\x33\x3f\x9e\x5c\x90\xf3\x98\xee\x42\xe9\xdb\x30\x91\x7f\xcf\x8a\xf3\xf9\x1f\x67\x0b\x3e\xad\x18\x7c\x98\x3b\x8c\x11\xc7\xc0\xb1\x3b\x88\x65\x4f\x6b\x51\x20\xd9\xa3\x19\x9d\x19\x2b\xa7\xbb\x70\xb6\x28\x2f\xef\x16\x77\xe3\x31\xe1\x9a\x47\xa2\x33\xb7\x03\x59\x80\x06\x0b\xfe\x8e\x2c\xb8\x34\x0f\x17\x85\xbc\xaa\x8b\x92\xfb\x4d\x3c\xcf\x1f\xf6\x45\x59\x3b\x27\x8f\x3c\x49\x10\x29\xf6\x3c\xf7\x6d\x54\x5d\x17\x5f\xb1\x9a\x89\x5d\x93\x20\xb7\xcf\x37\x1e\xa1\xde\xfb\x68\xc7\xf2\x6b\xaf\xd9\xb7\xd8\xf6\xe6\x99\xd6\x92\x9c\xec\x66\xf3\x9e\x97\x65\x51\x2a\x2b\x25\xcf\x1b\x76\x18\xc4\x6b\x97\x28\x62\x1c\x00\x34\x6a\x10\x80\xf9\xcb\x77\xdf\xfe\xb9\xae\xf7\xd2\x6a\x6a\xc1\x70\xd4\xde\x9f\xbe\x7e\xe7\x75\x58\xf4\x9b\xee\x28\x9b\x16\x79\xc9\x59\xf2\x28\x08\x64\x1e\x6f\x59\xbe\x71\x65\x1b\x9f\x86\x80\x51\x58\xf2\x28\x93\x2b\xfb\x17\xb3\x19\x98\x3b\x4b\x4b\xe7\x96\x11\x16\x77\xb3\xdf\x89\x45\xdf\x17\x79\xc5\x3b\xf0\xe1\x17\x3c\x2d\x4a\x8e\x9a\x7e\x12\xf8\x71\x91\x57\xc5\x8e\x4f\x77\xc5\xc6\xf7\x20\x11\xd8\x60\xff\x97\xb7\x83\x09\x9e\xbb\x41\x5e\xd4\x83\xb4\xb8\xcd\x13\x8f\xd0\xe6\xf2\x0d\x67\x84\x1c\x29\x9b\x56\x10\xed\xd8\xe8\x97\x6a\xeb\xdc\xd6\x2f\x39\xb7\xae\xed\x58\xfd\xcc\xa0\x8f\xe2\x38\x89\x33\x7a\x62\x91\x51\xfa\xd4\x3b\xb7\xef\x8b\x81\xae\xda\x39\xb1\x8e\x93\xe9\x30\xe4\xca\xd7\xae\xdb\x11\x70\xd9\xe9\x2f\xb2\x6c\x60\x1b\xd7\x4c\xdd\xa6\x23\x96\x7e\x8f\x71\xc8\x09\x42\xde\x41\x38\x61\xd9\x69\xca\x67\x4f\x87\x04\x2f\x37\xfa\x23\x41\x63\x85\x54\xdc\x88\x0f\xfe\x28\x09\x5c\x0f\x40\xb9\xe7\xff\x5f\x9e\xf0\xff\xb6\xa9\x75\x11\x86\xe6\x78\xfd\xc3\x50\xae\x7c\x3c\xc3\x16\xf9\xa4\xe0\xdf\xb1\x3d\x6d\xcf\x0e\xde\x0b\xc4\xd4\x37\xa5\x76\x27\xad\x13\xac\xb6\x4b\x4d\x12\x12\x22\x36\x83\x90\x20\x06\x54\x1b\xf4\x82\xaa\x8d\x95\xcb\x5a\xe1\x6f\x9c\xa0\x56\xae\x59\x6b\xbb\xe4\x6d\xf6\x77\xee\x96\x40\xc4\x93\x67\x82\xaf\x9c\x0e\xa1\xd2\x6b\x51\xee\x8a\x68\x4d\x50\x80\x93\xf5\x9b\x13\x06\x2b\x5c\x67\xc6\x46\xab\x82\xa0\xd2\x71\xef\x81\xa7\xdc\xd2\x77\x81\xe4\x14\xea\x9e\x56\xb7\x51\x55\x97\x1d\x4e\x7d\xa6\x8a\xe4\x96\x5e\x91\xce\x6b\xbf\xf1\x31\xc5\x2a\xf5\x5f\x28\x27\x05\xb1\x7d\xb6\xc8\x8b\x56\x7c\xba\x3e\xbe\x6a\x90\xe5\x03\x46\xd8\xaa\x5e\x8f\x46\xe2\x7f\x3b\xed\x63\xbb\x24\x0c\x43\xec\x79\xe9\xf3\x55\xbd\x0e\xc5\x7f\x10\x25\x95\x95\x1b\x08\x96\x59\x41\x20\x53\xce\xe1\x35\x15\xcd\x09\x09\xa0\xaa\xf8\xbd\x30\x29\xa9\x25\x31\xd5\x3c\x61\x1d\x91\x60\xdb\x35\x0d\x3d\xdb\xa0\xdb\x7f\x3a\x59\xe7\xa6\xf8\xfb\xe9\x0a\xc5\x33\xed\xab\x9e\xf7\x36\x79\x24\xeb\x5a\x62\x09\x4e\xe7\xfc\xd5\xf9\x67\x33\x72\x3c\xfa\x44\xcd\xbb\x1b\x81\xf4\xcf\xbe\x8b\x98\x6f\x4c\xfe\xcb\x66\x97\xdd\x4b\xf0\x92\x6a\xc5\x8b\xfa\xaa\x4e\xd6\xb2\x73\x04\x5b\x13\x97\x1c\xc6\x6a\xad\x0b\xd4\x41\x6a\x85\x61\x55\x41\x45\x86\x76\x84\x69\x16\x72\xca\x43\x4f\xb7\x9a\x5c\x55\x1e\xa1\xfc\x70\xf0\x5b\xa5\x8b\x46\x1c\xd7\x46\x56\x70\x81\x99\xdd\x26\x56\x0c\x57\x5a\x85\x76\x83\xea\x8b\x47\x88\xad\xfc\x3d\x60\x79\x54\x9a\xa9\x00\x08\xe2\x28\x2d\xd4\xd3\xe5\x6c\x41\x74\x7c\xe6\x6d\xb6\x4b\x7c\xc8\x6f\x26\xa3\x7a\xe8\xa1\x20\x43\x29\x3b\xf7\x55\xc4\x4e\xb2\xc8\xa7\xb1\xfa\x4c\x98\xd1\x7c\x5a\xd5\x8f\x3b\xe9\xf7\x1a\x7a\xf3\xd9\xec\x9f\x3d\x5d\x28\xe3\x68\x61\xa9\x0c\xfd\xd0\x3f\xd5\x29\x66\x24\xc5\x21\xe5\x64\x81\xe1\x89\xcb\xd1\x08\xf7\xc3\xd8\x28\xef\xff\xf2\x16\x56\x9f\x1c\x3b\x36\x08\x90\x58\x2b\xb8\x14\x46\xc7\xec\xe0\x3a\x32\x9b\xeb\x00\x97\xa2\x53\xbc\x05\x03\x36\xe8\x53\x71\x37\x1b\xf6\x42\xf0\x37\xc0\x5f\x64\x8e\x36\xb4\x0a\xff\xf2\xf6\x87\xef\xa7\x10\x3c\xd8\x67\x3d\xfc\x05\x59\xb4\x67\xe0\x73\x5a\x11\x5a\x8f\x46\xb5\xd2\x02\xf7\xd2\xe1\xee\x64\x06\xf8\xf9\x60\xe0\x8d\xf5\x50\x68\x6f\xdb\x6f\xb2\x1d\xf4\x9c\x66\x1b\x9b\x4b\x11\xc8\x5c\x32\x24\x0b\x7b\x50\x9f\xd8\x50\xf8\x09\x7d\x32\x50\xe9\x05\x4f\x1e\x52\xdf\xe2\x17\x10\xe0\x5e\xf0\xc7\x19\xf5\xe4\x1d\x2b\x4a\x91\x3a\xf3\x82\xba\xbc\xe5\xd4\x33\xb2\x3c\x4f\xc6\x04\xf6\xe0\xc2\xb4\xda\x43\x8c\x5b\x0c\x0d\xec\xc1\xed\x25\xde\x89\x33\xe6\x99\xf0\xc0\x1e\x6a\x09\xc5\x1b\x00\x3f\x2f\x98\xe9\x8e\xbc\x8f\x66\x33\x19\x24\xd8\x44\x04\x78\xf2\x94\xa7\xba\x17\xfc\xe1\xff\xcf\xd7\xd5\xee\x44\x08\x03\xc1\x57\x31\x93\xf8\xc3\xa4\x62\x8b\x40\xb4\x3e\x0c\xe1\x4b\x8e\x28\x68\xb8\xf3\x87\x31\xbc\xbb\xd9\x76\xb7\x14\xf0\xfc\x77\xe9\xd2\xdd\x76\xa6\x70\x3d\xb6\x3b\xb7\x28\x29\x50\xff\x01\xfd\x8c\xb1\x18\xc6\xfe\xa1\x1f\x2e\xa7\xaf\x3a\xa1\x9d\x99\x12\xaf\x46\x6b\x05\xbf\x96\xc1\xf2\xc1\xe1\x3c\xd2\x3a\x62\x9d\xe4\x4a\xc4\x8e\xec\x6b\xf5\x7e\xee\x14\xaa\x69\x18\xe3\xe9\x73\xb3\xab\x5a\x86\x35\xc1\x4d\x39\x0e\x13\x79\x30\x0a\xe7\xef\xa9\xe1\x0b\x29\x8e\x3b\x5b\xb5\x06\x89\x42\x78\x28\xff\x8f\x90\x69\xef\xe1\xba\xff\x68\xd3\x72\xe4\x49\xf2\xd8\xb0\x26\x8f\xa1\x65\x6a\x22\x14\x74\x92\xad\x70\x2d\x0a\xfe\x35\xfe\xde\x1f\x8f\xaa\x20\xcf\x2c\x10\x04\x51\x24\xde\x43\x27\x12\x38\xa1\x41\x0e\xcd\x80\xd5\x89\xc1\x65\x1e\x7f\xcc\x9e\x6b\x44\x60\x0b\x62\x8e\xcb\x40\x60\x4d\x4a\xdc\x11\xef\xf1\x9b\x75\xea\x1f\xd2\xc0\x58\xa5\x89\xe1\xf7\x31\x64\xe6\x54\xee\x71\x42\x3c\x1e\xc9\x18\xd0\xba\xf0\x59\xa4\xab\x97\xb2\x5e\xb1\xe8\x25\x3a\xe3\xe2\xad\x2e\x94\x2b\x1f\xa5\x11\x05\xe8\x33\x9a\xc3\x8e\xa6\x80\xbb\xa1\xe9\x48\x72\xe3\xd0\xcb\x87\xa0\x45\x20\xf9\x02\xd8\x34\x62\xed\x29\x50\xf2\xe8\x86\xc4\x79\x8f\xd8\x0f\x41\xa6\x38\x11\x16\xdd\xf3\xe5\x54\xc3\x66\xae\x93\x50\xbd\xb5\xa5\x0e\xe8\x8d\x14\xad\x20\xe1\x9f\x39\x65\xdb\x8d\x1f\xd4\xef\x34\xb4\x5d\xd9\x54\x73\x1b\xe8\xab\xab\xe6\xad\x9f\xe9\x71\x54\x86\x25\x57\x17\xe6\x39\xcd\xb0\x31\xf2\xed\x8b\x6d\x6b\xf8\x5f\x53\x8b\x5c\xdf\xde\xe4\xf4\x85\x14\xdb\xe7\xee\xb3\xab\x2e\x6e\xdd\xdd\xf3\xe7\x8d\xdd\x83\x86\xc6\x31\xbe\x2c\x77\x2f\xbf\x01\x00\x00\xff\xff\x0d\xcc\x2b\xb4\x02\x39\x02\x00") func assetsLoginDistAllMinJsBytes() ([]byte, error) { return bindataRead( _assetsLoginDistAllMinJs, "assets/login/dist/all.min.js", ) } func assetsLoginDistAllMinJs() (*asset, error) { bytes, err := assetsLoginDistAllMinJsBytes() if err != nil { return nil, err } info := bindataFileInfo{name: "assets/login/dist/all.min.js", size: 145666, mode: os.FileMode(420), modTime: time.Unix(1571033118, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _assetsLoginDistRespondMinJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x57\x6d\x73\xdb\xb8\xf1\x7f\x7f\x9f\x82\xe2\x3f\x7f\x06\xb0\x20\x50\x72\xf2\xa6\xe4\xc1\xba\xc4\x71\x7a\xd7\x49\xee\xae\x67\x4f\x7b\x53\x49\x99\x01\xc1\xa5\x44\x89\x24\x68\x02\xd4\x83\x45\x7e\xf7\x0e\x48\xea\xc9\x8e\xa7\xed\x1b\x09\x58\x2c\x16\xfb\xf8\xdb\xa5\x7b\xd5\xb3\xfe\x00\x95\xcb\x2c\xa4\x4b\x65\xad\x47\xf4\x3d\xbd\xf6\xac\x34\xce\xdc\x94\x6f\x07\x9b\x38\xd4\x0b\x2b\x85\x30\xe6\xd6\x63\x09\xc5\xce\xca\x65\xb2\x8b\xe2\x24\xb1\xae\xac\x5b\x99\xef\x8a\x78\xbe\xd0\xd6\xf5\x70\xf4\xce\xba\x17\x52\x6b\xeb\x6f\xb0\x48\x7e\xb0\xae\xac\x2f\xb1\x80\x4c\x41\x68\x95\x59\x08\x85\xb5\xd0\x3a\x57\x9e\xeb\xce\x63\xbd\x28\x03\x2a\x64\xea\x2a\xc3\xbf\x84\x45\xe2\x76\x0a\xb8\x41\x22\x03\x37\xe5\x4a\x43\xe1\x7e\xf9\xe5\xf6\xee\xd7\xfb\xbb\xc1\xd7\x5f\x1e\x8c\x38\xeb\xca\xfd\xe1\x87\x5e\x54\x66\x42\xc7\x32\x43\x1c\xef\xed\x52\x81\xa5\x74\x11\x0b\x6d\xfb\x9c\xa6\x5c\x8b\xc5\x57\xa3\x28\x3b\xdf\x54\xd5\xf9\x9d\x35\x2f\xac\x80\x08\xc6\x69\x28\x45\x99\x42\xa6\xef\x12\x30\x7f\x24\x64\x82\x46\x71\xa1\x0e\x84\xdb\x45\x9c\x84\x55\xd5\x11\x9b\x1d\x01\xc6\xa9\x28\x80\x6b\xe8\x98\x90\x1d\xc8\x70\x67\x63\x12\xbd\x3c\x09\xe3\xb5\x8d\xfd\x02\x74\x59\x64\x56\x44\xe3\x90\xd9\xe9\xe3\x40\x83\xd2\x83\x91\x4d\x22\xaa\xf4\x2e\x01\x2a\x94\x7a\x80\xad\x66\x76\x2e\x55\x6c\xb4\xf4\x78\xa0\x64\x52\x6a\xf0\xb5\xcc\xbd\xc1\x68\x38\x84\xd4\x26\xd0\xb1\x07\x5c\xac\xe6\x85\x2c\xb3\x90\xd9\x99\xcc\xc0\x9c\xf0\x3c\x87\x2c\x6c\x34\x44\x11\x26\xe7\xe6\x9e\x5e\xcf\x32\x28\x7e\x7e\xf8\xfa\x85\xbd\x75\xd4\x62\xe7\xff\xd8\x88\x6b\xe3\xca\xec\xb7\x7d\xde\x7f\x6b\xdf\x58\xff\x77\x54\xd0\xda\x5b\x4d\xe4\x3d\xeb\xfd\x75\xbe\xf5\xad\xfa\x47\xb7\xb9\x71\xf3\x96\x08\x1a\x67\x0a\x0a\xfd\x11\x22\x59\x00\x02\x12\x62\x12\xb0\xf7\xd7\x8c\xb1\x88\xca\x28\x52\xa0\xff\x69\xae\x12\x41\x0b\x48\xe5\x1a\x5a\xcd\x00\x93\x7d\x13\x15\x50\x5e\x40\x9a\x87\x3d\x5e\xd7\x35\x3a\x85\x02\xd7\x48\x2f\x62\x75\x69\xc2\x45\x94\x0f\x07\x56\x80\xf0\xbe\x44\xbd\x21\xae\x4d\x44\x05\xdb\xd7\x3e\xa7\x45\x9b\x45\x4c\x10\x41\xcb\x3c\xe4\x1a\xd8\x51\x12\xde\xd7\xbe\x61\x0d\xd9\x64\x46\x2e\xe8\x4d\x4a\xb0\xde\xc8\xd7\xc5\x6e\x1f\xb0\x0c\x36\x16\xa7\x7f\x7e\xfd\xf2\xb3\xd6\xf9\x1f\xf0\x58\x82\xd2\xb5\x30\x8a\x23\x81\x8f\xe7\x1f\x84\x8e\xd7\xf0\xe7\x6f\xc1\x12\x84\x46\xf6\xd7\x58\x14\x52\xc9\x48\x37\x17\x1f\x1e\x7e\xb7\x71\x7d\xf0\xfd\xe9\xa5\x8e\x12\xd4\x35\x32\x19\x73\xb2\x92\x04\xad\x1a\x82\x01\xc2\xbe\x70\x1c\x24\xa8\xcc\x21\x43\xf6\x5f\xef\x1e\x6c\xc2\x49\x6f\x88\x89\xa0\x32\x2b\x80\x87\x3b\xa5\xb9\x06\xb1\xe0\xd9\xfc\xc2\x8e\xf7\x3d\xc6\x8c\xcb\x79\xb8\xbb\x37\x1c\x55\x75\x3d\x1c\x36\x34\x73\xa1\x54\x8e\xf3\x6e\xf8\xfe\x6c\x5f\x55\x01\x12\x9d\xcf\x14\x98\x24\xc4\x35\x79\x2e\xc4\x71\x04\x55\x90\x85\x28\x2b\x93\x04\xe3\xda\x8f\x23\x24\x28\x5f\xf2\x2d\x8b\x88\xa0\x8f\x25\x94\xc0\xc2\x26\xd4\x73\xd8\xb2\x7d\x1b\x57\xf7\xa7\xe6\x7f\xf2\x6d\xba\x9f\xf5\xa7\x7b\x64\x16\xd3\x7a\x76\x35\xdd\x4f\xbe\x4d\xeb\xe9\x7e\x76\x35\xad\x71\xdf\x9d\xc7\x64\x05\xbb\xa8\xe0\x29\x28\xcf\xfd\x09\x8d\xbd\xe9\x00\x8d\x3d\x59\xa5\xf2\xa9\xda\x40\xb0\x8a\x35\x9e\x0e\xf0\xf8\xc8\x74\x14\x38\xf6\xbe\x2f\xd2\xac\xcd\xca\x88\x2e\x8b\x44\x79\x2e\x2a\x8b\x64\x8a\xf0\xe4\xad\x3d\x1b\x1b\x3d\xdc\x29\x7e\x6b\xcf\x26\xdf\xbc\xe6\xbf\xdf\x1d\x4c\x31\x76\xe7\x24\x8a\xb3\xf0\xde\x64\xb9\x3a\x58\x60\x5d\xa1\xf6\x4d\x6c\xac\x98\xde\x4f\xd5\xac\x3f\xc6\x6f\x5c\x22\xb3\x64\xe7\xb9\xc8\xfc\x4d\x55\x1f\x8f\xd1\x84\x0f\x9e\x3e\x0c\xfe\x65\x38\xd5\xd8\x25\x69\x9c\x6d\x3c\x77\x8a\x26\x53\x35\xbb\x4a\xe3\x6c\xda\x02\xe9\x54\x5d\x79\x0d\xa9\x3d\x98\x0c\x07\x7f\x99\xd2\x59\x1f\xa3\x7c\x5b\x41\x8a\x1b\xe2\x14\xbb\x24\xe5\xdb\xb3\xeb\x7c\xfb\xbf\x5d\xaf\x89\xa0\x8d\xfa\x7f\x2f\xa1\x88\x41\xdd\x97\x79\x2e\x0b\x0d\xe1\x05\x30\x3a\x8e\x89\x69\x8f\x5d\x10\x91\x6d\x4c\xb2\x78\x92\xd8\xd8\x71\x5e\x3b\xa1\x5d\x21\x93\xde\x2b\x0f\xb5\xe9\x3c\x27\x0b\x12\x93\xe5\x19\xd8\x92\x15\x5b\xbe\x40\xde\xc4\x94\x64\x6a\x7e\x32\xf3\x23\xd9\xbe\x26\x39\x7b\x37\x24\x8f\x6c\x49\xe7\x70\xe0\x53\x1f\x77\x0f\x7c\xfe\x2b\x4f\x01\xd9\x0b\xe0\xa1\x8d\x27\xc3\x59\x55\xad\x48\xf1\x2a\x5b\xc0\x15\x34\x6c\x44\xb1\xc7\x57\x78\x92\x38\x5b\xd9\x98\xe8\xe7\x90\xc0\x49\xc0\x96\xdf\xc5\x74\x22\xd8\x92\x1a\xdc\x27\x21\x5b\x75\xb8\x1c\xc9\x4c\xdf\xc7\x4f\x40\x80\x89\xa6\x66\x2e\xa9\x91\xc1\x97\x43\xf9\xff\x67\xe4\x37\xf7\x06\x2a\x7e\x02\x6f\x04\xa9\xdf\x02\xf1\xc8\xb4\x01\x51\x55\x48\xb0\xe8\xa5\x62\x5d\x1b\x12\xaf\xb5\x09\x4c\x9e\x6b\xca\xec\xd1\x70\xf8\xff\x36\x79\xae\xeb\x89\x7e\xde\x57\x02\x4c\x22\xc7\x59\x5d\x42\xbf\x20\xab\xb3\xee\x88\x09\x67\xc1\x45\x03\x88\xc6\xab\x8b\x16\x20\xb0\x77\xd9\x13\x82\xef\xa8\x15\x12\x68\xf0\xef\x19\x19\x8c\xf8\x98\xe5\xbc\x50\xf0\x39\x91\x5c\x23\x8e\x6b\x52\x9e\xa2\x76\x84\x50\x5b\x24\x31\x64\xad\x0a\xb6\x09\xd1\x44\x18\xc4\xb7\x6f\xef\xef\x47\xb7\x32\xcd\xb9\xb6\x19\x33\x1e\x6c\xd6\x5f\x65\x08\x8e\x13\x56\x55\x1b\xd2\x89\x98\x55\x55\x48\x22\x93\x83\x92\xa9\x89\xa2\x09\x64\x73\xbd\x18\x8c\x66\xa4\x60\xc8\x80\xff\x27\xae\x01\x9b\x64\x7a\x88\x53\x03\xd7\x71\x84\x02\xc7\x99\x3b\x4e\x7e\x53\x0c\xe6\xb8\x8b\x32\xa7\x22\x01\x5e\x18\x1e\x59\x6a\xb4\xc0\x64\xc1\x38\x55\xed\x2d\x43\x29\x49\x8e\xc9\x5a\xc6\xa1\x35\xf4\xe7\xac\xf0\x23\x59\x20\x63\xc0\xda\x8a\x33\x2b\xc1\x71\x84\x12\xba\xe0\xea\xb7\x4d\xf6\x7b\x21\x73\x28\xf4\x0e\xad\x71\x6b\xe3\x86\x25\x93\xf5\x8c\x6c\xd9\x86\x1a\x9c\x21\x3b\xb3\xe0\xdb\x0d\x79\x62\xa6\xa4\x19\x63\x5b\xf2\xe1\xb0\xdc\x91\x8f\xcc\x86\xd4\xf6\xb7\x8e\x83\xb6\xe7\x0e\xdc\xe2\x2b\xb4\xa5\x71\x16\xc2\xf6\xb7\x08\x7d\xc4\x37\x83\xd1\x38\xae\x2a\x8d\xb0\x37\xc2\x98\xec\x1c\x07\xed\xce\xf9\x77\xf8\x0a\xed\x5e\xe7\xdf\x18\x75\x9b\x11\xd1\x71\xd0\x93\xe3\x7c\xa8\xaa\x1e\x7a\xaa\x2a\xb8\x61\x5b\x6c\xd6\x1f\xaa\x6a\x77\xc3\x00\xe3\xaa\x42\xd1\x64\xd3\x22\xc7\xec\x62\xc3\x26\x33\x4c\x4e\x5b\x9a\x97\x6a\x81\xd2\xc9\x86\x16\x65\x02\x6a\x86\x71\x7d\x70\xd3\xad\x71\x53\x86\xb3\xe7\x3e\xba\xc5\x8e\x93\x4d\x6e\x67\xed\x2f\xcd\x79\x01\x99\xfe\x55\x86\xc0\x18\x7b\x74\x9c\xc7\x8b\xfc\x33\x2c\xd8\xcf\xba\x18\xb3\xe1\x31\x08\x9f\x8c\xf4\xc8\x04\x21\x7a\xfe\xc0\xa7\x2e\x08\x77\x2f\x8b\xb0\x49\x59\x1b\x93\xcf\x2c\x9a\x7c\x9a\xd1\xa5\x8c\x33\x64\x4f\x33\x1b\xfb\x77\x54\xef\x72\x60\xb6\x86\xad\x76\x85\x52\x36\xb9\x6b\x4d\x64\x9f\xc8\xe3\x65\x51\xdd\x11\x49\x33\xd8\xea\xfb\x38\x48\xe2\x6c\x8e\xc9\x5d\x5b\x0a\xf7\x0b\x00\x3d\x3e\xdf\x1c\x11\xe4\xb3\x77\x77\x51\xac\x07\xc5\xcc\xa1\x31\x1d\x7d\xc6\x98\x64\xad\x33\xef\x70\x5d\x93\xf5\xc5\xec\x41\x3a\xb8\x36\xd3\x6d\x01\x79\xc2\x05\xa0\xae\xa1\xd3\x63\xeb\x25\xf6\x01\xf6\x8f\x67\x8d\x01\x66\x90\x01\xc7\x81\xce\x87\x55\x35\xf4\x03\x16\x50\x55\x06\x66\x66\xcb\xe6\x68\x48\x02\x9a\x70\xa5\x7f\xe9\xf2\xc6\x76\x6d\x8c\x9b\x51\x6c\xce\xbe\x33\xaa\xbe\x54\xc1\xf4\x71\x62\xbf\x19\xd9\xfd\xa0\x6f\xbf\xb9\x7e\xf3\xce\xc6\x35\x59\xb0\x5e\xe4\x38\xa1\x1f\x74\xef\x3a\x0e\x0a\xfa\xcc\xc8\x26\x66\x1d\xb1\x11\x3e\x06\x33\x36\x81\xbd\x89\xfd\xb8\xdf\x6f\x0d\x5d\x92\x15\xc9\x88\xf4\x17\x63\xb4\x64\x21\x49\x5b\xcf\xcc\x11\xc7\x18\x7b\x68\xc9\x60\x12\xcf\x9e\xd9\x7a\x1a\x0d\xb0\xe3\xfc\x01\xf3\xbb\x6d\x4e\xdf\x8c\x0e\x57\x0f\x84\x6b\xc7\x99\x9f\x36\xd8\x78\x9d\x2d\xa9\xca\x93\x58\x23\x9b\xd8\x98\x48\x76\x48\xb6\xa3\x76\x39\x1b\xfa\xf2\x26\xf7\xf3\x7e\x1f\xaf\x58\x36\xc9\x67\x24\x69\xa5\x76\xc3\xd4\xea\x20\x00\x35\xad\xec\x99\x62\xa6\x29\x9f\xa9\x74\x5d\x55\xb6\x69\xd1\xa4\x29\x18\x2f\x3d\xc2\x17\x39\x14\xa7\xb7\x3a\x96\xb0\x91\x78\x33\x18\xb5\xc3\xca\xea\x79\x74\xe3\x6c\x83\x1d\xe7\xac\xfe\x8f\x66\xe3\x3e\x3a\x7f\xcf\xc6\xed\xbc\xf2\x42\x02\xdf\xfe\xd7\x12\x6a\x5c\x97\x08\xd7\x64\x73\xde\x86\xe3\x08\x85\x9d\x01\x87\x31\x3d\xa4\x6a\x11\x47\x1a\x61\x3f\x42\x01\x5d\x14\x10\x9d\x3e\x16\x04\xde\xaf\x91\x20\x1d\x39\x38\xe4\xa7\x9c\xb4\x94\x19\xeb\x0d\xc9\x05\x04\x9f\x3d\xb5\x31\x8f\x0f\x8d\x1a\x35\xd9\x9e\xeb\x70\x08\x53\xc0\x86\x7e\xf0\xe3\xa1\x1d\xf8\xc1\x21\x97\x04\x53\x93\xc0\xf4\x17\xd1\x69\xc3\xba\x91\x88\xcc\x9b\x41\x3a\x71\x9c\x16\x17\x94\x29\x59\xd3\x79\x1a\x2a\xd5\xf2\x8b\xdc\x40\x71\xcb\x95\xe9\x21\xd0\x34\x90\x9e\x9c\xc0\xec\xd4\xfc\x9a\x22\x3f\x0e\x13\x6d\xc9\x17\x7c\x73\xdb\x56\xfd\x18\xad\xd1\x2b\x47\x04\x48\x64\xec\x06\x63\x32\xf6\x50\xcf\xfd\x76\x98\x4f\xbd\xd9\xd5\xd4\x9d\xba\xd8\xa5\xe6\x3b\x0f\x01\x76\x9c\x5e\x51\x55\x70\xac\xba\x53\x6e\x9b\x82\xef\x32\xcf\x6d\x32\x8f\x99\x51\x31\x91\x82\x1b\xd7\xd0\x85\x54\x1a\x3b\x0e\xb2\x5d\xd7\x58\x05\x17\x25\x7f\x6d\x4e\xe0\x9c\x3d\x2f\xa4\x96\x42\x26\x7d\xc0\x24\xec\xf2\xdb\x38\xcc\x83\xee\x5b\x30\xaa\x31\xc6\xb5\x89\x83\xbf\x45\xf8\xf4\x05\xb7\x25\xa2\x99\xdc\xd2\x7f\xf0\xa4\x04\xa6\x09\xa7\x3c\x0c\xef\xd6\x90\xe9\x2f\xb1\xd2\x90\x41\x31\x7e\x49\x42\x76\x01\x66\x80\xb2\x49\x40\x7a\x23\xec\x71\xca\xb5\xe6\x62\xd1\x30\x99\xc1\xf6\x6c\x6b\x26\xdb\x23\x37\xae\xbb\x8f\x50\xff\xdf\x01\x00\x00\xff\xff\xed\x16\x16\x7b\x19\x11\x00\x00") func assetsLoginDistRespondMinJsBytes() ([]byte, error) { return bindataRead( _assetsLoginDistRespondMinJs, "assets/login/dist/respond.min.js", ) } func assetsLoginDistRespondMinJs() (*asset, error) { bytes, err := assetsLoginDistRespondMinJsBytes() if err != nil { return nil, err } info := bindataFileInfo{name: "assets/login/dist/respond.min.js", size: 4377, mode: os.FileMode(420), modTime: time.Unix(1570872928, 0)} a := &asset{bytes: bytes, info: info} return a, nil } // Asset loads and returns the asset for the given name. // It returns an error if the asset could not be found or // could not be loaded. func Asset(name string) ([]byte, error) { cannonicalName := strings.ReplaceAll(name, "\\", "/") if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) } return a.bytes, nil } return nil, fmt.Errorf("Asset %s not found", name) } // MustAsset is like Asset but panics when Asset would return an error. // It simplifies safe initialization of global variables. func MustAsset(name string) []byte { a, err := Asset(name) if err != nil { panic("asset: Asset(" + name + "): " + err.Error()) } return a } // AssetInfo loads and returns the asset info for the given name. // It returns an error if the asset could not be found or // could not be loaded. func AssetInfo(name string) (os.FileInfo, error) { cannonicalName := strings.ReplaceAll(name, "\\", "/") if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) } return a.info, nil } return nil, fmt.Errorf("AssetInfo %s not found", name) } // AssetNames returns the names of the assets. func AssetNames() []string { names := make([]string, 0, len(_bindata)) for name := range _bindata { names = append(names, name) } return names } // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ "assets/login/dist/all.min.css": assetsLoginDistAllMinCss, "assets/login/dist/all.min.js": assetsLoginDistAllMinJs, "assets/login/dist/respond.min.js": assetsLoginDistRespondMinJs, } // AssetDir returns the file names below a certain // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: // data/ // foo.txt // img/ // a.png // b.png // then AssetDir("data") would return []string{"foo.txt", "img"} // AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("foo.txt") and AssetDir("notexist") would return an error // AssetDir("") will return []string{"data"}. func AssetDir(name string) ([]string, error) { node := _bintree if name != "" { cannonicalName := strings.ReplaceAll(name, "\\", "/") pathList := strings.Split(cannonicalName, "/") for _, p := range pathList { node = node.Children[p] if node == nil { return nil, fmt.Errorf("Asset %s not found", name) } } } if node.Func != nil { return nil, fmt.Errorf("Asset %s not found", name) } rv := make([]string, 0, len(node.Children)) for childName := range node.Children { rv = append(rv, childName) } return rv, nil } type bintree struct { Func func() (*asset, error) Children map[string]*bintree } var _bintree = &bintree{nil, map[string]*bintree{ "assets": &bintree{nil, map[string]*bintree{ "login": &bintree{nil, map[string]*bintree{ "dist": &bintree{nil, map[string]*bintree{ "all.min.css": &bintree{assetsLoginDistAllMinCss, map[string]*bintree{}}, "all.min.js": &bintree{assetsLoginDistAllMinJs, map[string]*bintree{}}, "respond.min.js": &bintree{assetsLoginDistRespondMinJs, map[string]*bintree{}}, }}, }}, }}, }} // RestoreAsset restores an asset under the given directory func RestoreAsset(dir, name string) error { data, err := Asset(name) if err != nil { return err } info, err := AssetInfo(name) if err != nil { return err } err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) if err != nil { return err } err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) if err != nil { return err } err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) if err != nil { return err } return nil } // RestoreAssets restores an asset under the given directory recursively func RestoreAssets(dir, name string) error { children, err := AssetDir(name) // File if err != nil { return RestoreAsset(dir, name) } // Dir for _, child := range children { err = RestoreAssets(dir, filepath.Join(name, child)) if err != nil { return err } } return nil } func _filePath(dir, name string) string { cannonicalName := strings.ReplaceAll(name, "\\", "/") return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } ================================================ FILE: template/installation/assets_list.go ================================================ package login var AssetsList = []string{ "/login/dist/all.min.css", "/login/dist/all.min.js", "/login/dist/respond.min.js", } ================================================ FILE: template/installation/installation.go ================================================ package login import ( "bytes" "fmt" "html/template" "strings" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/logger" ) type Installation struct { Name string } func Get() *Installation { return &Installation{ Name: "installation", } } var DefaultFuncMap = template.FuncMap{ "lang": language.Get, "langHtml": language.GetFromHtml, "link": func(cdnUrl, prefixUrl, assetsUrl string) string { if cdnUrl == "" { return prefixUrl + assetsUrl } return cdnUrl + assetsUrl }, "isLinkUrl": func(s string) bool { return (len(s) > 7 && s[:7] == "http://") || (len(s) > 8 && s[:8] == "https://") }, "render": func(s, old, repl template.HTML) template.HTML { return template.HTML(strings.ReplaceAll(string(s), string(old), string(repl))) }, "renderJS": func(s template.JS, old, repl template.HTML) template.JS { return template.JS(strings.ReplaceAll(string(s), string(old), string(repl))) }, "divide": func(a, b int) int { return a / b }, } func (i *Installation) GetTemplate() (*template.Template, string) { tmpl, err := template.New("installation"). Funcs(DefaultFuncMap). Parse(List["installation"]) if err != nil { logger.Error("Installation GetTemplate Error: ", err) } return tmpl, "installation" } func (i *Installation) GetAssetList() []string { return AssetsList } func (i *Installation) GetAsset(name string) ([]byte, error) { return Asset(name[1:]) } func (i *Installation) IsAPage() bool { return true } func (i *Installation) GetName() string { return "login" } func (i *Installation) GetContent() template.HTML { buffer := new(bytes.Buffer) tmpl, defineName := i.GetTemplate() err := tmpl.ExecuteTemplate(buffer, defineName, i) if err != nil { fmt.Println("ComposeHtml Error:", err) } return template.HTML(buffer.String()) } ================================================ FILE: template/installation/installation.tmpl ================================================ {{define "installation"}} GoAdmin Install

    数据库配置

    目前仅支持Mysql

    选择管理数据表

    选择管理数据表

    设置字段

    User表

    设置超级管理员

    超级管理员设置

    {{end}} ================================================ FILE: template/installation/template.go ================================================ package login var List = map[string]string{"installation": `{{define "installation"}} GoAdmin Install

    数据库配置

    目前仅支持Mysql

    选择管理数据表

    选择管理数据表

    设置字段

    User表

    设置超级管理员

    超级管理员设置

    {{end}}`} ================================================ FILE: template/login/Makefile ================================================ all: find ./ -name ".DS_Store" -depth -exec rm {} \; adm combine js --path=./assets/src/js/combine/ --out=./assets/login/dist/all.min.js adm combine css --path=./assets/src/css/ --out=./assets/login/dist/all.min.css adm compile asset --path=./assets/login/dist/ --out=./ --pa=login ================================================ FILE: template/login/assets/src/css/0_font.css ================================================ /* cyrillic-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 300; src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN_r8OX-hpKKSTj5PW.woff2) format('woff2'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } /* cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 300; src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN_r8OVuhpKKSTj5PW.woff2) format('woff2'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } /* greek-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 300; src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN_r8OXuhpKKSTj5PW.woff2) format('woff2'); unicode-range: U+1F00-1FFF; } /* greek */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 300; src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN_r8OUehpKKSTj5PW.woff2) format('woff2'); unicode-range: U+0370-03FF; } /* vietnamese */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 300; src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN_r8OXehpKKSTj5PW.woff2) format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; } /* latin-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 300; src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN_r8OXOhpKKSTj5PW.woff2) format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 300; src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN_r8OUuhpKKSTjw.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* cyrillic-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFWJ0bf8pkAp6a.woff2) format('woff2'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } /* cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFUZ0bf8pkAp6a.woff2) format('woff2'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } /* greek-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFWZ0bf8pkAp6a.woff2) format('woff2'); unicode-range: U+1F00-1FFF; } /* greek */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFVp0bf8pkAp6a.woff2) format('woff2'); unicode-range: U+0370-03FF; } /* vietnamese */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFWp0bf8pkAp6a.woff2) format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; } /* latin-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFW50bf8pkAp6a.woff2) format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; src: local('Open Sans Regular'), local('OpenSans-Regular'), url(https://fonts.gstatic.com/s/opensans/v17/mem8YaGs126MiZpBA-UFVZ0bf8pkAg.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* cyrillic-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN7rgOX-hpKKSTj5PW.woff2) format('woff2'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } /* cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN7rgOVuhpKKSTj5PW.woff2) format('woff2'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } /* greek-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN7rgOXuhpKKSTj5PW.woff2) format('woff2'); unicode-range: U+1F00-1FFF; } /* greek */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN7rgOUehpKKSTj5PW.woff2) format('woff2'); unicode-range: U+0370-03FF; } /* vietnamese */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN7rgOXehpKKSTj5PW.woff2) format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; } /* latin-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN7rgOXOhpKKSTj5PW.woff2) format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v17/mem5YaGs126MiZpBA-UN7rgOUuhpKKSTjw.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } ================================================ FILE: template/login/assets/src/css/2_animate.css ================================================ @charset "UTF-8"; /*! Animate.css - http://daneden.me/animate Licensed under the MIT license - http://opensource.org/licenses/MIT Copyright (c) 2015 Daniel Eden */ .animated { -webkit-animation-duration: 1s; animation-duration: 1s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .animated-fast { -webkit-animation-duration: .5s; animation-duration: .5s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .animated.infinite { -webkit-animation-iteration-count: infinite; animation-iteration-count: infinite; } .animated.hinge { -webkit-animation-duration: 2s; animation-duration: 2s; } .animated.bounceIn, .animated.bounceOut { -webkit-animation-duration: .75s; animation-duration: .75s; } .animated.flipOutX, .animated.flipOutY { -webkit-animation-duration: .75s; animation-duration: .75s; } @-webkit-keyframes bounce { from, 20%, 53%, 80%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); -webkit-transform: translate3d(0,0,0); transform: translate3d(0,0,0); } 40%, 43% { -webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); -webkit-transform: translate3d(0, -30px, 0); transform: translate3d(0, -30px, 0); } 70% { -webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); -webkit-transform: translate3d(0, -15px, 0); transform: translate3d(0, -15px, 0); } 90% { -webkit-transform: translate3d(0,-4px,0); transform: translate3d(0,-4px,0); } } @keyframes bounce { from, 20%, 53%, 80%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); -webkit-transform: translate3d(0,0,0); transform: translate3d(0,0,0); } 40%, 43% { -webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); -webkit-transform: translate3d(0, -30px, 0); transform: translate3d(0, -30px, 0); } 70% { -webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060); -webkit-transform: translate3d(0, -15px, 0); transform: translate3d(0, -15px, 0); } 90% { -webkit-transform: translate3d(0,-4px,0); transform: translate3d(0,-4px,0); } } .bounce { -webkit-animation-name: bounce; animation-name: bounce; -webkit-transform-origin: center bottom; transform-origin: center bottom; } @-webkit-keyframes flash { from, 50%, to { opacity: 1; } 25%, 75% { opacity: 0; } } @keyframes flash { from, 50%, to { opacity: 1; } 25%, 75% { opacity: 0; } } .flash { -webkit-animation-name: flash; animation-name: flash; } /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ @-webkit-keyframes pulse { from { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } 50% { -webkit-transform: scale3d(1.05, 1.05, 1.05); transform: scale3d(1.05, 1.05, 1.05); } to { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } } @keyframes pulse { from { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } 50% { -webkit-transform: scale3d(1.05, 1.05, 1.05); transform: scale3d(1.05, 1.05, 1.05); } to { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } } .pulse { -webkit-animation-name: pulse; animation-name: pulse; } @-webkit-keyframes rubberBand { from { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } 30% { -webkit-transform: scale3d(1.25, 0.75, 1); transform: scale3d(1.25, 0.75, 1); } 40% { -webkit-transform: scale3d(0.75, 1.25, 1); transform: scale3d(0.75, 1.25, 1); } 50% { -webkit-transform: scale3d(1.15, 0.85, 1); transform: scale3d(1.15, 0.85, 1); } 65% { -webkit-transform: scale3d(.95, 1.05, 1); transform: scale3d(.95, 1.05, 1); } 75% { -webkit-transform: scale3d(1.05, .95, 1); transform: scale3d(1.05, .95, 1); } to { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } } @keyframes rubberBand { from { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } 30% { -webkit-transform: scale3d(1.25, 0.75, 1); transform: scale3d(1.25, 0.75, 1); } 40% { -webkit-transform: scale3d(0.75, 1.25, 1); transform: scale3d(0.75, 1.25, 1); } 50% { -webkit-transform: scale3d(1.15, 0.85, 1); transform: scale3d(1.15, 0.85, 1); } 65% { -webkit-transform: scale3d(.95, 1.05, 1); transform: scale3d(.95, 1.05, 1); } 75% { -webkit-transform: scale3d(1.05, .95, 1); transform: scale3d(1.05, .95, 1); } to { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } } .rubberBand { -webkit-animation-name: rubberBand; animation-name: rubberBand; } @-webkit-keyframes shake { from, to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } 10%, 30%, 50%, 70%, 90% { -webkit-transform: translate3d(-10px, 0, 0); transform: translate3d(-10px, 0, 0); } 20%, 40%, 60%, 80% { -webkit-transform: translate3d(10px, 0, 0); transform: translate3d(10px, 0, 0); } } @keyframes shake { from, to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } 10%, 30%, 50%, 70%, 90% { -webkit-transform: translate3d(-10px, 0, 0); transform: translate3d(-10px, 0, 0); } 20%, 40%, 60%, 80% { -webkit-transform: translate3d(10px, 0, 0); transform: translate3d(10px, 0, 0); } } .shake { -webkit-animation-name: shake; animation-name: shake; } @-webkit-keyframes swing { 20% { -webkit-transform: rotate3d(0, 0, 1, 15deg); transform: rotate3d(0, 0, 1, 15deg); } 40% { -webkit-transform: rotate3d(0, 0, 1, -10deg); transform: rotate3d(0, 0, 1, -10deg); } 60% { -webkit-transform: rotate3d(0, 0, 1, 5deg); transform: rotate3d(0, 0, 1, 5deg); } 80% { -webkit-transform: rotate3d(0, 0, 1, -5deg); transform: rotate3d(0, 0, 1, -5deg); } to { -webkit-transform: rotate3d(0, 0, 1, 0deg); transform: rotate3d(0, 0, 1, 0deg); } } @keyframes swing { 20% { -webkit-transform: rotate3d(0, 0, 1, 15deg); transform: rotate3d(0, 0, 1, 15deg); } 40% { -webkit-transform: rotate3d(0, 0, 1, -10deg); transform: rotate3d(0, 0, 1, -10deg); } 60% { -webkit-transform: rotate3d(0, 0, 1, 5deg); transform: rotate3d(0, 0, 1, 5deg); } 80% { -webkit-transform: rotate3d(0, 0, 1, -5deg); transform: rotate3d(0, 0, 1, -5deg); } to { -webkit-transform: rotate3d(0, 0, 1, 0deg); transform: rotate3d(0, 0, 1, 0deg); } } .swing { -webkit-transform-origin: top center; transform-origin: top center; -webkit-animation-name: swing; animation-name: swing; } @-webkit-keyframes tada { from { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } 10%, 20% { -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); } 30%, 50%, 70%, 90% { -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); } 40%, 60%, 80% { -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); } to { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } } @keyframes tada { from { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } 10%, 20% { -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); } 30%, 50%, 70%, 90% { -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); } 40%, 60%, 80% { -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); } to { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } } .tada { -webkit-animation-name: tada; animation-name: tada; } /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ @-webkit-keyframes wobble { from { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } to { -webkit-transform: none; transform: none; } } @keyframes wobble { from { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } to { -webkit-transform: none; transform: none; } } .wobble { -webkit-animation-name: wobble; animation-name: wobble; } @-webkit-keyframes jello { from, 11.1%, to { -webkit-transform: none; transform: none; } 22.2% { -webkit-transform: skewX(-12.5deg) skewY(-12.5deg); transform: skewX(-12.5deg) skewY(-12.5deg); } 33.3% { -webkit-transform: skewX(6.25deg) skewY(6.25deg); transform: skewX(6.25deg) skewY(6.25deg); } 44.4% { -webkit-transform: skewX(-3.125deg) skewY(-3.125deg); transform: skewX(-3.125deg) skewY(-3.125deg); } 55.5% { -webkit-transform: skewX(1.5625deg) skewY(1.5625deg); transform: skewX(1.5625deg) skewY(1.5625deg); } 66.6% { -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg); transform: skewX(-0.78125deg) skewY(-0.78125deg); } 77.7% { -webkit-transform: skewX(0.390625deg) skewY(0.390625deg); transform: skewX(0.390625deg) skewY(0.390625deg); } 88.8% { -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg); transform: skewX(-0.1953125deg) skewY(-0.1953125deg); } } @keyframes jello { from, 11.1%, to { -webkit-transform: none; transform: none; } 22.2% { -webkit-transform: skewX(-12.5deg) skewY(-12.5deg); transform: skewX(-12.5deg) skewY(-12.5deg); } 33.3% { -webkit-transform: skewX(6.25deg) skewY(6.25deg); transform: skewX(6.25deg) skewY(6.25deg); } 44.4% { -webkit-transform: skewX(-3.125deg) skewY(-3.125deg); transform: skewX(-3.125deg) skewY(-3.125deg); } 55.5% { -webkit-transform: skewX(1.5625deg) skewY(1.5625deg); transform: skewX(1.5625deg) skewY(1.5625deg); } 66.6% { -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg); transform: skewX(-0.78125deg) skewY(-0.78125deg); } 77.7% { -webkit-transform: skewX(0.390625deg) skewY(0.390625deg); transform: skewX(0.390625deg) skewY(0.390625deg); } 88.8% { -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg); transform: skewX(-0.1953125deg) skewY(-0.1953125deg); } } .jello { -webkit-animation-name: jello; animation-name: jello; -webkit-transform-origin: center; transform-origin: center; } @-webkit-keyframes bounceIn { from, 20%, 40%, 60%, 80%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } 0% { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } 20% { -webkit-transform: scale3d(1.1, 1.1, 1.1); transform: scale3d(1.1, 1.1, 1.1); } 40% { -webkit-transform: scale3d(.9, .9, .9); transform: scale3d(.9, .9, .9); } 60% { opacity: 1; -webkit-transform: scale3d(1.03, 1.03, 1.03); transform: scale3d(1.03, 1.03, 1.03); } 80% { -webkit-transform: scale3d(.97, .97, .97); transform: scale3d(.97, .97, .97); } to { opacity: 1; -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } } @keyframes bounceIn { from, 20%, 40%, 60%, 80%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } 0% { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } 20% { -webkit-transform: scale3d(1.1, 1.1, 1.1); transform: scale3d(1.1, 1.1, 1.1); } 40% { -webkit-transform: scale3d(.9, .9, .9); transform: scale3d(.9, .9, .9); } 60% { opacity: 1; -webkit-transform: scale3d(1.03, 1.03, 1.03); transform: scale3d(1.03, 1.03, 1.03); } 80% { -webkit-transform: scale3d(.97, .97, .97); transform: scale3d(.97, .97, .97); } to { opacity: 1; -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } } .bounceIn { -webkit-animation-name: bounceIn; animation-name: bounceIn; } @-webkit-keyframes bounceInDown { from, 60%, 75%, 90%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } 0% { opacity: 0; -webkit-transform: translate3d(0, -3000px, 0); transform: translate3d(0, -3000px, 0); } 60% { opacity: 1; -webkit-transform: translate3d(0, 25px, 0); transform: translate3d(0, 25px, 0); } 75% { -webkit-transform: translate3d(0, -10px, 0); transform: translate3d(0, -10px, 0); } 90% { -webkit-transform: translate3d(0, 5px, 0); transform: translate3d(0, 5px, 0); } to { -webkit-transform: none; transform: none; } } @keyframes bounceInDown { from, 60%, 75%, 90%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } 0% { opacity: 0; -webkit-transform: translate3d(0, -3000px, 0); transform: translate3d(0, -3000px, 0); } 60% { opacity: 1; -webkit-transform: translate3d(0, 25px, 0); transform: translate3d(0, 25px, 0); } 75% { -webkit-transform: translate3d(0, -10px, 0); transform: translate3d(0, -10px, 0); } 90% { -webkit-transform: translate3d(0, 5px, 0); transform: translate3d(0, 5px, 0); } to { -webkit-transform: none; transform: none; } } .bounceInDown { -webkit-animation-name: bounceInDown; animation-name: bounceInDown; } @-webkit-keyframes bounceInLeft { from, 60%, 75%, 90%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } 0% { opacity: 0; -webkit-transform: translate3d(-3000px, 0, 0); transform: translate3d(-3000px, 0, 0); } 60% { opacity: 1; -webkit-transform: translate3d(25px, 0, 0); transform: translate3d(25px, 0, 0); } 75% { -webkit-transform: translate3d(-10px, 0, 0); transform: translate3d(-10px, 0, 0); } 90% { -webkit-transform: translate3d(5px, 0, 0); transform: translate3d(5px, 0, 0); } to { -webkit-transform: none; transform: none; } } @keyframes bounceInLeft { from, 60%, 75%, 90%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } 0% { opacity: 0; -webkit-transform: translate3d(-3000px, 0, 0); transform: translate3d(-3000px, 0, 0); } 60% { opacity: 1; -webkit-transform: translate3d(25px, 0, 0); transform: translate3d(25px, 0, 0); } 75% { -webkit-transform: translate3d(-10px, 0, 0); transform: translate3d(-10px, 0, 0); } 90% { -webkit-transform: translate3d(5px, 0, 0); transform: translate3d(5px, 0, 0); } to { -webkit-transform: none; transform: none; } } .bounceInLeft { -webkit-animation-name: bounceInLeft; animation-name: bounceInLeft; } @-webkit-keyframes bounceInRight { from, 60%, 75%, 90%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } from { opacity: 0; -webkit-transform: translate3d(3000px, 0, 0); transform: translate3d(3000px, 0, 0); } 60% { opacity: 1; -webkit-transform: translate3d(-25px, 0, 0); transform: translate3d(-25px, 0, 0); } 75% { -webkit-transform: translate3d(10px, 0, 0); transform: translate3d(10px, 0, 0); } 90% { -webkit-transform: translate3d(-5px, 0, 0); transform: translate3d(-5px, 0, 0); } to { -webkit-transform: none; transform: none; } } @keyframes bounceInRight { from, 60%, 75%, 90%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } from { opacity: 0; -webkit-transform: translate3d(3000px, 0, 0); transform: translate3d(3000px, 0, 0); } 60% { opacity: 1; -webkit-transform: translate3d(-25px, 0, 0); transform: translate3d(-25px, 0, 0); } 75% { -webkit-transform: translate3d(10px, 0, 0); transform: translate3d(10px, 0, 0); } 90% { -webkit-transform: translate3d(-5px, 0, 0); transform: translate3d(-5px, 0, 0); } to { -webkit-transform: none; transform: none; } } .bounceInRight { -webkit-animation-name: bounceInRight; animation-name: bounceInRight; } @-webkit-keyframes bounceInUp { from, 60%, 75%, 90%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } from { opacity: 0; -webkit-transform: translate3d(0, 3000px, 0); transform: translate3d(0, 3000px, 0); } 60% { opacity: 1; -webkit-transform: translate3d(0, -20px, 0); transform: translate3d(0, -20px, 0); } 75% { -webkit-transform: translate3d(0, 10px, 0); transform: translate3d(0, 10px, 0); } 90% { -webkit-transform: translate3d(0, -5px, 0); transform: translate3d(0, -5px, 0); } to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } @keyframes bounceInUp { from, 60%, 75%, 90%, to { -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } from { opacity: 0; -webkit-transform: translate3d(0, 3000px, 0); transform: translate3d(0, 3000px, 0); } 60% { opacity: 1; -webkit-transform: translate3d(0, -20px, 0); transform: translate3d(0, -20px, 0); } 75% { -webkit-transform: translate3d(0, 10px, 0); transform: translate3d(0, 10px, 0); } 90% { -webkit-transform: translate3d(0, -5px, 0); transform: translate3d(0, -5px, 0); } to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } .bounceInUp { -webkit-animation-name: bounceInUp; animation-name: bounceInUp; } @-webkit-keyframes bounceOut { 20% { -webkit-transform: scale3d(.9, .9, .9); transform: scale3d(.9, .9, .9); } 50%, 55% { opacity: 1; -webkit-transform: scale3d(1.1, 1.1, 1.1); transform: scale3d(1.1, 1.1, 1.1); } to { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } } @keyframes bounceOut { 20% { -webkit-transform: scale3d(.9, .9, .9); transform: scale3d(.9, .9, .9); } 50%, 55% { opacity: 1; -webkit-transform: scale3d(1.1, 1.1, 1.1); transform: scale3d(1.1, 1.1, 1.1); } to { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } } .bounceOut { -webkit-animation-name: bounceOut; animation-name: bounceOut; } @-webkit-keyframes bounceOutDown { 20% { -webkit-transform: translate3d(0, 10px, 0); transform: translate3d(0, 10px, 0); } 40%, 45% { opacity: 1; -webkit-transform: translate3d(0, -20px, 0); transform: translate3d(0, -20px, 0); } to { opacity: 0; -webkit-transform: translate3d(0, 2000px, 0); transform: translate3d(0, 2000px, 0); } } @keyframes bounceOutDown { 20% { -webkit-transform: translate3d(0, 10px, 0); transform: translate3d(0, 10px, 0); } 40%, 45% { opacity: 1; -webkit-transform: translate3d(0, -20px, 0); transform: translate3d(0, -20px, 0); } to { opacity: 0; -webkit-transform: translate3d(0, 2000px, 0); transform: translate3d(0, 2000px, 0); } } .bounceOutDown { -webkit-animation-name: bounceOutDown; animation-name: bounceOutDown; } @-webkit-keyframes bounceOutLeft { 20% { opacity: 1; -webkit-transform: translate3d(20px, 0, 0); transform: translate3d(20px, 0, 0); } to { opacity: 0; -webkit-transform: translate3d(-2000px, 0, 0); transform: translate3d(-2000px, 0, 0); } } @keyframes bounceOutLeft { 20% { opacity: 1; -webkit-transform: translate3d(20px, 0, 0); transform: translate3d(20px, 0, 0); } to { opacity: 0; -webkit-transform: translate3d(-2000px, 0, 0); transform: translate3d(-2000px, 0, 0); } } .bounceOutLeft { -webkit-animation-name: bounceOutLeft; animation-name: bounceOutLeft; } @-webkit-keyframes bounceOutRight { 20% { opacity: 1; -webkit-transform: translate3d(-20px, 0, 0); transform: translate3d(-20px, 0, 0); } to { opacity: 0; -webkit-transform: translate3d(2000px, 0, 0); transform: translate3d(2000px, 0, 0); } } @keyframes bounceOutRight { 20% { opacity: 1; -webkit-transform: translate3d(-20px, 0, 0); transform: translate3d(-20px, 0, 0); } to { opacity: 0; -webkit-transform: translate3d(2000px, 0, 0); transform: translate3d(2000px, 0, 0); } } .bounceOutRight { -webkit-animation-name: bounceOutRight; animation-name: bounceOutRight; } @-webkit-keyframes bounceOutUp { 20% { -webkit-transform: translate3d(0, -10px, 0); transform: translate3d(0, -10px, 0); } 40%, 45% { opacity: 1; -webkit-transform: translate3d(0, 20px, 0); transform: translate3d(0, 20px, 0); } to { opacity: 0; -webkit-transform: translate3d(0, -2000px, 0); transform: translate3d(0, -2000px, 0); } } @keyframes bounceOutUp { 20% { -webkit-transform: translate3d(0, -10px, 0); transform: translate3d(0, -10px, 0); } 40%, 45% { opacity: 1; -webkit-transform: translate3d(0, 20px, 0); transform: translate3d(0, 20px, 0); } to { opacity: 0; -webkit-transform: translate3d(0, -2000px, 0); transform: translate3d(0, -2000px, 0); } } .bounceOutUp { -webkit-animation-name: bounceOutUp; animation-name: bounceOutUp; } @-webkit-keyframes fadeIn { from { opacity: 0; -ms-transform: scale(0.95); -webkit-transform: scale(0.95); transform: scale(0.95); } to { opacity: 1; -ms-transform: scale(1.0); -webkit-transform: scale(1.0); transform: scale(1.0); } } @keyframes fadeIn { from { opacity: 0; -ms-transform: scale(0.95); -webkit-transform: scale(0.95); transform: scale(0.95); } to { opacity: 1; -ms-transform: scale(1.0); -webkit-transform: scale(1.0); transform: scale(1.0); } } .fadeIn { -webkit-animation-name: fadeIn; animation-name: fadeIn; } @-webkit-keyframes fadeInDown { from { opacity: 0; /*-webkit-transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0);*/ -webkit-transform: translate3d(0, -50px, 0); transform: translate3d(0, -50px, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes fadeInDown { from { opacity: 0; /*-webkit-transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0);*/ -webkit-transform: translate3d(0, -50px, 0); transform: translate3d(0, -50px, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } .fadeInDown { -webkit-animation-name: fadeInDown; animation-name: fadeInDown; } @-webkit-keyframes fadeInDownBig { from { opacity: 0; -webkit-transform: translate3d(0, -2000px, 0); transform: translate3d(0, -2000px, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes fadeInDownBig { from { opacity: 0; -webkit-transform: translate3d(0, -2000px, 0); transform: translate3d(0, -2000px, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } .fadeInDownBig { -webkit-animation-name: fadeInDownBig; animation-name: fadeInDownBig; } @-webkit-keyframes fadeInLeft { from { opacity: 0; /*-webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0);*/ -webkit-transform: translate3d(-50px, 0, 0); transform: translate3d(-50px, 0, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes fadeInLeft { from { opacity: 0; /*-webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0);*/ -webkit-transform: translate3d(-50px, 0, 0); transform: translate3d(-50px, 0, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } .fadeInLeft { -webkit-animation-name: fadeInLeft; animation-name: fadeInLeft; } @-webkit-keyframes fadeInLeftBig { from { opacity: 0; -webkit-transform: translate3d(-2000px, 0, 0); transform: translate3d(-2000px, 0, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes fadeInLeftBig { from { opacity: 0; -webkit-transform: translate3d(-2000px, 0, 0); transform: translate3d(-2000px, 0, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } .fadeInLeftBig { -webkit-animation-name: fadeInLeftBig; animation-name: fadeInLeftBig; } @-webkit-keyframes fadeInRight { from { opacity: 0; /*-webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0);*/ -webkit-transform: translate3d(50px, 0, 0); transform: translate3d(50px, 0, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes fadeInRight { from { opacity: 0; /*-webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0);*/ -webkit-transform: translate3d(50px, 0, 0); transform: translate3d(50px, 0, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } .fadeInRight { -webkit-animation-name: fadeInRight; animation-name: fadeInRight; } @-webkit-keyframes fadeInRightBig { from { opacity: 0; -webkit-transform: translate3d(2000px, 0, 0); transform: translate3d(2000px, 0, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes fadeInRightBig { from { opacity: 0; -webkit-transform: translate3d(2000px, 0, 0); transform: translate3d(2000px, 0, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } .fadeInRightBig { -webkit-animation-name: fadeInRightBig; animation-name: fadeInRightBig; } @-webkit-keyframes fadeInUp { from { opacity: 0; visibility: hidden; /*-webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0);*/ -webkit-transform: translate3d(0, 40px, 0); transform: translate3d(0, 40px, 0); } to { opacity: 1; /*visibility: visible;*/ -webkit-transform: none; transform: none; } } @keyframes fadeInUp { from { opacity: 0; visibility: hidden; /*-webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0);*/ -webkit-transform: translate3d(0, 40px, 0); transform: translate3d(0, 40px, 0); } to { visibility: visible; opacity: 1; -webkit-transform: none; transform: none; } } .fadeInUp { -webkit-animation-name: fadeInUp; animation-name: fadeInUp; } @-webkit-keyframes fadeInUpMenu { from { opacity: 0; visibility: hidden; /*-webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0);*/ -webkit-transform: translate3d(0, 20px, 0); transform: translate3d(0, 20px, 0); } to { opacity: 1; visibility: visible; -webkit-transform: none; transform: none; } } @keyframes fadeInUpMenu { from { opacity: 0; visibility: hidden; /*-webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0);*/ -webkit-transform: translate3d(0, 20px, 0); transform: translate3d(0, 20px, 0); } to { visibility: visible; opacity: 1; -webkit-transform: none; transform: none; } } .fadeInUpMenu { -webkit-animation-name: fadeInUpMenu; animation-name: fadeInUpMenu; } @-webkit-keyframes fadeInUpBig { from { opacity: 0; -webkit-transform: translate3d(0, 2000px, 0); transform: translate3d(0, 2000px, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes fadeInUpBig { from { opacity: 0; -webkit-transform: translate3d(0, 2000px, 0); transform: translate3d(0, 2000px, 0); } to { opacity: 1; -webkit-transform: none; transform: none; } } .fadeInUpBig { -webkit-animation-name: fadeInUpBig; animation-name: fadeInUpBig; } @-webkit-keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } .fadeOut { -webkit-animation-name: fadeOut; animation-name: fadeOut; } @-webkit-keyframes fadeOutDown { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(0, 40px, 0); transform: translate3d(0, 40px, 0); } } @keyframes fadeOutDown { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(0, 40px, 0); transform: translate3d(0, 40px, 0); } } .fadeOutDown { -webkit-animation-name: fadeOutDown; animation-name: fadeOutDown; } @-webkit-keyframes fadeOutDownBig { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(0, 2000px, 0); transform: translate3d(0, 2000px, 0); } } @keyframes fadeOutDownBig { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(0, 2000px, 0); transform: translate3d(0, 2000px, 0); } } .fadeOutDownBig { -webkit-animation-name: fadeOutDownBig; animation-name: fadeOutDownBig; } @-webkit-keyframes fadeOutLeft { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); } } @keyframes fadeOutLeft { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); } } .fadeOutLeft { -webkit-animation-name: fadeOutLeft; animation-name: fadeOutLeft; } @-webkit-keyframes fadeOutLeftBig { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(-2000px, 0, 0); transform: translate3d(-2000px, 0, 0); } } @keyframes fadeOutLeftBig { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(-2000px, 0, 0); transform: translate3d(-2000px, 0, 0); } } .fadeOutLeftBig { -webkit-animation-name: fadeOutLeftBig; animation-name: fadeOutLeftBig; } @-webkit-keyframes fadeOutRight { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); } } @keyframes fadeOutRight { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); } } .fadeOutRight { -webkit-animation-name: fadeOutRight; animation-name: fadeOutRight; } @-webkit-keyframes fadeOutRightBig { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(2000px, 0, 0); transform: translate3d(2000px, 0, 0); } } @keyframes fadeOutRightBig { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(2000px, 0, 0); transform: translate3d(2000px, 0, 0); } } .fadeOutRightBig { -webkit-animation-name: fadeOutRightBig; animation-name: fadeOutRightBig; } @-webkit-keyframes fadeOutUp { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0); } } @keyframes fadeOutUp { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0); } } .fadeOutUp { -webkit-animation-name: fadeOutUp; animation-name: fadeOutUp; } @-webkit-keyframes fadeOutUpBig { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(0, -2000px, 0); transform: translate3d(0, -2000px, 0); } } @keyframes fadeOutUpBig { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(0, -2000px, 0); transform: translate3d(0, -2000px, 0); } } .fadeOutUpBig { -webkit-animation-name: fadeOutUpBig; animation-name: fadeOutUpBig; } @-webkit-keyframes flip { from { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg); transform: perspective(400px) rotate3d(0, 1, 0, -360deg); -webkit-animation-timing-function: ease-out; animation-timing-function: ease-out; } 40% { -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); -webkit-animation-timing-function: ease-out; animation-timing-function: ease-out; } 50% { -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } 80% { -webkit-transform: perspective(400px) scale3d(.95, .95, .95); transform: perspective(400px) scale3d(.95, .95, .95); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } to { -webkit-transform: perspective(400px); transform: perspective(400px); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } } @keyframes flip { from { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg); transform: perspective(400px) rotate3d(0, 1, 0, -360deg); -webkit-animation-timing-function: ease-out; animation-timing-function: ease-out; } 40% { -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); -webkit-animation-timing-function: ease-out; animation-timing-function: ease-out; } 50% { -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } 80% { -webkit-transform: perspective(400px) scale3d(.95, .95, .95); transform: perspective(400px) scale3d(.95, .95, .95); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } to { -webkit-transform: perspective(400px); transform: perspective(400px); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } } .animated.flip { -webkit-backface-visibility: visible; backface-visibility: visible; -webkit-animation-name: flip; animation-name: flip; } @-webkit-keyframes flipInX { from { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } to { -webkit-transform: perspective(400px); transform: perspective(400px); } } @keyframes flipInX { from { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } to { -webkit-transform: perspective(400px); transform: perspective(400px); } } .flipInX { -webkit-backface-visibility: visible !important; backface-visibility: visible !important; -webkit-animation-name: flipInX; animation-name: flipInX; } @-webkit-keyframes flipInY { from { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); transform: perspective(400px) rotate3d(0, 1, 0, 90deg); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg); transform: perspective(400px) rotate3d(0, 1, 0, -20deg); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg); transform: perspective(400px) rotate3d(0, 1, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg); transform: perspective(400px) rotate3d(0, 1, 0, -5deg); } to { -webkit-transform: perspective(400px); transform: perspective(400px); } } @keyframes flipInY { from { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); transform: perspective(400px) rotate3d(0, 1, 0, 90deg); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg); transform: perspective(400px) rotate3d(0, 1, 0, -20deg); -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg); transform: perspective(400px) rotate3d(0, 1, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg); transform: perspective(400px) rotate3d(0, 1, 0, -5deg); } to { -webkit-transform: perspective(400px); transform: perspective(400px); } } .flipInY { -webkit-backface-visibility: visible !important; backface-visibility: visible !important; -webkit-animation-name: flipInY; animation-name: flipInY; } @-webkit-keyframes flipOutX { from { -webkit-transform: perspective(400px); transform: perspective(400px); } 30% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); opacity: 1; } to { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); opacity: 0; } } @keyframes flipOutX { from { -webkit-transform: perspective(400px); transform: perspective(400px); } 30% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); opacity: 1; } to { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); opacity: 0; } } .flipOutX { -webkit-animation-name: flipOutX; animation-name: flipOutX; -webkit-backface-visibility: visible !important; backface-visibility: visible !important; } @-webkit-keyframes flipOutY { from { -webkit-transform: perspective(400px); transform: perspective(400px); } 30% { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg); transform: perspective(400px) rotate3d(0, 1, 0, -15deg); opacity: 1; } to { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); transform: perspective(400px) rotate3d(0, 1, 0, 90deg); opacity: 0; } } @keyframes flipOutY { from { -webkit-transform: perspective(400px); transform: perspective(400px); } 30% { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg); transform: perspective(400px) rotate3d(0, 1, 0, -15deg); opacity: 1; } to { -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); transform: perspective(400px) rotate3d(0, 1, 0, 90deg); opacity: 0; } } .flipOutY { -webkit-backface-visibility: visible !important; backface-visibility: visible !important; -webkit-animation-name: flipOutY; animation-name: flipOutY; } @-webkit-keyframes lightSpeedIn { from { -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); transform: translate3d(100%, 0, 0) skewX(-30deg); opacity: 0; } 60% { -webkit-transform: skewX(20deg); transform: skewX(20deg); opacity: 1; } 80% { -webkit-transform: skewX(-5deg); transform: skewX(-5deg); opacity: 1; } to { -webkit-transform: none; transform: none; opacity: 1; } } @keyframes lightSpeedIn { from { -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); transform: translate3d(100%, 0, 0) skewX(-30deg); opacity: 0; } 60% { -webkit-transform: skewX(20deg); transform: skewX(20deg); opacity: 1; } 80% { -webkit-transform: skewX(-5deg); transform: skewX(-5deg); opacity: 1; } to { -webkit-transform: none; transform: none; opacity: 1; } } .lightSpeedIn { -webkit-animation-name: lightSpeedIn; animation-name: lightSpeedIn; -webkit-animation-timing-function: ease-out; animation-timing-function: ease-out; } @-webkit-keyframes lightSpeedOut { from { opacity: 1; } to { -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); transform: translate3d(100%, 0, 0) skewX(30deg); opacity: 0; } } @keyframes lightSpeedOut { from { opacity: 1; } to { -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); transform: translate3d(100%, 0, 0) skewX(30deg); opacity: 0; } } .lightSpeedOut { -webkit-animation-name: lightSpeedOut; animation-name: lightSpeedOut; -webkit-animation-timing-function: ease-in; animation-timing-function: ease-in; } @-webkit-keyframes rotateIn { from { -webkit-transform-origin: center; transform-origin: center; -webkit-transform: rotate3d(0, 0, 1, -200deg); transform: rotate3d(0, 0, 1, -200deg); opacity: 0; } to { -webkit-transform-origin: center; transform-origin: center; -webkit-transform: none; transform: none; opacity: 1; } } @keyframes rotateIn { from { -webkit-transform-origin: center; transform-origin: center; -webkit-transform: rotate3d(0, 0, 1, -200deg); transform: rotate3d(0, 0, 1, -200deg); opacity: 0; } to { -webkit-transform-origin: center; transform-origin: center; -webkit-transform: none; transform: none; opacity: 1; } } .rotateIn { -webkit-animation-name: rotateIn; animation-name: rotateIn; } @-webkit-keyframes rotateInDownLeft { from { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: rotate3d(0, 0, 1, -45deg); transform: rotate3d(0, 0, 1, -45deg); opacity: 0; } to { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: none; transform: none; opacity: 1; } } @keyframes rotateInDownLeft { from { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: rotate3d(0, 0, 1, -45deg); transform: rotate3d(0, 0, 1, -45deg); opacity: 0; } to { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: none; transform: none; opacity: 1; } } .rotateInDownLeft { -webkit-animation-name: rotateInDownLeft; animation-name: rotateInDownLeft; } @-webkit-keyframes rotateInDownRight { from { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: rotate3d(0, 0, 1, 45deg); transform: rotate3d(0, 0, 1, 45deg); opacity: 0; } to { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: none; transform: none; opacity: 1; } } @keyframes rotateInDownRight { from { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: rotate3d(0, 0, 1, 45deg); transform: rotate3d(0, 0, 1, 45deg); opacity: 0; } to { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: none; transform: none; opacity: 1; } } .rotateInDownRight { -webkit-animation-name: rotateInDownRight; animation-name: rotateInDownRight; } @-webkit-keyframes rotateInUpLeft { from { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: rotate3d(0, 0, 1, 45deg); transform: rotate3d(0, 0, 1, 45deg); opacity: 0; } to { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: none; transform: none; opacity: 1; } } @keyframes rotateInUpLeft { from { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: rotate3d(0, 0, 1, 45deg); transform: rotate3d(0, 0, 1, 45deg); opacity: 0; } to { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: none; transform: none; opacity: 1; } } .rotateInUpLeft { -webkit-animation-name: rotateInUpLeft; animation-name: rotateInUpLeft; } @-webkit-keyframes rotateInUpRight { from { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: rotate3d(0, 0, 1, -90deg); transform: rotate3d(0, 0, 1, -90deg); opacity: 0; } to { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: none; transform: none; opacity: 1; } } @keyframes rotateInUpRight { from { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: rotate3d(0, 0, 1, -90deg); transform: rotate3d(0, 0, 1, -90deg); opacity: 0; } to { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: none; transform: none; opacity: 1; } } .rotateInUpRight { -webkit-animation-name: rotateInUpRight; animation-name: rotateInUpRight; } @-webkit-keyframes rotateOut { from { -webkit-transform-origin: center; transform-origin: center; opacity: 1; } to { -webkit-transform-origin: center; transform-origin: center; -webkit-transform: rotate3d(0, 0, 1, 200deg); transform: rotate3d(0, 0, 1, 200deg); opacity: 0; } } @keyframes rotateOut { from { -webkit-transform-origin: center; transform-origin: center; opacity: 1; } to { -webkit-transform-origin: center; transform-origin: center; -webkit-transform: rotate3d(0, 0, 1, 200deg); transform: rotate3d(0, 0, 1, 200deg); opacity: 0; } } .rotateOut { -webkit-animation-name: rotateOut; animation-name: rotateOut; } @-webkit-keyframes rotateOutDownLeft { from { -webkit-transform-origin: left bottom; transform-origin: left bottom; opacity: 1; } to { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: rotate3d(0, 0, 1, 45deg); transform: rotate3d(0, 0, 1, 45deg); opacity: 0; } } @keyframes rotateOutDownLeft { from { -webkit-transform-origin: left bottom; transform-origin: left bottom; opacity: 1; } to { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: rotate3d(0, 0, 1, 45deg); transform: rotate3d(0, 0, 1, 45deg); opacity: 0; } } .rotateOutDownLeft { -webkit-animation-name: rotateOutDownLeft; animation-name: rotateOutDownLeft; } @-webkit-keyframes rotateOutDownRight { from { -webkit-transform-origin: right bottom; transform-origin: right bottom; opacity: 1; } to { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: rotate3d(0, 0, 1, -45deg); transform: rotate3d(0, 0, 1, -45deg); opacity: 0; } } @keyframes rotateOutDownRight { from { -webkit-transform-origin: right bottom; transform-origin: right bottom; opacity: 1; } to { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: rotate3d(0, 0, 1, -45deg); transform: rotate3d(0, 0, 1, -45deg); opacity: 0; } } .rotateOutDownRight { -webkit-animation-name: rotateOutDownRight; animation-name: rotateOutDownRight; } @-webkit-keyframes rotateOutUpLeft { from { -webkit-transform-origin: left bottom; transform-origin: left bottom; opacity: 1; } to { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: rotate3d(0, 0, 1, -45deg); transform: rotate3d(0, 0, 1, -45deg); opacity: 0; } } @keyframes rotateOutUpLeft { from { -webkit-transform-origin: left bottom; transform-origin: left bottom; opacity: 1; } to { -webkit-transform-origin: left bottom; transform-origin: left bottom; -webkit-transform: rotate3d(0, 0, 1, -45deg); transform: rotate3d(0, 0, 1, -45deg); opacity: 0; } } .rotateOutUpLeft { -webkit-animation-name: rotateOutUpLeft; animation-name: rotateOutUpLeft; } @-webkit-keyframes rotateOutUpRight { from { -webkit-transform-origin: right bottom; transform-origin: right bottom; opacity: 1; } to { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: rotate3d(0, 0, 1, 90deg); transform: rotate3d(0, 0, 1, 90deg); opacity: 0; } } @keyframes rotateOutUpRight { from { -webkit-transform-origin: right bottom; transform-origin: right bottom; opacity: 1; } to { -webkit-transform-origin: right bottom; transform-origin: right bottom; -webkit-transform: rotate3d(0, 0, 1, 90deg); transform: rotate3d(0, 0, 1, 90deg); opacity: 0; } } .rotateOutUpRight { -webkit-animation-name: rotateOutUpRight; animation-name: rotateOutUpRight; } @-webkit-keyframes hinge { 0% { -webkit-transform-origin: top left; transform-origin: top left; -webkit-animation-timing-function: ease-in-out; animation-timing-function: ease-in-out; } 20%, 60% { -webkit-transform: rotate3d(0, 0, 1, 80deg); transform: rotate3d(0, 0, 1, 80deg); -webkit-transform-origin: top left; transform-origin: top left; -webkit-animation-timing-function: ease-in-out; animation-timing-function: ease-in-out; } 40%, 80% { -webkit-transform: rotate3d(0, 0, 1, 60deg); transform: rotate3d(0, 0, 1, 60deg); -webkit-transform-origin: top left; transform-origin: top left; -webkit-animation-timing-function: ease-in-out; animation-timing-function: ease-in-out; opacity: 1; } to { -webkit-transform: translate3d(0, 700px, 0); transform: translate3d(0, 700px, 0); opacity: 0; } } @keyframes hinge { 0% { -webkit-transform-origin: top left; transform-origin: top left; -webkit-animation-timing-function: ease-in-out; animation-timing-function: ease-in-out; } 20%, 60% { -webkit-transform: rotate3d(0, 0, 1, 80deg); transform: rotate3d(0, 0, 1, 80deg); -webkit-transform-origin: top left; transform-origin: top left; -webkit-animation-timing-function: ease-in-out; animation-timing-function: ease-in-out; } 40%, 80% { -webkit-transform: rotate3d(0, 0, 1, 60deg); transform: rotate3d(0, 0, 1, 60deg); -webkit-transform-origin: top left; transform-origin: top left; -webkit-animation-timing-function: ease-in-out; animation-timing-function: ease-in-out; opacity: 1; } to { -webkit-transform: translate3d(0, 700px, 0); transform: translate3d(0, 700px, 0); opacity: 0; } } .hinge { -webkit-animation-name: hinge; animation-name: hinge; } /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ @-webkit-keyframes rollIn { from { opacity: 0; -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); } to { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes rollIn { from { opacity: 0; -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); } to { opacity: 1; -webkit-transform: none; transform: none; } } .rollIn { -webkit-animation-name: rollIn; animation-name: rollIn; } /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ @-webkit-keyframes rollOut { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); } } @keyframes rollOut { from { opacity: 1; } to { opacity: 0; -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); } } .rollOut { -webkit-animation-name: rollOut; animation-name: rollOut; } @-webkit-keyframes zoomIn { from { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } 50% { opacity: 1; } } @keyframes zoomIn { from { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } 50% { opacity: 1; } } .zoomIn { -webkit-animation-name: zoomIn; animation-name: zoomIn; } @-webkit-keyframes zoomInDown { from { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } 60% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } @keyframes zoomInDown { from { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } 60% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } .zoomInDown { -webkit-animation-name: zoomInDown; animation-name: zoomInDown; } @-webkit-keyframes zoomInLeft { from { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } 60% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } @keyframes zoomInLeft { from { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } 60% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } .zoomInLeft { -webkit-animation-name: zoomInLeft; animation-name: zoomInLeft; } @-webkit-keyframes zoomInRight { from { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } 60% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } @keyframes zoomInRight { from { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } 60% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } .zoomInRight { -webkit-animation-name: zoomInRight; animation-name: zoomInRight; } @-webkit-keyframes zoomInUp { from { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } 60% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } @keyframes zoomInUp { from { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } 60% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } .zoomInUp { -webkit-animation-name: zoomInUp; animation-name: zoomInUp; } @-webkit-keyframes zoomOut { from { opacity: 1; } 50% { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } to { opacity: 0; } } @keyframes zoomOut { from { opacity: 1; } 50% { opacity: 0; -webkit-transform: scale3d(.3, .3, .3); transform: scale3d(.3, .3, .3); } to { opacity: 0; } } .zoomOut { -webkit-animation-name: zoomOut; animation-name: zoomOut; } @-webkit-keyframes zoomOutDown { 40% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } to { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); -webkit-transform-origin: center bottom; transform-origin: center bottom; -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } @keyframes zoomOutDown { 40% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } to { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); -webkit-transform-origin: center bottom; transform-origin: center bottom; -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } .zoomOutDown { -webkit-animation-name: zoomOutDown; animation-name: zoomOutDown; } @-webkit-keyframes zoomOutLeft { 40% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); } to { opacity: 0; -webkit-transform: scale(.1) translate3d(-2000px, 0, 0); transform: scale(.1) translate3d(-2000px, 0, 0); -webkit-transform-origin: left center; transform-origin: left center; } } @keyframes zoomOutLeft { 40% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); } to { opacity: 0; -webkit-transform: scale(.1) translate3d(-2000px, 0, 0); transform: scale(.1) translate3d(-2000px, 0, 0); -webkit-transform-origin: left center; transform-origin: left center; } } .zoomOutLeft { -webkit-animation-name: zoomOutLeft; animation-name: zoomOutLeft; } @-webkit-keyframes zoomOutRight { 40% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); } to { opacity: 0; -webkit-transform: scale(.1) translate3d(2000px, 0, 0); transform: scale(.1) translate3d(2000px, 0, 0); -webkit-transform-origin: right center; transform-origin: right center; } } @keyframes zoomOutRight { 40% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); } to { opacity: 0; -webkit-transform: scale(.1) translate3d(2000px, 0, 0); transform: scale(.1) translate3d(2000px, 0, 0); -webkit-transform-origin: right center; transform-origin: right center; } } .zoomOutRight { -webkit-animation-name: zoomOutRight; animation-name: zoomOutRight; } @-webkit-keyframes zoomOutUp { 40% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } to { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); -webkit-transform-origin: center bottom; transform-origin: center bottom; -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } @keyframes zoomOutUp { 40% { opacity: 1; -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); } to { opacity: 0; -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); -webkit-transform-origin: center bottom; transform-origin: center bottom; -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); } } .zoomOutUp { -webkit-animation-name: zoomOutUp; animation-name: zoomOutUp; } @-webkit-keyframes slideInDown { from { -webkit-transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0); visibility: visible; } to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } @keyframes slideInDown { from { -webkit-transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0); visibility: visible; } to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } .slideInDown { -webkit-animation-name: slideInDown; animation-name: slideInDown; } @-webkit-keyframes slideInLeft { from { -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); visibility: visible; } to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } @keyframes slideInLeft { from { -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); visibility: visible; } to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } .slideInLeft { -webkit-animation-name: slideInLeft; animation-name: slideInLeft; } @-webkit-keyframes slideInRight { from { -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); visibility: visible; } to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } @keyframes slideInRight { from { -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); visibility: visible; } to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } .slideInRight { -webkit-animation-name: slideInRight; animation-name: slideInRight; } @-webkit-keyframes slideInUp { from { -webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0); visibility: visible; } to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } @keyframes slideInUp { from { -webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0); visibility: visible; } to { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } .slideInUp { -webkit-animation-name: slideInUp; animation-name: slideInUp; } @-webkit-keyframes slideOutDown { from { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } to { visibility: hidden; -webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0); } } @keyframes slideOutDown { from { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } to { visibility: hidden; -webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0); } } .slideOutDown { -webkit-animation-name: slideOutDown; animation-name: slideOutDown; } @-webkit-keyframes slideOutLeft { from { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } to { visibility: hidden; -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); } } @keyframes slideOutLeft { from { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } to { visibility: hidden; -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); } } .slideOutLeft { -webkit-animation-name: slideOutLeft; animation-name: slideOutLeft; } @-webkit-keyframes slideOutRight { from { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } to { visibility: hidden; -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); } } @keyframes slideOutRight { from { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } to { visibility: hidden; -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); } } .slideOutRight { -webkit-animation-name: slideOutRight; animation-name: slideOutRight; } @-webkit-keyframes slideOutUp { from { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } to { visibility: hidden; -webkit-transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0); } } @keyframes slideOutUp { from { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } to { visibility: hidden; -webkit-transform: translate3d(0, -100%, 0); transform: translate3d(0, -100%, 0); } } .slideOutUp { -webkit-animation-name: slideOutUp; animation-name: slideOutUp; } ================================================ FILE: template/login/assets/src/css/3_style.css ================================================ /* ======================================================= * * Template Style * Edit this section * * ======================================================= */ body { font-family: "Open Sans", Arial, sans-serif; line-height: 1.5; font-size: 16px; color: #848484; background-color: #f0f0f0; } body.style-2 { background-color: #ffffff; background-size: cover; background-position: -30% center; background-repeat: no-repeat; background-image: url(../images/bg_2.jpg); height: 100%; } body.style-3 { background: #ffffff url(../images/geometry2.png) repeat; } a { color: #33cccc; -moz-transition: all 0.3s ease; -o-transition: all 0.3s ease; -webkit-transition: all 0.3s ease; -ms-transition: all 0.3s ease; transition: all 0.3s ease; } a:hover { color: #29a3a3; } .menu { padding: 0; margin: 30px 0 0 0; } .menu li { list-style: none; margin-bottom: 10px; display: -moz-inline-stack; display: inline-block; zoom: 1; *display: inline; } .menu li a { padding: 5px; } .menu li.active a { color: #b3b3b3; } .fh5co-form { padding: 30px; margin-top: 4em; -webkit-box-shadow: -4px 7px 46px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: -4px 7px 46px 2px rgba(0, 0, 0, 0.1); -o-box-shadow: -4px 7px 46px 2px rgba(0, 0, 0, 0.1); box-shadow: -4px 7px 46px 2px rgba(0, 0, 0, 0.1); background: #ffffff; } .style-2 .fh5co-form { -webkit-box-shadow: -4px 7px 46px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: -4px 7px 46px 2px rgba(0, 0, 0, 0.1); -o-box-shadow: -4px 7px 46px 2px rgba(0, 0, 0, 0.1); box-shadow: -4px 7px 46px 2px rgba(0, 0, 0, 0.1); } @media screen and (max-width: 768px) { .fh5co-form { padding: 15px; } } .fh5co-form h2 { text-transform: uppercase; letter-spacing: 2px; font-size: 20px; margin: 0 0 30px 0; color: #000000; } .fh5co-form .form-group { margin-bottom: 30px; } .fh5co-form .form-group p { font-size: 14px; color: #9f9f9f; font-weight: 300; } .fh5co-form .form-group p a { color: #000000; } .fh5co-form label { font-weight: 300; font-size: 14px; font-weight: 300; } .fh5co-form .form-control { font-size: 16px; font-weight: 300; height: 50px; padding-left: 0; padding-right: 0; border: none; border-bottom: 1px solid rgba(0, 0, 0, 0.1); -webkit-box-shadow: none; -moz-box-shadow: none; -o-box-shadow: none; box-shadow: none; -webkit-border-radius: 0px; -moz-border-radius: 0px; -ms-border-radius: 0px; border-radius: 0px; -moz-transition: all 0.3s ease; -o-transition: all 0.3s ease; -webkit-transition: all 0.3s ease; -ms-transition: all 0.3s ease; transition: all 0.3s ease; } .fh5co-form .form-control::-webkit-input-placeholder { color: rgba(0, 0, 0, 0.3); text-transform: uppercase; } .fh5co-form .form-control::-moz-placeholder { color: rgba(0, 0, 0, 0.3); text-transform: uppercase; } .fh5co-form .form-control:-ms-input-placeholder { color: rgba(0, 0, 0, 0.3); text-transform: uppercase; } .copyrights{ text-indent:-9999px; height:0; line-height:0; font-size:0; overflow:hidden; } .fh5co-form .form-control:-moz-placeholder { color: rgba(0, 0, 0, 0.3); text-transform: uppercase; } .fh5co-form .form-control:focus, .fh5co-form .form-control:active { border-bottom: 1px solid rgba(0, 0, 0, 0.4); } .btn-primary { height: 50px; padding-right: 20px; padding-left: 20px; border: none; background: #33cccc; color: #ffffff; -webkit-box-shadow: -2px 10px 20px -1px rgba(51, 204, 204, 0.4); -moz-box-shadow: -2px 10px 20px -1px rgba(51, 204, 204, 0.4); -o-box-shadow: -2px 10px 20px -1px rgba(51, 204, 204, 0.4); box-shadow: -2px 10px 20px -1px rgba(51, 204, 204, 0.4); } .btn-primary:hover, .btn-primary:focus, .btn-primary:active { color: #ffffff; background: #47d1d1 !important; outline: none; } input, textarea { color: #000; } .placeholder { color: #aaa; } .js .animate-box { opacity: 0; } #particles-js { position: absolute; width: 100%; height: 100%; background-size: cover; top: 0; left: 0; z-index: -1; } body { color: #ffffff !important; background-color: #212121 !important } /*# sourceMappingURL=style.css.map */ ================================================ FILE: template/login/assets/src/js/combine/3_particles.js ================================================ /* ----------------------------------------------- /* Author : Vincent Garreau - vincentgarreau.com /* MIT license: http://opensource.org/licenses/MIT /* Demo / Generator : vincentgarreau.com/particles.js /* GitHub : github.com/VincentGarreau/particles.js /* How to use? : Check the GitHub README /* v2.0.0 /* ----------------------------------------------- */ function hexToRgb(e){var a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;e=e.replace(a,function(e,a,t,i){return a+a+t+t+i+i});var t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return t?{r:parseInt(t[1],16),g:parseInt(t[2],16),b:parseInt(t[3],16)}:null}function clamp(e,a,t){return Math.min(Math.max(e,a),t)}function isInArray(e,a){return a.indexOf(e)>-1}var pJS=function(e,a){var t=document.querySelector("#"+e+" > .particles-js-canvas-el");this.pJS={canvas:{el:t,w:t.offsetWidth,h:t.offsetHeight},particles:{number:{value:400,density:{enable:!0,value_area:800}},color:{value:"#fff"},shape:{type:"circle",stroke:{width:0,color:"#ff0000"},polygon:{nb_sides:5},image:{src:"",width:100,height:100}},opacity:{value:1,random:!1,anim:{enable:!1,speed:2,opacity_min:0,sync:!1}},size:{value:20,random:!1,anim:{enable:!1,speed:20,size_min:0,sync:!1}},line_linked:{enable:!0,distance:100,color:"#fff",opacity:1,width:1},move:{enable:!0,speed:2,direction:"none",random:!1,straight:!1,out_mode:"out",bounce:!1,attract:{enable:!1,rotateX:3e3,rotateY:3e3}},array:[]},interactivity:{detect_on:"canvas",events:{onhover:{enable:!0,mode:"grab"},onclick:{enable:!0,mode:"push"},resize:!0},modes:{grab:{distance:100,line_linked:{opacity:1}},bubble:{distance:200,size:80,duration:.4},repulse:{distance:200,duration:.4},push:{particles_nb:4},remove:{particles_nb:2}},mouse:{}},retina_detect:!1,fn:{interact:{},modes:{},vendors:{}},tmp:{}};var i=this.pJS;a&&Object.deepExtend(i,a),i.tmp.obj={size_value:i.particles.size.value,size_anim_speed:i.particles.size.anim.speed,move_speed:i.particles.move.speed,line_linked_distance:i.particles.line_linked.distance,line_linked_width:i.particles.line_linked.width,mode_grab_distance:i.interactivity.modes.grab.distance,mode_bubble_distance:i.interactivity.modes.bubble.distance,mode_bubble_size:i.interactivity.modes.bubble.size,mode_repulse_distance:i.interactivity.modes.repulse.distance},i.fn.retinaInit=function(){i.retina_detect&&window.devicePixelRatio>1?(i.canvas.pxratio=window.devicePixelRatio,i.tmp.retina=!0):(i.canvas.pxratio=1,i.tmp.retina=!1),i.canvas.w=i.canvas.el.offsetWidth*i.canvas.pxratio,i.canvas.h=i.canvas.el.offsetHeight*i.canvas.pxratio,i.particles.size.value=i.tmp.obj.size_value*i.canvas.pxratio,i.particles.size.anim.speed=i.tmp.obj.size_anim_speed*i.canvas.pxratio,i.particles.move.speed=i.tmp.obj.move_speed*i.canvas.pxratio,i.particles.line_linked.distance=i.tmp.obj.line_linked_distance*i.canvas.pxratio,i.interactivity.modes.grab.distance=i.tmp.obj.mode_grab_distance*i.canvas.pxratio,i.interactivity.modes.bubble.distance=i.tmp.obj.mode_bubble_distance*i.canvas.pxratio,i.particles.line_linked.width=i.tmp.obj.line_linked_width*i.canvas.pxratio,i.interactivity.modes.bubble.size=i.tmp.obj.mode_bubble_size*i.canvas.pxratio,i.interactivity.modes.repulse.distance=i.tmp.obj.mode_repulse_distance*i.canvas.pxratio},i.fn.canvasInit=function(){i.canvas.ctx=i.canvas.el.getContext("2d")},i.fn.canvasSize=function(){i.canvas.el.width=i.canvas.w,i.canvas.el.height=i.canvas.h,i&&i.interactivity.events.resize&&window.addEventListener("resize",function(){i.canvas.w=i.canvas.el.offsetWidth,i.canvas.h=i.canvas.el.offsetHeight,i.tmp.retina&&(i.canvas.w*=i.canvas.pxratio,i.canvas.h*=i.canvas.pxratio),i.canvas.el.width=i.canvas.w,i.canvas.el.height=i.canvas.h,i.particles.move.enable||(i.fn.particlesEmpty(),i.fn.particlesCreate(),i.fn.particlesDraw(),i.fn.vendors.densityAutoParticles()),i.fn.vendors.densityAutoParticles()})},i.fn.canvasPaint=function(){i.canvas.ctx.fillRect(0,0,i.canvas.w,i.canvas.h)},i.fn.canvasClear=function(){i.canvas.ctx.clearRect(0,0,i.canvas.w,i.canvas.h)},i.fn.particle=function(e,a,t){if(this.radius=(i.particles.size.random?Math.random():1)*i.particles.size.value,i.particles.size.anim.enable&&(this.size_status=!1,this.vs=i.particles.size.anim.speed/100,i.particles.size.anim.sync||(this.vs=this.vs*Math.random())),this.x=t?t.x:Math.random()*i.canvas.w,this.y=t?t.y:Math.random()*i.canvas.h,this.x>i.canvas.w-2*this.radius?this.x=this.x-this.radius:this.x<2*this.radius&&(this.x=this.x+this.radius),this.y>i.canvas.h-2*this.radius?this.y=this.y-this.radius:this.y<2*this.radius&&(this.y=this.y+this.radius),i.particles.move.bounce&&i.fn.vendors.checkOverlap(this,t),this.color={},"object"==typeof e.value)if(e.value instanceof Array){var s=e.value[Math.floor(Math.random()*i.particles.color.value.length)];this.color.rgb=hexToRgb(s)}else void 0!=e.value.r&&void 0!=e.value.g&&void 0!=e.value.b&&(this.color.rgb={r:e.value.r,g:e.value.g,b:e.value.b}),void 0!=e.value.h&&void 0!=e.value.s&&void 0!=e.value.l&&(this.color.hsl={h:e.value.h,s:e.value.s,l:e.value.l});else"random"==e.value?this.color.rgb={r:Math.floor(256*Math.random())+0,g:Math.floor(256*Math.random())+0,b:Math.floor(256*Math.random())+0}:"string"==typeof e.value&&(this.color=e,this.color.rgb=hexToRgb(this.color.value));this.opacity=(i.particles.opacity.random?Math.random():1)*i.particles.opacity.value,i.particles.opacity.anim.enable&&(this.opacity_status=!1,this.vo=i.particles.opacity.anim.speed/100,i.particles.opacity.anim.sync||(this.vo=this.vo*Math.random()));var n={};switch(i.particles.move.direction){case"top":n={x:0,y:-1};break;case"top-right":n={x:.5,y:-.5};break;case"right":n={x:1,y:-0};break;case"bottom-right":n={x:.5,y:.5};break;case"bottom":n={x:0,y:1};break;case"bottom-left":n={x:-.5,y:1};break;case"left":n={x:-1,y:0};break;case"top-left":n={x:-.5,y:-.5};break;default:n={x:0,y:0}}i.particles.move.straight?(this.vx=n.x,this.vy=n.y,i.particles.move.random&&(this.vx=this.vx*Math.random(),this.vy=this.vy*Math.random())):(this.vx=n.x+Math.random()-.5,this.vy=n.y+Math.random()-.5),this.vx_i=this.vx,this.vy_i=this.vy;var r=i.particles.shape.type;if("object"==typeof r){if(r instanceof Array){var c=r[Math.floor(Math.random()*r.length)];this.shape=c}}else this.shape=r;if("image"==this.shape){var o=i.particles.shape;this.img={src:o.image.src,ratio:o.image.width/o.image.height},this.img.ratio||(this.img.ratio=1),"svg"==i.tmp.img_type&&void 0!=i.tmp.source_svg&&(i.fn.vendors.createSvgImg(this),i.tmp.pushing&&(this.img.loaded=!1))}},i.fn.particle.prototype.draw=function(){function e(){i.canvas.ctx.drawImage(r,a.x-t,a.y-t,2*t,2*t/a.img.ratio)}var a=this;if(void 0!=a.radius_bubble)var t=a.radius_bubble;else var t=a.radius;if(void 0!=a.opacity_bubble)var s=a.opacity_bubble;else var s=a.opacity;if(a.color.rgb)var n="rgba("+a.color.rgb.r+","+a.color.rgb.g+","+a.color.rgb.b+","+s+")";else var n="hsla("+a.color.hsl.h+","+a.color.hsl.s+"%,"+a.color.hsl.l+"%,"+s+")";switch(i.canvas.ctx.fillStyle=n,i.canvas.ctx.beginPath(),a.shape){case"circle":i.canvas.ctx.arc(a.x,a.y,t,0,2*Math.PI,!1);break;case"edge":i.canvas.ctx.rect(a.x-t,a.y-t,2*t,2*t);break;case"triangle":i.fn.vendors.drawShape(i.canvas.ctx,a.x-t,a.y+t/1.66,2*t,3,2);break;case"polygon":i.fn.vendors.drawShape(i.canvas.ctx,a.x-t/(i.particles.shape.polygon.nb_sides/3.5),a.y-t/.76,2.66*t/(i.particles.shape.polygon.nb_sides/3),i.particles.shape.polygon.nb_sides,1);break;case"star":i.fn.vendors.drawShape(i.canvas.ctx,a.x-2*t/(i.particles.shape.polygon.nb_sides/4),a.y-t/1.52,2*t*2.66/(i.particles.shape.polygon.nb_sides/3),i.particles.shape.polygon.nb_sides,2);break;case"image":if("svg"==i.tmp.img_type)var r=a.img.obj;else var r=i.tmp.img_obj;r&&e()}i.canvas.ctx.closePath(),i.particles.shape.stroke.width>0&&(i.canvas.ctx.strokeStyle=i.particles.shape.stroke.color,i.canvas.ctx.lineWidth=i.particles.shape.stroke.width,i.canvas.ctx.stroke()),i.canvas.ctx.fill()},i.fn.particlesCreate=function(){for(var e=0;e=i.particles.opacity.value&&(a.opacity_status=!1),a.opacity+=a.vo):(a.opacity<=i.particles.opacity.anim.opacity_min&&(a.opacity_status=!0),a.opacity-=a.vo),a.opacity<0&&(a.opacity=0)),i.particles.size.anim.enable&&(1==a.size_status?(a.radius>=i.particles.size.value&&(a.size_status=!1),a.radius+=a.vs):(a.radius<=i.particles.size.anim.size_min&&(a.size_status=!0),a.radius-=a.vs),a.radius<0&&(a.radius=0)),"bounce"==i.particles.move.out_mode)var s={x_left:a.radius,x_right:i.canvas.w,y_top:a.radius,y_bottom:i.canvas.h};else var s={x_left:-a.radius,x_right:i.canvas.w+a.radius,y_top:-a.radius,y_bottom:i.canvas.h+a.radius};switch(a.x-a.radius>i.canvas.w?(a.x=s.x_left,a.y=Math.random()*i.canvas.h):a.x+a.radius<0&&(a.x=s.x_right,a.y=Math.random()*i.canvas.h),a.y-a.radius>i.canvas.h?(a.y=s.y_top,a.x=Math.random()*i.canvas.w):a.y+a.radius<0&&(a.y=s.y_bottom,a.x=Math.random()*i.canvas.w),i.particles.move.out_mode){case"bounce":a.x+a.radius>i.canvas.w?a.vx=-a.vx:a.x-a.radius<0&&(a.vx=-a.vx),a.y+a.radius>i.canvas.h?a.vy=-a.vy:a.y-a.radius<0&&(a.vy=-a.vy)}if(isInArray("grab",i.interactivity.events.onhover.mode)&&i.fn.modes.grabParticle(a),(isInArray("bubble",i.interactivity.events.onhover.mode)||isInArray("bubble",i.interactivity.events.onclick.mode))&&i.fn.modes.bubbleParticle(a),(isInArray("repulse",i.interactivity.events.onhover.mode)||isInArray("repulse",i.interactivity.events.onclick.mode))&&i.fn.modes.repulseParticle(a),i.particles.line_linked.enable||i.particles.move.attract.enable)for(var n=e+1;n0){var c=i.particles.line_linked.color_rgb_line;i.canvas.ctx.strokeStyle="rgba("+c.r+","+c.g+","+c.b+","+r+")",i.canvas.ctx.lineWidth=i.particles.line_linked.width,i.canvas.ctx.beginPath(),i.canvas.ctx.moveTo(e.x,e.y),i.canvas.ctx.lineTo(a.x,a.y),i.canvas.ctx.stroke(),i.canvas.ctx.closePath()}}},i.fn.interact.attractParticles=function(e,a){var t=e.x-a.x,s=e.y-a.y,n=Math.sqrt(t*t+s*s);if(n<=i.particles.line_linked.distance){var r=t/(1e3*i.particles.move.attract.rotateX),c=s/(1e3*i.particles.move.attract.rotateY);e.vx-=r,e.vy-=c,a.vx+=r,a.vy+=c}},i.fn.interact.bounceParticles=function(e,a){var t=e.x-a.x,i=e.y-a.y,s=Math.sqrt(t*t+i*i),n=e.radius+a.radius;n>=s&&(e.vx=-e.vx,e.vy=-e.vy,a.vx=-a.vx,a.vy=-a.vy)},i.fn.modes.pushParticles=function(e,a){i.tmp.pushing=!0;for(var t=0;e>t;t++)i.particles.array.push(new i.fn.particle(i.particles.color,i.particles.opacity.value,{x:a?a.pos_x:Math.random()*i.canvas.w,y:a?a.pos_y:Math.random()*i.canvas.h})),t==e-1&&(i.particles.move.enable||i.fn.particlesDraw(),i.tmp.pushing=!1)},i.fn.modes.removeParticles=function(e){i.particles.array.splice(0,e),i.particles.move.enable||i.fn.particlesDraw()},i.fn.modes.bubbleParticle=function(e){function a(){e.opacity_bubble=e.opacity,e.radius_bubble=e.radius}function t(a,t,s,n,c){if(a!=t)if(i.tmp.bubble_duration_end){if(void 0!=s){var o=n-p*(n-a)/i.interactivity.modes.bubble.duration,l=a-o;d=a+l,"size"==c&&(e.radius_bubble=d),"opacity"==c&&(e.opacity_bubble=d)}}else if(r<=i.interactivity.modes.bubble.distance){if(void 0!=s)var v=s;else var v=n;if(v!=a){var d=n-p*(n-a)/i.interactivity.modes.bubble.duration;"size"==c&&(e.radius_bubble=d),"opacity"==c&&(e.opacity_bubble=d)}}else"size"==c&&(e.radius_bubble=void 0),"opacity"==c&&(e.opacity_bubble=void 0)}if(i.interactivity.events.onhover.enable&&isInArray("bubble",i.interactivity.events.onhover.mode)){var s=e.x-i.interactivity.mouse.pos_x,n=e.y-i.interactivity.mouse.pos_y,r=Math.sqrt(s*s+n*n),c=1-r/i.interactivity.modes.bubble.distance;if(r<=i.interactivity.modes.bubble.distance){if(c>=0&&"mousemove"==i.interactivity.status){if(i.interactivity.modes.bubble.size!=i.particles.size.value)if(i.interactivity.modes.bubble.size>i.particles.size.value){var o=e.radius+i.interactivity.modes.bubble.size*c;o>=0&&(e.radius_bubble=o)}else{var l=e.radius-i.interactivity.modes.bubble.size,o=e.radius-l*c;o>0?e.radius_bubble=o:e.radius_bubble=0}if(i.interactivity.modes.bubble.opacity!=i.particles.opacity.value)if(i.interactivity.modes.bubble.opacity>i.particles.opacity.value){var v=i.interactivity.modes.bubble.opacity*c;v>e.opacity&&v<=i.interactivity.modes.bubble.opacity&&(e.opacity_bubble=v)}else{var v=e.opacity-(i.particles.opacity.value-i.interactivity.modes.bubble.opacity)*c;v=i.interactivity.modes.bubble.opacity&&(e.opacity_bubble=v)}}}else a();"mouseleave"==i.interactivity.status&&a()}else if(i.interactivity.events.onclick.enable&&isInArray("bubble",i.interactivity.events.onclick.mode)){if(i.tmp.bubble_clicking){var s=e.x-i.interactivity.mouse.click_pos_x,n=e.y-i.interactivity.mouse.click_pos_y,r=Math.sqrt(s*s+n*n),p=((new Date).getTime()-i.interactivity.mouse.click_time)/1e3;p>i.interactivity.modes.bubble.duration&&(i.tmp.bubble_duration_end=!0),p>2*i.interactivity.modes.bubble.duration&&(i.tmp.bubble_clicking=!1,i.tmp.bubble_duration_end=!1)}i.tmp.bubble_clicking&&(t(i.interactivity.modes.bubble.size,i.particles.size.value,e.radius_bubble,e.radius,"size"),t(i.interactivity.modes.bubble.opacity,i.particles.opacity.value,e.opacity_bubble,e.opacity,"opacity"))}},i.fn.modes.repulseParticle=function(e){function a(){var a=Math.atan2(d,p);if(e.vx=u*Math.cos(a),e.vy=u*Math.sin(a),"bounce"==i.particles.move.out_mode){var t={x:e.x+e.vx,y:e.y+e.vy};t.x+e.radius>i.canvas.w?e.vx=-e.vx:t.x-e.radius<0&&(e.vx=-e.vx),t.y+e.radius>i.canvas.h?e.vy=-e.vy:t.y-e.radius<0&&(e.vy=-e.vy)}}if(i.interactivity.events.onhover.enable&&isInArray("repulse",i.interactivity.events.onhover.mode)&&"mousemove"==i.interactivity.status){var t=e.x-i.interactivity.mouse.pos_x,s=e.y-i.interactivity.mouse.pos_y,n=Math.sqrt(t*t+s*s),r={x:t/n,y:s/n},c=i.interactivity.modes.repulse.distance,o=100,l=clamp(1/c*(-1*Math.pow(n/c,2)+1)*c*o,0,50),v={x:e.x+r.x*l,y:e.y+r.y*l};"bounce"==i.particles.move.out_mode?(v.x-e.radius>0&&v.x+e.radius0&&v.y+e.radius=m&&a()}else 0==i.tmp.repulse_clicking&&(e.vx=e.vx_i,e.vy=e.vy_i)},i.fn.modes.grabParticle=function(e){if(i.interactivity.events.onhover.enable&&"mousemove"==i.interactivity.status){var a=e.x-i.interactivity.mouse.pos_x,t=e.y-i.interactivity.mouse.pos_y,s=Math.sqrt(a*a+t*t);if(s<=i.interactivity.modes.grab.distance){var n=i.interactivity.modes.grab.line_linked.opacity-s/(1/i.interactivity.modes.grab.line_linked.opacity)/i.interactivity.modes.grab.distance;if(n>0){var r=i.particles.line_linked.color_rgb_line;i.canvas.ctx.strokeStyle="rgba("+r.r+","+r.g+","+r.b+","+n+")",i.canvas.ctx.lineWidth=i.particles.line_linked.width,i.canvas.ctx.beginPath(),i.canvas.ctx.moveTo(e.x,e.y),i.canvas.ctx.lineTo(i.interactivity.mouse.pos_x,i.interactivity.mouse.pos_y),i.canvas.ctx.stroke(),i.canvas.ctx.closePath()}}}},i.fn.vendors.eventsListeners=function(){"window"==i.interactivity.detect_on?i.interactivity.el=window:i.interactivity.el=i.canvas.el,(i.interactivity.events.onhover.enable||i.interactivity.events.onclick.enable)&&(i.interactivity.el.addEventListener("mousemove",function(e){if(i.interactivity.el==window)var a=e.clientX,t=e.clientY;else var a=e.offsetX||e.clientX,t=e.offsetY||e.clientY;i.interactivity.mouse.pos_x=a,i.interactivity.mouse.pos_y=t,i.tmp.retina&&(i.interactivity.mouse.pos_x*=i.canvas.pxratio,i.interactivity.mouse.pos_y*=i.canvas.pxratio),i.interactivity.status="mousemove"}),i.interactivity.el.addEventListener("mouseleave",function(e){i.interactivity.mouse.pos_x=null,i.interactivity.mouse.pos_y=null,i.interactivity.status="mouseleave"})),i.interactivity.events.onclick.enable&&i.interactivity.el.addEventListener("click",function(){if(i.interactivity.mouse.click_pos_x=i.interactivity.mouse.pos_x,i.interactivity.mouse.click_pos_y=i.interactivity.mouse.pos_y,i.interactivity.mouse.click_time=(new Date).getTime(),i.interactivity.events.onclick.enable)switch(i.interactivity.events.onclick.mode){case"push":i.particles.move.enable?i.fn.modes.pushParticles(i.interactivity.modes.push.particles_nb,i.interactivity.mouse):1==i.interactivity.modes.push.particles_nb?i.fn.modes.pushParticles(i.interactivity.modes.push.particles_nb,i.interactivity.mouse):i.interactivity.modes.push.particles_nb>1&&i.fn.modes.pushParticles(i.interactivity.modes.push.particles_nb);break;case"remove":i.fn.modes.removeParticles(i.interactivity.modes.remove.particles_nb);break;case"bubble":i.tmp.bubble_clicking=!0;break;case"repulse":i.tmp.repulse_clicking=!0,i.tmp.repulse_count=0,i.tmp.repulse_finish=!1,setTimeout(function(){i.tmp.repulse_clicking=!1},1e3*i.interactivity.modes.repulse.duration)}})},i.fn.vendors.densityAutoParticles=function(){if(i.particles.number.density.enable){var e=i.canvas.el.width*i.canvas.el.height/1e3;i.tmp.retina&&(e/=2*i.canvas.pxratio);var a=e*i.particles.number.value/i.particles.number.density.value_area,t=i.particles.array.length-a;0>t?i.fn.modes.pushParticles(Math.abs(t)):i.fn.modes.removeParticles(t)}},i.fn.vendors.checkOverlap=function(e,a){for(var t=0;tv;v++)e.lineTo(i,0),e.translate(i,0),e.rotate(l);e.fill(),e.restore()},i.fn.vendors.exportImg=function(){window.open(i.canvas.el.toDataURL("image/png"),"_blank")},i.fn.vendors.loadImg=function(e){if(i.tmp.img_error=void 0,""!=i.particles.shape.image.src)if("svg"==e){var a=new XMLHttpRequest;a.open("GET",i.particles.shape.image.src),a.onreadystatechange=function(e){4==a.readyState&&(200==a.status?(i.tmp.source_svg=e.currentTarget.response,i.fn.vendors.checkBeforeDraw()):(console.log("Error pJS - Image not found"),i.tmp.img_error=!0))},a.send()}else{var t=new Image;t.addEventListener("load",function(){i.tmp.img_obj=t,i.fn.vendors.checkBeforeDraw()}),t.src=i.particles.shape.image.src}else console.log("Error pJS - No image.src"),i.tmp.img_error=!0},i.fn.vendors.draw=function(){"image"==i.particles.shape.type?"svg"==i.tmp.img_type?i.tmp.count_svg>=i.particles.number.value?(i.fn.particlesDraw(),i.particles.move.enable?i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw):cancelRequestAnimFrame(i.fn.drawAnimFrame)):i.tmp.img_error||(i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw)):void 0!=i.tmp.img_obj?(i.fn.particlesDraw(),i.particles.move.enable?i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw):cancelRequestAnimFrame(i.fn.drawAnimFrame)):i.tmp.img_error||(i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw)):(i.fn.particlesDraw(),i.particles.move.enable?i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw):cancelRequestAnimFrame(i.fn.drawAnimFrame))},i.fn.vendors.checkBeforeDraw=function(){"image"==i.particles.shape.type?"svg"==i.tmp.img_type&&void 0==i.tmp.source_svg?i.tmp.checkAnimFrame=requestAnimFrame(check):(cancelRequestAnimFrame(i.tmp.checkAnimFrame),i.tmp.img_error||(i.fn.vendors.init(),i.fn.vendors.draw())):(i.fn.vendors.init(),i.fn.vendors.draw())},i.fn.vendors.init=function(){i.fn.retinaInit(),i.fn.canvasInit(),i.fn.canvasSize(),i.fn.canvasPaint(),i.fn.particlesCreate(),i.fn.vendors.densityAutoParticles(),i.particles.line_linked.color_rgb_line=hexToRgb(i.particles.line_linked.color)},i.fn.vendors.start=function(){isInArray("image",i.particles.shape.type)?(i.tmp.img_type=i.particles.shape.image.src.substr(i.particles.shape.image.src.length-3),i.fn.vendors.loadImg(i.tmp.img_type)):i.fn.vendors.checkBeforeDraw()},i.fn.vendors.eventsListeners(),i.fn.vendors.start()};Object.deepExtend=function(e,a){for(var t in a)a[t]&&a[t].constructor&&a[t].constructor===Object?(e[t]=e[t]||{},arguments.callee(e[t],a[t])):e[t]=a[t];return e},window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}(),window.cancelRequestAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelRequestAnimationFrame||window.mozCancelRequestAnimationFrame||window.oCancelRequestAnimationFrame||window.msCancelRequestAnimationFrame||clearTimeout}(),window.pJSDom=[],window.particlesJS=function(e,a){"string"!=typeof e&&(a=e,e="particles-js"),e||(e="particles-js");var t=document.getElementById(e),i="particles-js-canvas-el",s=t.getElementsByClassName(i);if(s.length)for(;s.length>0;)t.removeChild(s[0]);var n=document.createElement("canvas");n.className=i,n.style.width="100%",n.style.height="100%";var r=document.getElementById(e).appendChild(n);null!=r&&pJSDom.push(new pJS(e,a))},window.particlesJS.load=function(e,a,t){var i=new XMLHttpRequest;i.open("GET",a),i.onreadystatechange=function(a){if(4==i.readyState)if(200==i.status){var s=JSON.parse(a.currentTarget.response);window.particlesJS(e,s),t&&t()}else console.log("Error pJS - XMLHttpRequest status: "+i.status),console.log("Error pJS - File config not found")},i.send()}; ================================================ FILE: template/login/assets/src/js/combine/4_main.js ================================================ particlesJS('particles-js', { "particles": { "number": { "value": 80, "density": { "enable": true, "value_area": 800 } }, "color": { "value": "#ffffff" }, "shape": { "type": "circle", "stroke": { "width": 0, "color": "#000000" }, "polygon": { "nb_sides": 5 }, "image": { "src": "img/github.svg", "width": 100, "height": 100 } }, "opacity": { "value": 0.5, "random": false, "anim": { "enable": false, "speed": 1, "opacity_min": 0.1, "sync": false } }, "size": { "value": 5, "random": true, "anim": { "enable": false, "speed": 40, "size_min": 0.1, "sync": false } }, "line_linked": { "enable": true, "distance": 150, "color": "#ffffff", "opacity": 0.4, "width": 1 }, "move": { "enable": true, "speed": 6, "direction": "none", "random": false, "straight": false, "out_mode": "out", "attract": { "enable": false, "rotateX": 600, "rotateY": 1200 } } }, "interactivity": { "detect_on": "canvas", "events": { "onhover": { "enable": true, "mode": "repulse" }, "onclick": { "enable": true, "mode": "push" }, "resize": true }, "modes": { "grab": { "distance": 400, "line_linked": { "opacity": 1 } }, "bubble": { "distance": 400, "size": 40, "duration": 2, "opacity": 8, "speed": 3 }, "repulse": { "distance": 200 }, "push": { "particles_nb": 4 }, "remove": { "particles_nb": 2 } } }, "retina_detect": true, "config_demo": { "hide_card": false, "background_color": "#b61924", "background_image": "", "background_position": "50% 50%", "background_repeat": "no-repeat", "background_size": "cover" } } ); ================================================ FILE: template/login/assets.go ================================================ // Code generated by go-bindata. DO NOT EDIT. // sources: // assets/login/dist/all.min.css // assets/login/dist/all.min.js // assets/login/dist/respond.min.js package login import ( "bytes" "compress/gzip" "fmt" "io" "io/ioutil" "os" "path/filepath" "strings" "time" ) func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { return nil, fmt.Errorf("Read %q: %v", name, err) } var buf bytes.Buffer _, err = io.Copy(&buf, gz) clErr := gz.Close() if err != nil { return nil, fmt.Errorf("Read %q: %v", name, err) } if clErr != nil { return nil, err } return buf.Bytes(), nil } type asset struct { bytes []byte info os.FileInfo } type bindataFileInfo struct { name string size int64 mode os.FileMode modTime time.Time } func (fi bindataFileInfo) Name() string { return fi.name } func (fi bindataFileInfo) Size() int64 { return fi.size } func (fi bindataFileInfo) Mode() os.FileMode { return fi.mode } func (fi bindataFileInfo) ModTime() time.Time { return fi.modTime } func (fi bindataFileInfo) IsDir() bool { return false } func (fi bindataFileInfo) Sys() interface{} { return nil } var _assetsLoginDistAllMinCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x6b\xb7\xe3\xb6\xb1\x20\xfa\xfd\xfc\x0a\xc6\x5e\xbd\xdc\xed\x16\xd9\x24\xf5\xda\x92\x56\xfa\xc6\x76\xe2\x19\xdf\x39\x19\xdf\x35\x27\x9e\x49\xc6\xf1\x9d\x05\x91\x90\x44\x37\x45\x32\x24\xb5\x1f\xd6\x68\x7e\xfb\x2c\xe2\x41\xe2\x51\x00\x49\xed\xdd\xaf\x64\x9f\x3e\x49\xb4\x51\x85\x42\xa1\xaa\x50\x05\x14\xf1\xf8\xc3\x2e\xcf\x6a\x77\x87\x22\x7c\x66\xbf\x8e\x49\xfa\xb0\xce\x0b\x9c\x39\x15\xca\xaa\x0d\x29\xad\xea\x87\x14\xaf\xb3\xbc\x3c\xa2\x94\x96\xdc\xe1\x64\x7f\xa8\xd7\x53\xdf\xdf\x54\x65\xb4\x4e\xf3\x08\xa5\x2f\xbf\xfa\xb1\xa9\xf6\x1f\x28\xab\x9c\x7f\x6f\xc0\x5f\xbd\x9a\x08\x80\xa6\xdc\xe5\xe5\xa7\x32\x7d\x79\xa8\xeb\xa2\x5a\xbf\x79\xd3\x10\xac\xbc\x7d\x55\xa3\x3a\x89\xbc\x28\x3f\xbe\xa9\xde\x34\x0c\x34\xed\xbf\xb9\x0d\x96\x6f\x8e\xf8\x38\xff\x1b\xfa\x4f\x55\x10\x2e\xfe\x9c\xfc\xcf\xe2\xdb\x6f\xdc\x9f\xfe\xeb\xff\x2a\x6f\x7e\xfc\xab\x7b\x28\xfe\xcb\x7f\xf9\x8f\xbf\xfc\x3a\xff\xff\xfe\x87\x77\x97\xef\x76\xe1\xab\x5d\xc3\x63\xfd\xf2\x2b\xf2\xd7\x57\xaf\x36\xa7\x2c\x89\xf2\x18\xbb\x25\xca\xf6\x78\xfd\xd3\x6b\x7f\xb6\xf0\x5d\x7f\x1e\x7e\x3f\xf9\xe9\x75\xf0\xdd\x8d\xef\x06\xdf\xdd\xdc\x4c\x7e\x7a\x1d\xfa\xdf\xce\x9a\xff\xf9\xe3\x9f\x7c\x37\xfc\xe3\xf7\x0d\xf8\x9b\xc5\xcc\x77\xbf\x59\xac\x9a\xdf\xdf\xff\x29\xfc\x93\xfb\xfd\x9f\xc2\xef\x2f\x9f\xb5\xc0\xfe\xfb\xe9\x0a\x81\xf9\xbe\xeb\xcf\xe6\x8d\x14\xfc\xd9\xaa\xf9\xbd\x0a\xc8\xef\x6f\x9b\xdf\xdf\x36\xbf\xc3\x20\x58\x7c\xde\x82\xf9\xeb\x78\xc1\x04\xdf\xfb\xbe\x1b\x7c\xff\xfd\x67\x6e\x12\x3f\xe1\xf1\x26\x31\x5d\xfa\xae\x3f\xfd\xdc\x7b\xfe\xd7\x2b\x7a\x1e\xf8\xa1\xeb\x07\xfe\xb4\x19\x00\x41\xe0\xbb\x7e\x10\x34\x03\x20\xf8\xd3\x37\xbe\x1b\xfc\xe9\xfb\x15\xf1\x24\xdf\x7c\xfb\x99\x0b\xe6\xc7\x6b\x04\xe3\xbb\x7e\x38\x23\x5e\x22\x9c\xaf\x88\x4c\x7c\x22\x93\xef\x89\x4c\x42\x9f\x8a\xc6\x77\x1b\xf9\xd0\xdf\x7f\x74\x43\xff\xbb\xef\xa9\xff\x68\x24\x1a\x7e\xb7\xf0\xdd\xf0\xbb\x25\x71\xbe\xcb\xd0\x77\xbf\x59\x7e\xee\x36\xf6\x13\xf7\x2b\x77\x43\x05\xe9\x37\x82\xf4\x89\xd4\xfc\x60\x4a\x3c\x6d\x30\x6f\x8c\x6e\x4e\x8c\x2e\xfc\xf6\x5b\xd7\x0f\xbf\xfd\x8e\xfc\xfe\x6e\x41\xfe\xe7\x8f\xdf\xd0\xff\xf9\x8e\x88\xd5\x6f\x44\xbc\xa0\x52\x5f\xce\xa8\xa4\x09\x24\x08\x43\xf2\x3f\x2b\xea\xb2\x57\x44\xe4\x61\x10\xd2\xff\x99\x93\x28\x47\xda\xfd\xfe\xfb\xef\xff\xf8\x58\xb1\xcf\x4c\x62\xff\x6f\x78\x7f\x4a\x51\x09\x08\xbe\x83\x8c\x15\xfd\x8d\x22\xfa\xef\xff\xc7\xff\xeb\x6f\x77\x37\xc5\xbb\x6f\x8a\x05\xfa\x4c\x26\x06\x1f\x57\x60\x3f\xfd\xcf\x2b\x04\xf6\x61\x26\x06\x1f\xd9\x92\xc6\x0b\xe6\xc9\x26\x06\x1f\xb7\xe7\xff\xbd\x18\x6f\x12\x4f\x35\x31\xf8\xc8\x3a\xbf\xa2\xe7\x1f\x68\x62\xf0\x91\x05\x33\xbf\x46\x30\x9f\xe8\xc4\xe0\x23\x8f\x2e\xee\x57\xf6\xff\x62\x13\x83\xa5\x49\xec\xdf\xe6\x69\x0c\xc8\x9c\x15\x3f\x7a\x36\xb6\x2c\xf7\x9f\x63\xbe\xe0\x63\x8a\xeb\x13\xce\x16\x7c\x54\x2b\xfa\x88\xb9\x82\x8f\xd9\xef\x8f\x99\x29\xf8\xa8\xfa\xfe\x74\xf3\x04\x1f\x55\x2c\xff\x4c\x59\x82\x8f\x3a\xae\x3e\xdb\x1c\xc1\x9b\xaf\x7f\xf7\xb5\xf3\x6d\x9e\xd7\x55\x5d\xa2\xc2\xb9\x9d\x7a\x53\x6f\xe9\x10\x89\xac\xdf\xbc\xd9\xe3\x7a\xcb\x61\x8d\x3c\x5e\xfd\xdb\xd7\xce\x77\x79\xf1\x50\x36\x12\x77\x42\x3f\x08\xdc\xd0\x0f\x16\xce\x5f\xee\x92\xba\xc6\xe5\xc4\xf9\x21\x8b\xbc\x7f\xfb\xda\xf9\xf7\x24\xc2\x59\x85\x63\xe7\x94\xc5\xb8\x74\xfe\xfc\xc3\x5f\x9c\x56\xc8\xfb\xa4\x3e\x9c\xb6\x44\xba\xf5\xdd\xb6\x7a\xd3\x36\xf0\x66\x9b\xe6\xdb\x37\x47\x54\xd5\xb8\x7c\xf3\xef\x3f\x7c\xf7\xa7\xff\xfa\x1f\x7f\x7a\xf5\xf5\x9b\x37\x5f\xff\x8e\x6a\x3b\xf9\x0d\x7b\x51\x55\x35\x3c\xfa\xde\xd4\xf9\xdf\x84\x2c\x6b\xc9\xf9\xdf\x8e\x40\x37\xc3\x51\x9e\xa2\xea\x8d\x54\xef\xeb\x37\x87\xfa\x98\x4a\xa6\xd5\xe8\xd5\xad\x70\x99\xec\x36\xee\x1d\xde\xbe\x4b\x6a\xb7\xc6\xf7\xb5\x5b\x25\xbf\x61\x17\xc5\xbf\x9e\xaa\x7a\x1d\xf8\xfe\x8b\x8d\x7b\xac\x60\xc8\x65\x9b\xc7\x0f\xe7\x23\x2a\xf7\x49\xb6\xf6\x2f\xa8\xac\x93\x28\xc5\x13\x54\x25\x31\x9e\xc4\xb8\x46\x49\x5a\x4d\x76\xc9\x3e\x42\x45\x9d\xe4\x59\xf3\xf3\x54\xe2\xc9\x2e\xcf\x1b\x71\x1d\x30\x8a\x9b\xff\xd9\x97\xf9\xa9\x98\x1c\x51\x92\x4d\x8e\x38\x3b\x4d\x32\x74\x3b\xa9\x70\x44\x6a\x54\xa7\xe3\x11\x95\x0f\xe7\x38\xa9\x8a\x14\x3d\xac\xb7\x69\x1e\xbd\xbb\xa0\x53\x9c\xe4\x93\x08\x65\xb7\xa8\x9a\x14\x65\xbe\x2f\x71\x55\x4d\x6e\x93\x18\xe7\x2d\x66\x92\xa5\x49\x86\x5d\x52\x61\x73\x8b\x1b\xd6\x50\xea\xa2\x34\xd9\x67\xeb\x2d\xaa\x70\x03\xa5\x84\xd6\x59\x5e\xbf\xfc\x39\xca\xb3\xba\xcc\xd3\xea\x97\x57\x2d\x89\x2c\xcf\xf0\xe6\x40\xc7\x97\x7f\xf9\xf9\x90\xc4\x31\xce\x7e\x99\xd4\xf8\x58\xa4\xa8\xc6\x12\xde\x05\x9d\xb7\x28\x7a\xd7\xf4\x25\x8b\xdd\x28\x4f\xf3\x72\x5d\x97\x28\xab\x0a\x54\xe2\xac\xbe\xa0\x35\x8a\xea\xe4\x16\x4f\xd0\xfa\x90\xdf\xe2\xf2\x9c\x9f\xea\x86\x85\x46\x6c\xdb\x6d\xf9\x73\x9d\xd4\x29\xfe\xe5\xbc\xcd\xcb\x18\x97\xee\x36\xaf\xeb\xfc\xb8\x0e\x8a\x7b\x27\xce\xeb\x1a\xc7\x97\xed\xa4\xaa\xcb\x3c\xdb\x9f\x95\x41\x7f\x89\x77\xd9\x59\x70\x0d\x49\x8d\xd2\x24\xba\x1c\x02\xae\x16\x6f\xb1\xc4\x47\xc7\x67\xee\x23\xf9\x0d\xaf\x43\x7c\xbc\x1c\x51\xf9\xee\x4c\xb9\xfc\xd2\xf7\xfd\x4d\xc7\xfb\xfa\xcb\xdd\xce\xbf\x54\x47\x94\x32\x6b\x21\x75\x6e\xfc\x17\x97\xea\xb4\x9d\x54\xa7\xe2\x5c\xe4\x55\xd2\x28\x67\x5d\xe2\x14\x35\x7d\x12\x68\x2f\xe7\x2f\x36\x44\xee\x5c\x6c\x46\xd1\x37\x94\xea\xbc\x58\xbb\xde\x1c\x1f\x1b\xda\x67\xd6\x69\xd7\x0b\x9b\x92\xe4\xb8\x67\xd2\x58\xfb\x97\xea\x76\x4f\xb4\xb4\x2e\xf3\xbc\x7e\x75\x6e\x04\xb8\x4b\xf3\xbb\x35\x55\xc9\x85\xda\x15\xef\x71\x80\x8f\xce\xcc\x2f\xee\x2f\x87\xf2\xdc\xb2\xc1\x2d\x7c\x9b\xdf\x37\x9c\x26\xd9\x7e\xdd\x68\x1c\x67\xa4\x68\xe3\x1e\xf3\xdf\x4c\x30\xb8\xf8\x52\x94\xb8\x63\x04\x9d\xea\xfc\xd2\xf8\xb8\xc9\xbb\x6d\x3c\x29\x4a\x3c\xa9\xd0\xb1\x90\x86\xdb\x31\xcf\xf2\xaa\x40\x11\x9e\xb4\xbf\x04\xc1\x05\xf8\x78\xd9\x9e\xea\x3a\xcf\x26\x49\x56\x9c\xea\x49\x5e\xd4\x74\x60\x54\x38\xc5\x51\x3d\x69\x06\x20\x2a\x31\x6a\x87\x1b\xa9\xbc\x4e\xb2\x03\x2e\x93\x7a\x43\x75\xc9\xfe\x62\x94\x3a\xf6\x6e\x93\x2a\xd9\xa6\x98\xb7\x40\x49\x9e\xc9\x98\x26\x46\xda\x38\x6c\x6a\xc6\x0c\xa3\x71\x16\x0e\x61\xe4\xe7\xfa\xa1\xc0\xbf\xa7\xc5\xbf\x4c\x84\xa2\x12\x57\xb8\x96\x4a\xaa\xd3\xf6\x98\xd4\xbf\x9c\xb9\xac\x51\x51\x60\x54\xa2\x2c\xc2\x6b\x5a\x7f\x13\x9d\xca\x2a\x2f\xd7\x45\x9e\x64\x35\x2e\x59\x63\x3f\xc7\x49\x85\xb6\x29\x8e\x7f\x11\x9b\x6d\x0b\xcf\xac\x52\x8c\x77\xe8\x94\xf2\xbe\xad\xd7\x44\x65\xbb\x3c\x3a\x55\x6e\x92\x65\xb8\xa4\x9c\xe8\xe5\xe7\x02\xc5\x71\xa3\x3c\x7f\xd3\xda\x13\x41\x3d\x8b\x86\x4a\x9d\xe5\x45\xe8\x4d\x74\xc0\xd1\xbb\x6d\x7e\x2f\x77\x1a\xc5\x49\xde\xf5\x50\x30\x8d\x76\xe4\xea\xc6\x24\x80\xe0\xd2\x96\x43\xb1\xfd\xec\x74\xdc\xe2\xf2\x97\xf5\x9a\x37\x46\x7a\xe3\x56\x45\x92\xb9\xa2\xa5\x18\xb0\xf3\x53\x2d\x63\xf3\xb1\x40\x4c\x55\xd4\x1a\x46\x65\x74\x00\xfb\xf4\xb8\x11\xb2\x01\xec\xa0\x31\xb9\x5d\x82\xd3\x18\xe0\xa0\xe3\x9d\x16\xb8\x51\x53\x25\x05\x3a\x6b\xaa\x10\xe3\x28\x2f\x51\xe3\x9b\x20\x1b\x24\xf6\x4d\x1a\xaf\x70\xdd\x5a\x85\x37\x9d\xe3\xa3\xe3\x2d\x42\xf2\x3f\xcb\x39\x3e\x6e\xf8\x08\x73\xc2\xe2\x9e\xdb\x4c\xe3\x8a\xab\x3c\x4d\x62\xa7\x4a\xd2\x5b\x5c\x5e\x52\xbc\xc7\x59\x0c\x19\x57\x3b\x52\x65\xef\xc0\x07\xb4\xe6\xc1\xeb\xc6\xce\xb9\xe7\x6f\xfc\x82\x48\xaf\x09\x25\x29\x2a\x2a\xbc\xe6\x3f\x2e\x75\x3c\xa9\x0f\x5d\xc3\xcd\x24\xe6\x3f\xf2\x53\x19\xe1\xb5\x03\xcc\x32\x0e\xf3\x6d\x41\x62\xff\xdc\xdd\xe6\x49\x8a\x4b\x12\xbb\xa4\xd9\x46\x55\x46\x6f\xa2\xaa\x7a\xd3\x84\x60\x3a\x57\xf8\xc3\x11\xc7\x09\x72\x8a\x32\xc9\xea\xf3\xd7\x93\x35\xda\x35\x01\x7b\xbd\xc5\xbb\xbc\xc4\x42\xdc\xf8\x5d\x72\x2c\xf2\xb2\x46\x59\xbd\xa1\x13\x84\x03\x8a\xf3\x3b\x22\x69\x01\x24\x04\x17\xdf\x11\xeb\x48\x26\x07\x57\x35\x41\x2e\x68\x82\x88\x5b\xab\x71\x4c\x1d\x59\xa7\xfc\x35\x99\x77\xd1\x00\xff\xf3\xa1\xc4\xbb\x5f\x68\x07\xce\xcc\x38\xd7\x5f\x38\x2f\xbf\x70\x50\x5d\x97\x2f\x1b\xe8\xab\x2f\x5e\x7d\x21\x06\x61\x23\x32\x01\x53\x6c\x42\xf6\xff\xff\xfd\x17\xbf\xa2\x5b\x54\x45\x65\x52\xd4\xeb\x2f\x58\xc5\x49\x0b\xfc\xf2\x0b\x8d\xd6\x17\x17\x32\x21\xf9\xc7\x29\xaf\x71\x13\x26\xce\x9a\x79\x7d\xb9\x5a\xad\x36\x05\xda\x63\x77\x5b\x62\xf4\xce\x4d\xb2\x66\x36\xb5\x46\xb7\x79\x12\x5f\xea\x66\xce\xd4\xce\x3b\x88\xe1\xb8\x74\x1a\xe5\x12\xdb\x6a\xa2\xe6\xa4\x6e\x5c\x1e\x5c\xbf\x09\xaa\x47\x74\xef\xde\x25\x71\x7d\x20\x53\x38\x41\xa2\x87\x70\x72\x98\x4e\x8a\x73\x5e\x16\x07\x94\x55\xeb\xe9\xe6\x2e\x89\xf3\xbb\x6a\x3d\xa5\x20\x91\x2a\xe9\x16\x23\xea\x65\xe8\x76\x8b\x4a\x79\x3a\xe4\x6d\xeb\xec\xad\x17\xa1\x12\xd7\x13\x2f\x2e\xf3\xe2\x54\xbc\x15\xca\xb8\xb9\xd7\x79\xe1\x42\xe6\x74\xf1\x52\xb4\xc5\x29\x20\x1e\xdf\xf7\x2f\x9e\x34\x64\xb4\x11\x22\x92\x21\x98\x4e\x1d\x4f\xf8\xaf\x83\x3e\x4f\xfb\x72\xb7\xdb\x69\x75\x5c\x4a\x1d\xc7\x5d\x65\xa1\xe8\x00\x70\x16\xc7\xb1\x40\xc5\xb4\xa0\xdb\xa7\x0f\xc5\x21\x89\xf2\xac\x72\x0e\x28\xdd\xa5\x49\xb6\xaf\xc8\xca\x8d\x2f\xc5\xd6\x6f\xde\x3c\xa0\xac\x3a\x24\x5e\x75\x8a\x50\x72\x38\xe5\x64\x1c\x1f\xf3\x18\xa5\xd5\x9b\x70\xf1\x26\x5c\x2c\x67\x6f\x62\x7c\xcc\xe9\x8a\xed\x4d\x47\xd1\x6d\x29\xba\x25\xcd\xf4\x7a\x38\xaf\x5f\xbd\x5f\xf2\xff\x4f\xbb\xdc\xc3\xc7\x2d\x8e\x63\x1c\xbb\xcd\xaa\xb1\x71\xd4\xc2\x02\xf3\x69\x9b\x05\x97\x99\xef\xb1\x2d\xa9\xa9\xf7\xd6\x52\x5d\x77\x0d\xd5\xe5\x09\xbf\x57\x11\x56\xb7\xfb\xb6\xb1\xea\x76\xff\xd5\xab\x8b\xd7\xe2\x03\x53\xfc\x66\xaa\x1e\x14\xf7\x1b\x70\x79\xd5\x6b\xdf\xfd\x1f\x32\xc4\xb9\x58\xd0\x06\x06\x5a\xef\x98\xe7\xf5\xa1\x89\x75\x28\xab\x13\x94\x26\xa8\xc2\x31\x9d\x8f\xe4\xd5\xbd\x8a\xb3\x2f\xd1\x43\x15\xa1\x14\x0b\xfd\x71\x49\x9c\x4b\xaa\x77\x5d\x04\x63\xfe\xf8\xef\xbe\x1f\xa2\x2f\x44\xd4\x22\x3d\x55\x20\xda\x56\x42\xc3\xa7\x92\x61\x4d\xe4\xd2\x5c\xaf\x1c\xfa\x28\x92\x2a\x1f\x93\x0c\x6a\x24\x0c\x83\x50\xc2\x8b\xd2\xfc\x14\x03\x78\x0b\x3f\x90\x99\xc9\x6e\x71\x9a\x17\x18\x40\x5d\xfa\x2b\xb9\x7b\x38\x8b\x92\x14\x44\xdc\x49\x88\xfb\x14\x55\x00\x8f\xd8\x57\xda\x3e\x9e\xaa\x24\x02\xf1\xe4\xbe\xd0\x29\x1a\x88\x38\x95\x10\x0f\x18\x95\x35\x88\x37\x97\x09\xd6\xa8\x04\xd1\x16\x1a\x9a\x8b\x8f\x45\xfd\x00\x22\x2f\x25\xe4\x53\x85\x61\x9a\x37\x12\xda\x2e\x49\x8f\x20\x9a\x2c\xeb\xfa\xe0\xa6\xa8\xdc\x03\x6a\xc1\x7e\xe0\x2b\xa8\x20\x52\xa0\xd1\x4b\x2a\x50\x36\x8a\xe1\xe4\x80\xa5\x63\x3f\x90\x05\x5d\xe2\x63\x7e\x0b\x33\x37\x93\x10\x7f\xcb\xf3\xa3\x9b\x64\x20\xe6\x5c\xc7\xcc\x4f\x30\x8b\xb2\x5e\xf2\xdd\x0e\xc4\x92\x15\x52\x25\xfb\x0c\x01\xe6\x8a\xfd\x40\x56\x49\x94\xef\x41\x2c\x45\x23\x25\xaa\x40\x49\x87\xb2\x3a\x0e\xf9\x11\x14\x4c\x18\xa8\x76\x00\xa3\xc9\xda\xa8\x13\x03\x35\x45\x1f\x39\x02\x06\x3b\xf6\x43\x59\x1b\x71\x7e\x97\xa5\x39\x8a\x5d\x94\x82\x72\x0e\xe7\x20\x3a\x88\x2a\xab\xe4\x54\x18\x11\x65\xad\x24\xd9\x36\xbf\x07\xf1\x6e\x14\x5f\x8a\x1e\xdc\x28\x29\x23\x83\x98\x56\x8a\x3d\x16\x18\x81\x5d\x9a\xfa\x0a\xe2\xae\xc4\xb0\x1e\xa7\xb2\x82\x9a\xe1\x62\x92\xd3\x54\x56\x52\x13\xc8\x40\x34\x59\x49\xbb\x14\x81\x86\x36\x9d\xa9\x4e\x2c\x2e\x0e\x79\x86\x41\x17\x3a\x95\x55\x74\x9b\xa7\xa7\x23\x36\x8d\x88\xe9\x02\x42\x6e\xd4\x0a\x62\x2f\x21\xec\x53\x01\xe2\xca\xda\xfa\x47\x19\xe5\x31\xa8\xa8\xa9\xac\xa8\x2d\x32\x62\xce\x14\xb7\x06\x0b\x6b\x16\xa8\x58\xa0\x98\x66\xb2\x86\xb6\x39\xec\xd6\x66\x53\x0d\xed\x88\x4a\x18\x55\xd6\x12\x59\xdf\x82\x78\xb2\x82\x22\x74\xc4\x25\x02\x11\x65\xe5\x90\x94\x1c\x84\xb6\x54\x58\x4c\xc1\x61\x36\x93\x15\x42\x73\xb9\x20\xa2\xe2\xd6\x9a\xf5\x2f\x9b\x3c\x01\xd8\x73\x5f\xc7\xa6\x2b\x40\x08\x59\xd6\x0d\xc9\xda\xba\x29\xde\xc1\x94\x43\x00\x39\xc2\x59\x0d\x87\xd1\xf9\x14\x40\x2f\x8d\x6c\xcf\x00\xec\x5f\x4f\x55\x9d\xec\xc0\x58\x3e\x9f\x6b\x63\x1f\x44\x5b\x28\xbe\x2c\xc6\x59\x6d\xee\xa1\xea\xf9\x08\xb6\x99\x67\x65\xa2\x80\x22\xdc\x78\x7f\x97\x7c\x9b\x00\x2b\x28\xd3\xb3\x24\xaa\x4f\x25\x38\xb4\x16\xb2\x16\x8f\xa8\x70\x1b\x33\x87\x25\xbd\x50\x14\x43\xbf\xd9\x40\x88\x53\x25\x54\xc1\x06\xbc\x90\x75\x81\xe3\x04\x46\x53\xa6\x68\x07\x64\xe8\x8b\xac\x03\x92\x6a\x05\xf1\x64\xe9\x9b\xe6\x2b\x8b\x1b\x65\xca\x87\x0b\xb7\x59\xe5\xdf\xa1\x12\x1c\x67\x8b\x95\xa2\xa5\xaa\xb6\xe2\x2f\x7d\xc5\xff\x59\x50\x03\x2d\x02\x82\x68\xb2\x7e\x0a\x74\xaa\xc0\x9e\x2d\xa7\x4a\xcf\x72\xd0\x93\x2f\x67\x8a\x1b\x2a\x8d\xfc\xcd\xf5\xae\xdb\xd0\xd5\xc9\x34\x2e\xac\xe8\xb2\xbe\xf0\xaf\x38\x02\xed\x64\x79\xa3\xea\xff\xb6\xcc\xcd\x6e\x66\xb9\x02\xd1\x8d\xa3\xf0\xc6\xd7\x96\x74\x64\x26\x09\xe2\x06\xfa\xd2\xcc\x8c\x1c\x02\x33\x68\x33\xf6\x54\x99\x94\x9b\x31\x65\xfd\xfd\xe3\x84\xab\x66\xf9\x6d\xc6\x9f\x2b\x5e\x69\x97\x9b\x71\x15\x15\x46\x25\xc6\x59\x75\xc8\x61\xc9\x2d\xa1\x0e\x9a\xa7\x70\x37\x37\x6a\x17\x2d\xb8\xea\x2c\x22\xb3\x20\xaf\x64\x15\xa2\xb2\xcc\xef\x8c\xf6\xb1\x0a\x00\x64\xa3\x75\xac\x42\x00\x1b\x9e\x21\xad\xa6\x00\xaa\x69\xea\xb5\x9a\xe9\xce\xcf\x34\xf9\x5c\xcd\x15\x39\x93\x4f\xeb\xbb\x53\x0a\xae\x75\x56\x0b\x08\x9b\x7c\xa3\x05\xd1\x95\x51\x78\x1f\xa5\xe8\x88\x6c\x06\x15\x28\x8b\xfa\x7d\x02\x0a\x3a\x50\xd6\xf4\x29\x46\xd0\x94\x35\x50\x56\xf4\xbb\x04\x8c\x02\x81\xaf\x04\x95\x07\x4c\x32\x87\x20\xea\x5c\x43\x8d\xd2\x1c\xf4\x99\x81\x92\x00\xb8\x43\x65\x96\x64\x7b\x73\xd7\x97\xaa\xc7\xce\x60\xb2\x8a\xcf\x42\x29\xce\x62\x30\x05\x11\x28\x79\x80\x12\x65\x71\x0e\x25\x0c\x02\x25\x0b\x10\xe5\xc7\x23\x06\x03\x70\xa0\xa4\x02\x8e\x68\x9f\x61\x18\x31\x04\x7d\x25\x68\xdf\x81\x92\x11\xe0\xc8\x06\x0b\x0f\x94\xbc\x40\x89\xeb\x3b\x6c\xe0\x42\x9d\x08\xe4\x45\xd1\x28\x21\x82\x73\x3b\x41\xa0\xce\xa3\x53\x92\xd9\x37\xa9\x58\xc9\x12\x30\x74\x93\xf1\x28\xa9\x02\x36\x7c\xf8\xc6\x04\xb0\x86\xba\x32\x25\x35\x0e\x79\x99\xfc\x96\x67\x35\x5c\x47\x4d\x21\xc4\x50\x84\x0c\x94\x0c\xc2\xf6\x94\xa6\x87\xbc\x04\xd9\x56\xb2\x08\x5b\x0c\x8e\xf6\x40\xc9\x22\x44\x4d\xb7\x76\x49\x84\x6a\x50\x72\x4a\x32\xa1\x3e\x9c\x8e\xdb\xca\x60\x1d\x4a\x26\x81\xe1\x9a\x8c\x43\x49\x26\x1c\x50\x16\x1b\x7d\x70\xa0\x24\x14\x08\xb2\xc1\xbb\x07\x4a\x52\x81\xe0\x1a\x18\x5e\xe9\x98\x26\x76\x95\x9c\x02\x8d\x44\x3d\xa1\x23\x50\xd2\x0b\x52\x25\x13\xfb\x4a\x9e\x41\xaa\x03\x77\x43\x49\x39\x48\x35\x8c\xdd\x91\xf5\xba\x4f\xf3\x2d\xa8\x7f\x25\xf5\x70\x57\xe2\x0c\xcc\xca\x06\x4a\xda\xa1\x46\xd5\x3b\x68\x91\x1e\x28\x09\x87\x5d\x92\xc2\x8b\xbf\x40\xc9\x36\x6c\xcb\x04\xef\x22\x04\x8f\x6f\x25\xe1\xd0\xc4\x45\x3a\x6f\x81\x90\x95\x9c\x43\x8c\xaa\xc3\x36\x87\x27\xa8\x81\x92\x79\x28\x50\x81\xcb\x28\x4d\x40\x35\x28\xe9\x07\x92\x97\x36\x66\x92\x03\x25\x0b\x91\x26\x19\xb4\xa2\x09\xd4\x0c\xc4\x21\x87\xa3\x8d\x92\x81\x28\x4e\xd5\xa1\x00\x53\xb0\x81\x92\x82\x38\x55\x70\xc7\x65\xe9\xef\xb7\x70\x97\x65\xb9\x57\x39\xec\xad\x95\x84\x42\x83\xe6\x6e\x1f\x5c\x94\x16\x07\xb4\x85\x03\x82\x92\x56\x50\xab\x18\xe6\x49\x81\x92\x60\xe0\xd5\xe8\xb7\x57\x08\x7f\x6a\xc6\x37\xb6\x31\x83\x59\xab\xeb\x32\xd9\x9e\x6a\x30\x85\x17\x28\xc9\x06\xbd\x92\xb1\x35\x45\x5d\x19\x59\xfc\x62\x50\x69\x73\x75\x22\x57\xa0\x0c\x46\x54\x93\xe1\xf4\x43\xb8\xd1\x5b\x28\x59\x87\x16\x1f\xf6\x47\x4a\xe6\x21\xcd\xf7\xf0\xd7\x80\x60\x11\xa8\xb9\x52\x30\x4b\x1b\x2c\xd4\xd4\xeb\xde\xf0\xd1\x20\x50\xd2\x13\x19\xbe\x73\xef\x92\x2c\xce\xef\x40\x64\x75\x7a\x12\xe5\xb0\x17\x50\xd3\x14\x08\x4c\x2b\x04\x4a\x96\xc2\x34\xbd\x50\x92\x14\x0d\x35\xb8\x55\x25\xbb\x47\xb6\x0a\x80\x88\x2b\x55\xed\x06\x44\x25\x2f\x51\x61\xd8\x3a\x96\xaa\x5a\xf2\xa2\x78\x70\x63\xf0\x7b\x28\x0e\x94\xd4\x04\xc3\x36\xf6\x6a\xa9\xe6\xc7\x09\xba\xf1\xdb\x52\xa0\xa6\x2a\x3a\xf2\x20\xf6\x1c\xc2\x36\x69\x42\xc9\x56\x44\x25\x8e\x93\xba\x99\x73\xc2\x9c\xcb\x7a\xa3\x1b\x21\x61\xb7\xa2\xe6\x2b\x4e\x75\x8a\x4b\x30\x0c\x28\xa9\x0a\xba\x39\x07\x42\xbc\xd1\xa6\xfe\x45\x89\xab\x0a\x16\xb2\x92\xa4\xc0\xa8\x34\x06\x0e\x25\x45\x41\xf0\x4c\xbe\x48\x49\x50\xd4\xf9\x9d\x81\x57\xc5\x43\xd6\xa8\x06\x9d\xa2\x92\x96\xa8\x62\x63\xde\x33\x50\xb2\x12\x07\x1b\xaa\x32\xbe\x4e\x5b\xb2\x11\x0b\xe6\x40\xc9\x04\x92\x5d\x3e\x55\x8d\x4b\x03\x69\x35\xde\x9d\xc8\x8c\x31\xdd\x82\xba\x5d\xa9\x61\xaf\xc1\x9e\xbb\x01\x88\xab\xc6\xbb\x06\x77\x61\xc0\x55\x83\x5c\x83\xbb\x34\xe0\x2a\x73\x43\x7e\x1c\xc1\x35\x7c\xf2\x08\x56\xaa\x53\xdc\x27\x55\x4d\xf7\xc9\x99\xeb\x28\x9f\x3f\xd2\xfc\x14\xdb\x3e\x24\x06\x4a\xc6\x81\x56\x30\x7e\x4e\x0c\x56\x37\xca\xc8\xc3\xd8\x8d\xf2\x2c\x31\x8c\xbe\x95\xfa\x11\x17\x63\x37\xc6\x51\x12\x9f\x72\x68\x1b\x05\x0e\x7d\x65\x6c\x41\x4c\x84\x4a\xca\xa3\xf1\x40\xa6\x0f\xba\xa1\x92\xf7\x68\xfc\x8f\x19\x57\x99\x08\xe2\x5b\x9c\xc2\x81\x35\x54\x12\x20\x8d\x32\x41\x34\x65\x2e\x88\x2a\x70\x6d\x17\x2a\x89\x0f\x94\x62\x30\x6c\x84\x4a\x7a\x02\xff\xe3\x44\x8e\x89\x40\xb2\x0f\x95\x0c\xc5\x3b\xb2\x73\x19\x40\x0b\xd4\x04\x26\xe8\xa1\xd5\x0d\x2e\x05\x02\xe7\x27\xa1\x92\x97\xd8\x26\xd5\x01\x4c\x7c\x87\x4a\x46\xe2\x5d\x66\x58\xb9\x85\x4a\x42\x62\x8b\xb6\x0f\xee\x2e\x2f\x8f\xa7\x14\xfa\xae\x17\x2a\xf9\x88\x1a\xcc\xca\x84\x8b\x9d\xbc\x77\x68\x9b\xa2\xe8\x9d\x69\xed\x11\x2a\x69\x88\x2d\xe8\xea\x43\x25\xf5\x80\x8a\x02\x32\xb3\xdd\xcd\x4e\xde\xae\x83\x4b\x78\x29\x15\x2a\x09\x87\x43\x7e\x2a\x0d\x5b\x7b\xc2\x69\x20\xef\x71\x4a\xd1\x11\x14\xba\x92\x71\x88\x4f\x45\x6a\xca\x37\x84\x4a\xbe\xa1\x48\xf6\xfb\x07\x77\x8b\xc0\xc5\x51\xa8\x24\x1c\xaa\x28\xa9\xaa\xbc\x04\x87\xb8\x92\x6d\xd8\x26\x75\x94\x83\x93\xd2\x50\x49\x35\x6c\x6b\xe8\x8b\xaa\x8a\x75\xbf\x05\xad\x48\xc1\x7a\x80\x8c\xdc\xf7\x91\xdc\x8d\x5f\xa1\x51\xad\x61\x95\xa7\x2d\xa4\xe8\xd0\xdf\xc6\x2a\xde\x00\x2c\xb2\x03\x0e\xea\x81\x92\xf6\x48\x22\xec\xa6\x79\x9a\x82\x7e\x47\xc9\x76\xb4\xb8\x6e\xdd\x78\x20\xd0\x7a\x95\x64\x07\x8e\x4f\x11\xdd\x92\x0d\xe1\x2a\x9f\x47\xc8\x19\x31\x7b\x92\x2d\x54\xd2\x1c\xac\x8e\x25\x95\x17\x2a\x09\x8f\x23\xce\x4e\xee\x01\x1d\xb7\xa7\x72\x0f\x7b\x3c\x25\xf1\x41\xb6\x57\x9a\x17\x1d\xa1\x92\xff\xc8\xa1\xcd\x75\x38\x54\x92\x1f\xfb\x12\xc1\xc6\xaa\x24\x3e\xaa\x53\x46\x06\x2b\x38\xd9\x09\xd5\xcd\x16\xfc\x88\x1e\x88\x1b\xe8\xb8\x74\xf7\x33\x84\x1c\xea\xc8\xc2\x26\x7e\xa8\x86\xa2\xcb\xed\xaf\x38\xaa\xd9\x27\x7b\xf8\x9b\x65\xa8\x64\x42\xa4\x2a\xec\x28\x18\x54\x6b\x6e\xae\x65\x37\x1d\x25\x4f\x22\xd5\x34\xe4\xee\x42\x65\xdf\x86\x54\xc7\x66\x74\x4a\xb6\x45\xaa\x67\x4a\x2e\x86\xea\xa6\x8e\x32\x41\xd9\x3e\xc5\xe6\x0a\xea\xbe\x0e\x5e\xc1\xd4\x1b\x25\x07\xd3\xe2\x9b\xa5\xad\xa4\x5f\xda\x1a\x06\x95\xce\xd5\xc9\x69\x56\xe5\xb0\x1b\x52\x73\x2e\xa7\x02\x97\xec\x1c\x05\x84\x3d\x57\x57\x00\x16\xdc\x85\x3e\xde\x8d\x02\x59\xea\xb8\x66\x69\xdf\xe8\xc8\x86\xfc\x4a\xa8\xe4\x57\x08\x2e\x3c\x05\x5c\xf8\x5f\x5c\xbe\x7e\xe2\xf3\x64\x17\xe5\xbc\xce\x13\x53\xef\x0e\x12\xd3\x93\x8b\x7e\xd1\x1d\xf5\xaa\x51\xe1\x1e\x92\xfd\x21\x25\x6b\x12\xfd\x18\x2c\x39\x30\x2c\x6e\x17\x3f\xe0\xf4\x16\x37\xe3\xc8\xc9\xf0\x09\x4f\xfe\x33\xff\x73\xf2\x4d\x99\xa0\x74\x22\x9c\x51\x16\x5a\x9c\x15\xf7\xf2\x86\x71\x6f\x16\xde\xcc\x97\xc1\x6c\xca\xce\x41\x7e\x39\x9d\x4e\x37\xe0\x39\x0f\xf9\x90\xa5\x7a\xb6\x52\xe4\x8c\x9f\xac\xec\xda\xe5\x25\x62\xd3\xfc\xc4\x25\x3a\xb7\x2d\x2f\xd1\x76\xb9\x51\x8f\x24\xd1\x33\xc2\x6b\x72\x2e\xb1\x3d\x03\xcc\xaa\x84\xd3\x79\xb8\x8c\xb4\x2a\xc2\x29\x26\x5a\xaf\x3d\x33\x3c\x2f\xee\x1d\x74\xaa\x73\xa7\xdb\x27\x1f\x9d\x2a\xb7\x24\x5f\xd8\x1a\x9a\x1b\x86\xe9\xe6\xbb\x5d\x85\xeb\xb5\x1b\x16\xf7\xca\x29\x59\x9f\x1c\x06\x52\x4e\xe7\x1e\x93\x38\x4e\xf1\xc5\x8b\x50\x99\x9f\x2a\x9c\xd2\x33\x87\x6f\xbd\xa4\xc6\xc7\xb7\xe8\x6d\x72\xdc\x4f\x60\x18\x81\x24\xc7\xbd\x5b\xe2\xaa\xc8\xb3\x2a\xb9\xc5\x13\x8f\x7c\x30\xca\x50\x92\x3a\xac\x6a\x5b\xd0\xfc\x29\x9f\xe9\xde\xc8\xc7\x92\x36\xe2\x61\x45\x4a\xb8\x51\x24\x8e\xf9\xa1\x9f\x12\xc5\xc9\xa9\x5a\x2f\x8a\x7b\x0a\x6e\x49\xc3\x07\xc0\xcd\xd4\xdb\xc3\x97\x16\xa3\x02\x2d\x49\x3f\x19\xf8\x65\x1c\xc7\x1b\x99\xbf\x99\x38\x36\x9a\x71\x40\x8f\x55\xa0\x34\x75\xbc\xb0\x72\x30\xaa\xb0\x9b\x64\x6e\x7e\xaa\x37\x6e\xde\x87\x61\x07\x53\x39\xd0\x8f\x45\x8a\x94\xe6\xfe\x8b\xcb\xa1\x64\x9a\x27\xce\x3b\x6c\x06\x2d\xfb\x9b\xb9\x7f\x52\xc4\x0f\x31\x6e\xba\xf3\x59\x62\x07\x31\xc6\x17\xaf\x2a\xdd\x3c\x4b\x1f\xba\x43\x22\x68\x5b\xe5\xe9\xa9\xc6\x1b\x26\xe1\xe2\x9e\x0b\xb8\xf9\xd9\x9d\x90\x64\x96\xe7\x36\xa5\xca\x11\xee\x0d\xf9\x08\x53\xe2\xa8\x7e\xe9\x4f\xc8\xbf\x57\xdd\x81\x4a\xde\x22\x35\x73\xd4\xcc\x93\xd9\x61\x7a\x00\x42\x47\x4a\xcb\x1b\xbd\xcd\x82\x71\x46\xf4\x2d\xea\xbe\x3d\x4b\xad\x9e\x94\xa6\xfc\x10\xeb\xfb\xb9\xcc\xd3\xf6\x00\xf4\x59\x39\xc1\xec\x1d\x82\x89\x77\x08\x27\xde\x61\x3a\xf1\x0e\xb3\x89\x77\x98\x4f\xbc\xc3\x62\x72\x08\x26\xf4\x38\xdd\x61\x36\x39\xcc\x27\x87\x85\xd9\xb5\xb0\x43\x30\x73\xf5\x10\x8c\x17\x28\x87\xba\xbd\x43\xe0\x78\x64\xd3\xc7\xa4\xf9\xc9\x7f\x85\x5d\x61\xd8\x16\x4e\xbb\xc2\x69\x5b\x38\xeb\x0a\x67\x6d\xe1\xbc\x2b\x9c\xb7\x85\x8b\xae\x70\xc1\x0a\xbb\xc6\xdb\xb6\xbb\xa6\xdb\x96\xbb\x86\xdb\x76\xbb\x66\xdb\x56\xbb\x46\xdb\x36\xbb\x26\x79\x8b\x67\xfb\x11\x21\x36\x10\x97\xcb\xa5\xa4\x04\x2e\xf8\x1e\x63\x6f\x82\xd6\x63\x05\x7a\xad\x44\x84\xd8\xb9\x98\xbf\xb8\x48\x66\xc3\xad\x45\xe0\x3e\x30\x72\xff\x38\x7d\x3e\x4a\x2d\xfc\xb2\x07\x22\xfb\x43\x20\x14\x4e\x89\x4b\x6e\x74\x10\x8a\xa5\x94\xe3\x69\xa3\x19\xe1\x26\x8a\x19\xed\xc7\xe4\x30\x13\x27\x14\x37\xa4\x74\x3e\x39\xcc\xcf\x72\xd0\xbf\x10\x19\x2d\xc4\xd2\x26\xb0\x15\x6d\x4c\x73\x7c\x87\xca\x26\xc5\x28\x3e\x03\xfe\x4d\xa8\xb9\xe0\x7f\x0a\xf7\xec\x2a\xfe\xff\x42\xcf\x41\xbf\x3c\x26\x19\x8b\x1e\xcb\xc5\x4d\x71\xff\xea\x4c\xe9\x0b\x1d\x09\x8a\xfb\xcb\x85\x49\x4a\xbb\x3b\xa3\x11\xd3\x11\x95\xef\x26\xe4\xd6\x8d\xf6\xe0\x79\x88\x8f\x50\x64\x89\x76\x37\x78\x7a\xf1\xc8\x6c\xa0\x99\xb8\xd2\xd3\xcd\x34\x3e\x37\x7f\x33\x10\x99\xa7\x8a\x30\x52\xc0\x80\x74\x0b\xb6\x08\xa5\x25\x0c\xcc\x36\x51\x8b\x70\x56\xc4\x10\xb2\xfc\xae\x44\xc5\xf9\xee\x90\xd4\x98\x1c\x49\xc7\x6b\x5a\xc4\xf9\xca\xef\x70\x19\xa1\x0a\xab\x77\x48\xb4\x00\x86\x78\x2a\x0a\x18\xb1\x05\x70\x8e\x51\x41\xb6\xbb\xff\xa6\x61\x76\x10\x86\x7a\x3c\xd5\x38\x3e\x8b\xe3\x9f\x14\x17\x65\x42\xae\x8a\x91\xe6\x61\x17\x24\x01\xf9\xfc\x4b\x2e\x94\x27\x63\x37\x0b\x7f\xe5\x33\x9a\xd5\x29\x8a\x70\x55\xb5\x34\xa3\xe5\x62\x1a\x73\x9a\x0c\x28\xd3\xe4\x85\x32\xcd\xed\x7c\x16\x46\x8c\x66\x92\xed\xf2\x96\x60\xb0\xf4\x6f\x76\x9c\x60\x03\x91\xa9\x91\x12\x99\xd4\x6c\x1e\x2e\x56\x8c\x14\xdb\xda\xc6\x61\x37\x68\x11\x4f\xb7\x9c\x1a\x03\xca\x04\x79\xa1\x44\x73\xb1\x98\x07\x2d\x7b\x31\xca\xf6\x1d\x08\xad\x66\xb3\x59\xc8\x49\x52\x98\x4c\x91\x95\x49\x04\x6f\x66\xd3\xf9\x74\x76\xf1\xb6\x7b\x55\x2b\x64\xde\xa4\xd9\x7c\xab\xab\xae\x42\xdb\x88\x50\x44\xdb\xd0\xab\x73\x95\x6d\xf7\xad\xc2\x74\xa4\x78\xb7\xf3\xe3\x1b\xda\x86\xaa\x39\xa1\xc8\xd4\x46\x14\xe0\x70\x3b\x25\x6d\x10\x05\x02\x0d\xac\x70\xbc\x63\x9d\x90\x34\xc9\xff\x36\x91\x46\xbb\x78\xd5\xcc\xab\xb6\xfb\x56\xa1\x46\xb7\x80\x04\x2c\xb1\x01\x59\xaf\x40\xf5\x25\x8e\xb6\x73\xd2\x06\x53\x30\x80\x13\xc6\x38\xc6\xb4\x09\x45\xd3\x5d\x89\xa9\x01\x3c\xdb\xae\xb6\xab\x8b\x47\xee\x08\xa0\x5f\x3d\xb9\xa7\xe3\x0e\x78\xd5\xc6\xb1\xf5\xcc\x2f\xee\x1d\xdf\x11\xa6\x9c\xe2\x95\x47\xc2\x64\x33\x4f\x27\xa7\x54\x8c\x86\x3e\x14\x0a\xf3\xd4\xc9\xd3\x49\x9e\x3a\xa7\x06\xdd\x21\x95\x9c\xae\x1e\x43\xf5\x2f\x1e\x39\x0f\x76\xca\xc8\x49\xe4\xf6\xee\x0e\x9a\x1e\x68\x9c\x7f\xd5\x1d\x52\xce\x30\xc3\xa6\xcb\x08\x15\x97\x51\x26\x7f\xb9\x73\xb2\x72\x30\x57\x7e\x9b\x26\xf0\xaa\x84\x13\xa5\x39\x87\x79\x37\x59\xa6\x84\xe7\xc5\xfd\x25\xb6\xf6\xbe\x11\xe0\x25\x8e\x27\xb1\x7c\x99\x4d\xb7\x74\xb9\xc4\xb5\x7e\x63\x54\x1b\x19\x69\x67\xcc\x51\x2e\x4e\x85\x9c\x9a\xd3\x90\x4a\x73\x54\x93\x28\xc4\xe7\xfa\x0b\x1f\x9c\xcc\x63\x54\x52\x34\x35\x40\xd1\x82\xb6\x02\x4e\xd3\xa4\xa8\x92\x6a\x03\x85\x1a\xa5\x79\x99\xed\xe0\xa6\xe9\x3b\xbd\xb7\x23\x46\x35\x72\xf3\x32\xd9\x27\x19\x4a\x5d\x7a\x8b\xc7\x44\xbc\x56\x8b\xcd\xda\x0f\x38\x2d\x00\x7b\xa3\x57\x6c\x39\x34\x96\x24\x59\x42\x0e\x99\x57\x47\x21\x84\xaf\xfc\x17\x1b\x63\x00\xeb\x6e\xf4\x68\x63\x7b\x63\x95\x8e\x30\xed\x24\x33\x13\x75\x02\xb2\xf4\xe6\x9d\xf9\x73\x85\x8b\xc6\xdf\x11\x76\xf2\x74\x9d\xa2\xaa\x76\xa3\x43\x92\xc6\x13\x01\x50\x18\xca\x4f\x62\x05\x6d\x20\x08\x88\x6c\xd2\x22\x94\xb0\xeb\xd9\x84\x12\x3a\xa3\x91\xd7\xeb\xd2\xdd\x60\x3d\xd9\x98\x46\xb0\x5a\x93\x2c\x3b\xa5\xb7\x0c\x00\xc0\xad\xee\x5f\xfd\x3d\xf4\x83\x99\xf3\x77\xdf\xff\xc6\xff\xea\xe2\x75\xe8\x6e\x89\x6f\x71\x59\x89\x14\xbc\xe2\x94\xa6\x6c\xce\x24\x8f\xba\x40\x1b\x76\xbe\x6e\xb4\x7c\x39\xcd\xc7\xa9\xa0\x25\x49\x81\x3e\xc4\x86\xd2\x5f\x08\x43\xee\x38\x84\x61\x10\x99\xd0\x2f\xa3\x58\x45\x1c\x93\x84\x45\x1c\x58\xd8\xa0\x84\x79\x9b\x34\xdf\x68\xe9\x99\x19\x41\x24\x60\xed\x97\x0d\x45\x6a\xc5\xd6\x2b\xf9\x3a\x9e\xaf\x88\xed\x38\xc4\x8e\xbe\xba\xa0\x38\x2e\x9b\xb9\x83\x71\xd9\x20\xde\x5f\x61\x70\xb7\xf6\x2b\xe0\xfe\x8c\xb3\x34\x9f\xfc\x39\xcf\x50\x94\x4f\xbe\x23\xd9\x71\x54\x4d\xa2\xfc\x54\x26\xb8\x74\x32\x7c\xd7\x5d\x0d\x47\x28\xb5\xfe\x24\x2c\xee\x9d\x99\xe4\x3d\x1a\x8f\xc4\xa7\x26\xcb\x70\x3e\xc3\xd0\x52\x62\xb5\x0b\x77\x33\x3d\x23\x75\x79\xb7\x8d\x87\x91\x36\x4d\xd7\xa6\x0a\xd1\xa9\x90\xe6\x12\xae\x6c\x4a\xb2\x0a\xd7\x8e\xef\xb8\x01\x09\xf7\xe5\x7e\x8b\x58\x7a\xc7\x0b\xe7\xaf\x36\x83\x31\x1b\x86\x1d\x91\x69\xf1\x3a\x43\x92\xd0\x53\xaf\x42\x35\xdc\x2c\xa5\xde\x27\x45\x2e\xf1\x93\xfd\x1a\x6f\x62\x45\xbc\xb3\xb2\xb0\x14\x9b\x9d\x0e\x4a\x42\xdf\xe5\x65\x4c\xef\x4c\x5a\xb3\x9b\x93\xd2\x94\x16\x36\x31\x8e\x95\x35\x7f\x43\xfa\x9b\x37\xff\x80\x3c\x63\x14\x45\x80\x56\x8b\x12\x3b\x92\xd5\xf8\x40\xee\x5a\x4a\x29\x49\x51\xb7\x28\x31\xe1\x49\x67\x44\x48\xe0\x2b\xcd\xfa\x17\xaf\xa9\x56\x45\x65\x9e\xa6\xe4\x4e\xa6\x23\xba\xe7\x02\x99\xce\xc4\xb9\x81\xfb\xb0\xa6\x68\x17\xaf\x19\x7e\x28\x11\xae\xe6\x33\xba\xe2\xa0\xd3\x01\xc3\x11\xd2\x76\x14\x85\xe4\xe8\x8c\x33\x98\xae\x29\x56\x3e\x27\xb3\x06\x0d\x7f\xb5\x0a\x41\xfc\xd5\x12\xc6\x0f\x42\xdf\x07\x2b\x04\x01\xad\xd1\x01\xdc\x5d\x7a\x4a\xe2\x27\xeb\xaa\x57\xe6\x77\x67\x09\xcf\x15\xab\xd2\x19\x69\x53\xd2\xb0\x90\xba\xe9\xde\x0d\x26\xed\x2f\xbf\xfb\x29\x94\x86\xed\xcf\xee\xd7\xb4\xfd\x35\x6b\x7f\xcd\xdb\x5f\x8b\xf6\xd7\xb2\xfd\x75\xd3\xfe\x5a\xd1\x5f\xc7\x98\x37\xdd\xfc\xf2\xbb\x9f\x42\x69\xd8\xfe\xec\x7e\x4d\xdb\x5f\xb3\xf6\xd7\xbc\xfd\xb5\x68\x7f\x2d\xdb\x5f\x37\xed\x2f\xd6\x74\x75\xe4\x4d\x37\xbf\xfc\xee\xa7\x50\x1a\xb6\x3f\xbb\x5f\xd3\xf6\xd7\xac\xfd\x35\x6f\x7f\x2d\xda\x5f\xcb\xf6\xd7\x4d\xfb\x8b\x35\x7d\x5f\xf1\xa6\x9b\x5f\x7e\xf7\x53\x28\x0d\xdb\x9f\xdd\xaf\x69\xfb\x6b\xd6\xfe\x9a\xb7\xbf\x16\xed\xaf\x65\xfb\xeb\xa6\xfd\xb5\x02\x2e\x6c\x6a\x6c\x55\xcf\xc2\x5b\xcd\xef\xf2\x11\x3b\xd0\xad\x2c\x3a\x2e\xc2\x73\xf7\xc9\xa6\x2b\x0d\xf8\xd0\x0c\xbc\x05\xfd\xbf\xa5\x00\xf5\x19\xf4\x66\xea\x4d\xd9\xff\x75\xd0\x55\xeb\x05\xba\xb2\x1b\x56\xb6\x58\x00\xe4\x96\x0c\x38\xbf\x01\xa8\x2d\x38\x50\xe0\x6e\xce\xca\x66\x10\x73\x33\x06\x9c\x42\xbc\x4d\x19\x30\x14\x78\x6b\x05\x00\xf1\xc6\xe5\x00\xb1\x46\xe6\x3d\x41\x78\x66\xda\x16\xe5\x47\x41\x01\x03\x81\x42\xa4\x28\x3e\x43\x01\x25\x49\x50\x56\x0c\x43\x14\x27\x01\xdc\x30\x00\x28\x53\x82\xb1\x64\x18\xa0\x60\x09\xc6\x82\x63\xa8\xbc\xcf\x19\x00\x14\x31\xc1\x98\x31\x0c\x50\xce\x04\x63\xca\x30\x42\x95\xf3\x56\x64\x46\xce\xb9\xe4\x8c\x8c\x73\xb9\x51\x6f\xdd\x42\xaa\x43\xa3\x10\x3a\xd6\x64\x7d\x34\x90\x80\x42\x0c\xea\x68\x30\x7c\x8a\x61\xd0\x46\x75\x70\x57\x14\x41\x56\x46\x75\x70\x6f\x68\xb9\x41\x17\xd5\xc1\x5d\x52\x04\x83\x2a\xaa\x83\xbb\x60\x08\x2a\xd7\x73\x5a\x6e\x50\x44\x75\x70\x67\x14\xc1\xa0\x87\xea\xe0\x4e\x29\x42\xa8\xf2\xcc\x05\x65\xe4\x99\xc9\xcb\xc8\x32\x93\x96\xa4\x03\xfa\x2d\xbc\xd1\x82\x94\x47\x10\x95\xc1\x51\x02\x09\x05\xd4\x0a\x47\xf5\x25\x54\x50\x3d\x0c\x75\x25\x61\x8a\x7a\x62\x08\x37\x12\x02\xa8\x30\x86\xb9\x94\x30\x41\xcd\x31\xcc\x85\x8c\xa9\xf7\x75\x2e\x21\x80\xba\x64\x98\x33\x09\x13\x54\x2a\xc3\x9c\x4a\x98\xa1\xde\x53\x45\x05\x96\x9e\xca\x9a\xb0\x74\xd4\x1f\x9a\xd4\xfa\x68\xf3\x03\x2d\xc6\x91\x56\xb4\x18\x47\xd8\x30\xc6\x38\xc2\xaf\x31\xc6\x91\x66\x94\x18\xd7\x30\x61\x8c\x71\x0d\xaf\xc6\x18\xd7\x74\x49\x8d\x71\x4d\x87\x8d\x31\xae\x91\x8b\x31\xc6\x35\xe2\x53\x63\x5c\x23\x5c\x63\x8c\x6b\xba\x6a\x8a\x71\xd5\xd1\x18\xe3\x5a\x90\x39\xc6\xb5\x28\xe6\x18\xc7\x51\xb4\x18\xc7\x01\xe6\x18\xc7\x31\xcc\x31\x8e\x63\x68\x31\x8e\x03\xcc\x31\x8e\x63\x98\x63\x1c\xc7\xd0\x62\x1c\x07\x98\x63\x5c\x2b\x17\x53\x8c\xe3\x08\x7a\x8c\x23\x10\x30\xc6\xb5\x10\x63\x8c\x6b\x31\x8c\x31\x8e\x63\xa8\x31\x8e\x97\x1b\x63\x1c\x47\x30\xc6\x38\x8e\xa0\xc6\x38\x5e\x6e\x8c\x71\x1c\xc1\x18\xe3\x38\x82\x1a\xe3\x78\xb9\x31\xc6\xb5\xe2\x30\xc4\x38\x0e\xd7\x62\x5c\x75\xec\x8d\x71\x02\x4a\x5f\x8c\x13\x50\xfb\x62\x5c\x87\x6a\x88\x71\x1d\x42\x5f\x8c\xeb\x30\xfb\x62\x5c\x87\x69\x88\x71\x1d\x42\x5f\x8c\xeb\x30\xfb\x62\x5c\x87\x69\x88\x71\x1d\x42\x5f\x8c\x13\xe4\x6b\x8f\x71\x1d\xa2\x1a\xe3\x6c\x79\x8c\x8f\xb4\xfe\xd6\x82\x1c\x69\x45\x0b\x72\x84\x0d\x63\x90\x23\xfc\x1a\x83\x1c\x69\x46\x09\x72\x0d\x13\xc6\x20\xd7\xf0\x6a\x0c\x72\x4d\x97\xd4\x20\xd7\x74\xd8\x18\xe4\x1a\xb9\x18\x83\x5c\x23\x3e\x35\xc8\x35\xc2\x35\x06\xb9\xa6\xab\xa6\x20\x77\x8c\x8d\x41\xae\x05\x99\x83\x5c\x8b\x62\x0e\x72\x1c\x45\x0b\x72\x1c\x60\x0e\x72\x1c\xc3\x1c\xe4\x38\x86\x16\xe4\x38\xc0\x1c\xe4\x38\x86\x39\xc8\x71\x0c\x2d\xc8\x71\x80\x39\xc8\xb5\x72\x31\x05\x39\x8e\xa0\x07\x39\x02\x01\x83\x5c\x0b\x31\x06\xb9\x16\xc3\x18\xe4\x38\x86\x1a\xe4\x78\xb9\x31\xc8\x71\x04\x63\x90\xe3\x08\x6a\x90\xe3\xe5\xc6\x20\xc7\x11\x8c\x41\x8e\x23\xa8\x41\x8e\x97\x1b\x83\x5c\x2b\x0e\x43\x90\xe3\x70\x2d\xc8\x1d\xe3\xde\x20\x27\xa0\xf4\x05\x39\x01\xb5\x2f\xc8\x75\xa8\x86\x20\xd7\x21\xf4\x05\xb9\x0e\xb3\x2f\xc8\x75\x98\x86\x20\xd7\x21\xf4\x05\xb9\x0e\xb3\x2f\xc8\x75\x98\x86\x20\xd7\x21\xf4\x05\x39\x41\xbe\xf6\x20\xd7\x21\xf6\x07\x39\x21\xf9\xfe\x91\x12\xdc\x5a\x94\x23\xad\x68\x51\x8e\xb0\x61\x8c\x72\x84\x5f\x63\x94\x23\xcd\x28\x51\xae\x61\xc2\x18\xe5\x1a\x5e\x8d\x51\xae\xe9\x92\x1a\xe5\x9a\x0e\x1b\xa3\x5c\x23\x17\x63\x94\x6b\xc4\xa7\x46\xb9\x46\xb8\xc6\x28\xd7\x74\xd5\x14\xe5\xd2\xbd\x31\xca\xb5\x20\x73\x94\x6b\x51\xcc\x51\x8e\xa3\x68\x51\x8e\x03\xcc\x51\x8e\x63\x98\xa3\x1c\xc7\xd0\xa2\x1c\x07\x98\xa3\x1c\xc7\x30\x47\x39\x8e\xa1\x45\x39\x0e\x30\x47\xb9\x56\x2e\xa6\x28\xc7\x11\xf4\x28\x47\x20\x60\x94\x6b\x21\xc6\x28\xd7\x62\x18\xa3\x1c\xc7\x50\xa3\x1c\x2f\x37\x46\x39\x8e\x60\x8c\x72\x1c\x41\x8d\x72\xbc\xdc\x18\xe5\x38\x82\x31\xca\x71\x04\x35\xca\xf1\x72\x63\x94\x6b\xc5\x61\x88\x72\x1c\xae\x45\xb9\x74\xdf\x1b\xe5\x04\x94\xbe\x28\x27\xa0\xf6\x45\xb9\x0e\xd5\x10\xe5\x3a\x84\xbe\x28\xd7\x61\xf6\x45\xb9\x0e\xd3\x10\xe5\x3a\x84\xbe\x28\xd7\x61\xf6\x45\xb9\x0e\xd3\x10\xe5\x3a\x84\xbe\x28\x27\xc8\xd7\x1e\xe5\x3a\x44\x2d\xca\xb1\x27\x8d\x6c\x6f\x48\xb2\x67\x34\xdb\x4f\xc9\x75\x5e\xac\x6f\x84\x0f\x79\x6c\xc7\x4a\x53\xd4\x6d\xbc\xda\xa8\xdb\xc7\xeb\x03\xb0\xa3\x9c\x34\x2e\x1c\x90\x52\xce\x4b\x01\xbb\x0e\x69\x9d\xb7\xf5\x36\x8f\x1f\xde\xd6\xe5\xdb\xf6\x95\x24\xa1\xe8\xd0\x16\xed\xf2\xbc\x56\xb0\xda\xa2\x0e\xeb\x80\x51\xac\x60\xb5\x45\xdd\x8b\x67\x37\xe6\x8d\x17\xca\x71\xb6\x3a\x2f\x0c\x07\x99\xe2\x38\xbe\x00\x4d\xa8\x8f\x55\x92\xfe\x2a\x3b\x06\x43\x90\x0a\xd3\xcd\x6b\x4e\x6d\xbd\x4b\x4a\xbe\xfd\x4e\xe8\x8f\x1d\xad\x95\x44\x94\xa7\xe4\x3d\xaf\x5e\x72\x76\x3c\x59\xb2\x32\xcc\x44\xb2\x1f\xf5\x20\x3c\xde\xb5\xf6\x25\x43\x78\x4d\xfe\x5b\x84\x83\xd2\x72\x3c\x83\xb5\x93\x13\x9a\xec\xb1\xad\x28\xcf\x62\xf2\x8c\x2e\x60\x63\x20\xf0\x00\x00\x35\xbb\x03\x81\x50\x4d\xcd\x16\x41\x60\x67\x95\xf3\x76\x4c\xb4\xcf\x84\xc1\x6f\x84\xa9\x58\x50\xf7\x00\xd8\x41\x87\xe9\x9d\x03\x60\x40\x3d\xbd\x6b\x00\xcc\xf0\xc2\x99\xce\xfd\x28\x6a\x6c\x10\x31\xdf\x12\x76\x32\xab\xea\x32\x29\x84\x0e\xaf\xb3\xfa\xe0\xe6\x3b\xb7\x7e\x28\xf0\xcb\x3c\x8e\x5f\x41\xc6\xb2\x6a\xfe\x71\x0a\x64\x67\x7a\x57\xdf\xb8\x13\x9e\x6c\xaa\xa2\xee\xd6\x89\xf2\xf4\xe7\x28\x45\x55\xf5\xf5\xef\x1b\xf7\xfc\x8b\x76\x6e\x50\x7e\x6a\x2f\xca\xd3\xd3\x31\xdb\xd0\xc9\x3f\xd9\x3f\xc6\x9f\x97\x93\xa8\x4c\xf8\x53\x73\xa3\x68\xe3\x34\x15\x29\x2b\xce\xd4\xa3\x27\x1e\x01\x37\xdb\x42\x0e\xba\x03\x8e\x3d\x7e\x50\x52\x73\xcd\x2a\x84\x19\x0c\xd0\x8e\x0a\x81\xbc\xba\x81\x1a\xd0\x0e\x33\x09\xa0\x1d\x15\x02\xc5\x05\x03\xb5\xae\x1d\xb3\xc6\x41\x33\x61\xb5\xd6\xac\xb4\x35\x61\x2b\xd6\x01\xc6\x62\x60\x99\x45\x05\xa7\xeb\x02\xc5\x36\x61\x1d\x24\x2c\xe8\xbc\xc5\x4d\xf3\x4f\xb3\x12\x76\x8c\x05\x32\x93\x16\x04\xda\x09\x83\x42\x86\xa2\x82\xb8\x3d\x00\x6d\x69\x20\xd0\x56\x0c\x04\xa1\xb6\xb8\x4d\x00\x6d\x69\x20\xd0\x5e\x0c\x04\x85\xb6\xcc\x67\x85\x60\x5b\x90\x4e\x0a\x99\x4d\x46\x41\xeb\xb1\x19\x99\x4d\xc0\x68\x24\x72\x66\xab\xe9\x3b\xc6\x14\xfb\x78\x15\x2d\x34\xb3\x49\xb2\x5d\x0e\xd9\x0c\x2d\x07\x0d\xa6\x01\x41\xd6\x22\x95\x73\x7b\x50\xe9\xcb\xe5\xa0\x91\x40\x74\x34\xfa\xdc\x06\x54\xfa\x72\x39\x68\x18\x10\x1d\x4e\xdf\x7c\xba\x0b\xd6\x75\x77\xbc\xcb\x6c\x0f\x22\x4e\x8f\x31\x08\xac\x01\x96\xd0\x11\x32\x9b\x81\xf5\xbc\x59\x34\xc3\xd3\xdd\x54\xb3\x01\x76\x84\x0c\x32\x83\x16\x04\x5a\x02\x83\x42\xc6\xa0\x82\xb8\xde\x81\xb6\x34\x10\x68\x15\x06\x82\x50\x5b\xdc\x06\x80\xb6\x34\x10\x68\x21\x06\x82\x42\x5b\xe6\x73\x7a\xb0\x0d\x48\xa7\xf4\xcc\xa6\xa2\xa0\xf5\x58\x8b\xcc\x26\x60\x30\x12\x39\xb3\xcd\xf4\x1e\x21\x44\xbb\x30\x8a\x34\xb3\xa1\xe7\x02\x21\xab\xe1\x10\xd0\x68\x28\x10\xb2\x19\x05\xc2\xed\x42\x6f\x47\x85\x80\x06\x03\x53\x03\xda\xe1\x36\xa1\xb7\xa3\x42\x40\x63\x81\xa9\x75\xed\x98\xcf\x5b\xc2\x36\x20\x1e\xb7\x34\x5b\x8a\x8c\xd5\x63\x28\x12\x8b\x80\x9d\x88\xc4\xcc\x66\xd2\x77\x0e\x74\x1b\x45\xad\x95\x08\xb7\xc1\x9c\x85\xfd\xc8\x9e\x1f\xbc\xe8\xce\x05\xdc\x8b\x5b\xf8\x1d\x7a\xcd\xbb\x83\xb2\xd8\x79\xd9\x25\x21\x96\x8b\x25\x49\xf8\x6b\x54\x8d\x39\x0a\xb2\xc3\x59\x38\x7b\xc0\x4e\x26\xba\xc7\xaa\x3d\x7c\xc8\x0e\xf4\x34\x45\x0d\x07\x87\x84\x24\x51\xe8\x21\x85\x2d\x2a\xe1\xfb\x5d\xf4\x9e\xbd\x65\x8b\x59\xed\xb0\xa9\x01\x11\x5a\xef\xd9\x90\x0e\x16\x24\x7d\x05\x68\x43\xb2\x51\xd2\x57\x71\x36\xa4\x03\x7c\x35\x00\x5c\x4f\x5b\x0f\x9b\x65\x03\x2e\x8a\xc5\xec\x83\x91\x39\x70\xc9\x3c\xb6\x66\x27\xce\xab\x6b\x8e\x6e\xb3\x13\xfc\xd5\x35\xa5\x36\xcf\xca\x79\xc4\x51\x92\x16\xce\x92\x8e\x13\xf4\xb8\x8a\x82\x9c\xaf\xac\x38\xb6\x45\x41\xca\x57\x56\x14\x5b\x3c\x4b\xe7\x41\xc7\x08\x59\x20\x62\x1b\x6a\x3d\x15\xcd\x03\x59\x97\xd5\xf8\x16\xa1\x8a\x4a\xfe\x66\xed\x5f\x2e\xbb\x04\xa7\x71\x85\xeb\x73\xf7\x61\xd6\xd7\x2f\x7b\xf2\xbb\x6b\x9c\x52\xbc\xc7\x59\xac\x1c\xb7\x13\x1c\xb8\x5a\xd7\x70\x71\x4b\x18\x28\xf9\x5f\xf9\x68\x9b\x70\x3a\xb1\xbb\xc6\x0a\xb8\x5c\x60\xde\xfc\xbb\xa4\x68\x8b\x87\x5d\x19\x26\xf3\x34\x57\x2e\x8f\x59\xfa\xfe\x85\x5c\x29\xf7\x73\xfd\x50\xe0\xdf\xd3\xc7\xae\x7f\x79\xea\x9b\xf7\x84\x16\xc8\xab\x11\xdb\xfc\xfe\x97\x89\x50\x58\xa2\x38\xc9\x7f\xe1\xb7\xe1\xcc\xc8\x51\xca\x56\x9a\x2c\x03\xfe\xf7\x95\x24\x3c\x7a\x9c\x55\xa4\xbc\x4b\x52\xfc\x8b\xac\xa5\x8b\xd4\x46\xb6\x57\xe1\x82\x16\x2f\xf4\x4a\xbd\x9f\x8f\xa7\xb4\x4e\x8a\x14\xff\xc2\xee\xd8\xfb\xb9\xd1\xdd\x2f\x67\xf1\x5a\x37\xb5\x4d\x76\xdb\x04\xd4\x49\x1d\x44\xbb\xfa\x24\xf7\xe2\xe5\xa7\xba\x38\xd5\xf0\x31\x50\x22\xb5\xa5\x7c\xf0\xb3\xff\xf6\xc1\xf9\x7c\x7e\xf1\x76\x79\x79\x74\xa3\x3c\xab\xcb\x5c\x3d\x3b\xaf\xdf\x44\x37\x9d\x09\x37\xa5\x2d\x8a\x7b\x27\x08\xaf\x68\xd4\x74\x51\x5d\x57\x9a\x1c\xd1\x1e\xf3\xa3\xb0\x83\x8e\x95\xda\xce\xf5\x36\x75\x9b\xff\x88\xc7\x75\xfd\x25\x7c\xb2\xd7\x88\x0b\x5c\x8f\xc7\x98\x20\x5d\x10\xaf\xb8\x73\xbc\x60\x5e\x4d\x74\x86\x34\x1c\xe5\x32\x3d\x3b\x3d\x1b\x9d\xa7\x20\x22\x9b\x02\x33\x59\x91\xda\xfa\xcb\xc5\x02\xed\xf0\x8a\x5b\xe7\x1a\x3c\xbf\xdc\x27\xc8\x89\xef\xf8\xce\x0d\x07\x04\x7e\x38\x09\x96\xf3\x49\x38\x9d\x4e\xbc\xc5\x28\x8d\x58\x09\x29\x9d\x59\x13\x1f\x56\xa4\x28\xc2\x07\xf2\x08\x1b\xbf\xe8\x67\xb5\x5a\x6d\xf2\x02\x45\x49\xfd\xb0\x0e\x94\x4a\xcd\x8c\x9b\x0c\x65\x43\x45\xad\x0d\x26\x8c\x51\x75\x8e\x15\x7b\x2f\xc7\xfa\x4d\x55\xb8\x64\x50\xac\xff\x73\x9c\x90\xdb\x04\xe3\x5f\x26\x72\x79\x89\x51\x9c\x67\xe9\xc3\x2f\x13\x1e\xfe\x3a\x54\x47\x1e\xf2\xc0\xda\x08\x63\x93\x4c\x84\x06\x7b\x09\xb3\xcb\x4c\xb2\xbc\x76\x51\x9a\xe6\x77\x38\xbe\xf0\x0b\x4c\x65\x44\x83\xb3\x55\x83\x13\x2a\x0a\x8c\x4a\x94\x45\xec\xea\x1a\x60\x25\xc6\x51\x9b\x50\x1f\xe3\xdb\x24\xc2\x6e\x91\xdc\xe3\xd4\x25\x57\x95\xae\xfd\x57\x67\x81\x7e\x8c\x6a\xfc\x8b\xc4\x89\xe8\xb8\xeb\xe4\x68\x81\x36\x75\xc9\x83\xc9\x69\x1e\xa1\xd4\x8c\x77\xcc\xb3\xfa\x20\x83\xa5\x1b\x70\xa6\xe4\xb6\x38\x6a\x30\xe4\x0b\xa9\x5b\x1d\x1d\x95\xc7\x89\x05\x81\xb0\x69\x43\x50\x38\xb5\xa1\x52\x66\xd5\x6e\xfe\xc2\x6a\x54\x47\x5d\x3c\x10\x44\x15\x0d\x84\xc3\xc4\xc2\x41\xb2\x48\x7c\x55\x24\xe9\xbe\x47\x24\x32\x02\x20\x12\x9d\x82\x51\x24\x32\xaa\x5d\x24\xe9\xde\x24\x12\x19\x02\x8b\x44\xc6\x91\x44\x92\xee\x25\x91\xcc\x16\xe4\xa8\x3e\xb1\x22\xc2\xe5\x59\x4f\x22\x5c\x3c\x3e\x0b\x99\x78\x64\xd2\x01\x9c\xb5\x56\x6f\xb2\xed\xbf\xbb\x91\xd3\x74\xc8\x04\x94\x51\xa6\x7f\x88\x99\x12\x32\xf5\x95\xce\x69\x03\x77\x59\xfa\x1b\xf5\xa6\x4c\xf5\x92\xd2\xb6\x35\x70\x02\xd9\x82\xd9\x75\x55\x06\x2c\xca\xa2\x36\x05\x63\x00\xa0\x2e\x9b\x8d\xea\xd7\xc4\x0a\x02\x9a\x91\x09\xa9\x74\x77\x41\x28\x09\xe8\xb5\x2a\xfe\xd7\x4c\x0b\x02\x11\x57\x52\x13\xe3\x44\xe6\xcb\xa2\x34\xf0\x46\xae\xe1\xb2\x06\x6f\x50\x36\x6a\x80\xb1\xf3\xda\xce\xed\x6b\x99\x77\xe8\x02\x30\xb6\x19\x8c\x5c\xeb\xac\xc5\x0b\x50\x81\x76\x3c\xa6\x4c\xa8\xa6\xc7\x2b\x80\x50\x21\x72\x69\xe4\xc0\x9a\x14\xd4\x55\x83\xe2\x99\x2a\x9e\x8e\x90\x24\x99\xae\x18\x0a\x9a\xaa\x88\x21\x1c\x49\xce\x36\x46\xda\xa6\xa4\x11\xab\x96\xda\xd8\xb0\xa0\x88\xa3\x1f\x62\x42\x0c\x73\x2e\xdd\x3d\x20\x7a\x09\x71\xf1\xd0\x2e\x58\x94\x4d\x61\x4b\xdd\x94\x41\xba\x9d\x0f\xb5\x40\xab\xa3\x72\x9d\x89\xaf\xdc\xa0\x75\xe9\x10\x85\xe8\xb3\x11\xf6\xca\x68\xd7\xe9\x84\xda\x02\x67\xae\x5f\x32\xc4\x56\x97\x30\x75\x2d\xd8\xa9\x4b\xd1\x2e\x64\xb6\xf3\x25\x95\x10\xdd\x81\xd9\x05\x84\x26\x92\x83\x93\xaa\x27\xea\x8f\xd2\x14\xeb\x9e\xb1\x41\x3d\x9e\x43\xf5\x85\x1e\x4b\xf3\x27\x05\xb9\x7f\xd2\x68\x13\x04\xb7\x43\x91\x3d\xd1\x26\x43\x75\x41\xdb\x2f\x9f\x4b\x17\xa5\x85\x00\xbd\x91\x2e\xd5\xeb\xae\xed\x6d\xef\x0a\x56\xc8\xb0\x1d\x97\x1b\xfd\xa2\x78\xc9\x78\x94\x46\xb4\x69\x81\xc1\x78\xd2\xbd\x6a\x3c\x1d\x21\x4d\x66\xe9\x1e\x36\x9e\xa7\xed\x96\xd2\xa2\xc5\x86\xe0\x9e\x82\xf5\x87\xd8\x50\xba\x1f\x69\x43\xaa\x3c\x14\x1b\x22\xec\x89\x36\x74\x23\x8a\x29\x18\x23\xa6\x8b\x77\x40\x95\xbb\xc3\x38\x6e\x96\x61\x7a\xf4\x97\xe1\x8a\x96\x64\xdf\x36\x0b\xbd\x79\x2b\x25\xce\xb8\x4e\xb9\x9d\xdd\xd0\x30\xcd\xfd\xe2\x6f\x6e\x92\xc5\xf8\x7e\x1d\x6e\xa0\x14\x10\xf1\xdc\xa2\x17\x57\xd7\x30\x1b\xed\x0a\xe7\x0d\x9b\x53\xb8\xf8\x16\x67\x75\xc5\x36\x8b\x59\x84\xfc\x1a\xe6\x5c\x9d\x9d\xf7\xa0\x19\x11\xf8\x09\x92\x45\xd7\x93\x7e\x33\x53\x9d\xc9\x20\x1e\xab\x63\x0f\x9a\x11\x81\x1f\x64\xf1\x05\x69\xc3\xee\xb4\xb1\x0a\xb6\x87\xc6\x11\x66\x9e\x60\x71\x3b\x75\x93\xa1\xac\x6d\x36\x4d\x90\x60\x07\x9c\x16\x74\xa2\xa9\x00\xc8\x04\x00\x2a\x83\xda\xd0\x16\x0f\x10\x8c\xcf\xc7\x01\x14\x61\xb6\x01\x00\xa4\x8a\xca\xc5\xd7\x32\x83\x72\xb6\x43\xca\x67\x51\xfc\xf7\x9d\x3a\xb4\xf0\x03\x66\xd9\xe8\x35\xdc\x57\xe7\xd6\x9a\x28\xf6\xe5\x62\xb9\x0d\x16\x37\xa3\xd3\x69\x42\x5d\x85\x6b\xd1\xc2\x51\x1c\xe7\x99\x2c\x73\x20\xa5\x4b\x77\xa7\x6d\x20\x89\x5b\x24\xd2\x0d\x06\xa0\x06\xdb\xfb\xa1\x9a\xbc\x56\x2c\x99\x63\x07\xd5\x4d\xbe\x85\xa9\x26\xdf\x02\x04\x93\x97\xcb\xa0\x36\x40\x93\x57\x61\x80\xc9\x73\x14\xcd\xe4\x25\x00\x68\xf2\xec\x32\x75\x99\x41\x8b\xc9\x53\xfc\x0f\x63\xf2\x20\x3f\x86\xc4\xf2\x3c\x78\xac\xc9\x47\x3e\x0a\x16\xdb\xeb\x4c\x9e\xd6\x55\xb8\x36\x9a\x3c\x93\xa1\x69\x57\xd5\x06\x92\xb8\x45\x22\x9a\xc9\x8b\x35\x70\x59\xe6\xa5\x6a\xf0\x4a\xa1\x64\x8a\x1c\xa6\x1b\x3b\x83\xa8\xa6\xce\x8a\x05\x43\x17\x4b\x74\xda\xa0\x91\xcb\x10\xc0\xc4\x29\x82\x66\xe0\x42\x31\x68\xde\xec\x62\x7f\x91\x2d\x8b\x71\x53\xec\x0f\x63\xdc\x00\x37\xa0\x69\xd3\x47\x06\x1e\x69\xda\xf8\x66\x76\x33\xbd\xd2\xb4\x49\x5d\x89\x67\xa3\x61\x33\xf9\x99\xf6\x80\x6d\x20\x69\x1b\xa5\xa1\x99\xb5\x88\xdf\x4e\x69\x89\xb6\xff\x8f\xa1\x22\x39\x99\x33\xe7\x13\x1e\xb9\x0e\x7f\x53\xc9\x56\xd7\xbf\x08\xd6\xae\x3d\xe4\xd5\x66\xab\xe6\x60\xf6\xb3\x3d\x9c\x36\x6d\xfe\x99\x2f\xea\x22\xcd\x33\xdb\x15\x73\xb4\x86\xaf\xf5\x72\x9a\xce\xf0\xb0\x99\x4e\x53\xfd\x42\x2b\x51\x15\x9e\x8d\x1a\x4b\x90\xaf\x6d\x20\xba\x4a\x35\xc1\x6c\x54\x74\xb2\x37\x63\x50\xdb\x02\x11\x07\x5a\xb2\x81\x78\x9a\xc1\x0e\x45\xde\xd6\xd9\xb9\x13\x8e\x99\x95\xb7\xb2\x90\xc5\x03\xf2\x52\x15\xc9\xab\xaa\x5b\xe9\x06\xf5\xbf\x73\xe4\x52\x31\x4d\x16\xdb\x4c\x06\x7a\x57\x61\x5c\x93\xdc\xef\xea\x0d\x33\x9f\xab\x26\xc7\x60\x2a\x70\xda\x1d\x20\x6a\xc9\xb1\x77\xd7\xbf\x4a\xa7\x4b\x65\x2a\xe6\xa5\xaf\x3a\xca\x59\x45\xe1\x15\x06\x55\xce\x10\xa8\x0d\x6d\x1a\x06\x8b\x85\x70\xb9\xfa\xd4\x06\xcf\x64\xda\xf4\x34\x8e\x41\xf6\xe5\x40\xf8\xbe\xb2\x6c\x17\xa6\x22\x9e\xfe\x41\xc8\x7e\xd3\xb2\xdd\x85\x49\xcc\x49\x76\x6e\xe8\x69\x6b\x84\xda\xeb\x4e\x00\xaf\x43\x94\xd9\x5d\xfa\x3b\x82\x55\x25\xa5\x60\xe6\x3c\x08\xb4\xa4\x0c\x70\x69\xc7\x90\x76\xaa\xa3\xad\x9d\x85\x96\x40\xbc\x5c\xbc\xc6\x11\xd9\xbe\xe4\x74\x9b\x69\xc0\x0f\x39\xdd\xe6\x1a\xeb\x6b\x73\xdd\x66\x1b\x3d\x1f\xa3\xef\x84\x35\x7c\x13\x72\x8f\x95\x5b\xe7\xa7\xe8\xe0\xa2\x88\x0c\xd6\x23\xca\x92\xe2\x94\x92\xd7\x3e\x37\x66\x88\xfc\x2d\xa9\x9d\xf0\x9c\x2a\x5c\xba\x34\x59\x47\x37\xf4\x90\xad\x18\x40\x69\xa5\x17\x6a\x05\x03\xb7\x08\x99\x6f\x82\x27\xdf\xdb\xb7\x75\xc6\xce\xad\x79\x74\xc3\x96\x50\xb2\x16\x4a\xba\x9f\x6b\x0d\x7d\xad\xa1\x3f\xc9\x26\x2f\xb5\x5d\xe1\xa7\xf4\x74\xd5\x74\x3a\x85\xdf\x6e\x15\xba\x22\xf2\x79\x86\x25\x37\x68\x27\xcf\xb4\xb8\x77\xe6\xca\x1c\x33\x30\x3c\x8c\x60\xc2\xa5\x7c\x75\x9f\xc7\xb6\x75\xd6\xb3\x97\xa4\x19\x31\xfa\x47\xa6\xcd\x2e\x49\xc9\x13\x1a\x69\x71\x40\x2f\xd9\x2e\x95\xdf\x2f\x84\xfd\x59\x3d\x4f\x29\xb4\x3b\x5b\xbc\xc5\xfc\x82\x64\xae\x00\x36\x08\xc6\x19\xcc\x65\x6e\xeb\xcc\x8d\xf1\x0e\x9d\xd2\xfa\xdc\xf7\x9c\xaf\x32\x73\x26\x47\x0f\x84\xfa\x82\xc6\x79\x11\xb3\x26\x2b\x61\xbc\x68\xfe\xa9\xcb\xcd\xa8\xf9\x27\x91\xd7\x4d\x67\x20\x2d\x14\x37\xff\x64\x56\x05\xdb\x6a\xe9\xf3\xb2\xbc\xc0\xd9\x5b\x2f\x2e\xf3\x22\xce\xef\x9a\x50\xb8\xdf\xa7\x78\xb8\xa0\x46\xf2\x00\x48\x4d\x1f\xc4\x2a\x84\x1d\x1b\xd1\xb9\x87\x74\x60\xa4\xb6\x96\xa9\xf5\xf6\x9b\x13\xef\x45\x5c\x0f\x46\x1c\xa0\xd3\x78\xd6\xfc\xeb\xb7\x8f\x47\xea\x14\x74\x2d\x72\x03\x7c\x40\x41\x2a\xe3\x30\x48\x69\x2d\x4c\x57\x5b\x37\x48\x01\xa2\x1d\x10\xa0\x2a\x00\x29\x59\x83\xfb\x51\x94\xd7\x83\xb5\x1e\x86\x65\x3c\xb6\xd6\xeb\x24\x1c\x6f\x8b\xe2\x3d\xee\x7b\xa2\x70\x4a\x2b\x8d\x78\xd0\x50\x69\x37\xc4\x8b\x18\xcd\x24\x2a\xa2\x84\xa5\x87\x0f\xed\xe4\xe9\x83\x87\x0a\xf9\x20\x0c\xb7\x33\x5f\x22\x2f\xdb\xf2\x08\x5a\xa1\x3f\x8b\x97\x0a\xab\xa2\x2d\x73\xfa\xfd\xb6\x3c\x48\x5c\x23\x79\x00\xa4\x06\xf8\x27\x05\x22\x18\xba\xcc\x3d\xa4\x03\x23\xb5\xc1\xfe\x49\x51\x70\x2f\x62\xbf\x7f\x1a\xa3\x53\x22\xba\x7e\xfb\x78\xa4\x4e\x2d\xfe\x89\x37\x00\xf9\x27\x15\x06\x29\x0d\xf2\x4f\x0c\x06\xfb\x27\x0d\x08\x50\x1d\xec\x9f\x64\xe5\xf5\x60\xf5\xf8\xa7\xbe\xc7\x4b\x87\xba\x0a\xc5\x4b\xf1\x6a\xf0\x0d\x3a\x4d\x3d\xe5\xed\x5a\xd8\x52\xe6\xd1\xf6\x66\x1e\x29\xad\xcf\x22\x84\x67\x91\x44\x45\x14\xb5\xf4\x7a\xaa\x9d\xfc\x6c\xb6\x8a\x67\xaa\x21\x86\xf3\xf9\x22\x9c\x4b\xe4\x87\x18\x35\x48\x6b\xba\xba\x99\x4d\x57\x32\xab\xa2\x51\x73\xfa\xfd\x46\x3d\x48\x5c\x23\x79\x00\xa4\x06\x38\x2a\x05\x22\x58\xbc\xcc\x3d\xa4\x03\x23\xb5\xc1\x8e\x4a\x51\x70\x2f\x62\xbf\xa3\x1a\xa1\x53\x2a\xba\x7e\xfb\x78\xa4\x4e\x2d\x8e\x8a\x37\x00\x39\x2a\x15\x06\x29\x0d\x72\x54\x0c\x06\x3b\x2a\x0d\x08\x50\x1d\xec\xa8\x64\xe5\xf5\x60\xf5\x38\xaa\xbe\xab\x43\x86\xba\x0a\xc5\x51\xf1\x6a\x66\x47\x25\x3e\x88\x6d\xf0\x52\xdb\xc8\xd7\xbe\x92\xcc\x16\xdb\x9b\x18\x75\x24\x44\x21\x77\xef\x2f\xf7\xd8\x5f\xb0\xf5\xe3\xb9\x1a\x28\xb7\x8b\xf8\x66\xde\x11\x1e\x64\xc8\x10\xa1\x70\xb1\x42\xdb\x48\xe0\x50\xb4\x62\x42\xb9\xdf\x84\xfb\x85\x33\xa6\x69\x55\x46\x80\x37\x12\x8b\x05\x9b\x16\xd8\xd5\x04\x0d\x13\x19\xec\x81\x44\xe5\xd9\xb1\xfa\x7d\xcf\x50\x7d\x51\xf9\xf4\x28\xfe\x6a\x7d\x59\xfc\x0d\xa1\x0b\x39\x1b\x09\xa0\x29\x04\x72\x33\x0d\x00\xf6\x31\x32\x44\x25\x36\xd8\xbb\x08\x8a\xb1\xa1\xf4\xf8\x15\xeb\x5d\x34\x83\x46\xb6\xea\x51\x58\x1d\xb3\x47\x51\xde\xc5\x87\x4d\x60\xe7\xa3\x78\xa6\x36\x8d\x31\x0a\xa7\x0b\x89\x8a\x28\x58\xe9\xe5\x75\x3b\x79\x1c\xad\x96\x81\xba\xf4\x5c\xdd\xcc\x77\x7e\x2c\x91\x1f\x62\xad\x20\xad\x78\x7e\x33\x0f\x42\x99\x55\xd1\x60\x39\xfd\x7e\x9b\x1d\x24\xae\x91\x3c\x00\x52\x03\x9c\x8d\x02\x11\x8c\x5b\xe6\x1e\xd2\x81\x91\xda\x60\xc7\xa3\x28\xb8\x17\xb1\xdf\xfd\x8c\xd0\x29\x15\x5d\xbf\x7d\x3c\x52\xa7\x16\x57\xc4\x1b\x80\xbc\x91\x0a\x83\x94\x06\xf9\x24\x06\x83\xdd\x92\x06\x04\xa8\x0e\x76\x4e\xb2\xf2\x7a\xb0\x7a\x5c\x54\xef\xd5\x47\x03\x5d\x85\x9a\x49\x62\xd5\xcc\x8e\x8a\xdd\x0d\x64\x37\x94\xd5\x7c\x3a\xd3\x06\xde\x6c\xba\x9b\x22\x91\x88\x94\xac\xa3\x77\xf4\x0c\xf0\x52\xd1\x6a\xea\x87\x6a\x1c\x5c\x2e\x82\x28\x58\x89\xc4\x87\x18\x34\x48\x0a\x45\xe1\x8a\xcf\xe5\x19\x9f\x52\x4e\x94\x52\x1f\x90\x12\x1d\x20\xa8\x71\x0c\xe8\xf2\x82\x72\xdc\x12\x40\xcc\x95\x8a\x8c\x03\xa2\x37\x91\x1a\x9e\xdf\x96\x94\xda\x87\x37\x20\xbb\x3d\x58\x8f\x54\x62\xbd\x26\xf1\x28\x3d\xda\x32\xdb\x94\x3a\x98\xd8\x96\x41\x80\xa2\xc0\xb4\x36\x01\x19\xb2\xda\x0a\x4c\x27\x39\x3c\xa7\x2d\x2a\xcc\x8e\xd4\x97\xd1\xb6\xdf\xb0\x35\xd0\x1f\x28\xbe\x88\xd7\x32\xfb\xa2\x34\xc9\xde\x9d\xb5\x93\xa4\x50\x92\xaa\x7b\xfc\x9b\xd7\x9b\xb4\xbf\x24\xb3\x68\x0a\xd6\x6a\x41\xff\xe7\x49\xca\x8a\xf5\xd8\xfe\xd0\xf7\xdd\x01\x0e\x35\x86\x44\xa5\x93\xbf\x99\xe4\x45\x01\x8b\xd7\xb0\xf7\x55\xe4\x4b\x8c\xe9\x3c\x5c\x46\xda\xc7\xe4\x53\x16\xe3\x32\x4d\x32\x20\x2e\x80\x8d\xc0\xc6\xa9\x40\xec\xa6\x29\xf0\x6a\x45\x91\xd8\x6f\xaf\x8e\x87\x3e\x84\xb7\xfb\x42\xde\x36\x7f\x31\x96\xf6\xe7\xa7\x3b\xd2\xd4\xb5\x51\x1d\x85\x36\xba\x83\x87\x8f\x39\x73\xd7\x11\xbf\xaf\x04\xe2\xf7\x55\xd7\x01\xfa\xb5\xfd\x4a\xda\xd0\xae\x48\x71\xe7\x5b\x8b\xf3\x5a\x40\x97\xb7\x4d\x8a\xf7\x35\x6c\x4f\x75\x9d\x67\xbf\x74\xb8\xd2\x69\x5a\x5c\xe1\xda\x00\xab\x4e\xdb\x63\x22\x02\xe5\xfd\x77\x28\xc6\x67\xfe\xd1\xde\x87\xae\x61\x61\x40\x72\x89\x89\xd3\xf4\x1d\x95\xca\xc5\x2a\x10\x86\x1d\x4c\xdb\xf5\x92\xec\x2c\xdc\x84\x11\xe5\x69\x8a\x8a\x0a\xb7\x32\xa3\x86\xc6\x8b\x1b\x6c\xf9\x3e\xa2\xba\x04\x81\xec\x6e\xab\xfc\xee\x42\xae\xcd\xb2\xe3\x50\x13\x68\x5b\x69\x26\xcb\xfa\x36\x3a\xa6\x6c\xbf\xbd\x4a\xb0\xbd\x48\x50\x13\x97\x5b\x27\xc7\x24\xdb\xbb\xbb\x53\x46\x37\xf1\x60\x54\x61\x59\x5e\x30\x4a\x2f\x09\xbd\xa9\xf8\xc4\x46\xa4\x37\x55\x2f\xbb\x51\x60\xe6\x4a\x3a\xd5\xa2\xcc\x0b\x5c\xd6\x0f\x6b\xda\xeb\xc9\x6d\x52\x25\xdb\x24\x4d\xea\x07\xa5\x09\x0b\xe2\x20\xac\x8b\x17\xa1\x12\xd7\xb6\x3d\xb7\x7e\x27\x7a\xe9\x71\x8e\xe2\xde\xb0\xbb\x4a\x78\x73\x60\x56\xdc\x3b\x31\xaa\x0e\x38\x56\x4b\xc9\x2e\xa6\xbf\xb7\x09\x67\x76\xc0\xcf\xb6\xbd\x89\x3e\x33\x02\x61\x5c\xda\x09\xce\x84\xfc\x3a\x15\xd0\x31\x43\x65\x12\xa4\xec\x65\xf2\x05\x84\x23\xce\x4e\x86\xe3\x84\xe4\xa6\x28\xba\x95\xb3\x3d\x50\x18\xf8\xbe\xbf\x11\xc7\xcb\xa6\x7b\x93\x6a\x23\xbc\x95\xb5\x50\x0f\x2a\xb7\x57\xb3\x85\xec\x7e\x30\x65\x23\x9c\xf2\x38\xc8\x26\x4d\xaa\x9a\x5d\x95\xa9\x6e\x15\x13\xe6\x91\x6d\x40\x16\xa0\x69\x52\xac\xbb\x63\xe8\xf7\x1b\x2b\xcc\x72\x1b\x95\x50\x2a\x6d\x7f\x22\x3b\xa5\x06\x5c\x57\x45\x37\xec\x37\x1e\x5c\xae\xaf\x1c\x4f\xb0\xa0\x29\x6a\xf2\xc8\xcb\x49\xc4\x7a\xce\xfc\xa0\xa7\xf0\x80\x8f\x84\xeb\x78\x71\x72\x9b\xc4\xb8\xe4\xa7\x5c\x83\x76\x2f\xe2\x7a\x45\xd4\xa1\xba\x16\x20\xf7\x42\x2f\xab\x93\x09\xbf\x4d\x93\xb7\x08\xbe\xb5\xac\x09\x45\x0e\xb9\xbd\x22\x4a\x31\x2a\xd7\xdb\xbc\x3e\x0c\xdd\xe0\x28\x6c\x7c\x81\xee\xf8\xd4\x59\xe0\xd3\x12\x00\x22\xcf\x87\x16\xcd\x3f\x70\x4e\x01\xd9\x14\xbb\xb4\x5f\xa6\xca\xdf\x06\x40\x6a\x73\x2d\x00\xe6\xa6\x03\x6b\x0b\xa0\x81\xfc\xb0\x19\xb0\x69\xe0\xbe\x6d\x97\x1e\x00\x6f\x1d\xc8\xc0\x9d\x80\xa0\xce\xc1\x2c\xed\x0c\x25\x06\xf6\x10\xd8\x01\x68\xbf\x27\x0b\xdc\xe6\xc8\x36\x0d\x16\x65\xbe\x4f\xe2\xf5\x1f\xff\xfa\x43\x03\xfa\x4b\x53\x6d\x97\x97\x47\xef\xcf\x49\x54\xe6\x55\xbe\xab\xbd\x7d\x33\x42\x71\x56\xbf\xc4\x19\x61\xee\xf7\x3b\x94\x56\xf8\xd5\x45\x5d\x2a\x12\x27\x28\xc7\x7a\x8a\x82\x8c\x3e\x73\xe0\x38\x24\x9e\x5c\x78\xeb\x6c\xc3\xb7\xc6\xb7\x58\x07\x8c\x9a\x61\xda\x33\xa2\xac\x53\x42\x75\x14\x35\x93\x68\xeb\x28\x6a\xc4\xda\xfc\xd1\x39\xfe\x5d\x72\x8f\x63\xe5\x10\x79\xbb\x67\x59\x89\x01\xab\x95\x7f\x11\x7c\x91\x2a\x47\x83\x48\x4e\x85\x43\xe3\xef\xc4\xcb\xd0\xed\x16\x95\x2e\x69\x93\xed\x8c\x76\x5a\x22\x0c\xeb\x1c\xe5\x59\x8d\xb3\x7a\xfd\xc5\x17\x62\x38\x55\xef\xd6\xd4\x83\xae\x00\x60\x71\xb7\x6b\x5f\x62\xb4\x97\x0f\xb9\x5b\x4d\xeb\x44\x83\xed\x99\x22\xfd\x85\x2a\xdb\x4e\x77\xd6\x18\x91\x8e\x4a\x1b\x10\x99\x05\xdd\x64\x53\xc2\x12\x63\x22\xac\x36\xf8\xc4\x65\xe8\x65\x44\x86\x33\x28\x3a\x41\x61\x11\xc3\x4e\xdd\xd0\xcd\xb5\x6a\x2b\xe2\xab\x95\x06\x2a\xd2\xfa\x1d\x80\xaf\xfb\xe0\xc2\x22\x15\x02\x0b\x89\x99\x8e\x55\xbd\x51\x43\x5b\x70\x13\x02\xe5\x73\x7b\xdf\x82\xd0\x43\xb2\xc4\x7d\xad\xc8\xa8\x2b\xd4\x14\xe5\x74\x3f\xc1\x5a\x02\x48\x3e\x25\xc2\x8e\x84\xf0\x75\x60\x9d\xe7\xe9\x16\x95\x32\x74\xae\x40\x9d\xae\x05\xb1\x44\x64\xaa\x2d\x17\x0f\x8a\xa9\xba\x64\x48\x6f\x35\x72\x6f\x0d\xe4\xde\x4a\xe4\xa4\x67\xf7\xa4\x45\x32\x95\x6e\x96\xd7\x2f\xc5\x6b\xa6\x5f\xd1\x92\xee\x8e\x60\x5a\xa0\xce\x77\x5f\x9d\xc1\x9c\x91\xa8\x4c\xe1\xea\x6a\xe5\xd0\x92\x19\x73\x64\xe3\x75\x5e\xd0\xf1\xdb\xb2\x21\xfb\x28\x05\xa8\xb5\xdc\x35\xa4\xcb\x41\xb2\x43\x75\xb6\xaf\x61\x8b\x1c\x35\xdd\x34\x31\x24\xc1\x54\x7e\x0c\x16\xa0\x22\x0c\xd0\x19\x75\x14\x3d\x2a\x62\xd4\x6c\xe2\x57\xc5\xa4\x0e\xce\x41\x24\x14\xe1\x3d\x91\xf2\x58\xd3\x36\x15\xea\x86\xf8\x48\x2d\x39\x9a\x21\x68\x9e\x8c\xcc\x6a\x34\x3c\x71\x92\x23\x77\xe3\xb5\x86\x2a\xdf\x52\x73\xa3\x5e\x14\x78\xa3\x0f\x62\x72\x89\x8b\x9d\x4c\x10\xaa\x74\x82\x50\x22\x64\xe0\xfb\x43\x9c\x72\xb1\x31\xd0\xa5\x8d\xc7\x64\x86\xf9\x0c\x07\xf0\x3b\xe4\xc8\x1b\x01\x32\x95\xb3\xc7\x93\x19\x83\xaa\x25\xb0\xa4\x45\x37\xc1\xb1\xd0\xf0\x1d\x46\x65\x48\x28\x97\x01\xe6\x39\xc5\x5b\x35\xfa\xcb\xd3\xd8\xee\x61\xb9\x8d\xf1\x95\x4f\x23\x3b\x22\x59\xf1\x85\x3a\x03\xba\x1a\x33\x01\xe8\xa0\x7e\xd8\xe9\x18\x83\x30\xb9\x11\x32\x50\xce\x69\xfa\x46\x6e\x07\x78\x49\x8b\x83\x54\x27\x3f\x16\x07\x67\x72\x2a\xb3\xe2\x7e\x63\x72\x75\x02\x0c\x74\x76\x03\xfd\x91\xc2\xa5\xcd\x17\xf6\xba\xbe\x71\xee\x58\xef\x80\xd2\xf5\x1e\xa3\x7b\x82\x18\x06\x92\xbd\x32\x98\x5d\x41\xcb\x10\xd5\x9e\x4e\x9d\xef\x25\xc0\xe9\x5a\x16\xdb\xff\xf5\x54\xd5\xc9\x2e\xc1\xb1\x9c\x55\x17\x5d\x0b\x4d\xb3\xa7\xe8\x21\x3f\xd5\x6c\x4d\xdb\x7d\x50\x23\x49\xf9\x75\x85\x0b\x54\xa2\x1a\x83\x94\x35\x3f\x28\x43\x94\xdb\x12\x68\x6b\xca\x13\x9a\x9c\x9d\x17\xe6\x06\x84\x49\xfd\x19\x76\x84\x30\xbe\xbc\x68\xec\x16\x8b\x3f\xc7\xa8\x46\x4c\xd3\xec\xbb\x4d\xf5\x0b\xa9\x09\x9f\xee\x1f\x86\xcf\xee\x66\x35\x23\x0b\x0e\x7a\x6c\x3b\x86\xaa\xc6\xbb\x7b\x49\xe2\xb6\xc4\x51\xcd\xc2\xb3\xff\x0a\xbe\x90\x4e\x5c\x5b\x98\x97\xbb\xd4\x6c\xcc\x86\x21\x50\x91\xdf\x52\x15\xb4\x3c\xec\x26\xd2\xbd\x7e\x31\x06\xc0\x57\x77\x5b\x9f\x90\x4c\x37\x3e\x02\x62\x23\xce\x12\xfd\x9c\xe0\x54\xbd\x79\xfb\xad\x72\x47\x87\x0a\x05\x6e\xe6\xb0\xa1\x6c\xeb\x8c\xfa\xc1\xf7\x7f\x71\xa6\xa1\x07\x06\x1c\xbd\x1f\x03\x10\xc1\xde\x0c\xbd\xa1\xd3\xca\x9f\x05\xdb\xc4\xe9\xc0\x2a\x9c\x67\xf5\x7a\x50\x03\x3b\x46\x2c\x9d\x8d\x41\xa8\xaa\xc8\x68\xee\x4a\xbe\x3e\xd1\x66\x73\x0d\xb4\xc7\xe6\x54\x14\xb5\xc9\xf7\x71\xc5\xaf\x81\x75\x03\xce\x20\x63\x1b\xd4\x8d\xa1\x77\x09\x5b\xf9\xb3\x60\x8f\x34\x36\x13\xcf\xb0\x6d\x68\xec\x18\xb1\x06\x1a\x5b\x9f\xc8\x34\x63\x53\x6f\x20\xea\xb1\x2c\x71\xbd\xd2\x85\x72\x9b\x77\xed\x9f\x16\x02\x8d\x8e\xae\x75\xed\xf2\x60\x40\x77\xf9\xdc\x64\xf0\xf5\x21\x00\xd5\x73\xdf\x83\x41\xd6\x4f\x7e\xe2\xbb\x41\xfa\xad\x26\xf0\xeb\x25\x03\xdf\x0c\x02\x78\xd5\x6e\x0e\x37\x7a\x08\x60\x53\x8d\x89\xda\x90\x2d\x47\xc0\xe6\x22\x8d\x9c\xe1\xea\x25\x2b\x9e\xf4\xd6\x96\xcb\x2e\x45\xb3\x4c\x07\xc4\xb7\xfd\x74\xcb\x34\x82\x95\x89\x3b\x9b\x16\xf7\x61\x08\xb3\xba\x1e\x64\x65\x79\xa2\x63\x0b\xaf\xc0\xa9\xcb\x32\x75\xcd\xd4\x5b\xf9\x7d\xa7\x6d\xad\x72\xd5\x1e\xed\x33\x2b\x4b\x5c\xfb\xe9\x34\x4d\x50\xb3\x22\x0c\x2b\xb2\xfe\xea\x50\xba\xb9\x47\xc6\x03\x35\x38\x00\xd7\x92\x8f\x1d\x91\x14\xb5\xc9\x4f\x7d\xab\x52\x75\x92\xc0\x17\xac\x76\x70\xfb\xe0\x87\x55\x30\x4a\x01\xdb\x72\x20\x3c\x92\x4b\x02\x3e\xe5\x40\xb8\x6d\x42\x17\x04\xb2\x0f\x54\x20\x4c\xfb\x4c\xf5\x54\xa3\x5d\xbd\xaa\x0c\x60\xfd\x4a\x5b\xe9\xb8\xdd\xe8\xd2\xc9\xd0\xad\x72\xbf\x9d\x76\xd3\x96\xb2\x83\x88\xd4\x79\x9b\x26\x7d\x0f\xe9\x70\xbc\xb7\xa8\xf7\xc9\x1d\x39\x0a\xcc\x19\x5f\xd2\xf6\x94\xf6\x6f\xcb\xa6\x08\x30\xe8\x71\x52\xc2\xc6\x0a\x69\x7f\x86\x06\x95\x5b\xb4\x6d\xee\x80\x37\x9f\x8c\xdc\x9a\x41\x38\x70\xd8\x2e\x89\x89\xf8\x87\xc0\x48\x5b\x64\x7c\xb7\x19\xab\xe7\x5b\xe8\x8e\x17\x46\x3d\x43\xb7\xee\xd3\xed\x63\xe2\xba\x78\x9b\x1c\xf7\xe7\x2e\x09\xdd\x1a\x87\x5b\xa3\x6d\x75\x36\xbe\xdd\x49\x9e\x61\xe6\x68\x8d\x21\x89\x3b\xdf\x24\xdb\x6b\x4d\x94\xa3\xbe\x45\xf2\x30\xb1\x6c\xe1\x18\x77\xf9\x99\xc3\x5e\xdb\x54\x5a\x83\xf6\x92\x37\xb2\x76\xe8\x7f\xa9\x3d\x11\xf6\x37\x41\xa5\x82\x42\x75\x98\x64\x5c\xcd\xa4\x8e\xd9\x11\xbb\xe5\xc6\x7a\x7f\x96\x22\x5d\xc5\xa3\xc3\x26\x47\x38\x20\x3f\xba\x74\xa0\x90\x2a\x91\xb5\xe7\x9b\xaa\x74\xea\x93\xb5\xaf\x61\x75\x9a\x13\x9e\x60\xd5\xe6\xad\x46\x02\xfd\xbb\x49\xba\x2c\x9e\x6d\xe7\x88\xa1\x0b\x40\x22\xb2\xcb\x3e\x0e\xef\x93\x7f\x19\x84\xdd\xed\x0b\xd2\x26\xde\xa6\xee\xeb\x86\x65\xc2\x50\x8d\xcc\x88\x27\x9a\xb6\x3a\x3c\xc7\x8b\xf0\x2d\xb2\x0e\xf8\x21\x23\xee\x03\xf7\x59\x1e\x1e\xe4\x20\x0d\xe5\xa5\x48\xd2\x54\xf1\x4b\x32\xa0\xeb\xab\xaa\x3a\x8e\xf1\x3a\x4d\xce\xca\xbe\x67\x19\x41\xe9\x9c\x56\x2c\xf6\x48\x07\x0e\xb9\xd1\xa0\x73\xff\x6e\x55\xa3\xe8\x1d\x3c\x56\x3b\x90\xc0\x32\xb9\x5e\x5a\xff\x02\x67\xf2\x15\x97\x7e\x97\x70\xad\x27\x78\x0f\x0e\x60\xdc\xb8\x1f\x3c\xdc\x05\xc9\x18\x5d\xe7\xf5\xee\xc0\x3e\x2c\x86\x0c\x89\xa7\x77\x01\x4f\x3d\xfc\x3f\x40\x1f\xc1\x21\x5f\xa3\xad\xcb\xf6\x48\x92\xc7\xd4\xdd\x02\x65\xea\x51\x16\x09\x87\xdd\x1c\xaa\x4f\x76\x09\x13\xaa\x7d\xaa\x9f\xb5\xaf\xf9\x74\x47\xf7\x30\x42\xd7\x44\x77\x77\x21\xcf\xf5\xd7\x0e\xc9\x86\x57\xdb\x3c\xa8\x6f\x93\x25\xe0\xe6\x7a\xf7\x65\xb2\x6d\xb8\x82\xef\x6c\xf7\x60\xb6\xe7\x84\x94\x4d\x2b\x73\x6d\xd3\x4a\x53\xc2\xe7\xa3\xee\xfd\x9a\x1c\x3d\x49\xbb\xa3\x34\x2d\xa8\x8a\xca\x3c\x4d\x9b\xa5\x03\xb9\x7f\x57\xdc\xe0\x0a\x4f\xfc\x7a\x9e\x1b\xf0\xe9\xd6\x95\x70\x3e\x9f\xf0\xff\x78\x81\xf1\x11\x04\x18\x5b\xeb\x2e\x39\x2d\xc5\x39\x7e\xe8\x77\x51\x92\xa8\x84\x2b\xec\xa5\xdd\xbb\x83\xf7\xc9\xa8\xcc\x68\x87\xb5\x88\xfd\xfe\x2e\x39\x16\x79\x59\xa3\xac\xde\x08\x49\x61\xa1\x54\x79\x8f\x50\x58\x2e\x30\xe5\x74\xb8\x7d\x02\x60\x15\x2e\xf0\xb6\x61\xa5\xae\xb2\xb9\xb8\xce\x0b\x33\x0a\xbd\xb2\x1f\xc4\xe9\x7b\xf0\xf0\xc9\x98\x21\xeb\xa1\xf6\x05\x30\x5f\xd8\xc8\x8c\xee\xf9\xdb\xcb\xec\xc9\xad\x1b\xbf\xb8\x7f\x45\x1f\x68\xce\xcb\x04\x67\x35\x5d\x44\xa6\x28\x8b\xab\x08\x15\xb8\xb3\x86\xa7\x64\x2a\xf4\x7d\x72\xf3\x76\xe3\xce\x50\x92\xe1\xd2\xdd\xa5\xa7\x24\x7e\xab\x93\x35\x61\xd0\x11\x2e\xc0\x6d\x75\x95\x5a\x8f\xbc\x90\xfd\x53\x60\xda\x57\xe6\x45\x17\xdd\xfc\xce\xd2\x29\x2f\x65\xf7\x18\xf1\x1d\xbd\x0e\x40\x20\xa6\x7e\x9f\x00\x6d\x55\xb7\x02\xf5\x4c\x82\xb4\x37\x5e\x3c\x88\x36\xf5\x7b\xb9\xe9\x69\xa9\x87\xc3\x06\x45\x3a\x73\x20\x8b\x02\x6a\xe4\xdc\xfa\x19\x35\x1b\x25\x91\x08\x84\x49\x44\x43\x62\x5b\xa2\x2c\x16\xf3\x09\x62\x70\x6c\xb3\x4c\x73\xfb\xa7\x74\xfa\x82\xb1\x48\x51\x98\x68\x74\x65\xe6\x44\x94\x5c\x99\x64\x49\xe4\xc9\x42\x8f\xb8\xdf\x76\x96\xe8\x48\xa4\x26\x3a\x02\x35\x73\x19\xed\xac\x8f\xa8\x96\x25\xbe\x6d\xd4\x70\xb8\x80\x18\x49\x2b\xa9\x15\xff\xc6\x23\x4c\x62\x6e\xba\x3f\x85\xf0\x2d\x6b\x89\x7c\xb8\x19\x7f\x1c\x69\xec\x7d\xf5\x52\x97\xf4\xa3\x99\x12\xd8\xf1\x92\x28\xcf\xdc\x66\x52\x03\x9d\xec\x0e\xc3\xee\x6d\x41\xfd\x2b\x56\xa0\xb5\xd6\x91\x7b\xdd\x11\x96\x1f\xc6\xee\x1d\x54\x4c\x15\xd2\x4c\xb3\x6d\x26\x43\xb7\x8c\xde\x7a\xe9\xcd\x8b\x7b\xc7\x6d\xf3\xa2\x0c\xcc\x52\xab\xe2\x4b\x0e\xbe\xfe\x70\x70\xa0\x7e\x0e\x0f\x95\x98\xc4\x59\x5b\x8a\xac\xb5\x29\x47\x75\x36\xdb\xda\x0d\xf5\x4f\xfa\x76\x2d\x32\x53\x91\x9e\xfc\xb0\x1b\x02\x55\xf9\xf8\xf9\x8c\x89\x43\x47\x3d\x10\x36\xe9\xab\x21\xc9\x91\x7e\xd6\xe4\xdb\x84\x43\x45\xe4\x96\xfa\x46\x07\x62\xad\xa6\x38\x16\x3b\xae\x96\xfb\x15\xee\x5e\xe9\x35\xb6\xc6\x9e\xb4\x3c\xab\x30\x4a\x58\x4e\x5f\x49\x79\x98\x4d\x6d\x0e\x98\x9a\xe4\x68\x76\x79\x79\x3c\x6b\x89\x7d\xab\x27\x71\x0d\xae\x44\x73\x67\xfd\xf3\x7c\xd3\x62\xf4\xd1\x6b\x81\xc9\xd3\x2d\x14\xac\xa4\xfa\x43\x72\x5e\x1e\x9f\xec\x5d\x2d\x9d\xe6\x23\xdf\xd5\x32\x12\xb4\xbf\xab\x25\x55\xbb\xf6\x5d\x2d\x13\x11\x75\x57\x8b\x19\x0f\xd8\x00\x32\x0c\x59\x7d\x57\xcb\x54\xcb\xf2\xae\x96\x54\xe5\xaa\x77\xb5\x64\x0a\xed\x73\x4a\x52\xf1\x13\xbf\xab\x05\x36\xc9\xdf\xd5\xd2\x1b\x36\xbc\xab\x05\x53\x81\x37\x77\x00\x44\xaf\x78\x57\x4b\xa2\x32\xe2\x5d\xad\xbe\xf8\xa9\x0d\x4e\x2d\xe3\x09\x0d\x11\x75\x27\xb8\x9e\x6e\x1c\xe2\x14\xc4\x94\x81\xe8\xb2\x7d\x7d\x0d\x6f\x5b\xd7\x8c\x0f\xcd\x6a\xc4\x30\x27\xc2\xfc\x47\x64\xc1\xe0\xc5\xb0\xb5\x49\x75\xed\xf0\xe1\x8e\x70\xf0\x59\x79\xb7\x31\x41\x09\x7c\x5d\x94\x13\x91\x3d\x76\x59\x92\x50\x27\xd0\xd3\x7b\x81\x0f\xd4\xba\xaf\xa4\x5a\x33\xbd\x96\x34\x75\xc6\xf7\xb5\x84\x0f\x3c\xf9\x68\x5d\x90\x8b\x74\xf4\xcf\xb8\xfa\x02\xa1\x4d\xef\xf5\xdb\x32\x39\x9c\xdd\xd1\x04\xf2\x4b\xf4\xe6\x00\x61\xe1\x22\xe4\xab\xf4\x89\x85\x5c\xed\xff\xc8\x44\xe4\x91\xd0\x99\x32\xf0\x96\x0b\x4f\x1e\xdf\x34\xff\xd4\x4b\x25\x97\xcd\x3f\xb5\xb6\xb2\x3a\x53\x76\x1f\x18\x11\x95\xc9\x21\x8c\x23\x7f\x36\x26\x5f\xe8\xfb\xb7\x1b\x40\xe4\x88\x0a\x07\xb0\xd6\x4e\x07\x47\xe0\xf6\xf4\x44\xd9\xdb\x21\x5c\x61\x72\x55\x4f\x1a\x72\xf2\x17\x84\x5e\xac\x01\x0c\x5a\xbe\xd4\x03\x3b\x25\xec\x76\x40\xe8\x89\x37\x8e\x0c\xc3\x1b\xc2\xa5\x69\xbb\x0a\xd9\xe8\x79\x95\x5d\x48\xbb\xc7\xf8\x75\x84\x6c\xe3\x83\xb9\x42\x0f\xaf\x0c\xc9\x78\x49\x62\x2f\x7d\x61\x3d\xaf\x57\xbf\xb9\xb9\x31\x56\xd7\xd2\xa6\x2a\x02\x89\xa1\xa3\x86\x35\x11\xbc\xb0\x81\xa7\x07\x67\x88\x1a\xa5\xed\x3e\x43\x4c\xad\x6f\x46\x02\xb4\x62\x59\xcd\x0e\x1b\xdb\x83\xd7\xb5\xe3\xea\x3e\x99\x17\x80\xdb\x18\xe4\x1a\x7a\xaa\x5e\xdb\xbf\x27\x76\x22\x86\x46\x86\x79\x96\xde\xca\x57\x77\xf2\x6a\x1f\x64\xec\x2b\x39\x1a\x3e\xc0\x28\xf5\x7b\x30\xc9\xc3\x5f\x2a\x76\x7b\xda\xdc\x46\x52\xbd\x26\xd4\x08\x1f\xde\x9e\x7e\x19\xe8\x00\x4c\xf3\xe5\xa0\x3d\x1c\x8f\xaa\xa2\x2a\xaa\xed\x44\x92\xdd\xe2\xb2\xc2\x80\x97\x0d\x43\xf5\xfe\x73\xff\xa6\xf9\xa7\x56\x85\xa7\x3f\xab\xb8\xf9\x67\xc7\x55\xa4\x04\xe3\xf4\x6f\x86\x81\xdc\x85\x4a\x4b\x9c\xfe\xf4\xb0\xa6\xce\x80\x06\xa2\xf7\x74\x06\x9e\x04\x5d\xdd\x1f\x78\x12\x64\xc5\x1a\xc0\xe0\xa8\x2d\x48\x3d\xd6\x60\x9a\x04\xf5\xe0\x0d\xe1\xd2\xe4\x80\x66\xb3\xd9\x95\xd6\x01\x4d\x82\xc4\xa1\x0e\x57\xe8\xe1\xb5\x67\x12\xd4\x4f\xdf\x3a\x09\x22\x37\x43\x1b\xaa\x6b\x93\x20\x15\x01\x98\x04\x05\x7e\xf3\xcf\xae\x4e\x65\x12\x64\xc1\x19\xa2\x46\x68\x12\x64\x35\xb5\xbe\x49\x10\xd0\x8a\x29\x84\x29\xb7\xca\x8d\xf2\x73\x96\x6f\x13\x6c\x0f\xf6\x35\x83\xa5\x7f\xba\xd6\xef\x88\x06\xcf\xd8\xc6\xd5\x7d\x32\x97\x35\x74\xc6\x36\xbe\xea\xb5\xfd\x7b\x62\x8f\x37\x7c\xc6\x76\x4d\xe5\xab\x3b\x79\xb5\xc3\x34\xf6\x55\x9c\x5e\xf5\xd8\xa5\x3e\xff\x00\x5d\x97\x3a\x69\x33\x51\x35\xcc\xdb\x74\xf8\xf0\x26\x8d\xf3\x36\x1b\x66\xef\xbc\xcd\xc4\xf1\xa8\x2a\xaa\xba\x2e\xde\xb6\xc4\x28\x8e\xca\xd3\x71\xdb\x7e\x7e\xbb\x51\xbe\xbe\x89\xfb\x03\x07\xdc\x0f\x4c\xee\x72\x05\x1f\x8c\x6f\x9b\x12\x37\xd3\xca\x9f\x74\x24\x9c\xd7\x69\xb2\xde\xe2\x5d\x5e\xb6\x1b\xb2\xe8\x75\x4a\x1b\x61\x85\xd0\xde\x57\xf9\xe6\xef\xbe\x8f\xfc\x2f\x24\x12\x7c\xf3\xa5\x38\x71\x2f\xd0\x3e\xc9\xc8\xee\x0b\xf8\x83\x06\x78\xbc\x89\x74\xde\x01\x37\xdd\x76\xf4\xf4\x5e\x29\xd0\x66\xbc\xca\x05\x55\x81\xec\x57\x37\x6e\xb4\x53\xbf\xea\xa1\xac\xde\xab\x7d\xc9\x55\xb6\x43\x2f\xe2\x35\x1d\x12\x51\x7a\x22\x9d\x4a\x53\x7b\x25\x01\x49\x0f\xa1\x4f\x05\xb6\xbc\xba\xe9\xf6\x20\xb9\x19\xe1\xf8\x9a\xc6\x82\x00\x23\x1c\x5c\x99\xb0\xd7\x5b\xed\xdc\xa6\x5a\xcc\x2e\xbb\xd4\x15\x0c\x57\x20\x10\xe5\x7c\xe0\x46\x7e\x4d\x62\xc8\xc1\x2d\x55\x37\x42\xf4\x83\x4a\x01\x5e\x94\x98\x05\xc2\x1a\x66\x8d\x00\x0b\x4d\xa0\x93\xad\x65\x36\xb6\xd6\x7b\x6a\x09\x7c\x30\x97\x9f\x56\x10\x1b\x14\x63\x22\x5c\x0e\xb1\xa9\x46\x32\x03\x54\xef\xbe\x04\xb2\x52\x16\x44\x20\x9c\x05\x1c\x72\xec\x0f\x78\xcd\x5c\xd1\xb6\x9b\xee\x35\xb7\xc2\xca\xa8\x67\xb9\xea\x4e\x18\xbd\x05\xf3\x70\x07\xe0\xea\x78\x13\x47\xf1\xc2\x3a\xc6\x17\xf2\x68\x63\xb4\x4d\xc3\x5c\x07\x5b\x47\xba\xde\xb4\x0a\x96\xda\xae\x8e\xba\x64\x69\x99\x24\xd9\x81\x37\x9f\xe8\xa4\x2d\x22\xd5\xe1\x36\x91\x4e\xad\x22\x9d\x42\xdd\x32\x8b\x54\x03\x5b\x45\xaa\x37\xad\x82\x49\xdb\xb8\x84\xcf\x0c\xf3\xa0\xaa\xdf\x47\xa1\x9d\x21\x26\x54\x1c\x38\xbe\x12\x00\xeb\x07\xfd\x4d\x98\xb6\x05\x77\xaa\xb6\x19\xb4\xef\xb0\xff\x9c\x24\xdf\xe5\x37\x6f\xbb\xe7\x28\x61\x81\x97\x8c\x3f\x7c\x4c\x2b\x7b\x19\xbe\xaf\xbb\x1e\xd1\x3f\x49\xa7\x84\xaf\x97\x2d\x72\x51\xe2\xdb\x24\x3f\x55\x42\x85\xb6\x48\xa8\x44\x77\x69\x31\x04\xc5\x5b\xca\x45\x72\x4f\x60\x1f\x29\x01\x48\x2b\x57\x38\xb7\x8b\x47\x77\x76\xc8\xaa\x6a\x95\xe4\x85\xf8\xe8\x78\x8b\xe6\xbf\xa6\xf8\x28\x8c\xb0\xe5\xfc\x85\x74\xdb\xc9\xd2\x74\xdb\x49\x7b\xe5\xbf\x64\x5d\xfd\x97\xb0\x6c\x51\x85\xe9\xab\x4d\x92\xca\xbd\x70\x8e\x8f\x17\x44\xb9\x66\x52\xe2\x7f\x0d\x7b\x6a\x80\x49\x86\x5d\xa2\xc6\xfa\xbf\xc6\xc7\xa2\x7e\x50\xce\x10\x91\x0b\x4b\xd9\xc6\x17\x6d\x7e\xc8\x8f\x07\x31\x02\x96\xef\xce\x64\xca\x2b\x21\xfd\x7c\x28\xf1\xae\x5d\x99\x40\x20\xe3\xf3\xad\xe4\x7b\x31\x27\xc7\x5e\xaa\x37\x3e\x72\xaf\xe0\x41\xcd\xca\x20\x53\xb3\xe1\xcd\xc2\x5f\xf9\x9c\x1c\xf0\xca\x37\x67\x8f\xbc\x3d\xad\xe0\x41\xcd\xca\x20\x53\xb3\xf4\xf5\x77\x4e\x4e\x7d\xe9\x97\xb7\x49\x5e\xa7\x15\x91\xa0\x06\x85\x72\x63\xf6\x8e\xbc\xeb\xcc\x09\x01\xef\x79\x72\xcb\x22\xaf\x4c\x2a\x78\x50\x9b\x32\xc8\x78\x11\x00\x79\xe7\xb5\xb5\x10\xed\xbd\x3e\x3e\xed\x20\xef\xc9\xc9\x68\xa0\x1d\x89\x10\x53\x9b\xf4\xe5\xc6\x0b\x7b\xb1\x0e\xde\x54\xd6\xbd\x68\x23\x6e\xc5\x9f\x16\xf7\xce\x52\x8f\xb5\xef\xd5\x15\xf0\x07\x87\xa0\x91\xa5\x46\x04\xb2\xc3\x86\x74\xcb\x3c\xa4\x69\xaf\x6d\x43\x5a\x7b\xb0\x8c\x55\xe2\xef\x96\x71\x1a\xd2\x2e\x2d\xfe\x88\xd9\x05\x31\x06\xb8\x77\xa2\x7f\x5d\xe9\x9d\x9a\x30\x4c\x59\x49\x6a\x7c\xe4\x93\x7a\xce\x4e\x77\xda\xb8\x5d\x42\xbc\x95\xdf\x21\xe4\xb3\x77\x83\xf3\x97\xc9\xf3\xba\x52\x8c\x83\x71\x5e\x33\x54\x69\x1f\xce\x5c\x3d\x35\xdd\xb1\x23\xae\x3f\xc9\xac\xe4\xd7\xd3\x71\x9b\xd7\x65\x77\xab\x16\xd9\xcf\x34\x05\x76\xc4\x4f\xf5\x9d\x54\xa4\x88\x76\x24\xc9\x0e\xb8\x4c\xa0\x85\x0b\x09\xe7\x6d\x33\x8e\x77\x08\x26\xc2\x9f\x87\xe0\x2c\x11\x10\x51\xd5\xed\x7f\xca\x01\x94\x30\x50\x4c\x3e\xf4\x7d\xa1\xfa\xdb\x43\x29\xce\xd7\xf8\x00\x9e\x37\xff\x2e\xe2\x49\x91\xb6\x86\x76\x0a\xca\x01\xc4\x63\x3d\x7b\x09\xdc\xba\x25\xf4\xbc\xa5\x7e\x56\x6e\xa0\xa6\xf9\x77\xa7\x8a\x4a\x8c\x33\x7a\xb2\x4d\xdf\xde\x05\x6b\x6a\x76\xa3\x6b\x6a\x46\xb6\xc5\x3d\xb2\x87\xe2\x03\x5a\xb4\x87\x0b\x5f\xe9\x8f\xa6\xc9\x4e\x37\x8b\x29\xd9\xd3\x5e\x1f\x4e\xc7\x6d\x86\x92\xd4\xf0\xbc\x8c\xbe\xcd\x2e\x54\xcf\x5d\x88\x57\x93\x5c\x3d\x45\x15\x5f\xc8\x12\x1e\xea\xa3\x48\x8e\x17\x56\x0e\x46\x15\x76\x93\xcc\xcd\x4f\xb5\xf2\xd8\x9f\x01\xa9\x17\x43\xe8\xbd\x43\xae\x7c\x99\x74\x05\xec\x06\x18\x61\xcc\x8a\xe7\x3f\xba\x13\xf9\xa8\xab\xc2\x1f\x0b\x11\x8a\x5a\xd7\xd6\x95\x40\xf7\xae\xf0\x59\x48\xc7\x8e\x17\xa1\x82\xe4\xfd\x84\x03\x4b\x1b\xf1\xeb\x19\x4a\x71\x59\x9f\xa5\x83\x5f\x23\x8f\x48\x43\x09\x42\x42\xd5\x39\xcc\xe4\x2d\xad\xca\xf0\xa7\x48\xf4\x7f\xf4\xc7\x59\x97\xcd\x10\x27\xb0\xb7\xc5\x84\xfd\x38\x69\x3b\xbc\x5b\x94\xd7\x85\xfa\xc0\x24\x23\x1c\x27\xd5\x31\xa9\xc8\xac\x7d\x22\x17\x25\x5b\xed\x75\x80\x29\x5c\xd1\xf1\xa2\x34\xaf\xa0\xfa\x0c\x62\x0a\x6e\x4d\xa8\x66\x1b\x2c\x89\x0f\x83\x24\xd0\x4e\xef\xb8\x5a\xa2\xe5\x62\x0a\xad\x1e\xe2\xdd\xce\x8f\xd5\xfd\x94\xf1\x02\xaf\xa2\x85\x42\xca\x01\x1d\x62\xb4\xc2\xe1\x76\xaa\xa2\x8a\xf2\xe7\xb3\xcf\xed\x7c\xd6\xcc\x56\x28\x84\x4c\x03\xdb\x29\xdb\xd2\xbf\x81\xdf\xf0\xc6\xf1\x4e\xcd\x59\x6d\x23\x7c\xb3\x0b\x44\x3a\x30\x63\x68\x81\x03\x2c\xb5\x07\x72\x35\x9b\x87\x8b\x15\xc7\x52\x9e\xf4\xbf\x41\x8b\x78\xba\x85\xfc\x46\xb4\xbb\xc1\x53\x85\xb1\x1d\xc2\xdb\x28\x52\x48\xc1\xbc\xed\x96\x38\xd8\xce\x55\x54\x80\xbd\xc5\x62\x1e\x74\x42\x93\x9f\xf3\x46\xab\xd9\x6c\x16\x42\xdc\x85\x31\x8e\xb5\x77\xd7\xb7\x51\x14\x07\x32\x25\x98\x39\x3c\xdb\xae\x22\x5f\xc1\x04\x78\xbb\x99\x4d\xe7\xd3\xd9\xe5\x0f\xdc\x31\xbe\xc3\x0f\xbb\x12\x1d\x71\xe5\x14\x65\xbe\x2f\x71\x55\xb9\x5b\x72\xa2\xb6\x4c\x0a\x5c\x9d\x77\x65\x7e\x14\x27\xb1\xad\x71\xcf\x48\xf2\xe2\x52\xe7\x20\xd4\x77\xfc\xcb\xe5\x0f\x6e\xfe\x5e\xc9\xbf\x47\xda\x1e\xa7\x78\x16\x4e\xa9\x41\xde\xb0\xff\x1e\x30\xd3\x07\xa1\xbe\x13\x55\xda\xd3\x8c\xc6\x03\x53\x3a\x66\xc7\x3f\xd9\xee\xa0\xdd\xef\xdd\x3e\x38\x4a\x6e\xaf\xb2\xe4\xee\xc2\x6e\xae\x67\x58\x42\x18\x73\xd6\x96\xee\xb9\xc2\x49\x2e\xe9\x7d\xcb\xa1\x98\x40\x54\x27\x1d\x73\xbc\x05\x8d\xc6\x4a\x34\x57\x80\x46\x88\x2c\x37\x66\x49\xf1\xa4\x2b\x65\x25\x8e\x2c\x5f\xed\x94\x21\xe7\x8f\x3e\x03\xec\xb6\x0f\x02\xce\xe6\x31\xde\x4f\x80\x13\x6c\xf3\x57\x4e\x38\x7f\x31\x11\x42\xa9\xf6\xf7\xdc\x7f\x61\xa8\x69\x86\x2c\x15\x1a\xca\xdf\xaf\xf4\xa3\xc5\x6e\xfe\x19\x32\xfd\xc9\x73\x0c\x3c\x18\x4b\xc6\x1b\xf1\x44\x33\x5f\x4e\xc4\xca\x10\xd9\x24\xdb\xc7\xe3\x78\x21\x2b\x50\x0c\x92\xb7\x87\xb2\xe4\x48\x17\xb8\x90\x87\x74\x42\xfe\x50\xb5\x93\x64\xbb\x24\x4b\x6a\x32\x6e\xc6\x57\x1a\x5d\x43\x1d\x67\xbd\x49\x2d\xfb\x00\x84\x08\x3c\x0f\xc4\xe7\x81\xa8\x71\xac\xd8\x5d\x4f\x56\xb3\xc7\xe8\xd4\xda\xcf\x16\xf7\x6c\x71\x7d\x16\xd7\x9f\xd9\xee\x31\x3a\x80\xc0\xb3\xdd\x3d\xdb\x5d\x9f\xdd\xf5\x7e\xda\xe8\x31\x3b\xbd\xfe\xb3\xd5\x3d\x5b\x1d\x60\x75\x24\xa7\xad\x1e\x92\x66\xc5\xd0\xf3\xb7\xec\x2d\x09\x02\x9f\xd0\xff\x71\xb7\x79\xfc\x70\x56\x17\xd6\xbf\xe5\xf9\x71\x1d\x5c\x44\x14\x96\x4b\xc7\xb3\xb6\x05\x37\xdf\xfe\x8a\xa3\x5a\xbd\x6d\x52\x84\x79\xc9\x71\xef\x76\x19\x6a\xf5\x42\x6e\x8a\x4a\xf2\x74\x8c\x9d\xb7\xc2\xa3\xe3\xf2\x46\x0e\xfa\xc1\x8b\xd6\x68\x0a\xe4\x0a\xe4\x44\xb6\xf2\xfd\x40\xa8\xd0\xf4\x60\xa2\x57\x66\xed\x00\x57\xad\x2a\x1f\xe6\xea\xbc\xe0\xa4\xe8\x37\xba\xb3\xe1\xb6\x09\xde\x1c\xb9\x28\x4c\xfd\xd0\x4f\x4a\x39\xce\x01\xa3\x86\xd9\xb3\xe5\x4e\x8b\xb9\xd0\xe3\xa4\xaa\xd5\x8d\x2d\xda\xc6\x95\xee\xfb\x95\xfd\xde\x7c\x7a\x09\x90\xf2\xb5\x6b\xfc\x4d\xf8\xc0\x8d\xe8\xe3\x76\x79\x2a\x1c\x0c\x79\x46\xb0\xe7\x3e\x04\x9d\xa6\xf9\xca\x8a\xc7\x3d\x2e\x89\xd4\x96\x26\xf4\xf1\x3b\x4d\xac\xdd\x39\x4a\xbd\x8e\xa3\x16\x70\xab\x30\x10\x33\xe2\x8b\x47\xfc\xb4\x56\xba\xcd\x23\x4a\x39\xdd\x61\x03\x37\xc5\x2a\x19\x80\xda\x11\xd1\xa1\x5b\x7e\x49\x7a\xee\x62\x10\x95\xf8\xc8\x63\x97\xfa\xa2\x7b\x89\xd4\xcf\xc3\x7c\x3f\xd0\xc4\x08\x69\x77\x0b\x98\xe0\xd7\xed\x93\x24\xdf\x5a\x4d\x34\xcd\x0a\xed\x61\xf3\x9a\x8a\x84\xff\x3e\x93\x68\x3f\x79\x0c\x67\xb9\x91\xfd\x78\x7e\x7b\x6a\x19\x98\xd5\xae\x76\x80\xb7\x01\xe8\x84\x69\xb9\x49\xc7\x0c\x6a\xd8\xf1\x6c\xbb\x96\xdc\xb0\xfb\x17\x6e\x60\x84\xd6\x7a\x2a\xbc\xf5\xaa\x23\x4a\xd3\xf1\xf5\xac\xd5\x46\xdb\xd6\xa0\x6a\x3d\xbc\xf6\xd5\xb6\x57\xb6\x1b\xf5\x95\xd5\xfa\x38\xee\xa9\x4d\x2a\xf7\x8d\x27\x93\xa2\xe0\x71\x61\x17\x95\xb5\xce\x80\x91\x14\x2d\xe3\x18\xeb\x9b\x5e\x46\x7e\xf0\xd4\x23\x09\x27\x60\x08\x0b\x30\x7d\x33\x99\xb1\xe1\xaf\xb7\x9e\xa2\x23\x63\xc3\xa6\x88\xd8\xc2\x6d\x91\x51\x21\xd2\x83\x24\x9f\xc0\x37\x0a\xdc\x27\x1f\x93\x8d\x0c\x75\x3b\x13\xec\x08\x7d\x1d\x93\x6c\xa8\x87\x75\xde\xe6\x20\xac\x41\xc2\x90\xdd\xb2\xdd\x19\x33\x49\xc9\xce\x98\xda\x93\x46\x7e\xc4\x87\x72\x40\xc4\x4d\x6d\x13\xe3\x3a\x65\x03\x81\xd1\xa6\x6c\xad\xd4\x6b\xc7\x4d\x6d\xa3\xae\x09\xd0\xaa\x61\xa1\xba\x0d\x43\xb6\x5d\x93\x60\xa3\x19\x9e\xee\x80\x69\x27\xa1\x61\x36\x5c\x01\x6a\xed\xc9\x20\x93\x15\x9b\xea\x47\xe9\xef\xfa\x18\x4b\x65\x72\x91\x2d\x95\xda\x8a\x46\x7b\xdc\xe6\x09\x40\xa6\x8c\x80\x89\x77\x90\xbe\x99\xcc\x68\xab\xed\xab\xd7\x6b\xb8\x8c\x80\x51\xe3\x1c\x6e\xd5\xb6\x4c\xa4\x07\x49\x52\xa1\x59\xe0\x68\x17\x46\x91\x99\x61\xb3\x1d\xcb\x08\x7d\x1d\x1b\x64\xcd\x4a\x9b\x83\xb0\x06\x09\x63\x84\x59\x73\x49\x49\x66\xcd\xec\x49\x23\x3f\x6a\xd3\x0d\x20\x64\x5a\xdf\xc4\x3c\x44\xdd\x48\x64\xb4\x49\xf7\x54\xeb\xb5\x68\x5a\xdf\xa8\x77\x06\xb6\xea\x5b\x22\x61\xc7\x91\x34\x67\x14\x34\xde\x46\x11\x68\xcd\x94\x8a\xd9\x98\x25\x78\x4f\x9f\x06\x99\xb2\xdc\xe0\x10\xa4\x21\x62\x18\x61\xc7\x5c\x46\x92\x1d\x33\x1b\x32\xea\xbc\x2f\x27\x07\xce\xbd\xf5\xb7\x29\xa5\xe3\x8e\x17\xaf\x40\x99\x76\x53\x6e\xe8\x0f\x4f\x9a\x59\xb7\x7e\x42\x3b\x80\xe8\x86\xa5\x40\xd9\xb0\xe4\xcb\x9b\x7f\x8c\x48\x8c\x61\x9a\xfd\x15\xf7\xa9\x72\x00\x97\x96\x9e\x18\x1c\x72\xc5\x75\xff\x09\x43\xe8\x08\xa0\xd2\x36\xf8\xf6\x16\xbb\x11\x47\x59\xaf\xd1\x7a\x75\x52\xa7\xd8\xa6\x5f\x5f\xdc\xa0\xb5\xd0\x77\x8e\x0a\x64\xda\x55\xa5\x5e\x46\x8f\xba\x75\xa5\xca\x9f\x40\x3d\x56\x0d\xe6\x7a\x97\xe7\x75\x77\xb0\x51\x14\x74\xcf\x06\x38\xf9\x16\x72\xe0\x01\xc6\x9e\x23\x96\xc0\xe9\xce\x0c\xa7\x6f\x85\x01\x30\xe1\x45\x94\x53\x7e\x7b\x8f\x88\xa2\x6f\x1d\xd6\xa8\x68\xee\x77\x00\x59\xad\xce\x59\x7f\x7f\x63\xa3\x3d\xa0\xae\x35\x2d\x66\x9d\x35\x92\xf2\xeb\xd9\xbd\x2c\x0d\xa6\x75\x96\x1e\x4c\x7a\xd4\x50\x90\xda\xef\xb2\xdd\x7a\xf3\xe2\xe3\xd2\xfd\x3d\x19\x46\x49\x7d\x50\xee\x69\xac\x4b\x1a\xe2\xaf\xc7\x98\xc0\x90\x4f\x08\xd6\x8b\x9c\x95\xa6\xaf\x68\x8a\xed\xf9\x14\x83\xc4\x6b\x79\x18\x43\xc8\x06\x85\xd4\x74\xf7\x3c\x83\x02\x7f\xb9\x25\xae\x8a\x3c\xab\xc8\x51\x29\x52\x62\x1c\x6d\x20\x6d\x87\x1d\x53\x90\xa9\xc2\xa5\x7a\x5b\x8e\x72\xc8\xc1\x7a\x72\xe7\x62\x22\x26\xbf\x3a\x4d\xa0\xe0\xb8\xd3\x20\x03\x4e\xa9\x5b\x07\xce\x48\x46\xde\xd6\x4d\x28\x94\x4b\x4a\x33\xa7\x63\x08\x37\x06\x37\x98\xf0\x23\x78\x1a\xd5\xea\xa7\x26\x5e\xa7\x8e\x9f\x46\xda\xbd\xed\x1c\x3e\x88\x56\x9f\xac\x3f\xbd\xed\x58\xfa\xf3\x74\x1a\x78\x3a\x19\x3f\x9d\x14\x1f\x23\x27\x8b\xf9\xbf\x57\x13\x07\xe2\xf4\xfb\xb0\xf0\xa7\x68\x66\x80\x6a\x3e\x48\x33\xe6\xde\x3c\x99\xf4\x9f\x4c\xbe\x4f\x26\xc1\x47\xc8\xc8\x76\xc9\x8a\xd9\xb6\x85\x9b\x5a\x18\x07\x46\xd6\x4c\x33\xc4\x6b\x67\x84\xa3\x78\x61\xea\x11\x0b\xca\x41\x76\x68\x27\xda\xcc\xde\x06\x12\xbd\x96\x99\xe1\xed\x7d\x7a\x62\x1d\x1c\xcd\x1e\xd5\xc6\xc0\xc8\xfc\x08\x4d\x3e\x51\x3f\x7a\xda\xb0\x45\xbf\xa7\x11\xf9\x13\x49\xf5\x89\x04\x77\xb5\x6c\xce\x1f\xc7\x92\x1f\xef\x2e\x7a\x45\xfe\x9e\x3d\xd2\xd3\xf4\xa2\x57\x55\x8f\x77\x81\xd6\x18\xf7\x24\x12\x7d\x1a\xa1\x5d\x2b\x97\x1e\x57\xad\xac\xcf\x9b\x4e\xbe\x56\x56\xfa\x1a\x44\xd0\x9f\xcc\xe3\x6b\x01\xd7\xa8\x72\x11\xe9\x6c\x4c\x14\xca\x43\x6b\xc8\xdc\x69\x32\xb6\xc6\x41\x4a\x83\x29\x63\x99\x82\xb0\xd9\x72\x55\xc4\x33\x7f\x15\xcc\x40\x88\x32\xf4\xb6\x2e\xdf\x5a\x3d\x3c\x80\x6e\x0b\x3a\x1d\x7a\x63\x12\x23\xa8\xb7\xe8\xc3\xa8\x37\xf3\xbb\x11\xd4\x5b\xf4\x61\x01\xf3\x4a\x59\x0d\x22\x70\x2d\x07\x83\xe4\x39\x88\xc0\xb5\x1c\x0c\x92\xf9\x20\x02\x60\x48\xe3\x2f\xfd\xf5\x5b\xab\xd1\x8f\x83\xe2\x1e\x80\x2d\xc8\x76\x0c\xf6\x20\xda\x82\xd4\xc6\x60\x0f\x0a\x88\xd7\x49\x69\xa0\x99\x5e\x55\x7f\x88\x24\x07\x1a\xe9\x55\xf5\x87\x48\x7b\xa0\x89\xea\x21\x8b\xbf\x39\xd7\x63\x74\xb2\x93\xef\xb5\x51\x65\xe1\xda\x67\x1a\x43\xa9\x83\xe8\x2a\xf5\x01\xa6\x60\x6f\x6f\x34\x81\x31\x1c\x0c\xea\xf1\x68\x02\x07\xf5\x2b\x4d\xaf\x3e\xc5\x89\x4d\xbf\x3a\x45\x6c\xb3\x36\x99\xa1\x0f\xa4\x0d\x61\x5f\xa3\x4b\x5b\x6b\x63\xeb\x8f\x69\x7f\x48\x6f\xc7\xd6\xef\xd3\x63\x47\xcf\x70\xd4\xa5\xfb\xc0\x05\x7d\x97\xa5\xa7\x82\x04\xb8\x43\xff\x30\x9d\x9b\x91\x6f\x2d\x57\x6b\xbd\x96\x2b\xb7\x77\x43\xe9\x98\xed\x3e\x02\xb8\x77\x20\xae\xed\xa3\xe0\x64\x54\xbd\x11\x53\x61\x99\xa2\xf6\x31\xcf\xc0\x31\xc5\x53\x1b\x76\x80\x86\xb5\xed\x12\x62\xdb\xed\xad\xab\xf2\x25\x54\x1a\x82\xf2\xf5\xd4\xfa\x56\x9d\xb2\x59\x60\x28\xcd\x81\x42\x1c\x4c\xcf\x91\xef\x71\xe4\x4c\xc1\x8f\x0e\x81\x84\x60\x19\x43\x7c\xb1\x45\x98\xce\x5a\x7b\xc3\x2c\x78\xfc\x43\xc2\x31\x88\xf8\x8a\x53\x25\x36\xb2\x23\xa5\x3c\x84\xa4\x33\xe6\xc2\x4c\x90\xd0\xb5\x82\x96\xb9\x6b\x2f\x10\x01\x2f\x54\x93\x70\x4c\xe6\x7c\xd5\x55\x6d\x36\xca\x63\x8d\x7a\x00\x49\x45\xdc\x9c\x35\xc3\x5e\x77\x03\xad\xab\x4d\x5b\x62\x90\xde\x9e\x01\xde\x11\xd7\x21\x98\x64\x7d\xd5\xd5\x73\x46\xb2\x23\x05\xdd\x4b\x4f\x95\x32\x63\xca\xb0\x4f\x1b\x22\x74\xad\x88\x65\xd6\xda\xbb\x22\xc0\x0b\xef\x24\x1c\x83\xa0\xaf\xbb\x4a\xcf\x46\x79\xa4\xac\x87\x90\x54\x9d\x35\x63\xcd\xb0\x7f\xd8\x40\xeb\x5a\x89\xcb\x0c\xf2\x6b\x12\xc0\x3b\xfc\x44\x14\x83\xbc\xaf\xbb\x1c\xd0\x42\x78\xa4\xb8\x07\x50\x54\xa5\xcd\x18\x33\xec\x72\x85\x49\x5d\x2b\x6c\xce\x1e\x3e\x6e\x71\x2c\x4e\x2e\xfb\x0e\x8a\xb3\x3d\xaf\xdd\x75\xd1\xbe\x7a\x71\x9f\x4e\xd4\xd1\x4a\xd8\x36\x40\x0d\x91\x14\x00\xe5\x09\xb9\x9d\x10\x00\xd0\x9b\x08\x00\xc0\x6d\x12\xe3\xbc\xeb\x0d\xda\x56\x79\x7a\xaa\xe9\x05\xa2\xcd\x2c\x97\xef\xe3\xa5\x47\xe8\x85\xc3\xc9\xe2\x75\x7e\xdd\xcc\x5a\xeb\x40\xb0\xd8\x3e\xac\xce\xca\xc5\xc1\xf3\x85\x17\xce\x5f\x00\xd8\xb3\xed\xc3\x54\x45\x5e\x36\x98\x77\x38\x4d\xcf\xc7\x24\x93\x6e\x09\x6c\xb7\x82\xae\x0c\xf7\xc6\xda\xe7\x7a\xe2\x24\x13\x4f\x9b\x7f\xe3\xaf\x4c\xec\xd9\x57\xdc\x83\x4a\xfb\xe5\x10\x8b\xf9\xc7\x29\xaf\x81\x67\xbc\xe5\x01\xa8\xdc\x4a\x48\xeb\xbb\x69\xb7\xfd\x38\x9c\xc1\xb7\x43\x13\xbc\xea\x28\x5d\xc4\x2b\xa3\x91\x2c\x3c\xbd\x4e\x56\xb8\x0f\xdc\x76\x0d\xb6\xf1\xe6\x77\xdf\x67\x4f\x8c\x48\xbb\xab\x7d\x87\xcc\x0e\x77\x49\x5a\xe3\x72\x8d\xd2\xe2\x80\x5e\xe6\x05\x8a\x92\xfa\xe1\xf7\xa1\xff\x6a\xc3\x7e\xaf\xbd\x90\xf1\xc1\xcf\x35\xd3\x3f\xa4\x6d\xee\x6d\x0b\xf6\x0b\xd5\xe1\xc6\xe6\x62\x63\xed\x39\x7c\xda\xf5\xf6\x1a\xbb\xa2\xc0\xa8\x44\x59\xc4\x5e\x5d\xeb\x46\xb1\xd2\x42\x67\x63\x6b\xdf\x11\xd7\x98\xc7\x3c\x46\xa9\x9b\x17\x38\x53\x2f\x16\x61\xb0\x6e\xd0\xed\x92\x7b\x1c\xb3\x11\xc7\xb2\x4d\xda\xc8\xe3\xe7\xb7\x03\x7f\xee\x6f\xc4\x5b\xee\xb5\xfb\x40\x79\x17\x78\xb9\x5b\x45\x65\x9e\xa6\x0d\xf7\x75\x7e\x8a\x0e\x9b\xfc\x54\x37\x6a\x6b\x99\xf4\x76\x28\xc6\x0e\x63\x38\x4e\x50\x9a\xef\xcf\xc0\x75\x97\x52\xd1\x2e\x2f\x8f\x8e\x37\x65\x17\x51\xeb\x97\x59\xf3\xbf\x74\x3c\x01\xc9\x44\x49\x6d\x88\x22\xa6\xa8\xc6\x2f\xfd\x89\x1b\xce\x5f\xbc\xda\xb8\xc7\xca\x0e\xcf\xad\x60\x0b\x8c\x0b\x25\xc9\x6c\x22\xd1\xea\xfa\x36\x9e\x7c\x0b\x43\xbe\x89\x1b\xff\x95\x68\x44\x8c\x99\xd6\x96\xdc\x7b\xae\xef\xb6\xe4\x81\xde\xe5\x2d\x73\xad\xc7\x29\xea\xc3\x85\x7b\xc0\xf9\x25\x31\xa4\x1a\x7b\xdd\x0f\xa8\x07\x1f\xd0\x00\xee\x99\x8c\xd2\xa4\x58\x77\x4e\x5c\xf6\xc3\x1a\x4c\x73\xc5\xab\xd5\x4a\x2f\x15\x1d\x5f\xf8\x4a\xf7\x70\x9d\x51\xc3\x67\x40\xa6\xc5\xbd\xb3\x52\x1c\xb0\x7a\x04\x04\xc6\xe1\x82\x69\x3a\x11\x97\x79\x71\xed\xb0\x9d\xf9\xd0\x83\xa4\xbe\xaf\xd2\x27\xa3\xf1\x0c\x3a\x2e\xc1\x6f\xe9\xd5\x92\x0c\xae\xa4\x78\x3b\x56\x8d\x3d\x9b\x2b\xdd\xbc\x6e\xcc\xc0\x90\x57\x68\x94\xaa\xfc\xea\x71\x21\xb5\xe5\x86\x9d\x19\x89\x47\x4c\xb4\x63\x40\xfc\xa2\xfd\xb6\x0f\xe4\x70\x8d\x66\x70\xf2\x71\x1b\x8a\xaa\x1e\x02\x69\xf8\x16\xae\x49\xa1\x31\x0b\xce\x61\xc9\xbd\xa0\x84\xc8\x43\x9d\xaf\x9b\xff\xd2\x12\x7c\xe2\x1d\xf9\x1a\x03\x4e\xf7\x66\x88\x4e\xa2\x7d\x28\x12\xaa\x43\x62\xfd\xeb\xee\xa7\xfc\x52\x23\xaf\x41\x5d\xf6\x16\x95\xee\x11\xa3\xea\x54\x62\xc3\x0c\xcd\x5d\xad\x56\x4d\x28\xa7\x63\x7a\xde\x4c\x7a\x98\x94\xe7\xd2\x55\xd1\x94\x5e\xfb\xfe\xb2\xf6\xe6\x83\xe4\x32\x28\x68\xe1\x77\xf7\x4f\x93\x07\x38\x1c\xd1\xbb\x70\x37\x01\x0e\xb6\x39\x3b\x99\x63\x1d\x6d\x06\xa4\x56\x02\xfc\x26\x9c\x69\xc3\xc7\x45\x67\x7d\xb5\x0a\x05\xd6\x53\xce\xf6\x8a\xa2\x7b\x75\x9e\xa7\x75\x52\x00\x72\xeb\x86\xe4\xd2\x57\x26\xed\x64\x76\xb3\x43\xc7\x24\x7d\x58\x1f\x70\x7a\x8b\xeb\x24\x42\x4e\x86\x4f\x78\xf2\x9f\xf9\x9f\x93\x6f\xca\x04\xa5\x93\x0a\x65\x95\x5b\xe1\x32\xd9\x81\x8f\xe3\xf0\x1b\xa9\xca\x23\x4a\xa5\x49\xd3\x4c\x9d\x34\x75\xcf\x4e\x28\xd7\xfd\x88\x7f\x57\x35\x2a\x6b\x78\xc6\x23\x4e\xb4\xba\x82\x2e\xa4\x90\xb2\x14\xd7\x35\x2e\xc9\xb3\x3b\xcd\xb0\x61\x7c\xdd\xe5\x65\xec\x6e\x4b\x8c\xde\x49\x25\x10\xd6\x5d\x89\x8a\xb6\x40\x7a\xc2\x87\xf6\xb0\xcf\x5d\xd1\x3e\xd3\xb6\xa8\x1d\x31\x05\x19\xfd\xd6\x4a\xf4\x5b\xab\x0e\xbf\xce\x0b\xe9\x2d\xc0\x76\xa4\x92\xf1\x40\x66\xb1\x1c\x55\xba\x40\x8d\x3d\x64\xab\x3d\x4c\xc3\x91\xd9\x75\x65\x46\xd2\x12\xb2\x78\xd3\x1a\x40\x58\x62\xc3\x4d\x32\xf9\x29\x96\xd0\x57\x9f\x58\xba\x19\x7f\xe5\x79\x33\x03\x06\xbe\x41\xf0\x36\x51\x59\xe6\x77\x80\xf1\x2b\x97\xb1\xfb\xf2\xf2\x02\x38\x9a\x48\x0d\x99\xb8\x50\x49\x07\x8e\xd2\x94\x1c\xf8\xe6\xfe\x0b\x59\x20\x42\x7c\x61\xbe\x8a\xbe\x9e\xe4\x48\x07\x91\xc4\xa8\x28\xb4\x45\x68\xa8\x0d\xb6\x4f\x10\x6d\x54\x97\xcd\xaf\x62\x7b\x5c\x9b\x84\x7e\x4f\x2f\xf5\xeb\xdf\xae\x6f\x13\x6c\x8f\x7c\x31\xf2\x5f\x6c\xe4\x1b\xec\x88\xa5\x1b\x5b\x92\x5a\xa3\x1b\xad\xa0\xf6\x20\x99\xf2\xe6\xf8\x6c\xa6\xb7\x3d\x9f\xb7\xb8\x11\xb6\x73\x80\xcd\x51\x01\x41\x0d\x0e\x36\x19\xad\x31\x39\x55\x03\x34\x07\x1a\x8e\x38\x61\x13\x34\x08\x77\xf2\x8a\x36\x8d\x8a\xd4\xad\xe6\xfa\x36\x8b\xbc\x20\xeb\x61\x53\xe2\x46\x9b\x7e\x2e\x94\x55\xa3\xe0\x8e\x96\x0b\x31\x97\xc2\x23\xd8\x63\xc2\xe0\xec\x5f\x34\x0c\x7e\xa8\x25\x52\x14\x45\x57\x2c\x91\xcc\x73\x35\x5f\x99\x86\x85\xd0\x5c\x0d\x40\xd2\x82\x3a\x33\x4b\x12\xa4\x45\x1b\xa7\x2b\x4c\x0e\xa5\x71\x59\x1c\xec\x32\x9c\x85\x62\xf1\x4a\x57\x09\x4e\xa2\xaf\x3c\xd9\x16\xe1\x6c\xf1\x21\x3d\xae\xdf\x3d\x00\x26\x1f\x6e\x37\xbc\x48\xbb\x6c\xfe\x59\x16\x44\xdb\xe6\x9f\x22\xe2\xd6\xf7\x3a\xdd\xf8\xec\x96\xd3\x5d\xde\x8d\x30\xd3\x62\xbc\xf5\x88\x83\x98\x28\x7f\xaf\xd1\xae\x06\x87\xb7\x3c\x61\x7d\x5c\x38\x97\x9b\x54\x4e\x8e\x07\x3a\x93\x8c\x29\xd6\xa7\xf5\x17\x5f\xc8\x7e\x4b\x56\x52\x9d\x17\x1d\x61\x76\x37\x2a\x79\x3c\x1f\x74\xf6\x04\xa4\x47\xc8\x2e\x17\x20\x94\x4a\x46\x38\x7f\xa5\x78\xc9\xee\x34\xb1\xc6\x08\xe3\xbf\xd3\xe7\x46\x33\xa2\x4d\xdb\x39\xe7\x0b\x80\x1f\xe1\x7d\x70\x53\x73\xc4\xb8\x79\xcf\xa5\xf8\x4d\x3b\x29\x0d\x0b\xa1\xd7\x52\xa4\x16\xfa\x2d\x96\x1b\x7a\x4e\x82\xae\x95\x11\xb9\xe7\xb4\xa7\x74\xe0\xc1\x5d\x96\x98\x11\x3a\x0d\xb7\x44\xc9\x8a\x7d\x1e\xa3\x6a\x6e\xc3\x60\xb0\x13\x04\x21\x01\x14\x49\x18\x78\x61\xdd\x66\x89\x80\xe1\xda\xb6\xb2\x44\x37\x06\x08\xae\x48\x55\x36\x7b\x72\x6d\x80\xb6\x95\x76\xc4\xc9\x93\xd0\x71\xa1\xd8\xd8\x6d\x81\x0f\xd6\x69\x76\x0a\xbd\x9b\x1f\x1b\x7b\xdc\xcb\x0b\xe9\x71\x84\xca\xfc\x54\x41\x8f\x23\x77\x30\xb6\xd4\x31\xe5\x1c\xc9\xb7\x22\x2d\x19\x2e\x57\x7e\xeb\x25\xf6\x7b\x98\x49\x20\x07\xd2\xd3\xfc\x41\x25\xf6\x2a\xa2\x43\xe6\x0e\x72\x52\x1a\x44\xe9\x81\xc3\xfc\xbd\x65\x0f\x2d\x82\xb0\xe4\xb8\x3f\x4b\x73\x1b\xfe\xee\x26\x4a\x53\xfa\xe8\x66\x3b\x2d\x71\xa7\xf1\xab\xc9\x4b\x2d\xb3\xdc\x14\x9f\x61\xc1\x0c\x4b\xcc\x2f\x6c\x0f\x4d\xca\xb9\xf9\x85\xf1\xb9\x49\x0b\x3d\x61\x46\xb3\x43\x11\x76\x6f\x93\x2a\xd9\x26\x69\xb3\x56\x17\x5e\x25\x33\x80\x78\xed\x02\x97\x55\x81\xe9\x25\x46\x01\x9e\x36\x93\x50\xb5\x04\x96\x3e\xbb\xf9\xc8\x63\x77\xa6\x83\x28\x19\xbe\xaf\xcf\x6c\x16\x6c\xc9\xdc\x4f\xe3\x97\x8d\x55\x4e\x4c\x79\x78\x11\x6e\x67\x86\xde\xa8\x0e\x62\x14\x25\xbe\x1d\xc6\x8b\xdb\xc7\x8c\x3b\x8c\x1b\x8b\x50\xfa\x18\x65\xb3\xb3\x41\xec\xfa\x36\x56\x29\xf0\xa2\xf3\x69\x62\x31\x23\x17\xbe\xaa\xa5\x44\x78\xca\xed\xfa\x30\xc5\x33\xcf\xa1\x8e\x20\x6c\x5a\x3f\x09\x8f\xe6\x82\xe4\xce\x6c\xda\x0a\xc1\x3b\x75\xbb\x66\x02\x06\x35\x68\x1a\x30\x75\x96\x4e\x82\x6d\xad\x88\x83\x04\x64\xb7\x09\x05\x65\x9e\x8e\xfd\xf8\x3f\x17\x9f\xef\xeb\x7f\xad\x4f\xff\x10\xac\x3e\x1e\xb8\x78\xa5\x4f\xc1\xc5\xa9\xeb\xa0\xcf\x1a\x6a\xaf\xa8\x7c\x06\xbf\x1e\x42\xb4\x21\x67\xa2\x1d\x5f\x2a\xf0\x7d\x3f\x78\xe5\x34\x22\x1c\xf6\xb4\xc7\x63\x29\x32\x46\x3b\x7a\x84\xfe\x84\x64\x34\xea\xbc\x98\xd0\x34\x43\xf3\x6b\x57\xe6\xc7\x97\x72\x4b\xaf\x26\x75\xfe\x52\x6b\xeb\xd5\x80\xf7\x3d\xea\xdc\xa1\x6e\x75\x30\xeb\x4c\x3d\x45\x99\xef\x93\x78\xfd\xc7\xbf\xfe\xd0\xd0\xfd\x0b\x77\x09\xde\x9f\x93\xa8\xcc\xab\x7c\x57\x7b\x6d\x1b\x64\x19\xff\x5d\xa3\xe7\xaa\x2e\x7f\xff\xd5\x97\x37\x3e\xfd\xbf\xaf\x26\x38\x8b\x85\x72\xbf\x2d\xff\x4f\xac\xea\x5f\x1e\x0a\xfc\xfb\x40\xea\x46\x89\x0b\x8c\xea\x35\xfd\x1f\xf7\x1e\xb0\x04\x3a\x02\x78\x4e\xab\x7d\xf4\xd8\x2c\xf3\x5e\x55\xd2\xee\xfb\xaa\x8c\x1e\x61\x1c\x23\x29\x3e\xc2\x38\xa8\x25\xa8\xf6\x31\xbf\xde\x38\xac\xac\x3f\xde\x38\x7c\x83\x71\xdc\x3c\x89\x71\xb4\x7b\x4c\xd4\xf2\x61\xef\xf7\x9b\xbf\x5c\xb4\x9f\xa3\xc5\x6f\x18\x6a\x2b\x8e\xb7\x4f\x1f\x8a\x43\x12\xe5\x99\x1b\x1d\xf0\x6d\x99\x67\xae\x12\x17\x2c\x98\xea\xf4\xa7\x45\x25\x58\x4a\xd0\x93\x81\x96\xd8\xd7\xac\x60\x78\xda\x70\xde\xce\xba\x93\x8c\xe6\x7a\x48\xd6\x41\xcf\xec\x3c\xa6\x63\x1d\x43\x86\xf5\xe2\xe0\x16\xfa\x05\xc2\xbf\x1a\x74\x6d\xf0\xc5\x9a\xa1\x91\x81\xa2\xe4\x1f\x76\xba\xef\xaf\xe4\xb7\x98\x48\xa5\x49\x52\x79\x5d\x60\xa3\xb9\xde\xe2\x5d\x5e\xe2\x36\xdb\xf2\xd5\xdf\x43\x7f\xba\xfa\xca\xca\x24\x58\x07\x7d\x25\xcd\x0d\xe2\x24\x42\x75\x5e\x56\x80\xfa\x79\x62\xc4\x17\xd7\xee\x6d\x0a\x79\xbe\xe1\x1f\x86\x5f\x6c\xe0\x97\x75\xd8\xb7\x2f\xf9\xe5\x12\x36\x0d\x20\x47\x53\xc4\x77\x7a\x00\x96\x9c\x34\x39\x83\x06\xd7\xe5\x97\xba\x6d\x87\x5d\x42\x2f\xe0\x7b\x00\x1a\x46\xb3\x9a\x7c\x14\x6f\x66\x25\xa6\x8d\x5a\x42\x22\xfd\xef\x2b\xfb\xd4\x43\x4f\xbd\x0a\xc9\x10\x96\xf7\x53\x4c\x47\xe8\x0e\x9f\x97\x32\xf6\x43\x81\xfd\x50\xcc\x47\x1a\x0e\x1f\x74\x8a\xe6\x17\xcc\x69\x1a\xe3\x57\xcd\xbd\xd8\x88\xfb\x1e\xd9\x6d\x73\x82\xee\xda\x6d\xa8\x64\xd0\x8a\x9b\x27\xa5\x0d\x93\x8f\x9e\xc8\xe9\x4c\x93\x5d\x0f\x67\x35\x3b\xcf\x57\xc4\x55\x54\x62\x9c\xd1\x45\xb1\xbe\x2b\xe1\xd3\x72\x97\x7c\x3b\x42\xa7\xc5\xa9\xaf\x66\x78\xda\x41\x4f\x26\xc7\xd3\x27\xf4\x8d\xef\xcf\x25\xda\x1d\x21\x33\xbd\x92\x39\x35\x96\xca\x0c\x05\x1f\xc0\x0c\x68\x6a\x1a\x06\x67\xf1\x68\xdd\xa5\xdb\x38\xe3\xf2\x97\xc1\xde\x76\x65\x34\x77\x35\xe9\x41\xa2\x5e\x8e\x62\xd5\x79\x9e\x6e\x51\x29\x56\xe4\x45\x1c\x2d\x4a\x31\x2a\x77\xc9\x3d\xc7\x69\xff\x6e\x11\xf2\xac\x46\x49\x86\x4b\x77\x97\x9e\x92\xb8\xc5\x53\x8a\x35\x74\x0d\xb1\x45\x89\x53\xf7\x90\x97\xc9\x6f\x0d\x20\x75\xe2\x96\xa4\x56\xce\x2b\x90\xac\x8f\x00\xa2\x05\x92\x4c\x6c\x28\x9c\x8c\xb8\xdf\x88\xd7\x93\xca\x64\x44\xba\x95\x4b\x46\x64\x65\x1c\x31\x43\xb7\x1c\xde\xfc\x14\x8a\xb7\xa8\x6c\x37\xd2\x0b\x28\x52\xb1\x82\x2e\xb7\x27\x17\xca\xa8\x32\x4e\x0b\x2c\xd0\xbe\xab\x4f\xff\xe8\x40\x7c\x27\x7f\x07\x6f\x4b\x38\x52\x9b\x1e\xa5\x3f\x59\xb8\x94\x9e\xbe\x13\x33\xa4\x23\xac\x55\xb1\x43\xcd\xe6\x7a\x4c\xcc\x68\x20\x03\x94\x0f\xe9\x19\x52\xa9\xa0\x46\x83\xba\x40\xc5\xc8\x9a\x90\x64\xaf\x0b\x5a\x10\x2e\xfb\x58\xd4\x08\x62\xbd\xcd\xeb\xc3\xc5\xa3\x81\x84\xed\x7b\x93\x3f\x64\x49\x4e\x48\xd8\x9b\xea\xb6\xcb\xb5\x8b\xf8\x28\xa2\xb0\x43\xfd\x77\xc9\xb1\xc8\xcb\x1a\x65\xf5\x45\x78\x05\x91\x22\x34\x3f\x45\xf8\x21\x89\x3b\x6d\x37\x71\x48\x04\x56\x87\xfc\x4e\xe6\x4a\x84\x26\x19\x49\x64\xa6\xf8\xac\x25\x34\x2f\x1e\x09\x6f\x84\x78\xe3\xfc\xd7\xfe\x1b\xdf\x41\x1b\x7d\x36\xa1\x7d\xa3\x1e\x32\xf7\xf0\x09\xdb\x31\xce\x8c\x8c\xa3\xdd\x2e\xb9\x57\xb6\xa5\x5e\xfe\xe0\x1e\x2b\xf7\x36\xc1\x77\x0d\x1a\x8b\x5d\x31\xbe\x4d\x22\x4c\x83\xec\xc5\x63\xfd\x71\xd3\xfd\xa4\xfd\x7d\x8c\xbb\xdf\xd5\xb1\xfb\x7d\x5f\x19\x5b\xef\xc8\x50\xc5\x4e\xc4\x12\x3a\x8b\x03\x8a\x54\xdc\x63\x0c\x94\xa8\xb5\xdb\x22\x15\xb7\x3a\x02\x25\x6a\xed\xb6\x48\xc5\xbd\xaf\x80\x12\xb5\x76\x5b\xa4\x98\xaf\x22\x0e\xbe\x4d\xb1\xdd\x5d\xb1\x5c\x2c\xc9\x5c\x06\x90\xa4\x6a\x63\xc4\xfd\x40\x88\x04\x20\x22\x96\x46\x2c\xb7\xcc\xef\x44\xcc\x58\xc0\x9c\xd4\x07\x73\xbd\x08\xa7\xa9\x50\x71\x48\x47\xa0\x81\x3c\x96\x04\x95\xa9\x32\xeb\xbf\x8e\x88\xc2\x8e\x58\x08\x11\x54\x66\x9b\x6c\x0e\xda\x36\xb3\x5a\x05\x52\x33\xd5\x71\xa0\xde\x04\x44\x8b\xde\x54\x2c\xb3\xde\xaa\xa3\xa8\x37\xad\x9e\x49\x6f\xa3\xbb\x37\x54\x9b\xe3\x09\x0f\xd6\xf1\xb5\xa4\xaf\xd5\x3c\xdd\x42\xac\x36\x13\x04\xcd\xf2\x51\x68\xe7\x18\x0f\x54\xbd\x80\x68\x51\xbd\x8a\x65\x56\xfd\x31\x16\x55\xaf\xd5\xeb\x55\xfd\xe0\xfe\x8d\xd6\xfd\x70\xca\xe3\x95\x3f\x96\xf6\xb5\xda\x0f\xc8\x3e\x5c\x81\x62\xba\x1f\xa8\x67\x01\xd1\xa2\x67\x15\xcb\xac\xe7\x74\x2f\xea\x59\xab\xd7\xab\x67\xa0\x27\xa3\x35\x0a\xd1\x18\xaf\x3b\x33\x95\x91\x5a\xd2\xdc\x3d\x9d\x03\x59\x26\x22\x63\xbd\x08\x23\x28\x38\xd4\x5e\x82\x3d\x96\xc9\x28\x0a\xe3\xb4\x97\x62\x2b\x2f\x56\x57\xd0\xbd\x5a\xb7\x15\x69\x51\x26\x59\x6d\x9f\x7f\x38\x14\xc7\x50\xc5\x6e\xdc\x32\xae\xc5\xbe\x01\x44\xb3\x89\x13\x64\xd1\xca\xa1\xda\xaa\xa1\xcb\xc8\x43\x26\x5e\x60\xc7\xfb\xc6\x82\x82\xad\x58\xfd\x88\x76\x7a\xc7\x0b\x88\x7f\x7d\xbf\xae\x18\x59\x9c\x10\xb3\x37\xab\x2d\x5d\xfe\x10\x1d\x50\x59\xe1\xda\xf9\xe2\xa7\xbf\x7c\xef\xde\x7c\xb1\x79\xf3\xf5\xef\xbe\xc9\x92\x23\xaa\xb1\x17\x55\x95\xe3\x3a\x87\xba\x2e\xd6\x6f\xde\xc4\x28\xc3\x31\xce\xbc\x23\x7e\x83\x28\xfc\xdf\xfe\x3d\x89\x70\x56\xe1\xd8\x39\x65\x31\x2e\x9d\xfa\x80\x9d\x3f\xff\xf0\x17\x27\xa5\xc5\x5d\xd5\xbc\xc0\x59\x95\x9f\xca\x08\x7b\x79\xb9\x7f\xc3\xe0\xd5\x9b\x3f\xff\xf0\x97\x7f\xfb\x2e\x2f\x1e\xe8\x97\xac\x97\xd1\x2b\x27\xf4\x83\xb9\xf3\x47\x94\x25\x38\x75\xfe\x14\xe3\xec\xeb\x37\x1e\x6b\x2c\xee\x8e\xed\x92\x82\x24\xcf\xdc\xf8\xc4\xbe\xd3\x04\xd5\x06\x2e\xd5\xeb\xec\x92\x34\x75\x8f\x79\x8c\xc9\x7a\x75\x63\x02\x5c\xda\x76\xdd\x1d\xaa\x6a\x5b\xe3\xde\x1c\x6c\xbd\x29\x7e\x82\xe6\xbd\x24\xdb\x25\x59\x52\x63\x80\x85\xa4\xc6\xb4\x31\x37\xca\x4f\x59\xbd\xe6\xa8\x9b\x7e\x14\xa1\x81\x43\x92\xed\x21\xea\x6d\x4f\x42\xb0\x7f\x61\x25\xd0\xd8\xe6\xa7\x2c\xc2\x3f\x64\x13\xb5\xe8\xc7\x93\x5d\x76\x4b\x83\xf0\x96\x73\x91\xfc\x2e\x4d\x8a\x1f\x4f\xf5\x5f\x27\x5a\xd1\xdf\xae\xa6\xfe\x07\x5e\xf1\x1d\x7e\x20\x37\x2a\x54\x0e\x65\xf9\xbc\x2b\xf3\xe3\x24\xf4\x5f\x4c\xe6\xd3\x17\x93\x1b\xff\xc5\xa4\xce\x81\x56\xea\xe4\x98\x64\x7b\x77\x77\xca\x22\x42\x34\x3a\x6d\x93\xc8\xdd\xe2\xdf\x12\x5c\xbe\xf4\xbd\x30\x98\x4f\x7c\x6f\x11\xf8\x13\xdf\x9b\xce\xe7\x93\xc0\xf3\x7d\xff\xd5\xe6\xb1\xf5\x1f\xbf\x57\x67\xe6\xbf\x98\xcc\xa6\x2f\xc6\xf7\x68\x39\x6f\x38\xf2\xe7\x0d\x47\x37\xf4\xf7\x62\x4c\x8f\x0c\xf5\xfb\x7a\xe4\x4e\xfd\xe2\xde\xd6\x2b\x8e\x70\x59\xfa\x9f\x51\xaf\x82\x79\x4f\xaf\x18\xc2\x65\x25\xf4\xca\x88\x3c\xeb\x21\x46\xe1\x97\xcb\x1f\x9e\x8d\xfd\xd3\x36\x8b\x67\x63\x7f\x3a\x63\x67\x21\x08\x10\x53\x86\x8e\x4d\x9c\x6d\xa0\x1b\xb8\x54\xdf\xae\x9b\x97\xc9\x3e\xe1\x1f\x4a\x1d\xfa\xbd\x6b\x63\x07\x43\x31\x66\x97\xa2\xea\x40\x47\xdd\x9c\x8e\x36\xbe\x79\x24\xb8\x84\xf3\x17\x93\xe5\xfc\xc5\xb9\xbb\x00\x40\x1c\xb0\x23\x6b\x7a\x14\xdf\xd0\x79\x02\x54\xfb\x4e\x0a\x21\xa6\x8b\x53\x5a\x51\x57\x01\x68\xa7\x8a\x50\x4a\xf6\xd0\x4e\x82\x49\x20\xaa\x45\x06\x5c\xe6\xa0\x6e\x5b\x24\xcf\x27\xe3\x9e\xfe\x17\x48\x46\xc6\xb8\x08\x8e\x6a\x3c\x33\xa2\x60\xff\x09\x7b\xe7\xd1\x3e\x19\x94\x4f\x80\xaa\xf2\x49\x21\xa4\xfc\xf2\xb4\xdd\xe2\xf2\x5b\x94\xc5\x8f\x95\xd1\xb4\x47\x46\x61\xe3\x51\x96\x73\x03\x0d\x01\xdc\xf8\x75\x0b\x25\x8a\xd5\xe0\x83\x94\x44\x70\xaf\xde\x48\x64\xba\x31\xf2\xd4\x81\x2f\x8b\xb9\x8d\x92\xb7\xe2\xea\x85\x08\x09\xd0\xcb\xd2\x4a\x87\x60\x11\x74\xa3\x15\x51\xe8\xd3\x8d\x8f\x67\x03\xf8\x57\x34\x00\x4f\x50\xbb\xc1\x8f\x74\x18\xaa\x33\xe9\x20\x90\x47\xa9\x0e\xe8\x1d\x9b\x79\x82\x3c\x8e\x9d\xe5\x05\xfe\x8b\xc9\xb4\x99\xc2\xfa\x2f\x26\x4b\xff\xc5\xa4\x7f\x16\x41\xb6\xc0\xf4\x9c\xc1\x60\x08\x97\x66\x72\xdc\xcc\x23\x17\x3e\x99\x20\xf7\x50\xee\x23\xdc\xd1\x15\x87\xd8\xb3\x44\xe8\x8c\x8d\xca\xc1\x60\x6e\x04\xa8\x5a\x1a\x29\x04\x8d\xec\x2e\xc9\xf6\xe7\x10\x64\xaf\xcc\xeb\x4e\x5c\xc1\x24\x98\xc7\x78\x2f\xb2\x07\xc2\x0d\x3e\x47\xc1\x75\x03\xdf\x4e\x8c\x21\x5c\x16\x43\xa8\xf5\x30\x46\xf9\x82\x55\xa0\x36\xdb\x43\x8a\xc2\x61\x9f\xa1\xa0\xf6\x74\x90\x76\x4f\xb2\xee\x67\x55\x7c\x54\x55\x78\x54\x01\xc6\x35\x4d\x9d\x17\x0e\xdf\x00\x6a\x81\x99\x86\x65\x43\x5c\x1b\x96\x4d\x21\x34\x2c\x6b\x14\xa3\xc7\x4e\x23\x1a\xef\x06\x5b\x53\x17\x4e\x27\xe4\xff\x5f\xa9\xa2\x9d\x2a\x02\x1b\x56\xe1\xd2\xef\x4b\x85\x19\xc1\x84\xfd\x47\xa5\x65\x6a\xbb\xaf\xca\xc5\xee\x6b\x07\x90\x31\x76\xbb\xb7\xce\xd3\xcd\x22\x9f\x15\xff\xaf\xa4\x78\x8f\xa8\xdb\xe0\x31\x1a\x98\xea\x30\x9a\x32\xc8\x5f\xdc\xe5\xdb\x6d\x6a\x5c\x9d\xd3\x5b\x60\xa4\x3f\x2f\x01\x38\x7d\x96\xa6\x32\xe1\x9c\x9e\xaf\xed\x73\xcc\xc3\x2b\x19\x96\x36\x22\x81\xd0\x07\xeb\xab\x1a\x1a\x5a\xe5\x32\xeb\xef\x67\x60\x60\xd9\xd6\xa6\xbd\x92\x21\x56\xca\xf3\x39\xb0\x7e\x68\x69\xd3\x56\xc5\xb0\x1c\x92\x58\x36\x70\x1c\xd8\xba\x69\xab\x03\x1b\x3f\x64\x6c\xa2\x87\x7b\x36\xd5\x67\x53\xfd\x94\x4d\xd5\x63\x06\x6a\xf0\xca\x14\xaa\xfa\x65\x5a\x0a\x79\xe6\x5f\x71\x9a\xe6\x74\xcd\x1a\x04\x5e\xf0\x02\x5e\xb9\x42\x9c\x84\xa1\x17\x82\x01\xed\x1d\xbe\xfb\xeb\x4b\x37\x08\x3d\x62\xa8\xcd\x9f\x7f\xeb\xfe\xdc\x0c\x45\xbc\x4c\xa7\xde\xd4\x4c\x7f\xe1\x85\x42\x2d\xfe\x97\x46\x1d\x46\xbb\xcc\x66\xde\xcc\xc2\xfb\xd4\x0b\xc4\x6a\xdd\xdf\x3a\xf7\x46\xd4\xcb\x7c\xee\xc1\x29\x20\x52\x31\xf0\xe6\x0b\xb1\x62\xf7\xb7\xd6\x86\x19\xf5\xb2\x58\x78\x0b\x4b\x3f\x7c\x6f\x79\x23\xb3\x27\x94\xe8\x7d\xb1\xa2\x5f\x96\x4b\x6f\x69\x6e\xcb\xf7\xa6\x2b\x5f\x62\x53\x2c\xd1\xda\xb2\xa3\x5f\x6e\x6e\xbc\x1b\x6b\xbf\x82\xd5\x7c\xaa\xb2\x2a\x94\x41\x7d\xeb\xa9\x22\x05\x81\xe7\x51\xf1\x3c\x2a\x9e\x47\x05\x4d\x3b\xd0\xb1\x60\x08\x37\x04\xa8\x46\x1b\x5a\xd8\xf3\xf1\xd5\xf4\xd5\xd5\xbc\xa5\xe7\x87\xac\xdb\xe7\x20\xac\xa9\x3e\xa1\xbd\x0e\x17\x5f\xf8\x78\x0b\x7c\x50\x6f\x97\xab\xd3\x09\xf9\x7f\x70\x29\xcb\x61\x17\xfb\x1a\x59\x5c\xfb\xf5\x2c\x0d\x7b\xbe\xb3\xb4\x8b\x67\xdb\xc2\x9a\xcc\xc3\xda\x4f\xd5\x96\xbe\x05\x9e\x3f\x9d\xb4\xff\x65\xf8\xba\x21\x62\x18\xd2\x6d\x1d\x07\xcb\x09\xfb\x0f\xcc\x60\x07\xbe\x88\x5f\xd3\x6d\x2c\x8e\x48\x78\x3c\x9b\xde\xb3\xe9\x7d\x48\xd3\x6b\x37\x61\xda\x37\xbc\xfc\x90\xc1\x5b\x5e\x7e\xc8\x6c\xfe\xf3\x8f\xf9\x1d\x33\xe4\xc6\x80\x97\x73\x92\x0d\xfb\x8c\x8c\x58\x5c\x4f\x91\x5d\x54\x7e\xff\x46\x2b\x86\xd2\x6b\x44\x72\xc5\xb0\x67\xaf\x13\x83\x0f\x58\x2b\xfa\x13\xf6\xcd\xcd\xb6\x71\xca\x1f\xbe\x71\xaa\x87\x31\xc6\xd7\x55\xa9\x8f\x67\x33\x79\x36\x13\x63\xda\x41\x32\x8e\x1e\xdf\xd4\xe0\x98\xfc\x53\x03\xb3\xf9\xa8\x7f\x27\x87\xc2\xff\x39\x8c\xaf\xb5\x2b\xcb\x07\x79\x01\x65\x94\xf1\x51\xd3\x32\x13\x6e\xe1\x43\xf2\x59\x23\xb6\x0d\xf4\x1b\x5f\x0f\x63\x2d\x5f\x8f\xf2\x51\xcf\x66\xf2\x6c\x26\x46\x1f\x45\x8c\xa3\xc7\x47\x35\x38\x26\x1f\xd5\xc0\x6c\x3e\xea\xbf\xd1\xab\x2d\x3e\x61\xeb\x23\x9f\x2f\x86\xda\x5f\xbf\xf9\x5d\x6b\x7d\x6e\x9f\xf9\xb9\x63\xec\x6f\xf8\x1e\xa4\x01\x3b\xa5\xfa\x18\x7b\x1a\x37\xf5\x6c\x29\xcf\x96\x62\xf3\x54\xd4\x3e\x7a\x5c\x15\x41\x32\xf9\x2a\x02\xb4\x39\xab\x9f\x8a\x7f\x1e\xfb\xf3\x27\xfd\x93\xf9\x6b\xe7\xf2\x6e\xd8\x37\xff\x0e\xfd\xe1\xb3\xf9\xbe\xc9\xfc\x98\xb9\xbc\xdb\x77\xf0\xc6\x36\x9b\x97\x51\x07\xdc\x02\x0e\x78\xb1\x67\x13\x7a\x36\xa1\x51\x17\xc9\x0b\x86\xd3\xe3\xdb\x7e\x2a\x4c\x8e\xed\xa7\xc2\xec\xd5\x7e\x3c\xd5\x86\x9d\xa8\xe3\x32\x8b\x73\xff\xc5\x64\x3e\x1f\x9a\x5d\x1c\x9e\xf5\x14\xb2\x81\x8f\x4f\xc6\xea\x23\xf2\x5f\xab\xfb\xd6\x43\xe8\x82\xc9\xfc\x78\x32\x04\xc9\x1f\x4f\x96\x00\xf9\xe3\xa9\x26\x29\x0d\x58\x9e\xd7\x8d\x48\x72\x60\xb5\x47\xae\xd7\x7a\x8e\x1e\xd9\xca\xb5\xc2\x5e\x57\xd7\x62\xc0\x66\xf6\x2c\x1a\xd1\xa1\x71\x81\xf4\x99\xa1\x39\xff\xc5\x80\x56\x73\x24\xab\xd7\x70\xcc\x1a\xbf\x67\xb6\xdb\xc2\xc7\x48\xc8\x0d\xfb\x93\x12\x02\x0a\x6c\x3e\x9f\x69\x57\x3c\xb9\x03\x7d\xea\x36\xa7\x12\x18\xd0\xaa\x6e\xba\x04\x18\x23\x24\xb7\x4f\x4a\xee\x55\x62\xea\x97\x52\xaf\xbe\x3f\xd7\xbe\x78\x4a\x0f\xfa\x34\x6e\x59\x91\x71\xa8\x55\xe7\x3f\x15\x83\x9c\xea\xf0\x4f\x02\xe3\xdd\x6a\x9f\x57\xbd\xca\xa9\xba\xfd\x5e\xd5\xed\x89\x38\xcf\xa2\x51\x2c\xb2\x6f\x0e\x4d\x50\x8c\xb6\x08\xcf\xa2\x77\x28\xe6\x7b\x1a\xc4\x2e\x1c\x2b\x75\x96\xf6\xd2\xf7\x56\x73\xe8\x6e\x08\x11\x0a\x96\x2a\x5f\xc4\x01\xd2\x81\x07\xde\x3a\x21\x00\xa1\x42\xf9\x36\x85\xcf\xb9\x1f\x1e\xe3\xde\xa0\x5d\x0a\xd5\x6e\x77\x20\xa5\x66\x9d\xb6\xdf\x6e\xc7\x98\xe6\xbc\xcf\x30\xe7\xba\xc5\x43\xc3\xa8\x2f\x2b\xfa\xa9\xb2\xe8\x09\x8c\x59\xb5\x01\x4d\xec\x3a\x88\x5d\x2b\xdf\x26\xfb\xd1\xbd\x1e\xe5\x33\x9e\x4c\x39\x9f\x24\xa7\x9e\xcc\x5f\xaf\x9a\xbe\x4d\xb4\xe3\x8c\x12\xd0\xac\xac\xf6\xd3\xe2\xf0\x09\xe6\xbc\x6f\x12\x33\x87\x26\x31\xd7\x6b\xe9\xd3\x63\xd1\x13\x18\xb3\xea\x06\x9a\x2c\x77\x10\xbb\x56\x46\x1b\xe6\xd8\x99\xff\x93\x29\xe7\x93\xe4\xd4\x93\xf9\xeb\x55\x93\x71\x08\x31\xa0\x59\x59\xdd\x67\xaf\xc1\x02\xe8\xb3\xcf\x27\x1e\x41\x9f\x1c\x87\x9e\xc8\x97\x55\x35\xe0\xe2\x43\x00\xf5\xa8\x65\xb4\x69\x8e\x5b\x4b\x3d\x9d\x76\x3e\x41\x46\x3d\x85\xbd\x7e\x3d\x19\xc7\x10\x87\x9a\xb5\xc5\xbe\xba\x08\xdd\x37\xbf\xd0\x6b\x0a\xba\xb3\x9e\xa0\x3c\x7b\xca\xb9\xc3\x07\x66\x58\x20\xce\x6e\xdb\xdd\x5c\xab\x50\xf3\x1a\x8b\xc3\x61\x25\xda\x56\x57\x3f\x15\x7f\xc6\xd9\xe9\xf1\x12\xb9\x62\x35\x1a\x6c\x00\xd9\x5c\xaf\xd5\x0f\xde\x8f\x27\xd5\x2c\xe1\xbe\x47\xbb\x0d\x8e\x49\xc3\x0d\xcc\xa6\xe5\x2b\x66\xcb\x63\x72\xcf\x4f\x34\x32\x3f\x41\x2e\x3d\x91\xb7\x1e\x05\x19\xdd\x28\x01\x99\xd4\xf3\xe3\x49\x09\xf1\x81\x94\xb3\xd1\x04\xd5\x8b\xef\x71\x2c\x0b\xbb\xc0\x67\x28\x56\x6c\x61\x53\x5f\x13\x07\xe3\xd2\x4b\x43\xfd\x26\xd0\xe5\x0f\xd7\xb6\x27\xb6\x68\x17\xa1\x69\xa5\x6d\xf9\x80\x22\x80\x35\x6b\x1f\xd9\xa3\x6b\xbf\x9b\x7d\x2c\x16\x3c\xa5\xe1\x7e\xd9\x1a\x06\x54\x07\xb5\x48\x58\x5f\x7d\x8e\xea\xdb\x98\xa7\xf3\x01\xe1\x7e\xc8\xd6\x3d\xb1\x4d\xbb\x50\x4d\xeb\x5a\xcb\x27\x20\x01\xfc\x38\x6b\x79\xcc\xb7\xba\x8f\xc7\x84\xa7\x34\xdd\x2f\x5f\xb3\xd1\xf6\xac\x48\xdb\x0f\x3b\xd7\x77\xaf\xcf\x6c\xac\x36\xfb\x01\x1b\xf7\xa4\x26\xed\x32\x35\xae\x24\x6d\x1f\xb1\x44\xf8\xe3\x2c\xe6\xfa\x0f\x8e\x1f\x8d\x07\x4f\x6d\x79\x80\x80\xcd\x56\xdb\xb7\x06\xa4\x5f\x7f\x1e\x13\x45\x98\x33\xb3\x7e\x26\x23\x08\x90\x78\x3f\x5c\xdb\x5e\xd7\xa2\x5d\xa0\xf0\x42\xcc\xfa\x9d\x8b\x00\x1f\x1b\x8d\xaf\xff\xb0\xf9\xb1\x58\xf0\xa4\x86\xfb\xa4\x6a\xb6\x51\xf3\x04\x3b\x4d\x0a\xd3\x35\x49\x05\x2e\xab\x02\x93\x37\xb5\x5f\xce\xc8\xc3\x49\xc2\xb5\x37\xc1\xc4\x9f\xb8\xd3\x85\x7a\xeb\xe1\xf0\x3a\x7a\x67\xd4\x7d\xa3\x18\x55\xd8\xcd\xa5\x89\xb8\x09\xc5\x70\x42\x59\xe7\x46\x16\xb5\x3f\x09\xe6\x10\x8f\xc1\xaa\xbf\x5f\xe3\x28\x3d\x6d\x6f\xe1\x8b\x92\xaf\xe6\x71\xf9\x64\xbd\x5d\x8e\xea\x6d\x92\xf5\x75\x36\xc9\x0c\xa7\xbb\x75\x0e\xc5\xeb\x9b\xd9\x7f\xec\x5d\x02\x2b\x3c\x25\xe7\xe0\x36\x5c\x9d\x0f\x2b\x93\x4f\xca\x90\xfc\x84\xc1\xf3\xc0\x7f\x1e\xf8\xcf\x03\xff\x5f\x63\xe0\xcb\x8f\x75\xb5\xdc\x6d\x51\xf4\x6e\x87\x22\xec\x02\xb9\x5a\x1b\xcc\x34\x11\x49\x13\x7d\x66\x97\x26\xf0\xa4\x2e\x4d\x8a\x1f\xb2\xbf\x5e\xe1\x82\x1a\x83\xf3\x27\x03\x06\x2a\x5c\xe3\x09\xe5\xba\xe9\x92\x8a\x43\xdd\x90\xc2\x93\x1b\x8e\xee\x06\xaf\xf2\x94\xf6\x01\x5f\xcf\xd8\xcb\x8a\x76\xa9\xf7\xd0\x1a\xdd\xe4\x79\xe8\x20\x57\x85\xa0\x5e\x85\x35\xb0\xc6\x93\x0c\x4d\x2d\x8e\x3e\xdb\xf1\xb3\x1d\x7f\x96\x76\xec\x71\xeb\x1d\x10\x10\xba\x97\x4a\x6d\xa1\x41\xc0\xb2\x04\x89\x1f\xb2\xbf\x42\x71\xe2\x87\xec\xaf\xe6\x50\xf1\xb7\xab\x67\xab\x63\x86\x98\x54\xe3\x13\x19\x62\x6c\x8e\x35\x66\x88\xc9\x55\x3e\xea\x10\xa3\xac\x8c\x19\x62\x52\x8d\x47\x0c\x31\x26\x84\x11\x43\x4c\xac\xf1\xbe\x42\xc5\xb3\x1d\x3f\xdb\xf1\x67\x68\xc7\x1e\xb7\xde\x0f\x1e\x2a\xfe\x06\x87\x8a\xbf\x99\x42\xc5\x8f\xa7\x7a\xc4\x74\xcc\xde\x6d\xf8\x7e\xf6\xf7\x39\x1d\x92\xf2\xca\x1f\x72\x3e\x69\xd8\x50\xf1\x2c\xd0\x27\x10\x68\xfb\x6a\xb6\x31\x85\xcf\xe0\x90\xa9\x93\xf2\xf7\x30\xea\x2c\xe3\x67\x44\x8c\x7a\x62\x75\xf3\x7c\xd2\x78\x67\xc7\xaa\x5c\xaf\xee\x47\x06\x59\xeb\xf8\x79\x16\xe8\xa3\x04\xaa\x3f\x31\xff\x81\xa2\x4f\xd3\xa6\x61\x4c\x82\xf1\x27\x4d\xf6\x87\xfa\x3f\x0a\x8c\x63\x7e\xa0\x6d\xe0\x96\x00\x7e\xe5\xba\x2a\xac\x01\xc8\x9d\x9c\xe0\x39\x0d\xc5\xd6\x1c\xa8\x54\xdc\x37\x3b\x61\x2d\x1a\x2e\x20\x1f\x64\x28\xc0\xee\x41\xa1\x8a\x38\x66\x9e\x85\x78\xad\x10\x3d\x49\x74\x06\xbb\x16\x71\x54\xdb\x96\x60\x4f\xfb\xe9\xc2\x3a\x5a\xe0\x3d\x9b\xa3\xd4\x3e\x46\xeb\x9a\xd2\x61\xf3\xfb\xe8\x5c\x79\x32\x2f\xbd\x0a\x05\x76\xad\xca\xc0\xa7\x5c\x41\x41\xef\x53\x13\x47\x6e\x1c\xb5\xc3\xde\x0e\x00\xf6\x50\xa8\xcf\xed\x84\x7e\xdf\x73\x92\x1c\xa3\x13\x26\xa4\xb9\xab\x19\x1a\xee\xcc\x9e\x45\xc2\x5c\x53\x2b\x08\x83\x15\x73\xb8\xf6\x7e\x31\x2b\xb7\xd9\xdb\x1f\xf3\x3b\xe1\x34\xa5\xb1\x4f\x29\xde\xd5\xce\x36\xaf\xeb\xfc\xa8\x77\x4c\x04\xf6\x8b\x7b\xd6\xf7\x70\xe8\x6c\x3e\x42\xd8\x8f\x60\x6c\xbc\x25\x3e\x0b\xab\xd7\x46\x5b\x11\xf5\xd8\x2a\xc7\x33\xd9\x2c\x87\xf7\xd9\xae\xb0\xb3\xd4\xd8\xed\xb2\xc1\x31\xf6\x5b\x82\xf6\x6a\xa4\x4f\x21\xa3\xf4\xf1\x28\xc6\xae\x33\xdf\x67\x79\x0d\xb1\x60\xeb\xe6\x61\x0d\xd1\x66\xc3\xc6\x6d\xc4\x1c\xe9\xa7\xe2\x83\x7a\x94\x27\xd5\xc7\x07\x75\xbe\xcf\x82\xb2\x9a\x2d\x13\x4f\x8f\xcd\x52\x2c\x93\xc1\x52\xa8\xdd\x5a\x3f\xb4\x03\x71\xb5\x2c\x88\x01\xe1\xe3\xbb\x10\xd0\x68\x9f\xe5\x35\xc4\x76\x07\x39\x5c\x86\x66\xb6\xde\x1e\x67\xdb\x2e\x4a\xaf\x9d\xba\xdb\x17\xb3\x4f\xb5\x20\xe9\x5d\x8f\xe8\xcb\x11\xdd\xf4\xfe\x89\xfb\xea\x75\x3d\xb4\x1a\x0c\xb0\xa4\x6f\x01\x56\x23\x79\xea\x69\xfe\x30\x51\x7e\xc4\xd0\x05\x9a\xcf\xbf\x9e\x14\x3c\xbd\xef\x7d\x06\x66\x5f\xc6\x08\x08\xbd\x06\xf7\xc4\x71\x62\x98\xb4\x9f\x34\xf0\x8c\x5f\xab\x1a\xed\xee\x5f\x52\x18\x1e\x20\x82\x21\xf6\x67\x09\x8a\x22\x86\xd5\x02\x9f\x76\x72\xfd\xa1\x87\xfa\x53\x99\xde\xbf\x9e\x14\x3c\xb5\xef\x7d\x06\x67\x5b\x40\xb4\xe0\x1e\x53\xfb\xec\x47\x77\xdf\x14\xdb\xfa\x5d\xfb\x5f\x5b\x10\x9e\xd6\xfd\x7e\x8b\xb3\x3b\x38\xcb\xb4\xff\x90\x64\x7b\x7c\x86\xbe\x28\xf2\xee\xd6\x79\xe1\x34\x83\x4c\x17\x44\x0b\x19\xfc\xe1\x67\xc8\xe7\x3c\x8a\x75\x09\xe9\x1b\xba\xc0\x07\x31\x45\x80\x37\x3d\x02\xbe\x91\xb7\xf7\x7d\x2a\xfd\x9b\xd1\xf7\x81\xfb\xfb\xa7\x1d\x86\x83\xe1\x9f\x58\xff\xfa\xbe\x35\x93\x5f\xed\xc9\xaf\x65\xdf\xb1\xe5\x16\x01\x76\x18\xcf\x56\xfc\x6c\xc5\x9f\xa9\x15\x7b\xd4\x76\x0d\x2e\x9e\x00\x55\xbf\x4e\x0a\xe1\x09\x44\x9a\x02\x77\x5d\x5b\xd9\xee\xee\xb2\x51\xa7\x42\x81\xb6\x21\x65\x54\xbd\xc7\x5e\x4b\xf6\xf9\x77\xc6\x63\x5d\x30\x86\xef\x06\xaa\x07\xed\xa6\xd4\xa4\xdd\x9e\xeb\xc7\x86\xde\x11\xa3\xf4\xd2\x2e\x9c\x9e\x5a\x9a\xd2\x3e\x49\x1e\x3d\xce\x99\x45\x19\x60\x36\x8c\x14\x43\xea\xf8\x2d\xcf\x8f\x43\xec\x73\xdc\x53\x46\x73\xf1\x61\x0c\x49\xb4\x1f\xa4\x3d\x8f\xb5\x62\x90\x12\x85\xaa\x42\xa2\xa5\x66\x19\x0d\xbb\xcd\xbd\xe5\x2d\x98\x90\xff\x57\x0e\x87\x37\x43\x54\x73\xaf\xc3\xeb\xf4\x07\x07\xe5\x21\xb9\xf9\xdc\x9f\xf8\x9e\x3f\x27\xcf\xc9\x2d\x9b\xff\x0e\x56\x63\x1e\xa2\x83\xeb\xf7\xbe\x16\xd7\xf6\x68\xb6\x9c\x4f\xda\xff\x52\xfa\xb5\x30\x0b\x62\x48\xb5\xd1\xb2\x08\x08\xff\x37\x37\xcd\x7f\x4f\x43\x7f\x12\x8c\x90\x83\x5e\x17\xb0\xea\x67\x0b\x79\xb6\x10\xc9\x42\x3c\xc1\x2e\xac\xbe\x08\xba\x04\xb2\x83\x98\x7d\xd2\xb0\xeb\xf1\xad\xd6\xd3\xda\xce\x08\x8b\x93\xea\xfc\x13\x59\x1c\xf4\x9a\xee\xa8\x6a\x1f\xdd\xe2\x34\x9f\xf4\x6c\x21\xcf\x16\x02\xf9\x24\x5b\x0e\xb8\xc3\x80\x7d\x92\x29\xf3\x4b\xa1\x03\x1f\x1c\xb0\x9a\xcf\x15\x16\xf7\x4f\x6a\x70\xee\x95\x16\xe7\x7e\x42\x26\xa7\x39\xa5\x67\x13\x79\x36\x11\xd0\x2b\x59\x3f\x14\x08\x28\xb0\x5f\x32\x7e\x1e\xa0\x60\xfd\xd5\x86\xd1\x93\xf3\x2b\xe6\xe6\xff\xa4\x53\x73\xf7\xca\xb9\xb9\xfb\xc9\x4c\xce\x35\xaf\xf4\x6c\x1f\xcf\xf6\xa1\xbb\x24\xf3\x4d\xbd\x1c\x0e\x3b\x23\xf8\x9e\xde\x06\x06\x64\x16\xc5\xfc\xd5\xe3\xb3\x61\xc6\xa7\x1f\x3e\x42\xeb\x1e\x6f\xd3\x22\x44\x20\x63\xc9\x8a\x2d\x22\x24\x8b\xea\xd9\xe7\x69\xaa\xef\x69\xe0\x0e\x7d\x8d\x1e\x76\x44\xd0\xad\xcb\x83\xab\xf4\xec\x1b\x35\xee\x42\x90\xc1\x1f\x7d\xcc\xeb\x63\xe5\xd9\xcc\x9e\xcd\xec\xfd\x84\x96\x9e\xe7\x61\x04\x14\x83\x73\xb4\xa5\x06\xf9\x53\x1e\x4f\x60\xb9\xb3\xf0\xaa\xd5\x45\x5b\x6d\x90\xbd\xbc\x54\xf3\x47\xf0\x73\x05\xfd\xb8\xf6\xed\x77\xa6\x5d\xec\x02\x10\x72\x02\xcf\xa2\xbc\x52\x94\x9e\x28\x40\xbb\xa1\x9b\xd2\x4d\x96\x67\x65\x18\x98\x2e\x1a\x9f\x40\x3d\xee\x95\xfa\x71\x1f\xa7\xa0\x11\xfa\x19\xa4\x1e\xba\xb3\xcf\xa4\x1f\x11\x0a\xd9\xfa\xb3\x34\xaf\x97\xa6\x27\xc9\xd0\x6e\xef\xc6\x3c\x86\xed\x49\x1a\x06\xff\xa9\x78\x9a\x29\xc9\x87\xfe\xbe\xf6\x49\x4e\x48\xc0\xe7\x46\x86\xd7\xf9\x27\x99\x92\xe8\x8e\xe0\xd9\xc8\x9e\x8d\xec\x3d\xcd\x7b\xed\x39\x15\xf0\xf5\xa3\x16\x00\xb9\xc5\x2a\x4d\xf8\x83\xf7\x43\x2e\xc3\x1a\xf1\x62\x13\xf0\xbe\xec\x90\x3d\x94\x96\x57\xb6\x7c\xfd\x91\xaf\xcf\x91\x7d\x4f\x64\xda\xa0\x4c\x01\x45\x55\xa7\x00\xb2\x28\xd4\x72\x48\xe7\xda\xa7\x0e\x3f\xa4\x42\x3f\x2b\xf6\x3d\x91\x69\xbb\x42\xa1\xa9\xba\x00\xb2\x28\xd4\x76\x0e\xe6\xba\x77\x00\x3f\xa4\x3e\x3f\x27\xee\x3d\x89\x67\xbb\x3e\xc1\xa9\xa8\x08\xb3\x68\xf4\x27\xe3\x0b\x49\x32\x57\x7d\x1e\xeb\x23\xf8\xdb\xcf\x86\x75\xaf\x63\xd8\xae\x48\x3d\x6c\xb6\x00\xa3\x0a\xa5\x77\x91\x1f\xcf\xac\xfc\xa8\xf9\xc0\x17\xd3\x07\x4a\x58\x57\xe2\x67\xc5\xbc\x27\xb1\x6c\xd3\xa4\x21\xef\x27\xc2\x6c\xfa\x1c\x1a\x77\xde\x93\x48\xae\x7d\xf6\xf8\x73\x64\xdf\x93\x98\xee\xd1\xa9\x31\x6e\x5a\x72\x5c\x1c\x3e\x38\xf6\xbc\x27\xa9\x5c\xf7\x2a\xf0\x67\xc8\xbd\x27\xf3\xdc\xa3\x52\x73\xe8\xb4\xa5\x71\x38\xc2\xd0\x08\xf4\x9e\x3c\xd7\x75\x6f\xe6\x7e\x7e\xcc\x7b\x02\xcb\x3d\xfa\x34\x44\x50\xba\xf2\xdc\xe6\xf1\xc3\x79\x97\x67\xb5\xbb\x43\xc7\x24\x7d\x58\xe7\x05\xce\x9c\x0a\x65\xd5\xe4\x9b\x32\x41\xe9\xa4\xf9\xe9\x56\xb8\x4c\x76\x9b\x34\xc9\xb0\x7b\xc0\x8d\x05\xac\x03\x6f\xbe\x21\xd5\xaa\xe4\x37\xbc\x0e\x16\xc5\xfd\x26\xca\xd3\xbc\x5c\x7f\x79\x33\x6b\xfe\x91\x3b\xb8\xf7\x65\x7e\xca\x62\x97\x01\x76\x7e\xf3\x8f\xb4\xe8\x55\xf5\x43\x8a\xdd\xf0\x0c\x60\xed\x76\x62\x5d\x42\x3e\xca\x6f\x71\x29\x96\x16\x79\x95\x90\x05\xba\x3b\xf5\x5f\x88\x80\x12\x17\x18\xd5\xeb\x2c\x67\xbf\x44\x58\x72\x44\x7b\xbc\x3e\x95\xe9\x4b\xcf\x7b\x43\xfe\xa8\xde\x6c\xf7\xff\x2b\xf4\x7e\x2d\xf6\xaf\x36\xbc\x5f\xbe\xff\x42\x64\x71\x2a\xb0\x48\x98\x73\x64\x02\x7b\x9c\x1f\x71\x5d\x3e\x84\x5e\x91\xed\x5f\xd1\x46\x2f\xe8\xcc\x3a\x33\x8d\xa2\x8d\x7b\xcc\x7f\xa3\x1a\xa7\x2c\xa3\x34\x75\xbc\x69\xe5\x60\x54\xe1\x8d\x9b\x9b\x41\xa2\xb1\x40\xf0\x63\x65\x84\x19\xca\x2f\x68\x7d\x68\x44\xc9\xd9\x0b\x57\x68\x8a\xa6\x17\xef\x88\xb3\xd3\xb9\x40\x71\x9c\x64\xfb\xb5\xbf\x39\xa2\x72\x9f\x64\xeb\xa9\x5f\xdc\x3b\xbe\xe3\x53\xb8\x93\x26\xe7\x34\xa9\x6a\x97\xc8\x85\x1e\xab\xa3\x88\x2e\x4d\xc5\xac\x03\xbf\xb8\xdf\xc4\x49\x55\xa4\xe8\x61\x4d\x7a\x9d\x64\xc4\x64\xaa\x1a\x45\xef\x5a\x08\x2b\xdc\xa6\x79\xf4\x6e\xf3\x5b\xde\x54\xdc\x7c\x2d\x03\xdb\x16\x1d\xd4\xb2\x35\x2f\xee\xdb\x62\x0f\x91\x6b\xe4\x9d\x56\xce\xdb\x69\xf3\xef\xe2\xed\x0e\xf3\x28\x77\x9b\x81\xd3\xd6\x6b\x7a\xc1\x19\xad\xf3\x62\x3d\xc3\x5d\xd2\x68\x9b\xdf\xbb\xd5\x01\xc5\xf9\xdd\xda\x9d\x15\xf7\xce\xb2\xb8\x77\x66\x8b\xe2\xde\x09\x8b\x7b\xa7\xdc\x6f\x11\x1d\xcd\x13\x2f\x78\x45\xd5\x38\xaa\x42\x3e\x0a\x7d\x14\xae\x6c\x92\x17\x3e\x9c\x1c\x51\x00\x9f\x79\x27\x2f\x7f\x38\xe2\x38\x41\x4e\x15\x95\x18\x67\x0e\xca\x62\xe7\xe5\x11\xdd\xbb\x77\x49\x5c\x1f\xd6\xcb\xc5\x4d\x71\xff\xea\x0c\x29\x3c\x68\x2c\x45\x34\x05\xe7\x10\x9e\x6b\x7c\x2f\xba\xdd\x53\x51\xe0\x32\x6a\x46\x4a\x8a\xeb\x1a\x97\x6e\x55\xa0\xa8\xa9\x1c\x16\xf7\x82\x5b\x0b\x3b\xdb\x59\xfb\x8e\xef\x10\x5b\x62\x26\xe7\xfb\xbe\xd4\x88\x47\x72\x94\x8d\x56\x8a\xb3\x3c\x2e\x9a\x5a\x26\x54\xa7\x38\x0b\x5e\x74\xd6\x91\x5f\xed\x9a\x7f\x94\x97\x3b\xea\x9a\xa6\xe6\x16\x9d\xa2\x1b\x0b\x2a\x63\x29\xda\xe2\xf4\xac\x10\xda\x28\xad\xf6\xb7\x13\xe5\x59\x5d\xe6\xe9\x59\x71\xfa\x2a\x5d\xe6\x46\xe7\x8d\xa4\x98\x46\xdc\x14\xef\xea\xb5\xdf\xfe\x49\xbe\x2f\xad\xfd\xcd\x36\x2f\x63\x5c\x52\x4f\x42\x7f\xb7\x9e\xa4\xb8\x77\xaa\x3c\x4d\x62\xcd\xdc\x74\x9b\x26\xd5\x55\xbb\xa5\x85\xb9\x56\xa4\xa1\xb4\xf4\x48\xf3\x25\x8a\x93\x53\xb5\xf6\x39\x3d\xb5\xb0\xd2\xca\xc0\x8a\x9f\x88\xb3\x37\xea\x70\xbd\xe6\xcd\x25\x59\x71\xaa\xdd\x22\x45\x11\x3e\xe4\x69\xdc\x46\x06\x51\xec\xd3\x57\x1b\xd3\xe8\xb1\x36\xd1\x48\xe2\x7d\x50\x6e\x44\xf1\x68\xbe\xa3\xbc\x78\x20\x76\x58\x51\xd7\x90\x64\x31\xce\xea\xb5\xbb\x5a\xad\x56\xc5\x3d\xb7\x62\x5f\x9a\xf2\x88\x83\xc6\xdf\x34\x71\x74\x97\xe6\x77\x6c\x6e\x67\x65\xf8\x3d\x49\x62\x97\x47\xa7\x6a\x62\x86\xd3\x28\x79\x1e\x32\xb6\x66\xaf\x2e\xde\xb6\xce\xdc\xa2\x4c\x8e\xa8\x7c\x38\x43\xc3\x98\x8e\xdb\x50\x1b\xd9\xa4\x44\x1a\xcc\x42\x78\x6a\x66\x40\xc2\xcc\x0e\x0a\x4a\x8d\xef\x6f\xe6\x0e\x4e\x43\xc8\x71\x03\x1e\x0a\xe6\xc1\x24\xf4\x67\xe4\x3f\xde\x0c\x88\x4d\x43\xeb\xe5\xd7\xd4\x1a\x5f\x45\x12\x20\x9d\x67\x4d\xa4\x22\xa6\x2e\xb1\x88\x69\x08\x9c\xfa\xae\xbf\x9c\x2d\xe3\x20\x0e\x84\x17\x6b\xf2\x53\xdd\x18\x24\xbd\xc4\x80\x8c\x81\x49\x63\x36\xa8\xc4\xb2\xf7\xd7\x8d\xed\x4b\x84\xd0\xc5\xfb\xb5\x72\xf8\x8b\xd0\x8d\x4c\x84\x3d\xad\x5f\x16\xa8\xac\x93\x28\xc5\x95\xfb\x6b\x75\x6e\xa7\xd7\x68\x5b\xe5\xe9\xa9\xc6\x1b\x1a\x75\x9b\xc9\xb1\x38\x51\x36\x4c\xd4\x9b\x69\x96\xbf\x61\x5e\xff\x37\x32\xb6\xee\xd7\x6e\x40\xd7\x1a\x5d\x5f\x95\x07\x7b\xe4\x65\x40\x18\x34\xff\x84\x57\xab\xfe\x6f\x00\x00\x00\xff\xff\x71\x15\x71\x5b\x22\xdb\x02\x00") func assetsLoginDistAllMinCssBytes() ([]byte, error) { return bindataRead( _assetsLoginDistAllMinCss, "assets/login/dist/all.min.css", ) } func assetsLoginDistAllMinCss() (*asset, error) { bytes, err := assetsLoginDistAllMinCssBytes() if err != nil { return nil, err } info := bindataFileInfo{name: "assets/login/dist/all.min.css", size: 187170, mode: os.FileMode(420), modTime: time.Unix(1570965576, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _assetsLoginDistAllMinJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\xfd\x0b\x97\xa3\x36\xb6\x30\x0c\xff\x95\x32\xd3\x87\xa0\xf6\xb6\xcb\xee\x24\xf3\x3d\x83\x5b\xc5\xca\x75\x92\x49\xe7\x72\xd2\x3d\x93\xcc\xc1\xf4\x2c\x01\x02\x53\x85\xc1\x85\xa9\xae\xea\x18\xe6\xb7\x7f\x4b\x5b\x12\x08\x8c\x3b\x99\xf3\xbc\xef\x5a\xef\xea\xd5\x65\x10\xba\x6b\x6b\xdf\xb4\xf7\xd6\xf5\xf3\xd9\xed\x7f\x3f\xf0\xea\xfd\xd5\xbb\x17\xcb\xf5\xf2\x93\xab\xe6\xca\x89\xc8\xd5\x8b\xd5\xea\x53\xb8\x7a\xb1\x5a\x7f\x7a\xa5\x3e\x7f\x5d\x3e\x14\x31\xab\xb3\xb2\x80\xab\x6f\x8b\x68\x79\xd5\x5c\xdd\xde\x8b\x2f\xcb\xb2\x4a\xaf\xf3\x2c\xe2\xc5\x91\x3f\xbf\x9e\x25\x0f\x45\x24\x72\x39\x0c\x42\x72\xb2\xca\xf0\x96\x47\xb5\x45\x69\xfd\xfe\xc0\xcb\xe4\x6a\x5f\xc6\x0f\x39\xb7\xed\x0b\x1f\x96\xfc\xe9\x50\x56\xf5\xd1\x1b\xbe\x52\xb6\x8c\xcb\xe8\x61\xcf\x8b\xda\x0b\x1d\x06\xb3\x15\x71\xfb\x86\xc8\x29\x4b\x9c\x59\x9f\x85\xd4\xbb\xaa\x7c\xbc\x2a\xf8\xe3\xd5\x57\x55\x55\x56\x8e\xa5\xc6\x50\xf1\xfb\x87\xac\xe2\xc7\x2b\x76\xf5\x98\x15\x71\xf9\x78\xf5\x98\xd5\xbb\x2b\x76\xa5\x4b\x5a\x64\x53\xf1\xfa\xa1\x2a\xae\x42\x87\x91\xd6\xc5\xbf\x8e\xf5\x50\xc4\x3c\xc9\x0a\x1e\x5b\x33\xdd\x5d\x59\xde\x93\x3f\x6e\xbd\xcb\x8e\x30\x1c\xf9\x3b\x56\x5d\x45\xd4\x0f\x20\xa6\xd1\xf2\x28\xe6\x07\x38\x8d\x96\x51\x59\x44\xac\x86\x84\x46\xcb\xc3\xc3\x71\x07\x29\x8d\x96\x59\x11\xf3\xa7\x1f\x13\xd8\xd1\x53\x0b\x19\xdd\x2d\xeb\xf2\x75\x5d\x65\x45\x0a\xb7\x74\xb7\xdc\xb1\xe3\x8f\x8f\xc5\x4f\x55\x79\xe0\x55\xfd\x1e\xee\x44\xa6\xdc\x98\x10\xd8\x53\x0b\x97\xce\x82\x82\x0e\xfb\xa0\xc6\x22\x26\xa2\x58\x26\xc5\x32\x2b\xb2\x1a\xbf\xb4\x50\xd2\xeb\xb7\xfe\xf6\xb8\x7d\xf8\xfa\xab\xaf\xbf\xde\x3e\x7d\xb6\x0a\xe6\xcd\xe8\xfd\xd9\x75\x0a\x07\x7a\xfd\x76\xb1\x3f\x2e\xae\xe1\x9e\x5e\x2f\x1c\x7f\x1b\xb3\xc5\x6f\x01\xb9\x4e\x33\xa8\xa6\x1b\x0b\x97\x75\xf9\xf7\xc3\x81\x57\x5f\xb0\x23\x77\x48\xbb\x11\x2d\xd3\x62\x79\xa8\xca\xba\x14\x93\x47\x4f\x12\x6e\xdc\x3d\x44\x65\x71\xac\xab\x87\xa8\x2e\x2b\xb7\x80\x23\xcf\x39\x3e\x5a\x16\xe4\xbc\x48\xeb\x9d\xbb\x82\xba\xfc\xac\xaa\xd8\xfb\x7e\xb5\xbb\x86\xe2\x65\xc4\xf2\xdc\x11\x53\x4f\x5a\x48\x79\x3d\x80\x08\x3d\xf4\x87\x3c\x9f\x51\xe6\xad\x6e\x98\x27\x72\xfa\x6c\x2e\x7e\x96\xb2\xfe\xc0\x95\x69\x81\x3b\xac\x4c\xac\xcc\xeb\x9a\x45\x77\x83\x2a\xc5\x8a\x86\xb4\x58\xee\x79\x95\x72\xcc\xba\x34\x06\xe0\x10\x60\x3d\xf4\x2c\x0f\x15\x7f\xf7\x23\x82\x38\x45\xe0\x08\x45\xde\x9a\x3f\xc9\x57\xfd\x02\x61\x0b\x9c\x45\x3b\x77\x7a\xdd\x96\xe2\x1b\xb6\x04\x72\xd5\xf6\xec\x30\x35\x4a\xac\xb2\xeb\xb4\x53\x2c\xf7\xec\xe0\x0c\x61\x32\x84\xa8\xcb\xce\xe4\x60\x43\x88\x44\xa5\x84\xb4\x80\xf0\x39\x31\xc7\xa3\x8a\xe3\x25\x3b\x1c\xf2\xf7\xaa\x47\x55\x8a\xf0\x77\x14\x15\x24\x59\x75\xac\x2f\x55\xc0\xef\x9d\x15\x69\x21\x67\x1f\xcc\xb2\x58\x93\x16\xf8\xfd\xc4\x94\x1b\x2b\x06\x11\x9d\xb3\xb9\x23\x96\x33\x74\x57\xdd\x7c\x8f\xfa\x19\xdd\xd0\x95\x6d\x87\x37\x91\xe7\xe3\x02\x47\x41\xe0\xfa\x81\xa8\xbe\x88\x2f\x8e\xb2\x5b\xb0\xa6\x39\x5b\x5b\x01\x46\x0a\x2e\xdc\x04\x8e\x65\x55\xbb\xd1\x52\xfc\xc0\xf1\x80\x53\x17\x2d\xe5\x43\x0b\xc5\x92\x3f\xd5\xbc\x88\x29\xee\x38\xf5\x6c\xb4\x29\x86\xc4\x40\xcc\x7d\x0c\x1c\x12\x48\x69\x37\x91\xfe\x2a\x68\x9a\x53\x0b\x3b\xba\x86\xac\x4f\xd6\x43\xbf\xa5\xb3\xf5\x26\x11\xe8\x2c\x2c\xcb\x9c\xb3\xa2\x47\x9e\xa9\x6d\x3b\xb7\x34\x1d\x54\xb6\x53\x95\xcd\xe7\x04\xce\xb0\x6d\xda\x34\xc5\x32\x3b\x7e\xad\xfb\x95\x92\xa6\x71\x52\x7a\x6a\x09\xec\x28\xa5\x99\x6d\x3b\xa9\x04\xdc\xdd\x62\x41\x36\xd9\xcd\x6e\x23\x2a\xca\x12\x47\xee\x28\x87\x0d\x5a\x22\x44\xf4\x2b\xbc\xca\x8a\x2b\x46\x22\x9a\xfa\xa1\xc0\x7b\x4c\xfc\xa4\x33\x4a\x63\xd1\x3d\xdb\x16\x3f\xa2\xd5\x9f\x72\x96\x15\x72\xae\x9d\x58\x34\xcc\xa9\x48\xc6\x8d\xee\xc4\x84\x10\xcf\xe1\x9e\xc3\xe9\x6c\x2d\xf0\xa4\x6d\xf7\x1f\x23\xe2\x45\x62\x25\xdd\x2e\xdd\xac\x0b\xbf\x9e\x5a\x10\xcd\x53\x3d\xf7\xce\x2d\x24\x10\x13\xe2\xbe\x2b\xb3\xf8\x6a\xa5\x7a\x83\x59\x62\xd2\x01\x50\xda\x2f\x9c\x73\xe2\x4f\x07\x56\xc4\xa5\xab\xc8\x86\x35\x77\xf6\xf3\xef\x59\xbd\x5b\x56\x22\x79\xef\x10\xb2\xac\xf8\x21\x67\x11\x77\xae\xb7\x5f\x5e\xa7\x60\x59\x04\xb2\xe3\xcf\x9c\xc5\xef\xdd\xd9\x0a\xb8\x20\x3a\x03\x38\x1e\x13\x24\x46\x5a\x28\xca\xf2\x60\x02\x63\x0b\xfd\x7a\x4c\x6c\x72\x4b\x27\x59\x94\xd2\x62\x29\xd6\x11\xab\x51\x53\xe3\xe2\x5f\x3d\x51\x90\x1d\x7f\x91\x94\xe9\x32\x4e\xb4\x6d\x46\x29\x65\x4b\x49\xc2\x44\x45\x3f\x3c\xec\x79\x95\x45\x13\x65\x66\xfd\x12\x30\x62\xdb\x6c\x71\x60\xd5\x91\x7f\x9d\x97\xac\x76\x18\x99\xaf\x6f\xe8\x4a\x54\x60\x2c\xc6\xd4\x08\x14\x10\xce\x8c\xfe\x37\x0d\x5b\x16\x65\xcc\xdf\xbc\x3f\x70\x09\x92\xb2\xdf\x0e\x23\xde\x6c\xed\x32\x73\x17\xda\xf6\xec\x56\x62\xae\x41\x72\x4f\x59\xc0\xca\x8e\x3f\xe9\x97\x1f\x13\x0b\xab\x98\x61\xcf\xbe\xda\x1f\xea\xf7\x13\x3d\x43\x04\xb3\x31\x80\x57\x8d\x77\xad\x00\x43\x94\x16\xb5\x5d\x9a\x47\x4a\x99\xc7\xe6\x96\xe5\x9e\xed\x30\xd6\x34\xe6\x92\xe9\x54\x6f\xe7\x67\x6a\x10\x24\x68\x1a\x5d\xcc\xd5\xdf\x5b\x48\xf3\x32\x64\xf9\x57\xef\x58\x7e\xde\x53\x88\x28\x7f\xc7\xf2\x0d\x13\x33\x58\x65\x7b\x87\x11\x60\xb6\xed\xac\x71\x25\x15\x1f\xe1\x58\x0f\x47\x7e\x75\xac\xab\x2c\xaa\x2d\xe2\x39\x21\xcd\x97\x51\xc5\x59\xcd\xbf\xca\xb9\xd8\xb1\x8e\x75\x8c\xaa\xec\x50\x5b\x04\xc2\x25\xd2\x24\x06\xf9\x72\xc7\x19\xe2\x77\x5e\xc4\x5f\xec\xb2\x3c\x76\x42\xb2\x3c\xb0\x8a\x17\xf5\x0f\x65\xcc\x97\x15\xdf\x97\xef\xb8\xfe\x42\xdc\xc8\x61\x02\xf1\x47\x6c\xcf\x73\x41\xea\xa7\x66\x88\x75\xfb\xe4\x00\xd6\xfe\xb8\xb0\xfa\x8d\x73\x0f\x15\xee\x81\x98\xff\xc0\xf6\x7c\x9a\xfe\x49\xd0\x10\xdf\x6d\xbb\x7f\x5e\xd6\xe5\xab\xf2\x51\xf3\x17\x94\xd2\x70\x98\x32\x41\x51\x05\xed\x13\xf3\x17\x03\xa7\x2b\x48\x28\xd3\x28\x35\xa5\x47\x87\x91\x4d\x96\x38\x11\x32\x91\x29\x39\x09\x58\xd8\x24\x37\x7c\xc3\x25\xbe\x8b\x69\xa8\xa8\x1e\xf3\x79\x00\x11\x81\x98\x52\x3a\x5b\x93\xb0\xe2\xec\xae\xe5\xf9\x91\x5f\x89\x32\x5c\xc2\xcf\x1f\x2c\x71\xb9\x2d\x09\x1b\xa2\x20\x07\xf1\xf3\xc7\xda\xfb\x70\x29\x8d\xe5\x58\x0b\x02\x6a\x3e\x04\xcc\x96\xe5\x3a\x02\xa0\xfb\x95\x2a\x05\x7a\x13\xac\xc7\x1d\x1f\xb1\x62\x06\x9f\x1b\x36\x8d\x1f\x6c\xc6\x08\xc6\x39\x3a\x0a\x35\x33\x42\x3c\xcd\x39\x45\x60\x1d\x91\xbd\x35\xb7\x85\x60\xc2\x18\x71\x13\x39\x92\x08\x18\x21\x10\xb5\x90\x15\xe7\x6d\x1a\x9c\x8c\xec\x75\xe8\x2d\xd6\x6e\xaa\x99\x1a\x06\x91\xe8\xae\x68\x6a\xd4\x55\x31\x6d\xb2\xbb\xf3\x50\x43\x40\x4c\x57\xc0\x3b\x80\xd8\x44\x37\xf1\x26\x9e\xcf\x09\xf3\xf9\x7c\x1e\xd0\xd0\x8f\xbb\x51\xe9\x3c\x94\x83\xd8\xa5\x15\x3f\x9c\xf5\x4a\x37\x20\xe0\xcc\x0f\x20\xa1\x2b\x41\x91\x75\x53\x3b\x3a\x8b\x36\xe9\x4d\xb2\x49\xe6\x73\x12\xd3\x59\xe8\x30\x3f\x09\x20\x21\x10\xcf\x28\xdd\xd9\x36\x47\x16\x06\x53\x3b\xc2\xc4\xc7\x4c\x9f\x09\xcd\x67\x0d\x08\x68\x86\x8c\xfa\x81\x00\xe9\x1d\x12\x65\xa3\x45\xdd\xa0\x00\x49\xb9\x46\xb1\x6d\x67\xb2\xd1\x98\x6c\x3a\xd0\x4a\x24\x68\xfd\x6e\x01\xdd\x45\x05\xed\x7e\x00\x99\xe0\xc4\x1f\xb2\xd8\x5d\xc3\xa1\x2a\x9f\x26\x61\x45\x70\x3d\xaa\xe8\x19\x1c\x84\xb6\xed\x44\x92\x6f\x08\x29\x03\x46\x45\xc3\x26\x9f\xc2\x04\x6f\x40\x15\xb7\xde\x71\x20\xf0\x82\x40\x42\xcf\x19\x3b\xa6\x7a\x16\x4a\x96\x0e\xb8\x12\xbf\x9c\x71\x05\x04\x79\xd8\xa5\xe8\x3a\x65\xe6\x8f\xa0\x49\xe2\x77\x3e\x87\x44\xb3\x10\x02\x6d\x3d\xba\x5f\xb2\x9a\x2f\x8b\xf2\x11\x8e\x0f\x07\x21\xa3\xba\x77\xad\xe8\x2b\x72\xec\xd6\xe7\x92\x41\xbb\xfa\xe1\x61\x1f\xf2\xea\x4a\x4a\x73\x57\x7a\x14\x57\x08\xd3\x57\xa2\x86\xab\x9f\x79\xfa\xd5\xd3\xe1\x4a\x6e\x13\xc9\x1d\x58\xc8\x4b\xd6\x8e\x75\x65\x91\x91\x50\xb9\xf3\x2d\x5f\x52\x8c\x2b\x6b\x1e\xce\xad\xc0\x0a\xce\xd0\x1f\xd9\xe8\x32\x57\xc7\x9e\x87\xb6\x24\x8c\x58\x62\x65\x05\x36\xed\xd8\xe9\x8e\x14\x6f\x26\xf8\x8c\x68\x82\x26\x4b\x5a\xa3\x89\xb6\x6d\x87\xde\x6c\xe5\x5a\x4c\x0c\x49\x15\x59\x09\xa4\xdc\x34\x56\x81\xa3\x1f\xac\x6e\x78\x23\x18\xf3\xc5\x1a\x21\xac\x15\x5d\xab\xe9\x04\x95\xd3\xbc\x31\xec\x20\x83\x5b\xb8\x83\x1c\xf6\x50\x40\x09\x07\xb8\x87\x0a\x8e\x50\xc3\x03\xb5\x8e\xd9\x6f\xbf\xe5\xdc\x9a\xaf\x9f\x0b\xce\x4a\x4c\x27\xbc\x33\x05\xe3\x47\xba\x82\x27\xba\x82\xf7\x74\xc7\x1c\x02\xbf\xc9\x9f\xcf\xe4\xcf\xe7\xd3\xe2\xab\xe0\x89\x04\x14\xe6\x74\xb6\x22\xb0\x6a\xe1\x0b\xba\x7e\xf9\xf2\xe3\x35\x7c\x49\x4f\xed\x58\x16\xff\x4a\xec\xf2\xaf\xe9\x57\xcb\x43\x79\x80\xbf\x8a\x5f\x21\xd2\x7f\xa3\x1f\xbe\xa5\x5f\x29\xc9\xff\x6f\xf4\x12\x26\x5a\x09\x3e\x59\x63\x9f\xf8\x26\xda\x44\x92\x14\x30\x3f\x0a\x44\x57\x14\x43\x72\x15\xa9\xe5\x59\xac\x5b\xf8\x8e\x5a\xd1\x8e\x47\x77\x3c\x6e\xa4\xcc\xcc\xe3\x86\x1d\xdf\x17\x51\xc3\x1e\xea\x32\x29\xa3\x87\x23\x3e\x1d\x72\xf6\xbe\x11\x92\x66\x55\xe6\xc7\x26\xe6\x09\xaf\x9a\x38\x3b\xb2\x30\xe7\x71\xb3\xcb\xe2\x98\x17\x4d\x76\xdc\xb3\x43\x93\x97\xe5\xa1\xd9\x3f\xe4\x75\x76\xc8\x79\x53\x1e\x78\xd1\x54\x9c\xc5\x65\x91\xbf\x6f\x94\xd2\x24\x6e\x8e\x51\x79\xe0\xb1\x05\xaf\xa8\xe5\x6f\xb7\x4f\x2f\x56\xdb\x6d\xbd\xdd\x56\xdb\x6d\xb1\xdd\x26\x81\x05\xdf\x53\xcb\xf1\xdc\xed\x76\xbb\x5d\x36\xfe\x76\xfb\xb8\x08\x1a\xff\xed\x76\xfb\xb4\x5a\x2d\xb6\xdb\x27\xb6\x0a\xc8\xdc\x82\x1f\xe8\xf7\x1d\x65\xb1\x1e\x2d\xb0\x1e\xff\x64\x11\xf8\x91\x5a\xdb\xad\x6f\xcd\x5f\xcd\xad\xe7\x8e\x35\xff\x7e\x6e\x11\xc7\x73\xd5\xbb\xff\xfc\xed\xb3\x66\xf6\xef\xc0\xa3\x44\xa5\x78\xee\x47\x4e\xdf\xd4\x5b\xf1\xfb\x51\x40\x9e\x93\x8f\x9a\xad\x35\xfe\xb0\xb5\xc4\x97\xad\xd5\x38\xd6\xfc\x87\xb9\x45\x48\xa3\x6a\xd9\x6e\x03\x0b\x7e\xa2\x96\xdb\x37\xb8\xdd\x3a\x8e\xf3\x9f\x57\x4d\x9a\xf1\x17\x87\xf8\xdb\x6d\x10\x34\xd6\xfc\xc7\xb9\x45\x9e\x93\x66\xf9\x9c\x6c\xb7\xa2\x69\xf8\x6f\x2a\x80\x55\x6e\x7b\xe7\xd5\xdc\x9a\x5b\x60\xa5\x16\x81\x9f\xcd\x74\xeb\x2d\xf6\x71\x8e\x15\xbf\x55\x95\x06\x44\xb7\x42\x9e\xcb\x31\xcc\x9f\xa9\xc2\xaf\x27\x0a\x3f\x07\xf9\x63\x11\x78\x33\xf5\xd9\xf1\x6f\xe6\xff\x16\x5d\x7c\x35\xb7\x48\x97\xf5\xef\x83\xac\x54\x67\x7d\xbb\xdd\x06\x1f\x6d\xad\xe0\xb9\x67\xce\x1e\xb6\xfd\x0f\xb3\xc4\x4f\x04\x7e\x19\x37\xf6\xc3\xdc\x7a\x66\x11\xf8\x95\x9e\xbe\xfd\xd2\x1d\x7c\xfb\x93\x9a\x7a\x8b\xc0\x17\xaf\x3e\x7b\xfd\x7a\xf8\x75\xbb\x5d\xf6\xdf\xdf\x7c\xf6\xd7\xe1\x57\xf1\x69\x04\x49\xcf\x2d\x22\x33\x7f\xf6\xe6\xcd\xcf\xee\xa8\x17\x3f\x12\xf8\xe9\xf5\x57\x7f\xff\xf2\xc7\xf1\x87\x9f\x08\x7c\xf1\xcd\xb7\xaf\x46\x5d\x73\x1d\x04\x7e\xd4\x6b\x34\x39\x3b\xd6\x4d\x51\xef\xc4\xff\x85\x78\x21\x0b\x27\x12\x9c\x70\x53\x26\x0b\x81\xdc\x14\xf0\xa8\xd9\xe2\xef\x78\xd1\x94\x71\xdc\x38\x8e\x3f\x5f\x04\x0d\x71\xb6\xdb\xf8\x39\x29\x9a\x1e\x7e\xd5\x07\xf5\xbe\xdd\xc6\x73\xd2\x90\x6e\x6a\x11\x50\xac\x4c\xf0\xe7\x65\x99\x8f\xc6\x2d\xf6\xc5\x77\x73\x8b\x3c\x53\x59\x0a\xce\xe3\xe3\x17\x52\x9f\x34\x1e\x9b\xa8\x4e\x2e\xb3\xdb\xf7\x8a\xdf\x37\x69\xdd\xe4\x72\x44\xfd\x00\x87\x63\x70\x3c\x77\xb1\xdd\xc6\xc4\xc3\xae\x1b\x1d\x73\x3c\xea\xbf\x5d\x04\xcd\x33\xd5\xc5\x16\xfe\x49\xaf\x45\xaf\xb2\xe2\xf0\x50\x2b\x84\xd4\x88\xce\xb0\x8a\xb3\x26\x7c\xa8\xeb\xb2\x20\xcf\xae\x33\xf8\x1f\x7a\xfd\x76\xb7\x8d\xc5\xe3\x33\x7a\xfd\xd6\x7f\x7b\x0a\xe6\xdb\xd3\xf6\xf8\x7c\xeb\x17\xac\xce\xde\xf1\xab\xed\xe3\x35\xfc\x4b\xd6\xf6\x27\xc7\x17\x18\x64\x4e\x1a\x67\xfb\x38\x27\xcd\x76\xa9\x13\xc8\xb3\x6b\x60\x8c\x5e\xfb\xf3\x7f\x07\xd7\x10\x32\x7a\xfd\x51\xb3\xdd\x5e\xa7\x10\xb1\x01\xe4\xe1\x3e\xf4\xb7\xdb\x98\x2d\x92\xe0\xb4\x86\x3f\xb7\x38\x0a\xaf\x91\x43\x24\xcd\x12\x47\x20\x40\x38\x66\x74\x92\xc1\xa2\xd6\xea\xc9\x9a\x87\x8b\x3f\x7f\xfa\xe9\xc7\x7f\xd6\xec\x8e\x60\xd6\xe2\xa6\x89\xbc\xd0\x5d\xdd\xc4\x9e\xa4\xed\xcb\xa4\x2a\xf7\x5f\xec\x58\xf5\x45\x19\x73\x27\x9e\x63\x09\xe2\x4e\x7e\xbc\xb9\x59\xaf\x9a\x4f\x3f\x7d\xf1\x97\x3f\xc3\x7a\xf5\xe2\x63\x3b\x6e\x3e\xfd\xf3\xc7\x2f\x56\x28\xb8\x98\x4c\xcc\xde\x21\xed\xa6\xae\xde\x9f\xbe\x51\x6c\xcc\x57\xf4\x5b\xc9\xb7\xbc\x5b\x22\xf4\x09\xb9\xec\x48\x60\xf8\xf6\x95\x6f\xbe\x6b\x45\x67\x47\xaf\xdb\x88\xd5\xd1\xce\x49\x18\x39\x7d\x43\x4f\x58\xaf\xfb\x95\xca\xe5\x0d\x89\xd4\x5f\xb5\x14\x03\xaa\xd9\x90\x90\x76\x92\xfb\x67\x06\x37\xbd\x79\xdc\x65\x39\x17\xf4\x4b\x31\xd0\xf3\x79\x40\x36\x1d\xf3\x1c\x2d\xd6\x6d\xdb\x76\x1c\x4a\xca\x70\xc2\x63\xe0\xb2\xae\x04\x76\x8a\xde\x97\x48\xe7\x1f\xe1\x49\xb0\xb2\x4e\xe8\x85\xcb\xf2\xb1\xe0\xd5\x97\x8a\xb8\x37\x4d\xe8\xbe\x23\x33\x4a\x0b\xdb\xde\x3b\x21\x81\x50\xb0\x1c\x05\xc4\x62\x6d\xfc\x00\xee\x68\xd8\x8d\xb9\x93\x37\x66\x86\x70\x3e\x63\x4d\xb3\x9e\x51\x7a\x67\xdb\x7f\x91\x3f\x6b\x7c\xd5\x04\x37\x16\xed\xce\xb8\x6d\x1f\x50\x32\x5c\xab\xbc\x4e\x42\xff\xb5\xe4\x4f\x1c\xc5\x5f\x41\xa8\x6f\x69\xe2\xaf\x03\xcc\xf3\x17\x2a\xca\x8b\xa7\x1d\x0d\x97\x29\xaf\x95\xbc\xfd\xf9\xfb\x6f\x63\xe7\x96\xc0\x6c\xd7\x34\xb3\x9d\x21\x54\x0f\xda\xda\x2d\x33\x21\xb3\xdd\x76\x89\x92\xcf\xde\x11\x88\x3b\x99\x71\x34\x09\xb6\x8d\x2d\x0d\xd2\xce\xdb\x25\xb6\x5d\x3b\x21\xec\x88\x6d\xff\x5e\x1b\xa2\xef\x89\xff\x22\xd0\xdf\x35\xe4\xc5\x60\x8e\xe7\xf8\xf9\xfb\x37\x2c\x15\xb2\xb8\x98\x04\xc0\xde\xe3\x3c\x7c\x1c\x10\xdb\x8e\x86\x39\xbf\xc8\xd9\xf1\x28\xf2\xfe\x6e\x9d\x5d\x4e\xd1\x67\x88\x5b\x21\x95\x2f\xef\x8f\x42\x8e\x9c\xdd\x37\xcd\xec\x7e\x59\xf3\x23\x8a\x92\x38\xc7\x47\x5a\xd1\x07\x78\xa4\x21\x3c\x51\xb5\x38\x0c\x04\x73\x7a\xd7\x9f\x2e\xcd\xa8\x02\x83\x73\xc5\x01\x39\x95\x34\x15\xe2\x92\x53\xc9\xc5\xfa\xac\xae\xab\x2c\x7c\xa8\xb9\x63\x65\xb1\x45\x88\x77\xa4\x55\x47\x60\x42\x06\xd6\x76\xfb\xcc\xb6\x88\x1b\x2e\x8f\xe3\xcc\x70\x24\x70\xa4\x96\x9f\xc5\xf4\x23\x6b\x7e\x9c\x5b\x1f\x05\x57\x16\xe4\xb4\xd4\x8c\x9d\xdc\x13\xf9\x62\x41\x4a\x3f\x0f\xe8\x71\x5e\x31\x47\x3c\x91\xcd\x23\x65\x4c\x8f\xcb\xb6\x0f\xcc\x09\x4d\xf8\x68\x1a\x31\xba\x72\x79\x5b\x66\x85\x63\x81\x45\xc4\xa4\x3c\x11\x81\x14\xce\x66\xf3\x71\x89\xc7\x2a\xaf\xd5\x29\xca\x67\x79\xee\x3c\xe1\x3c\xca\x1d\xff\x9e\x9c\xda\x24\x2b\x58\x9e\xbf\x3f\x55\x4d\x13\x2a\x85\xce\x68\xd4\x6d\xdb\xaa\x8a\x33\xa7\xd7\xde\xfc\x0c\xd6\xb3\xb5\xa0\x46\xb8\x51\xfb\xdd\x2b\x18\x69\xa9\xd0\x16\x22\x67\x97\x1c\x3a\x91\xd8\xcf\x9d\x10\x86\x30\x16\xcd\x85\x3c\x73\x23\x24\xaf\x68\xc7\x5f\xe1\xbc\xd8\x76\xcc\x73\x5e\xf3\xab\xd0\x67\xcb\xe3\x2e\x4b\x6a\x87\x04\x10\xfa\x98\x37\xa0\x5c\xf7\x25\xec\x9b\xcc\x98\xa9\x5f\xf2\x1f\x02\x3a\x5b\x01\xeb\xbf\xdf\x32\xf3\xa8\x66\xa4\xf6\x8a\xb3\x77\x16\xd9\xf4\xb3\x37\x9b\x31\x27\x24\x6a\x82\x3a\xad\xc2\x6c\xdd\x4d\x94\xb9\x18\xb6\x1d\x5e\xd6\x87\x41\x48\x85\x80\x6c\x60\xb6\x3b\x36\xc4\x90\x4a\xa6\x6b\x2c\x62\xea\x1b\x24\x60\xf0\xc5\x82\xc4\x4b\x56\xd7\xd5\x37\xac\x88\x73\xee\x47\x3e\x0f\x02\x6a\x0c\x3b\x1f\xd4\x16\x0a\x50\x8f\x69\x64\xdb\x63\x61\x6c\x4d\xa9\x81\xf8\x6c\xdb\xf9\x77\xb8\x3c\x96\x0f\x55\xc4\xbf\x2d\x62\xfe\xd4\x34\x5f\x90\x85\xf3\x6f\x36\x4e\x13\x3b\x38\x1e\x60\xa3\x88\xc8\xae\x45\x34\x5a\x16\xfc\xa9\x7e\x9d\x85\x79\x56\xa4\x02\xe3\x45\x86\x5c\xb2\x58\x77\xea\x11\x6f\xed\x2e\xd6\x7d\x8f\xf7\xe6\x42\xf5\xc7\x50\xdd\x10\x2e\x6c\x4b\x2d\x85\x22\x37\x81\xf2\xa4\x98\x77\x3c\x37\xa4\x94\x19\xf3\x5b\xfc\x5f\xd5\xef\x18\x0d\x34\x8d\x25\xb9\x14\x7c\x23\x17\xda\x2b\xcd\xf6\x32\xe6\x98\x4d\x6a\x30\xa5\xf3\x10\xcc\x4f\x11\xc4\xb2\x3f\x1c\x12\xca\x1c\x3f\x80\x48\x53\xca\x90\x40\x4a\x93\x21\x18\xa4\x8b\x05\x89\x7c\x4e\x13\x3f\x0d\x02\xdb\x76\x04\x14\xd0\x99\x13\x8b\x1f\xf1\x4c\x48\x2b\xfe\x75\x5d\x3a\x0c\xf6\x82\x6d\x4f\x9d\x53\xb3\x49\xbc\x6d\xdb\xac\x8d\x68\xca\x96\x4a\x79\x41\x4f\x2d\x24\xe2\x3d\x3b\xfe\xfa\xfd\xab\x73\x89\x1c\x95\x79\x6c\x4c\x81\x19\xe9\x64\x6d\xd5\x42\x77\xfe\xe9\x59\xdf\xbc\xf9\xfe\xd5\x10\xff\xba\xb3\x75\x0b\x7b\x6c\x95\xd7\xba\x96\x09\xe9\x9f\x43\x4a\x99\x77\xde\x9a\xfb\xae\x3b\xad\x91\x74\x5f\xd0\xdb\xd4\x00\xf6\x74\xdc\x1d\xcf\x29\x68\x0a\x25\x3d\xfb\x00\x5c\xa4\xf1\x84\x3d\xe4\xf5\x3f\x32\xfe\x08\xdc\xb6\xf9\x8c\x52\x01\x2c\x07\xdb\x76\xf8\x92\xc5\xf1\x57\xef\x78\x51\xbf\xca\x8e\x35\x2f\x78\xe5\x9d\x27\x39\xd6\x43\x91\x97\x2c\xb6\x80\x33\x98\xad\x89\xcb\xc5\x16\x66\xd1\x0e\x73\xd9\xf6\xe0\xd5\xb1\xca\xa2\xcf\x4e\x08\x1c\xe8\x2c\x71\x52\x02\x11\xee\x7b\x44\xc1\x47\x7a\x6b\x00\x8f\xa9\x46\x8f\x34\x69\xa4\x56\x66\xc1\x8c\x8d\xe8\x55\xf7\xd9\x22\xad\xa8\x71\x6a\xc9\x2f\xd6\x6d\xaa\xfc\x53\x85\x31\xbf\x28\xf7\x12\x63\x5a\x84\xa8\xe6\xce\x69\xbf\x90\x17\x15\x00\x9f\xb7\xda\x11\x73\xfa\x4c\x92\xb7\xf4\x12\x5b\x20\x4b\x0a\x5e\xe5\x42\x17\xcb\x41\x17\x19\x11\x3c\xcc\x03\xcc\x46\x15\x8a\xba\x9a\x66\x2a\xd5\x79\x18\x77\x53\x34\xe6\x39\xf1\x32\xc9\x8a\x78\xf9\xed\x97\x23\xe5\x4c\x96\x4c\x5a\x7c\x8c\x39\x3a\xe4\x0c\x35\xb2\x19\x31\x5d\xbd\x25\x40\x24\x18\xa2\x9e\x6c\x78\x7e\x14\xb8\x7e\xd0\xb6\x20\x5a\xcf\x6b\x5e\x0d\xdb\xef\xf6\x5b\x47\x7b\x23\x06\x71\x5f\xdd\xe4\x0a\x9e\x33\x2f\x02\x43\xb7\x2d\x71\x1d\x45\x5f\xbb\xa1\xfe\x3f\xd0\xac\x1c\xf2\x45\x5c\xd3\xf5\x44\xd2\xcc\xf3\x34\xd9\xc3\xc1\xfc\xbc\x63\xf9\x03\x57\x7d\x06\xd5\xd7\x37\x9f\xfd\x95\x4e\x43\xb2\x37\xa5\xb8\xfb\xbd\x15\x33\x8a\x5f\x64\x65\x5d\x64\x37\xbd\xf0\x9c\x91\x62\x9d\xee\x77\x52\xa3\x1d\x53\x3f\x50\x47\x4b\x17\x2b\x17\x44\xd5\x7a\x2e\x48\x0c\x23\x27\x4d\x5b\x13\x3c\x66\x20\x82\x6a\x47\x06\x22\x53\x6c\x79\xd4\xcd\x52\xac\x39\xa1\xa4\xd5\xf3\x83\x0a\x93\xf1\x0c\x75\xbb\xca\xb6\x27\xb5\x9b\x87\xf1\xe0\x7b\x9e\xbb\x1f\x22\x54\x62\x38\xf7\xe2\x8f\x64\xc0\xfb\x2d\x3c\x9e\x18\x21\x5b\x38\xa3\x5d\x7b\xbe\x5d\x8b\x82\x57\x82\x1c\x50\xeb\x25\xbb\x92\x3c\xf2\xc3\xdc\xfa\xe8\xe6\xe5\x35\xbb\x79\x29\x15\x06\x7d\xf2\x62\x9b\x04\x1f\x5d\xed\x8f\x2c\xcf\xcb\xc7\x88\x1d\xea\x87\x8a\xd3\x8f\x3e\xba\x79\x59\x1e\xa4\x4e\x5b\x69\x3c\x31\xed\x5a\x26\xde\xbc\xbc\x96\xc9\x37\x16\xb0\xf3\xd5\xb3\xfc\x61\x75\x6f\xe9\x47\x1f\x05\x1d\xee\xb2\xed\x7b\x39\xdd\x96\xff\xfc\xed\xb3\x80\xf6\x3a\xc6\x8f\x9a\xad\xb5\x45\x85\xd2\x64\xa5\xba\x27\x7d\x55\x4d\xa3\xab\xea\xb5\x99\x9e\x8b\xd0\xdd\x48\xa5\xcd\xa5\xba\xb2\xf8\xdf\x54\x0e\x7f\xaa\xb6\x7f\xd3\x0b\xe5\x5c\xa5\x07\x9e\x28\xd3\x7f\x9a\x2c\xc9\xfe\x84\xcd\xcd\x9f\x4f\x14\x5d\xfe\x69\x39\xf7\xe7\xff\x0e\x90\x9a\x8c\x56\x57\xe2\x89\x74\xcc\x59\x4b\x6e\x8a\x6c\xc6\xc2\x91\xd8\x89\x16\x58\x52\xd9\x8c\x5d\x19\x9d\x30\x0f\xb3\x17\x82\x86\x81\xf5\xe5\xa5\x69\x12\xdf\x69\x3c\xb5\x76\x58\x52\xea\xbb\x3a\x75\xf1\xa5\x49\xe3\x05\xaa\xc0\xa7\x26\x4d\x7f\x02\xcb\xd5\x9a\xf2\x0b\xb5\x3c\x07\xf7\xc9\x22\xa0\x4b\xc2\xf2\xb9\x2b\xe6\x8b\x88\x3d\xb3\x17\x02\x05\x3f\xea\xfc\x7a\xff\x1c\x69\xa9\x3f\x35\x4d\xb9\x7c\xe4\xe1\x5d\x56\x7f\x3f\xcc\x2b\x3e\xec\xcb\xdf\x26\x52\xcb\xa9\x9c\xc7\x51\xa2\xd8\x90\xa3\x15\x8b\x96\x71\x76\x8c\xca\xa2\x40\x60\xc5\xfc\xf4\xa8\xce\xbf\x40\x8a\x44\xd0\xbf\xfb\xc7\x99\xd8\x1d\x38\xb6\x4a\x8d\x6d\x46\x2d\xf8\x49\xc0\xc2\x3d\xbd\xef\x26\xde\x50\xb5\xdd\x2b\xf9\xb4\x11\xdc\x42\x45\xab\xa9\x3c\x95\x99\x27\xd4\x33\x52\x2e\xa3\x72\x2f\xa8\xa3\x66\xf3\x7e\x2a\x8f\x99\xe8\x38\x81\x9a\x86\x4d\x63\x64\x2b\x6a\x96\x15\x47\xe2\x4d\xe9\x9f\xfe\x32\x90\x82\x3c\x36\x66\xf7\x5c\x21\x2d\x85\x43\x01\x6e\x63\x1c\xf8\xc4\x4d\x33\x73\x66\xb1\x54\x08\xc5\x86\x41\xca\xcc\x89\xba\xa6\xbd\xfe\xd1\x89\x09\x9a\xa6\x4c\x76\xdd\xb6\xd7\x7f\xb6\x2f\x7e\x45\xfb\xa6\x31\x15\xc9\x12\x27\x54\xf2\x56\x48\x07\x0a\x00\xf1\x05\x49\x86\x36\x47\xd9\x74\x32\x2a\x7c\x4e\x43\xef\xac\x1e\x66\x1e\x1a\xe5\x42\x38\x5e\x6d\xa4\x2e\x73\x76\xb1\x4f\x8b\x59\x78\xe9\x53\x47\x80\xbc\xd8\x75\x62\x3a\x25\x03\x50\x4a\xc7\x7a\xa9\xa6\x09\x89\x77\x79\x0a\x42\xe2\xae\x61\x6d\x8b\x59\x97\x56\x74\x5f\x72\xc1\x27\xf3\x58\xac\xd0\xa5\x42\xd8\x50\xec\x89\xf1\xa5\x4d\x33\xea\x07\xa5\xf4\x9d\x6d\xd7\xce\x3b\x60\xc4\x5b\xac\xdd\x50\xe6\x0a\x2f\xe5\x0a\x89\xb7\x76\xef\xbc\xbf\x39\x77\xc0\xc8\x42\xfc\x84\xc4\x5d\xb9\x9f\xd8\xb1\x28\xbd\x9e\x5a\xa0\x4b\x13\x1b\x75\x26\x04\xfd\xb2\x21\x1f\x60\xbc\xee\xa8\xcf\x02\xc8\xa8\x1f\x06\x52\xab\xd8\x34\xb3\x84\x18\x00\x98\x76\x9d\xf6\xd6\x2e\x17\x2f\xc9\x54\x07\x45\x61\xc1\x27\x75\x65\x95\x5a\x60\x13\x51\xb6\xe9\xe5\x75\x03\x7e\x76\xcb\x87\x42\x2a\x56\x22\x91\x2b\x9c\xce\x95\x99\xb9\x64\x8e\x9d\x1f\x07\x94\xd2\xcc\x8f\x03\x12\xcf\xe7\x3d\x1c\xe4\x0c\xbf\x01\x7e\x71\x55\xb6\x77\xa2\xcb\x99\x7e\x5e\xbb\xab\x16\x52\xe2\x16\x2d\xa4\x4c\x63\xbc\xe9\xe3\x56\xd4\xff\x16\x0f\x79\x2e\xff\x84\xc4\x2c\xd2\xe1\xcf\xb3\xc5\x98\x82\x43\xad\x0b\x66\xa8\x0b\xee\x18\xd9\xbf\x83\x45\x3f\x7a\xb6\x16\x04\x1f\x66\xce\xec\x0c\x39\x37\xcd\xec\xd0\x34\x95\x6d\x57\x12\xd7\x84\xa4\x69\xee\x05\x5d\x51\x6f\x04\xb5\x6d\x72\x0b\x75\x68\x32\x94\x1a\x93\xa6\x99\x40\xae\x02\x38\xe3\x4e\x41\x8b\x7a\xe3\x3e\xa1\xc3\x2d\x9d\xb2\x45\x69\x9f\x38\x39\xb5\xfd\x9c\x84\x50\xc8\x09\xf1\x59\xa0\xa9\xd4\xcd\x0a\xe7\x46\xe3\xa0\xc9\xf9\xfc\x9d\x79\xd1\xc6\xdf\x29\x43\xa1\x73\x54\xc5\x87\x0b\x23\xb0\x73\x3a\x50\x53\x8d\x4c\x0f\x02\x48\x28\xb7\xed\x2f\xe5\x2c\x99\x39\x61\x94\x93\x78\x1c\xf5\xfe\xb3\x83\xe6\x3a\x35\x80\x75\x56\x9a\x89\x97\xb8\xa6\x6c\x2c\xd6\xc9\x1b\xc9\x3a\x21\x71\x9d\x84\x4e\x88\x18\xa1\xa0\x83\xc9\xf2\x78\xe0\x51\x96\x64\x3c\xf6\x12\x29\x63\xb8\xa8\xa4\x13\xe3\x47\x1b\x4d\xfa\x21\x1b\x4d\xeb\xf5\xfb\xa2\x66\x4f\x57\x98\x13\xae\x1e\x8a\x8a\x47\x65\x5a\x64\xbf\xf1\xf8\x8a\x3f\x1d\x2a\x7e\x3c\x66\x65\xe1\x5e\x59\x73\x26\xa7\xf4\xa1\xc8\xee\x1f\xf8\xeb\xb2\x9a\x52\x6a\x18\x22\x02\x6e\xe3\x9c\xce\xa2\x65\xcc\x6b\x1e\xd5\x5f\x3e\x1c\xf2\x2c\x62\x35\x3f\xc2\x1d\x55\x18\xf1\x75\x2d\x78\x0f\x21\x3e\xa1\x01\x81\xb3\x12\x4c\x88\xf8\xe0\x7c\x4e\x20\xd7\x02\x44\x48\x99\x9f\x08\x01\x02\x69\x84\x9f\x04\xb6\x8d\xd6\x31\x48\xb6\x13\x42\x0c\xf5\x22\x53\x06\xca\xa8\x4d\x82\x35\xd1\xc0\x76\x87\x7a\x4b\x60\x2d\x70\x9a\xe2\x4c\xbe\xe1\x4f\x93\x36\x19\xd4\xb2\x10\xd5\x25\x06\xa9\x15\x23\x49\xe4\xf9\x88\x40\x4b\x4d\xf3\x17\xf9\xb3\xc6\x57\x29\x4a\x9f\xd9\x7a\xa1\xc9\x21\x1e\x58\x16\x75\x87\x04\xcd\x44\xb4\xc7\x64\x94\x2d\xf1\x70\x12\x59\xc5\x0d\xdb\x88\x04\x53\x13\x19\xcd\x29\x5a\xc0\xea\xb3\x91\x8f\x65\xd3\x9f\x98\xf8\x51\xf6\xf4\x1f\x62\xe9\x65\xbe\x7e\xde\xf0\x5c\x0a\xeb\x08\x7b\x61\xb4\x85\x58\xea\xa7\x24\x6e\x38\xd2\x93\xa1\xad\x76\x3f\x5d\x81\x64\x7b\x7f\x3a\xf2\x87\xb8\x74\x33\x06\x88\x4c\xdc\x5f\xa1\x07\x75\xf7\xd4\x82\x10\xd0\xc4\x6f\xc5\x73\x3c\xd8\x74\x4f\xd6\x8d\xe5\x9e\xe2\xac\x72\xad\x1e\xed\x5a\xca\x6a\x7e\xb6\x6a\xc1\xba\x9a\xf8\xde\x82\x35\xef\x92\x2b\xfe\x2e\x2b\x1f\x8e\x6a\xf4\x83\xb2\xff\xbe\x94\xa9\x6d\xe1\x50\xf1\xaf\x51\xe0\x77\x4f\x78\x2a\x3e\xa5\x40\xf0\xd7\x01\x15\x7f\x46\xc2\x3f\x30\xff\xe3\x80\x3a\xe2\x6f\xd3\x30\xff\x13\xfc\xfb\x69\xd0\x34\xa6\x75\xa0\xca\x2a\x44\x14\x84\xc1\x17\x02\x06\xb1\xa0\x25\x76\x86\xff\x71\x80\x7a\x7f\xe8\x00\x19\x3e\x21\xad\x3a\x70\xff\x60\x5f\x06\xf8\x02\xac\xa2\xde\xc9\x06\xd6\x41\x57\xd3\xc7\xc4\x53\xbd\xd3\x1b\xda\x61\xfe\x2a\x10\x1d\xff\x24\xa0\x73\x47\xfc\x78\xa2\xcb\xe2\xf1\xcf\x41\xd3\xac\x89\xfb\xe2\xb9\x63\xf1\x77\xbc\x90\x95\x7d\x8c\x26\xb8\x71\xac\xdf\x88\x28\xfb\xa9\x2c\xfb\xff\x0b\xe6\xcc\xff\x3f\x67\x19\x5c\xf1\x63\xdb\xe3\x16\x5b\x6d\x5d\x30\xb5\x73\x66\xa2\x79\xdb\x16\xb3\xa3\x41\xed\xd7\x25\xce\x81\x3a\xfa\x11\x75\x78\x62\x23\xba\x38\x20\x4f\xe4\xa4\xc3\x29\x77\x23\xdb\xfe\x87\xcc\x1e\x09\xa9\x3b\xa4\xa9\x13\xc1\x6c\x45\xe4\x4b\xd4\x5b\xff\x12\xab\x53\x33\x2f\x42\xb2\xd0\xcf\x04\x17\x66\x25\xea\x5d\xf5\x73\x18\x8a\x11\xbf\x08\xb4\x8f\x12\xa6\x98\xab\xf5\x31\x21\xad\x00\x68\x09\x42\x6f\x3e\xfb\xeb\x84\x7f\xc6\x58\x6b\x34\xad\xd1\x97\xba\x0f\xef\xcc\x4a\x6f\x36\x50\xaa\xfc\xc7\xc6\xbf\x6d\xab\x6c\x47\xce\xfb\xf5\xde\x67\x78\x90\xd4\x69\xa5\x9b\xc6\x09\x07\x36\x02\xce\xdb\xce\xfe\x85\xcd\x2d\x69\x18\xd0\x3c\x23\x96\x98\xd4\xf7\x0e\x83\x89\x7e\x85\x72\x0d\x26\xd0\x5a\xd4\x2b\x5f\x8c\x97\xa6\xf9\x7d\x55\xd9\x58\x4d\xa6\x34\xba\x16\xc1\xbd\xd6\x92\x16\x46\x7b\x77\x60\x04\xdb\x25\xeb\xc3\x06\xaa\xe8\xbb\x13\x1b\x2e\x49\xd2\x54\x96\x7b\x42\x9a\x13\xf3\xe6\x86\x9e\xc3\xe7\x02\xa9\x5b\x32\xc1\x13\x9c\x65\xe4\xea\xef\x1e\x9f\xe1\xeb\x5b\xf5\x1a\xd9\xf6\x8a\x52\xca\x3b\x38\x8b\x88\x6b\x3d\xef\x3f\x9a\x1f\x6e\x16\x6b\xd7\x7a\x66\x7e\x93\xe0\xd4\xc3\xa2\x6c\xea\xdf\x2a\x8b\x23\x70\x05\xef\xa0\xe8\xbf\x05\x3a\x24\x88\x37\xc6\x95\x36\x66\x5f\x9b\x86\x77\x70\xaa\x6b\x9e\xaf\xb1\xee\xb9\xb5\xb0\xdc\xd9\x9a\x08\x04\x79\x8e\x6e\xb4\xfb\x8d\xb2\x39\xa0\x88\x5d\x90\x4f\xeb\xc1\x1e\x52\x6a\xe5\xec\x58\x9b\xe9\x8b\x4f\x08\xec\xa8\xa5\x8c\x7e\xb0\x27\x7a\x7a\x05\xc1\x8b\xd5\x14\x79\x13\x0e\x14\x33\x53\x3e\x30\x00\x5e\xf4\x24\x93\xfd\x18\xd8\x39\xd2\x64\x26\xa4\x01\xcb\xa0\x78\xd6\x04\x15\xb8\x1f\x0a\x1a\x15\xdd\x09\x19\x6a\x7a\xb7\xc0\x91\xce\x32\xdb\x9e\xed\x04\xd5\xbe\x47\xe2\x9c\x68\x4e\xe2\x40\x4e\x79\x27\x1d\xe4\x34\xf7\x0f\x81\x90\x3d\x77\x5e\x7e\x79\xeb\x55\x68\x0a\x9a\x8f\x59\xda\xd9\x7a\x53\xd2\x03\xb5\xca\x22\x47\x83\x50\x66\xdb\xb3\xd2\xb6\x07\x23\x69\xbb\xad\x9f\x25\x4e\x49\xfd\xd4\xbb\x37\x88\xbd\x7b\xbf\x14\x33\x8f\xcf\x01\xa4\xb6\x7d\x24\xa7\x3b\x7a\xef\x3f\x04\x4d\xe3\x88\x1f\xf4\x53\xba\xa5\x77\x3e\x0b\xd0\xd8\xa3\xa0\xb7\x02\xb1\x51\xfa\x68\xdb\xb7\xfe\x3a\x80\xfd\x20\xe1\x45\x00\xb9\x60\x63\xef\x0d\xc3\x18\xbf\x08\xba\xd1\xce\xe7\x85\x6d\xe7\xb6\x2d\x46\xdd\x34\xce\x9e\x16\x74\x45\x9a\xa6\x5c\x1e\xca\x83\x83\x46\x1e\xc3\x81\xda\xf6\x7c\xbe\xb7\xed\x1c\x25\xc2\x93\xe8\x05\xf5\x1f\xa1\x80\x7d\xb0\x91\x46\xfa\x1d\x4f\x72\x44\xbf\x2c\x27\x94\x5d\x0f\x55\xd7\x89\xe0\xea\x45\xc7\x64\x17\x89\xe8\xed\x3a\xd8\x18\x0c\xca\x1f\xe9\xd3\x7f\xb8\x38\xaa\xd3\xd8\x25\x27\x97\x1d\xca\x8d\x0e\x89\x21\xec\x03\x02\x72\x54\x43\xbf\x81\xfd\x82\x72\xd8\x4b\x45\xc9\xfe\xbf\x62\x4a\xe9\xca\xb6\xf7\xd7\xf1\x0d\x5d\xb5\xed\x04\xe5\x33\x6c\xbd\x05\x37\x8a\xdc\xd2\x11\x17\x2b\x5e\x1e\x79\x2d\x19\x92\xa3\xcf\x46\xe2\x83\x41\xc7\xad\x87\x42\x1d\x4d\xf2\xf8\x4a\x56\x20\x39\xed\xce\xe8\xdc\x7f\x08\x3c\x94\x00\xb8\x96\x8f\xd6\x9e\x13\x51\x9f\x01\x03\xcb\x82\x30\x00\xb3\xad\x91\xe5\xae\xc3\xc6\xf2\x88\x79\x6c\xcb\x4c\x0b\x7b\x14\x54\x2e\x1c\xd6\xc6\xf4\x6f\x82\x48\xf8\x29\xf2\x1c\x71\x40\x67\x4e\x24\x7e\x30\xa5\x25\x53\x64\x4d\x54\xb7\x82\x48\x7c\xe5\x82\x3d\x93\x73\xe3\x9e\x8a\xb2\x76\xb3\x29\x55\xab\x1f\x80\x72\x23\xde\x9d\x5b\x64\xf4\x07\x04\x62\x3a\x86\x63\x10\x98\xa5\xb3\xaa\x4a\x69\xac\x05\x6d\x0e\x7e\x20\xd0\xd8\xc8\x06\x61\xb7\x58\x10\x27\xa1\xa9\xbf\x0b\x24\xa7\xb0\x13\xc3\x09\xc5\x4f\x42\x86\x83\x01\x0e\x49\x4f\x0f\x91\xa5\x80\x58\xc8\xac\xa2\x7a\x74\x16\xc0\x44\x7c\x9d\x45\x12\x62\xdb\x96\xc0\x8e\x1d\xc7\x63\x9c\x38\xbf\x37\x35\x03\xa1\x21\xfc\xb6\x04\xb4\xec\x7b\xa1\x16\x76\xc6\x89\xc0\x79\xc5\x4e\x68\x8a\x1a\x4d\x13\xca\xf3\x09\x21\xf5\x34\x0d\x4a\x8e\x1d\xcd\x61\x82\xe6\x88\x76\x73\x56\xa4\x17\xda\xfc\x45\x71\x70\x48\xa9\x2f\x01\x30\x96\x47\xf0\x85\xf3\x3e\x8e\x90\xf4\x99\x29\xc3\x26\x2e\xaf\xd0\xea\xe2\xe0\x85\x4b\xac\x69\x6c\xae\xf4\xb4\xcf\x5d\xf1\x41\x74\x60\xfc\x4d\xa6\x77\x56\xe4\x34\x1a\x35\x17\x09\x0c\x2d\x4d\xf6\x7b\x16\x92\x09\xf2\xa9\xa5\xc7\xb1\x4a\x72\x6c\x64\x42\x7a\x95\x64\x4b\xa0\x66\xd5\xc0\x15\xdb\xb4\x11\x2c\x23\x26\x15\xa4\xfd\xb3\xd8\x97\xbb\xc1\x59\xa0\xa4\xb4\x6b\xe9\xd8\x95\xc5\x2d\x54\x65\x39\xe9\xda\xcd\x28\xa5\x65\x0b\x68\xee\x7e\xe9\x7b\xb1\x64\x91\x10\xc0\x94\x1e\xd8\xb6\x9d\x19\x36\xf9\x35\xda\xc8\x37\xfd\xb3\x23\x38\xbe\xd9\x4c\xe0\x05\x54\xfc\xb2\xe5\xae\xe2\x49\xd3\xfc\x9b\x2d\x6b\x16\xa2\x9d\x0c\xba\x0f\xe3\x89\xc0\x34\xbb\xaa\xcf\x0b\xd0\xef\xaa\x05\xfd\xfa\xfb\x99\x57\x2d\xa8\xb3\x9a\x49\xde\xfa\x0f\xda\xc9\x84\xa2\xff\x6c\xa9\x1d\x03\x1a\x4b\x1e\x8d\x19\x9f\xf4\x79\x55\x0b\xfa\x69\xba\x6f\xa6\xc9\x93\xf9\xd6\x55\x80\xd3\x01\x7d\x85\x6a\x10\x7c\x7f\xa8\xdf\x0f\xaa\xfc\x43\x72\x7c\x96\x38\xbd\x42\xe1\xe5\x9f\xa7\x3c\x30\x65\x1f\xa6\xfc\x52\x3b\xea\xb2\xc4\xd6\xd1\x23\x76\xc7\x59\xcc\xab\xa9\xb1\xfd\x8f\xda\xac\xdd\x9c\x92\x16\x70\x02\xa7\x32\xff\x73\x22\xb3\xb4\x13\xfa\xbf\x5c\x26\xc3\xda\x48\x83\x9b\x91\x14\xb6\x80\x96\xdc\xe7\x5e\xaa\xe3\xaa\x2e\xb5\x69\xdb\x96\xa8\xa1\xaf\xdf\xb6\x1d\xc9\xfd\x3b\x21\x1d\x0b\x1a\xc8\xc8\x12\x21\x68\xe8\x32\x63\x55\x9d\x76\xee\x2f\x0d\xfc\xa7\x27\xc9\x5f\x05\x88\x1e\x47\x9f\x0d\x8d\xa4\x1f\x2e\xd6\x22\x0f\xbf\x1f\xe7\xe8\x25\x18\x7f\x75\x13\x79\xd1\x3c\x74\x23\xcc\xf9\x8e\x17\xe7\xb5\x19\x1e\x33\x9b\x10\xdd\x64\xe8\x0b\xc2\xc6\xe7\xe4\xac\x25\x50\xc6\xf1\x87\x8a\xaf\x7f\xa7\x78\x7e\x36\x94\x81\x67\x1f\xed\xfa\xba\x59\x2c\x04\x03\xb4\xd1\xd5\xc4\x83\x6a\xd2\x3f\x5c\xcd\x7c\x1e\xbf\x0c\xa7\x6b\x41\x33\x11\x0d\xe0\x45\xbd\xa3\x06\xb8\xdf\x77\x5e\xcb\xa7\x8a\xc5\x59\xe9\xce\x56\x12\x8d\x84\xe5\x93\x78\x4e\xb2\x9c\x8b\xdf\x03\x3b\x1e\x1f\xcb\x2a\x16\xcf\xd9\x9e\xa5\x22\xb1\x25\x3d\x57\x16\x06\x74\xcf\x9c\x90\xf4\xd5\x1d\x1f\xc2\x7d\x56\x8b\xfc\x15\x3f\xf2\xfa\x3c\x7f\x21\xf3\x6b\x33\xb4\x7b\xe6\x90\x53\x7b\xcf\x8c\x10\x1f\xda\xca\xe4\xd8\xf7\x78\xc0\x8e\xa1\x10\x7e\xcf\x20\x15\xa2\x6a\x5d\xde\xf1\x22\xfb\x8d\xd3\x0b\xce\x82\xbd\x1b\x18\xfd\x4d\x4b\xf4\x59\xe2\x74\x96\xda\xa1\xb7\x72\xef\x3a\x3d\xe9\x66\x47\x19\xba\x40\xc2\xad\x68\x5c\xab\xbf\x34\x97\x43\x4e\xce\x2c\xc2\x90\x03\xaf\xa5\x19\xf7\x8e\xa0\x06\x85\xa3\x2d\xf5\x4e\x55\xc3\xfd\x55\xa0\x45\xd5\xa6\xd9\x11\x50\x4e\x8f\x09\xf5\x03\x22\x88\xe6\x6c\x0d\x0e\xa7\x6f\xba\x2a\xd0\x6f\x91\x6b\x1b\x56\x48\x64\xf6\x93\x54\x3a\x47\xd2\x85\x1c\x2b\x35\x18\xb8\x2b\x3c\x5f\xef\x1b\xed\x84\x63\xb9\x16\xe9\x55\x56\x5c\xe9\x89\x24\x33\x87\xd3\x5f\xfd\x34\xe8\x5a\x6c\x9a\x5b\x3f\x0d\x6c\x5b\x7c\x10\x4f\x0e\x17\x69\xbf\xdf\x8b\x14\xd4\x01\x88\xcb\x2f\xb5\x9e\x25\xce\x2c\x52\xfe\xc6\xdd\x1c\xef\xd4\x77\x77\xe7\xf5\xba\x2f\xe2\xfe\xe6\x30\xc8\x48\x37\xfb\x6d\x0f\x16\x15\xd3\x24\x40\xa2\xc8\x15\x0c\x1c\x05\x2c\x6b\x13\xdd\x84\x9b\x70\x3e\x27\xf1\x1c\x5d\x3e\xa5\x8a\xbe\x37\x79\xe9\xdd\x18\xd9\xd0\x2b\x23\x5c\xc6\x59\x05\x9c\x46\xb6\x6d\xaa\x4b\x85\x7c\x02\x09\x7d\xea\x4f\xab\x42\x49\x79\xbc\x81\xb4\x9d\xf4\xda\xf3\xd0\x8f\x03\x2d\xde\x85\xc6\xb1\x6f\x77\x3a\xc3\x54\x89\x91\xc0\x9e\xca\x9e\x20\x54\x0a\xb9\x29\x41\x80\x4c\xcf\x2b\x9e\xa8\xd9\xb6\x99\xaa\xa3\x3b\xd3\x1d\xaa\xa6\x2f\x77\x4a\x48\xec\x19\x1d\x09\x93\xe0\xec\xe4\x29\x9d\x6d\xef\x3a\x99\x77\xe7\xaf\x03\x53\x0f\x2e\x64\x60\xba\xf3\x5f\x60\x3f\xf1\x9c\xee\x16\x30\xed\xbc\x2f\x86\xc9\x6b\x3d\xb0\x2f\xed\xc5\xac\xc1\x5c\x74\x4a\xa7\x09\x9b\x66\x0c\xcb\xe4\xf3\x40\x65\x9c\x20\xed\x2e\x13\x24\xa4\x6b\xf1\x81\x4d\x60\x4a\xe0\x54\xbb\x6b\x6f\xb8\xf2\xcf\x96\xd2\x81\x1f\x07\x10\x19\xda\xfb\xae\x9e\x77\xcc\x54\xf2\xe8\xba\x84\x18\xe4\x07\xb0\xa3\x2b\xc8\x7a\x50\xbc\xa5\xd2\xb5\x39\xec\xa2\x9c\x38\x09\x65\x4a\x0c\x12\xb8\x22\x72\x12\xac\x47\xbc\xa7\xfa\x6c\x05\x6e\xd1\x9c\x40\x7a\x4f\x18\x61\x44\xba\x2e\x3c\x1a\x5d\x30\xc4\xa5\xd8\xb6\x67\x42\x58\xb3\x6d\x27\xa6\x8f\xcc\x89\x09\x01\x6e\xdb\x33\x2e\xd3\xb8\x48\x13\xf9\xc9\xc0\x90\x58\xe1\xc0\x81\x9e\x88\xa2\xe2\xc3\x0f\xd0\xbe\x55\x8d\xe5\x40\x93\xa6\x79\x60\x4e\xd8\x34\xd6\x73\x0b\x76\xbd\x4d\x84\xbf\x0b\xdc\x1d\x4a\x7e\xf7\x74\xc6\x9a\x66\x96\xd8\x76\xe8\x1d\xdc\x77\xcc\x39\xc0\x1e\x18\x56\x0f\x15\x8d\x3c\xde\x34\x4e\xe2\x31\xb7\x6c\x9a\x98\x78\x7e\xe0\xa6\xee\x3d\x5a\x84\xdb\x76\xe4\xdc\x43\x25\x73\xc6\xe4\x74\x4b\xdf\x31\xa7\x82\x82\x40\xec\xdc\x82\x98\x58\xf1\xe1\x8e\xde\x0e\x01\xe1\x4e\x08\x96\x39\xbd\xf5\xef\x70\x46\x2b\xbf\xf0\xef\x02\x21\x5b\xde\xab\xa7\x9c\xa0\x5b\x83\x3c\x2e\x12\xbc\xb7\x7c\x10\x0d\xa0\x23\x4f\x35\x59\x5f\x25\xeb\xbb\x95\x6b\x70\xef\xdf\x89\x8a\x36\x1c\x39\x1d\x69\xc1\x76\x0b\x19\x69\x7f\xa7\xb8\x73\x4b\xb9\xf7\x37\x27\x81\x9c\xb8\x7b\x91\x74\xb3\x58\xdb\xb6\x93\xf8\xb7\xa2\x87\xa9\xf8\x11\xdd\x93\x3b\xb4\xc2\x01\xe3\x29\x7d\xa5\x8f\xd3\x4a\xd0\xf5\x13\xb7\x22\xc0\x3d\xd5\x83\x14\x2a\xc8\x88\xab\xdd\x33\x52\xa8\x06\xa6\xdb\x4f\x43\xe4\x08\x48\xe8\xcc\xb8\x14\xf1\x52\x1f\x1e\xf9\xa8\xaf\x17\xb8\x5b\x80\x6e\xda\x34\xc6\x27\x41\x0b\x21\x43\xab\x81\x15\xdc\xd1\xe3\x05\xb1\x18\xb9\xca\x1d\xcc\x56\x04\xf2\x0b\x99\xfe\xe6\x84\x20\xe5\x5d\x95\x71\x4f\x7d\x53\x21\xd2\xef\xf3\x59\x2a\x60\xb7\x69\xa2\x19\xa5\xb7\x82\xe4\x38\x21\x8d\x48\x0f\x69\x77\x2a\xbb\x9b\xab\x87\x3e\x2a\x96\x54\x09\xf0\x36\xd8\x24\x37\xd9\x26\x93\x9e\xce\xd1\x70\xac\x99\x1a\x2b\xd9\x53\xff\xc8\x9c\x9a\x39\x7b\x02\x11\x91\xea\xb1\x93\xca\x2f\x89\xa2\x91\x5b\x4d\xb3\x3c\xcb\x14\xa9\x8a\xc8\x11\x88\xfc\x87\x40\xce\x34\xa7\xf3\x79\x36\x08\xb7\x61\xb6\xcb\x75\xbb\x03\xcd\xd7\x23\x73\xb2\x9b\xb5\x6d\xcb\x6e\xe0\xa3\xa0\x6b\x9d\x9e\x38\x5b\xac\x89\x0e\x2a\xa0\xe8\xac\x75\x25\x0f\x8b\xb2\xc5\x0b\x59\xa5\x67\x3d\xb7\x5c\xcb\x6a\x8d\xb0\x41\xda\xa1\x26\x02\x7e\x93\xd9\xf6\x53\x5f\x65\x26\x10\x0d\x24\x37\x5c\xa6\x76\xaa\xe7\x2e\x15\xc9\x2a\x69\xf7\x9a\x77\xd5\x14\x1a\x7b\xd8\x03\xd8\xfb\xa1\xc3\x48\xa7\x46\x31\x9c\x4f\x6e\x56\x66\xd0\x04\xcd\x66\xdd\xc9\x32\x39\xec\x51\x0d\xbd\x82\x7b\x6a\xad\x2c\xa8\x68\x62\xdb\x7e\x00\x47\xb1\xb3\x6a\x7a\x0b\x0f\x02\xd5\xa0\xad\xaa\x36\xd7\x75\x04\xca\xb9\x23\xf0\x8e\x3e\xce\xa9\x14\x38\x6a\x6f\xed\x0e\x22\x27\x35\xcd\x72\x0d\x4f\xf4\x41\xef\x49\xb1\x2e\x77\x32\x78\x95\x34\x35\x48\xc9\xe6\x7e\x46\xe9\x93\x6d\xab\x40\x53\x39\x7d\xf0\xef\x03\xb2\xb9\x9f\xcf\x25\x5e\xb0\xed\x9c\x9c\xf6\x9d\xa3\x61\x49\x99\xbf\x9f\xcf\x91\x64\x96\x8e\xd8\x78\x3b\x42\x4e\x8a\x5f\xcb\x89\xd2\xc8\x8a\x36\x1e\xe9\x3b\xd2\x46\xa8\xfe\xa4\xb3\x52\x54\x63\xdb\x87\xc5\x02\x12\xdb\xae\x74\x76\xc4\x44\x87\x39\xbd\x87\xc8\xb6\x45\x47\x0e\xc3\xb6\x42\xd9\x56\xe9\x54\x70\xc4\xa6\xfa\x13\xf0\xc3\xcd\x4a\xd9\x70\xdd\x2f\x16\xa4\xf2\xef\x83\xa6\x39\xe2\x5f\x47\xfc\xd0\xaf\xa5\x59\x44\x46\xc8\xe6\x28\x10\xc9\x91\xb4\x1a\x3b\x64\x70\x24\x70\x67\xdb\x02\x29\x1f\xbb\xd5\xb1\xed\x43\x17\xa7\x44\x00\xde\xc0\xc4\xc0\xc9\xfa\x23\x7c\x39\x36\xb8\xa5\x35\x81\xaa\xed\xc8\x21\xea\x03\x89\x9b\xe8\x7c\x3b\x9a\x4a\x9b\xac\x2c\x9f\xe6\xb5\x95\x8d\x02\x46\x2e\xf9\xcc\xe0\xb4\x67\x09\x39\xc9\xb3\xb3\x14\x1d\xfe\x7a\x78\xd2\xe6\x44\x8b\x05\x49\xe8\x13\x73\x42\x3f\x0a\x08\x24\xfe\x43\xe0\x75\x56\x08\x2e\xd7\x4f\x9b\x84\x7e\xe6\x30\x78\x2f\x28\x9c\xa0\x7b\x49\x77\xd0\x4e\x99\x61\xe0\x9c\xf5\x47\xf0\x43\xb7\x5c\xa4\xa3\xa2\xab\x46\x4c\x08\x3a\x15\x64\xc9\xb6\x19\x94\x54\xcc\x66\xea\x30\x5a\x74\xcd\x08\xda\x22\x6d\xa8\x38\x9e\x1b\x08\x16\x4b\xfb\xe8\xe1\x1a\xde\xd2\x52\xf0\x50\xa5\x71\x42\x4a\x40\xd3\xb3\x9b\x17\xb6\x6d\x7d\xfb\xa5\xd8\xdd\xce\x1d\x1e\x30\x10\x25\x5e\x77\x4e\x05\xd2\x27\xc5\x74\xc0\x3a\x88\x1d\xd2\xa1\x99\x5b\x3c\xd9\x46\x34\x83\x46\x7f\xb4\x77\x42\x70\xee\x34\xce\x32\xc5\x04\xa5\xc6\x0c\x89\xe8\x2f\xf1\x57\x01\xcc\x3a\x23\x34\xbe\x29\xf0\xe8\x77\xa0\x9d\x83\x1e\x65\xdc\x6a\x41\x40\x32\xd6\x7a\x9c\x6d\x46\x7f\x5d\x9a\x4e\xe3\xda\xfd\xd0\x5b\xb9\x23\xd2\x9d\x2d\x16\xd8\x4f\x31\xda\x2c\x00\x63\x20\x39\xbd\x1b\xa0\x4b\xc1\xeb\xee\xa9\x1c\x8c\x9f\x23\x65\x4d\xe8\xfe\x83\x63\xd2\x7e\x8f\xb7\x9a\xbc\x4d\xfb\x3f\x2a\x6f\xcf\x5b\x4d\x70\x33\x58\x8b\x41\x26\x9d\x91\x69\xc5\xd0\xb7\x96\x8d\xfd\x4b\x05\xb4\x00\xd7\x27\x32\x0a\xbe\x9c\xa2\x69\x76\x0e\x83\x92\x10\x27\x41\x03\x24\xe0\xf0\x3b\x1e\x98\x04\x78\x0b\xa6\x59\x0e\x7d\xd0\xde\x7c\x16\xd1\x46\x39\xca\xbc\x15\x5d\x2f\x1e\xe0\xdc\xb4\x87\xce\x66\x39\xec\x1d\x02\x43\x8b\xc7\x0b\x2e\x2f\xeb\x0f\x18\x90\x4e\x7b\x35\x4e\x98\x6a\x77\x8c\xfb\xd0\x00\x7f\x57\xf1\x84\x7e\xf4\x27\x69\x7e\x6f\x81\xf5\x27\xa9\x28\xea\x75\x74\x23\x0d\x91\xc8\x2f\x24\xd5\xa6\xb9\x63\x52\x5f\xd4\xa0\x6e\x74\xc7\xb3\x74\x57\x37\x8f\x59\x5c\xef\x2c\xb8\x70\x36\x1d\x79\xd2\xa0\xcb\x1d\x5b\x6e\x81\xd5\x1d\xa1\x0e\xf5\x4d\xde\xda\x7d\x21\xbd\x98\x7a\xdb\xaf\x33\x9b\xe6\xc9\xa1\xa1\x62\xec\x1a\x5d\x00\x8c\xc1\x0c\x0d\xcc\x71\x27\x58\x18\xb0\xcf\xfa\x9d\x71\xcb\xac\xdd\xc0\x55\xc9\x4b\xe3\x6c\x1a\xa5\x98\x9b\x5d\x56\xcc\xf5\x73\xa1\x5d\xcf\xd0\x30\xe9\xd2\xc2\xa9\x90\x5c\xa3\x6e\xf5\x66\xe9\xaa\x67\xdf\x9d\xf5\x09\xe5\xa6\xcd\xd9\x0a\xf8\x61\x80\x9a\x5a\x6f\x34\xe3\xae\x13\x5f\xb4\xa1\x8b\x0d\x1b\xba\xd8\xb4\xa1\x23\x90\xb2\xd6\x61\x64\x53\xe0\x9e\xa7\x35\xc6\x4f\x3c\x54\xb4\xee\xad\xa7\x54\x92\x6f\xb9\x96\x8c\xc7\x78\xa8\x3a\x6d\x50\xa1\x68\x19\xad\x0d\xa2\x06\x85\x0c\x47\x57\x6b\x3b\x34\x0c\xfe\xf4\xeb\xf7\xaf\xbe\x2c\x23\x5a\xcb\x47\x28\x7a\x13\xc8\xba\x7b\x44\xeb\xc4\x07\xdd\x08\x22\x9d\x01\x8e\x83\x77\xf4\xfa\xed\x4b\x0c\x25\xb1\x3d\x3e\xdf\x5e\x7b\x37\x8e\xe7\xbe\xdc\x5e\x6f\xd7\x37\x0d\x79\x76\x0d\x8f\xf4\xfa\xed\xd2\x7f\xeb\xfe\x69\xeb\x6f\x97\x10\x3c\x7f\x76\xdd\x2b\x32\x9e\xf4\xbc\x66\x89\x33\x08\x46\x15\x76\xe7\x2a\xc5\x32\xad\xf8\x61\x60\x30\x22\x18\x66\x7d\xf6\xaf\xe3\xb3\x41\x0c\x68\x52\x19\xb5\x48\x86\xc2\x33\x6b\xd0\x89\x7a\x86\x6c\x7c\x5f\xf8\x3c\x76\x16\x76\xf0\xb1\xb3\x5b\xed\xaa\x94\xcc\xb2\x8a\x8c\xb6\x09\xa9\x99\xd2\x31\x11\x1f\x6a\xb9\x0f\xad\x46\x6e\xe8\x4a\x76\xa1\xd5\xb5\x5c\x88\x9c\x11\xfa\xab\xc0\x38\xd7\x71\x18\xb5\xdc\xa2\xac\x1d\x34\xb4\x21\x16\x01\xa9\xde\xd0\x48\x1c\xcd\x27\x7a\x19\x42\x02\xd5\xd8\x54\x17\xed\x59\x3c\x3f\x0e\x5c\x3f\x70\x87\x59\x1c\x06\x6a\x04\xe1\xd4\x08\x86\x6e\xd2\x18\xf2\xd6\x08\xcf\xea\x9c\xd0\x60\x6f\xca\x72\xcb\x0c\x3d\xab\xd8\x23\x91\x64\x2e\x40\x6f\xd3\xa3\xa7\x7c\x1c\x8e\xd7\x61\x44\x4f\xb9\xa1\x41\x47\x7d\x2b\x5d\x75\x5a\x30\x84\xae\xce\xc3\x80\xfb\x61\x00\x18\x8e\xb8\x57\xcd\x28\xc5\xa0\x59\x48\xce\x82\xc3\x00\xf3\xf7\xca\xe3\x98\x9e\x85\xc4\x5d\x7b\x7a\xcf\x39\x31\x71\x63\x82\x0a\x59\xc5\x7e\x61\x66\xfd\xe6\x0d\xde\xe6\x68\xc7\xe7\x32\x88\x3b\x33\xb0\x89\x09\x1e\xb5\xf6\xa4\x42\x04\x23\x97\x35\x5b\xe3\x7c\x4f\x9f\xe2\x7d\xb0\xe0\x8a\x60\x80\xd3\xa9\x83\x9f\x99\xca\x79\x6e\x87\x65\xdb\x0f\x1d\x47\x23\x4a\xb8\x5d\x2f\xb4\x17\x68\x2b\x8d\x99\xdf\xc3\x6f\x32\xd6\xcc\xf6\xf8\xdc\x79\xe9\x6f\x1f\xb7\xbf\x04\xf3\x1b\xe2\xbf\xbd\x09\x9e\x37\x2a\xfe\xcc\x73\x0c\x37\xf3\x19\xed\xc2\x67\x4f\x33\xce\xc8\x25\x0f\xd6\x7f\x72\x8b\x4a\xcd\x46\x44\xad\x97\x52\x44\x5c\x05\xb6\x6d\xdd\xc8\x67\x2d\x95\x2d\xd6\x41\x1f\x9f\xed\x86\x7e\xec\xf9\x52\xa8\xc5\xd3\xf5\xc0\xfd\x4d\x07\x1f\x81\x59\xd4\x34\xb3\xc8\x17\xd9\x35\x4b\x38\x0b\x9b\x26\x5c\xca\xf0\xda\x9e\x13\x36\xcd\x7b\xa2\xe0\x83\xb8\x67\x31\x8d\xc3\xee\x1b\x6a\x77\x74\x10\x93\x90\x86\x57\x59\x71\xac\x59\x11\x89\x2e\x17\x9e\xd8\xc9\x6e\x08\x66\xdc\x6b\x28\x96\x18\x00\x56\x10\x5e\x2c\x09\xa1\x36\x3b\xc2\xed\x3b\x11\xab\x25\xc7\xd5\x84\x77\xca\x82\x51\xb4\x76\x1e\xc0\x37\x94\x71\x84\xa3\xab\xac\xb8\x0a\xc9\x00\xd7\xaa\x38\xce\xc4\x53\x0f\x52\xd4\x90\xa3\x42\x5b\xb7\x08\x30\xc5\x8c\x08\xdd\x76\x9b\x21\x1f\x3b\xe8\x46\xfe\x8b\x80\x40\x8c\xae\x96\xc6\x71\xa7\x63\xec\x77\xba\xc6\xfd\x27\xe4\x81\x98\x80\x19\xb5\x9b\xe6\x30\xd8\x22\x94\x81\xd9\x9c\xe1\x89\xe4\x0c\x8a\xe9\xea\x64\xf6\x61\x33\xc4\x1d\xc7\x39\x9c\x32\x1b\x7c\xbf\xac\x38\x8b\xdf\x7b\xea\x17\xa1\xdb\x29\x88\xeb\x74\x66\xf3\xbd\xf1\xb2\x1e\x4d\xdf\xcb\xee\x71\x38\x1a\xa6\x9f\x88\x58\x64\x1d\xe6\xd3\x61\x0a\xfd\xb4\x9b\xcf\x8c\x93\x1d\xb1\x11\xe0\x3d\x2d\x84\x68\x2d\x80\xff\x73\xb9\x85\xe4\x24\x1e\x9b\x43\xc5\xdf\x39\x9e\xfb\xf7\xa2\xce\xf2\x06\x1d\x44\xaf\xe1\x0b\x7a\x42\xbb\xab\x8a\x17\x78\x48\x25\x2d\x2f\x8e\xe2\xb9\xe0\x4f\x78\xd0\x24\x8a\xb9\xb3\x55\xbb\xe9\x51\x72\x9c\x55\xd3\x51\x2f\x25\x16\xee\x06\x1c\x69\x33\x05\x86\x87\x08\x44\x86\xf3\xe9\xd7\x40\xab\xd2\x8d\x14\xa5\x46\x40\xbc\x9c\x1d\x9d\x48\x5b\x3b\x29\x91\xb5\x27\x8a\x71\x0b\x47\x79\x4a\x7d\x31\x92\xa8\x1f\x4c\x1c\x69\x8f\xa3\x72\xb0\x19\x1e\xfc\x46\xba\xfe\x5e\x63\x8d\x31\x23\x0d\x42\xb4\x63\xc7\xa9\x98\xf3\x7a\x31\x4c\xd1\xdb\x44\xa0\xd3\xd4\x45\x46\x66\x11\xc4\x82\x6d\xd8\x19\x85\x91\x61\xe9\x7d\x16\x98\x14\xa6\x85\x28\x2f\x8f\xdc\x0c\xd4\x3e\x1c\xb0\xf2\x76\x32\xe9\x62\x22\x56\x24\xa5\x1d\xd6\x6d\x9a\x73\xd2\xe8\x61\x3d\x7d\x64\x75\x04\x37\x77\xd5\xe9\xf3\x71\xdb\xcb\x0d\x12\x07\x9b\xc8\xb6\x23\x31\x65\x9b\xb1\x9f\x52\xe2\xf4\x6e\xd2\x2f\xd7\x6b\xdb\x76\x52\x2f\x95\x66\x2b\xca\x42\x74\xec\x4a\x7d\x81\x93\xc0\x00\xb3\xe4\x94\x74\x27\xc0\x83\xd3\xae\x11\x51\x4a\xfa\xa3\x8f\x8e\x84\x26\xc4\x4d\xd0\x7a\x20\xe6\x4f\x93\x66\x14\xde\x44\x90\x5b\xc5\x48\x15\xe8\x8b\x23\x91\x01\xd1\x81\x6b\x25\xdd\xd3\xc8\x5b\xd0\x06\x57\x61\x6d\x24\x13\xea\xc1\x0c\x25\xa0\x56\xbe\x3a\x0a\x11\x5f\xec\xa0\xcf\xf2\xdc\xd1\x44\xce\x5d\xac\x5b\x60\x71\x3c\x1d\x59\xf9\xec\xc2\x00\x35\xaa\xc1\xe5\x06\x29\xaf\x1d\x02\xb2\x20\x06\x48\x65\x71\xfc\xf9\xf8\x52\x04\xb3\x42\x16\xc7\x8e\x8e\x23\x3c\x8a\xa9\xef\x8e\xde\x35\xc4\x32\x42\x5a\x33\x62\xe9\x97\xb2\x9b\xe3\x2d\xbd\x1e\x6e\xe9\xfe\x88\x5c\x05\x5c\x3d\x4d\x58\x88\x68\xc3\x8c\x73\x97\xcf\x50\xb9\x65\x99\x14\x4b\x79\x06\x29\x3c\x36\x19\x21\x79\x19\x67\x95\xc3\xc0\x3c\x72\x24\x5d\x09\xc4\x78\x17\xc3\x14\x4f\x14\xc5\x28\xc5\xc5\xd8\xd2\x43\x15\x10\xd3\x30\x30\x98\x25\xad\xc4\x91\x97\xf2\x8e\x0d\x83\x55\xdd\x9f\xe5\xf9\x07\x87\x32\xd1\xc4\xef\x15\xb9\xd0\xd2\x1f\x1b\xbf\xd9\x1e\x4e\x80\xa8\xed\x0f\x4e\xdd\xd8\xf4\x59\x14\x57\xd8\xf9\xc2\x7a\xa9\xaf\x8e\x63\x02\x41\xd3\x9c\x5a\x62\x48\xfd\x42\x06\x82\x8e\x3e\x7d\xb0\x1e\x53\x59\x20\x0a\x69\x42\x36\xa9\x99\x50\x5f\x7b\x1e\x48\xef\x2d\x3f\x00\x66\x46\xec\x6b\xdb\x51\x90\x5f\x41\x10\x7c\x16\xf4\x9c\xa6\x71\xf8\x62\x5c\xed\x11\xf6\x47\x9f\x16\x4e\xe1\xc0\x52\xfd\x53\x82\x27\x8c\x11\x32\x39\x67\xa8\x28\xc6\xa3\xc6\x4e\x10\xc4\xd3\x4d\x93\x29\xb9\x11\xa8\xf5\x0b\xb4\xd8\xed\x70\x03\x27\xf0\x79\xaf\x27\xe3\xcb\x8a\xbf\xe3\x15\x5a\x08\xc1\x08\x9d\x70\xa2\x59\xec\xaf\xe8\xf5\xf6\xf5\xfc\x3a\x85\xaf\xe9\xc9\x30\x0d\xf8\x6b\xbf\x3f\xbf\x16\x23\x3d\x75\x4a\x6b\xb5\x9f\x95\x0b\xa8\xf3\x15\xea\x3d\x61\x68\x99\x2b\xf8\x3c\x2a\x88\x15\x84\x6d\xb1\xfc\x82\xe5\x79\xc8\xa2\xbb\xe3\xc0\x67\x8d\xd1\x09\xf4\xfb\x35\x0e\x48\x34\xee\xf6\x14\xb7\x05\xe5\xdb\x38\x08\x3b\x2c\x48\x5a\x46\x67\x6c\x59\x16\x11\xc7\x83\x8f\xdb\xbe\xfe\x5c\x0b\x6f\x6c\xb9\xe7\xfb\xb2\x7a\x6f\xdb\x39\x44\x74\xb6\x82\x94\xf2\xa6\x59\x29\x3f\xbf\x5d\x2f\x38\xce\x56\x9b\x9d\x6d\x27\x37\xe9\x26\x95\x74\x78\xe7\xa7\xfa\xcc\x2a\xf7\x57\x01\xe4\x82\x21\x46\xcb\x41\xf4\xf9\xab\xcb\xc3\x8f\xc5\xd7\x2c\x3f\x72\x72\x0a\xe9\x6c\xad\xc8\x53\x4c\x67\x6b\xd8\xd9\xb6\x93\x79\x59\x27\x3a\xdf\x3a\x99\x56\xf4\x12\x37\xf4\x44\xd7\xdd\x3b\x6d\x60\x88\xf6\x5b\x77\xf4\x34\xa0\x04\x32\x44\xa1\x3e\x1b\xd2\xdd\xdc\x74\x57\x37\x5d\xa5\x0e\x82\x21\x2e\x45\x38\xba\x43\x46\xf2\x60\x2a\x6a\x74\x44\x36\x83\x78\xd1\xb1\xa7\xcf\x28\x6c\xfb\x6e\xb9\x63\x82\xb9\x6a\x9a\x9d\xa6\xb2\x2e\x5a\x78\xea\x8e\xf7\x5c\x02\x8d\x6d\x3b\x75\x22\xd2\x92\xd6\x88\xc9\x0d\xb1\xd7\x4f\xa2\x1b\x22\xc8\x46\x70\x8b\x61\x28\x4d\x2e\x1f\x64\x28\xb6\x89\x8b\x5d\x76\x82\xfe\x4b\x80\xea\x42\x85\x4f\xc8\x6f\x9a\x83\x8c\xa8\x90\xf1\x24\xf7\x1b\xc2\x0e\x22\x22\x58\x0a\xb2\xd3\xaa\xe7\x08\xd6\xb8\x9d\x9c\xe4\x86\x46\xb6\x9d\x2c\x16\x90\xe2\x53\xba\x58\x90\x56\x6e\x83\x16\xc6\x2c\x5c\xc7\x10\xf4\x95\x33\xd8\x21\xb3\x32\x73\x54\x48\x48\xad\x9a\x1f\xdb\x50\xf6\x23\xd1\xf1\xe4\x65\x1b\x6a\x75\x27\x33\x66\x34\x54\xdc\xf1\x30\xf3\xc4\xcd\x37\xb3\x5d\x0b\x79\x69\x52\xf4\x3e\xc2\x99\xae\x23\x6c\x1a\x03\x9a\x54\x95\xa2\xd0\x64\x85\x19\x5a\x0b\xf2\x5f\xb2\x7a\xfa\x4e\x23\x31\xde\xc8\xb6\x67\x19\x1e\x27\xe1\xad\x01\x10\x52\x9f\x41\x28\x11\x97\xa7\x7e\x1d\xe2\x86\x01\xc4\x9e\x3a\xc7\x0b\x89\x8b\xeb\xae\x9a\x17\x4d\x4c\xf4\xf9\x6e\xa9\xdb\x1e\xdf\x50\x64\x94\x9b\xea\xf5\x2c\x6a\x3b\x0c\x74\x67\xde\x04\xf3\x25\x4f\x78\x55\x4d\x1a\xe6\xfa\xbe\x55\xf1\x63\x99\xbf\xe3\x16\x58\x71\x59\x70\x0b\x0c\x64\xe4\x58\x02\x71\x5c\x49\xf4\x60\x11\xd0\x79\x63\x2b\x00\x51\x10\xa3\x53\x82\x95\xb0\x2c\xff\xbd\x72\xb7\x68\x63\x8b\xe5\x8a\xb2\xce\x92\xf7\x96\x20\x86\x65\x5a\xf1\xe3\x71\x54\x56\x17\x0b\x02\x88\xa8\x75\xe0\x45\x8c\x94\x32\xa6\xa7\x63\xcd\xea\xa9\x29\x8b\x5a\x60\xf9\x23\x7b\x7f\x9c\xf8\xc6\x97\x62\x58\xc6\x86\x5c\x8a\xee\x3a\x67\xb3\x5a\xef\x4c\xc2\xa9\x03\x42\x76\xd9\x7a\xd4\xae\x67\xd3\x08\x90\x37\x8d\x66\xd4\x31\x5f\x4a\x87\x32\xb1\xe4\x05\xc5\xcf\x86\xfb\x89\xbf\x0e\x02\xe7\xac\xd9\xd4\xb6\xd3\xe9\x5b\xaa\x36\x4c\x2a\x1c\xfa\xfa\x84\x58\xbb\xcf\x8e\x9c\x78\xdd\xa3\x43\xe4\xa0\xa3\xa5\x5a\x30\x35\x68\xf1\x2e\x16\x42\x30\xda\x72\xea\x51\x12\x11\xcb\x41\xdc\xc8\x4f\xfc\x55\x30\xb7\x04\xe4\x59\x01\xb6\x8b\xb8\x30\xea\x6b\x95\x37\xc4\xa5\xf2\x9a\x8b\xae\x4b\xad\xc0\x1a\x4c\x46\x8e\x24\x7d\x66\xc1\x16\xe1\xe3\x87\x6e\x34\xeb\x80\x94\x41\x4c\xdc\xb8\x6d\x81\x1b\x74\x34\x5e\x1e\x32\xb4\xc3\x14\x8b\x03\xe7\x73\xcc\xfa\x39\x4e\xfc\x17\x01\xec\x30\x7a\xeb\x26\x96\xd3\x4a\x53\xc1\xcb\x0b\x4a\x83\x0f\xe6\x2c\x47\x74\xd7\x42\xe8\xaf\xdf\xb2\xc0\x7f\x11\x68\xc4\x00\xa1\xff\x02\xdf\x05\x62\x20\xc0\x71\x42\x82\x89\x1b\x19\xf8\xe4\x54\x71\x2f\x76\xa7\x77\xec\x30\x3f\x4d\xbb\x1d\x8e\x81\xc2\xf4\x8c\x71\xbc\x05\x47\x5d\x6b\xc6\x81\xe3\x89\xdd\xe3\x8e\x4f\x59\x6a\xaf\x20\x3a\xbb\x3f\x82\xe0\xd5\x7c\x9d\x38\x2b\x64\x03\xde\x34\x1f\x80\x17\xee\x0a\x5a\x8f\x4e\xee\x1e\x73\x0d\xc8\x26\x62\x26\xa7\x39\xd9\x2e\x59\xd0\x74\xc1\xf5\xe0\x88\x23\xf1\x34\xbe\xea\xeb\x66\xed\x9d\x75\xd1\xe5\xe8\xab\x91\x79\xa9\x82\x3b\xc4\x73\xa2\x01\x77\xb1\x48\x9a\x26\xd5\x10\xdb\xa5\xb7\xad\xb4\x9a\xc5\x13\xef\x9b\x35\xca\xd8\x19\x5a\xde\x4a\x2a\xc4\x09\xdc\x0e\x5f\xef\x06\xaf\x1b\xae\x94\xcc\x91\x1f\x06\xa3\xb9\x10\x49\xfd\x74\x98\x6f\x7a\x07\x89\x3e\xdc\x09\x12\x2a\x37\x50\x7a\xbe\x81\x44\x8e\x5b\xc8\x08\x0e\xa0\x8b\x34\x37\x1e\x89\xa8\x03\x52\x63\x73\x28\xd6\xf2\x1b\xbc\x58\x50\xea\xc1\xe8\x24\xdb\x8e\x9f\xc6\xdd\x62\x1a\xb2\x7a\x24\xdf\xdd\xdc\xb5\x06\x2c\xf2\x0b\xcb\x6a\x77\x0d\xbb\x32\x8f\xe5\x87\x01\x63\xe9\xa9\x8a\x45\xae\xf9\xdc\x55\x6f\xce\x6c\x45\x5a\x59\x7c\x90\x1d\xc3\xc6\xcc\x56\xde\x62\x61\x14\x43\x55\x1f\x56\x4d\x9a\xc6\xe9\x5e\x30\x92\xed\x4c\x64\xb7\xed\x41\xfe\x9b\x55\xd3\x38\xdf\x0c\x66\x25\x07\xbf\x08\x94\xee\xa8\xae\xb2\x34\xe5\x2a\xfc\x40\x65\xdb\x8e\xe0\x50\x47\xa9\x8e\x85\xb5\x59\x42\x9e\xcf\xc9\xb2\x4c\x92\x2e\x85\x8c\x44\xf0\x6f\x1d\x72\xca\x55\x78\xdb\x51\xbc\xcb\x2f\x7f\xfc\x5e\xf9\x4d\xbd\x2a\x59\xcc\x63\x0b\xbe\x85\xd9\x9a\x00\x9b\xce\x2e\xa3\x5d\xca\x2c\x7a\x9e\x48\x3b\x5a\x18\x3a\xe1\xfb\xf5\x8d\x18\x2f\x1d\x6c\x2b\x2b\x2a\xf7\x87\x9c\xd7\x78\x64\x9c\xcb\x2a\x5e\x0b\xa2\xe6\x1d\x79\xfd\x26\xdb\xf3\xf2\xa1\x76\x54\xd5\xc4\x75\xf2\x89\x68\x9d\x97\x7b\x7f\x9e\xd7\xe8\x3a\x21\xf0\x4d\x07\x45\x21\x9e\x1c\x8d\x20\x0b\xe1\xf1\x6f\xe8\x6c\x14\xf1\xe3\x71\x84\x00\xb4\x50\xa1\x6c\x86\xa7\x8c\x4f\x29\x8d\xf0\xbc\xa0\xbb\x43\xac\xe7\xaf\xc9\x89\x0b\xe9\x41\xec\xdd\xdd\x55\x56\x5c\x45\x44\x37\x83\xb5\xef\x20\xf2\x77\x01\xcc\x56\xd8\x42\xe7\x77\x3a\xb8\xeb\x4e\x54\x30\xbc\x45\x27\x96\xb7\xfd\xcd\x56\x68\xc6\xea\xa4\x9e\xd3\x9f\x50\xea\x50\xc6\xc4\x75\x6e\x69\x08\xe1\x25\x74\x76\x6b\xe8\xb2\x22\x0c\x7c\xa6\xb4\xf7\x9d\x19\x6d\x88\x4e\x84\x10\x41\xea\xc5\xfa\x82\x4d\x4c\xd9\x81\xfe\x44\x7a\xe3\x40\xee\x31\xf7\xd6\xd3\xfd\x20\x6e\xe6\x85\x18\xae\x40\x20\xb8\xa4\xdd\xc8\x51\x1f\xea\x2f\x59\xcd\xa6\xb6\xfb\x50\xe5\x2a\x03\x91\x98\xef\xb3\xb9\x71\xfe\xd7\x03\xfb\x77\x0e\x39\x29\x8d\x94\x54\xb6\x77\x1e\xa2\x52\x53\xc9\xa2\x9d\x20\xab\xb0\x82\xd3\xc0\xad\x4d\xb7\x7b\x6a\x5b\xc5\xf8\x2f\xd5\xad\x81\xf2\x0c\x5a\x3c\xcd\xbf\x5b\xe2\xcd\x41\x2d\xfe\xd2\x35\x7c\xa7\xc6\x70\xa4\xe6\x68\xe0\x3b\xf3\x6e\xd4\x3b\xfe\xfe\xec\x66\xdb\xae\x9c\xc3\xba\x63\x5d\x19\x7c\x2a\x14\x7d\x8b\x28\xf3\xcd\x1e\x04\xca\x80\xff\x14\x51\xd5\x03\x0c\x79\x1d\x0e\x33\x51\xed\x16\xd0\xc2\xd4\x04\x64\x78\xa6\xda\x05\xc7\x8e\xc9\x59\xf9\x08\x0c\x16\x24\x24\xed\x40\x79\x8a\x13\xe7\x47\x41\xd3\x38\x83\x77\xb4\x58\x8f\x5a\x38\xf2\xfa\xe2\x0d\x6d\x58\xe0\x8e\xbf\x17\x90\x95\x50\xa3\x38\x0f\x2e\x1c\x7c\x27\x7e\x18\xd0\x68\xa3\xa1\x5f\xc0\xba\x71\xe1\x9f\x93\x10\xd2\x75\x75\x50\x1d\x84\xc6\xad\x57\xb1\x3c\x75\x4a\xfc\x78\x78\xef\x57\x32\xbe\x5c\xb6\x37\xab\x34\x2a\x33\x3a\x1d\x0c\x63\x19\xc9\x20\x08\xae\xa0\x91\x2d\xc8\xad\x3b\x3d\xf4\xf3\x62\x4d\x13\x4e\x28\x6f\x42\xdb\xee\xb2\x44\x9e\xa3\x8e\x7a\x53\x2e\xa3\x3b\x41\xbf\xf7\x15\x57\xa5\x3e\x15\xcb\xee\xae\x3e\x0c\x6b\xe5\xea\xe3\xa1\x5a\xf5\xa2\x2f\x19\x79\x91\x1b\x92\x73\xc1\xda\x3c\xf2\x44\x83\x65\x73\xa9\x52\x73\x3a\xa4\x47\x44\x3f\x12\x32\xf8\x26\x18\x55\x34\xe7\xed\xaf\x95\x0c\x89\x87\xf7\xd8\x49\x53\xda\x10\xd5\x5c\x46\x8f\x45\x77\x39\x1d\x0e\x01\xf0\xca\xc6\xd4\x8b\xa9\x1f\x02\x0f\x5c\x27\xa6\x1c\x62\x1a\xcb\x54\x3f\x0e\xdc\x78\xa0\x46\x42\xcb\xc5\xf8\xdc\x72\x51\xc5\xc8\x4d\xfd\xd8\x8f\x82\xa0\x45\x09\x5e\x6c\xcc\x4b\xf7\x60\x9a\xa0\x65\x0c\x6b\xb4\x09\xf1\xf6\x55\x82\xd2\x77\xc4\xaa\xa1\x04\x39\xca\xda\x85\xc1\xff\x40\x6d\x6d\x8b\x1b\xfe\x15\x72\x68\xdf\xc1\xf7\xea\xf7\x07\x75\x82\x7d\x92\xc7\xd7\xcf\xb7\x6d\xb3\xf5\xf5\x73\x40\x9e\x5d\xc3\x8f\xf4\xda\xf1\x3f\x5b\xfc\x4f\x40\xae\xd3\x1e\xef\xfd\x34\x84\x3c\x73\xad\xce\xa2\xca\xcb\x3b\x06\xad\x98\xd5\x6c\x61\xcd\xfb\xc8\x6a\x3f\x82\xb5\x78\xb6\xb6\xc6\x0e\xcc\xd1\xd8\x64\x29\x26\xe7\xa7\xf4\x11\x39\x09\x9c\x14\x51\xab\xae\x1e\x90\xa6\x47\x78\x8d\x58\xc2\xf2\xa3\x7e\x5d\xbb\x96\x20\x44\xf2\x0d\x83\xe3\xcc\xa3\xb9\x25\x5f\xe7\x91\xfb\x83\x0e\x86\xe3\xa9\xd3\xe8\xbf\xbd\xfe\xf1\x07\x54\x32\x19\x21\xd5\xbe\x37\xe0\x5b\x52\xc7\x88\x0e\x03\x8e\x45\xed\xe0\xf4\xed\xc2\xc2\x5f\x7d\xbf\x54\x1f\xf1\x80\xeb\x95\xf1\xd6\x42\x3c\x2c\x33\x20\x93\xdf\x9b\xd4\x3a\xea\xf6\xd4\x97\xe3\x22\xe4\xf4\xbd\x62\xa2\x54\x8c\xb6\x7f\x7d\xa8\xd6\x57\xe3\x5a\xff\x75\xb1\xda\x57\x83\x6a\xc7\xe7\x8d\x67\x8d\x9c\xef\x6f\x41\x83\x53\x9a\xd8\x76\x62\x58\xe4\x0d\x20\x46\x92\x29\x43\x7d\x8c\x4c\xc7\xf7\x88\x77\x12\x69\xe9\x93\x18\x47\x72\xb3\x57\xf2\x0b\x58\x6a\x12\x05\xa8\x1c\x05\x23\x7a\x8a\x3a\x57\x16\x63\x7f\xa6\x7e\x24\xdd\x65\xc4\xc3\xb2\x60\x7b\x0e\x2b\x34\x17\xea\x22\x1e\x49\xd0\x94\x1a\x6f\x13\x47\xc4\x4a\x99\xf4\x29\x21\xf0\x93\xf4\xe2\xf1\xe3\x40\x30\x1d\xaf\x10\x2e\xc6\x5d\x00\xc1\xc5\x6b\x7e\x44\x3d\x9c\x5f\xec\x2a\xcf\xb6\x50\xa2\x36\xf8\x01\x09\x69\x52\x8a\x25\x2d\x71\xff\x36\xbe\x80\xbb\xb7\xb2\x36\xbb\x28\xad\x2f\x12\x03\xa5\x87\xca\x48\x44\xcd\x1f\x30\x13\x31\xf7\xd7\xc1\x0d\xf2\xc4\x1f\xc8\x23\x07\x2e\x3f\x4f\x66\x93\xfb\x62\x72\x50\x92\xcc\xc9\x56\x70\x38\x31\xd9\x18\x03\x8d\x05\xbd\x59\xc8\xc3\xb9\x6e\x31\x70\x21\xfa\x66\x6c\xdb\x9c\x19\xbc\x70\xbc\x55\xc1\x1e\xe1\x5c\xee\x95\x5f\x94\x30\x35\x01\xd1\xa3\x5b\xc3\xcf\xd6\x40\xc1\x7a\xb7\x0c\x12\xe0\x35\xb4\xdf\x3f\xf0\x07\xfe\x61\xe2\xcb\x3c\x27\xa4\xe8\x3f\x95\x3c\x59\x64\x6e\x61\x11\x0b\x62\xfa\xaa\xa7\xb0\x91\x6d\x63\xb4\xd8\xc1\xbd\xd4\x22\x87\xb1\x29\x4d\x4b\x8a\x88\x10\xb7\x0b\xe9\x4d\x00\x2f\x28\xea\xa3\x6d\xc7\xfc\xbc\x5b\xe4\x84\xca\x51\xd1\x07\x19\x64\x94\x16\x4b\xcc\x25\x3b\x10\xf7\xda\x0a\x4e\xa3\xde\xdf\x93\x16\xcb\x7f\x61\xb6\x6f\xca\xf2\xee\xd8\x05\x2e\xe9\x27\xa8\x58\xaa\xd6\x24\x36\xd8\x58\x59\xd1\xa9\x12\x29\xa5\x5c\xea\xd8\xbb\x0a\xe3\xc5\x02\xbd\xd3\x1c\xd1\x11\xaa\x6c\x18\x74\xa8\x50\xb3\x2c\x01\x45\xc1\x12\x3c\xbb\x00\xae\xc5\x89\x14\x5d\xd9\x66\xb1\x6d\x23\x02\x41\xf5\x36\xea\x70\x1c\x81\xb4\xfa\xbe\x4e\x5f\x2a\xab\xa6\x1f\x73\x58\x9b\x0e\xf7\xc9\x85\x88\x10\x0f\x77\x53\x1e\xc1\x49\x2a\xcf\x2f\x6b\x53\xc7\xba\x2c\x03\x35\xfa\x61\xb7\xd4\x51\x20\xaf\xd9\x18\xa3\xca\xa9\x55\x92\xfd\x7c\x31\xba\xce\x74\x66\xd8\xa2\x39\xf2\x1e\x53\x31\x81\x20\x90\xd9\x19\xcc\xbf\x8c\x3c\xbd\xb6\x1a\xdb\x76\xa1\xd8\x91\x75\x14\xa9\xee\x07\x76\xa7\x59\x1a\x37\xd8\x66\x08\x05\x6a\x2f\x80\x5a\x43\x66\xdb\xe6\xca\x89\x2d\x8a\x06\x06\x3d\x68\xf4\x9b\x67\x02\x36\x3f\xbc\x01\x27\x2b\x89\x72\xce\xaa\xff\xfe\x60\x3d\x0a\x26\x25\xc4\x03\x5e\xd5\x7f\xae\x02\x35\x1d\x55\xd6\xc0\x87\xfa\x01\x49\xab\x34\x13\xda\x5d\x88\x6b\xf4\x6d\xb1\x88\x9b\x86\x0f\xb4\x28\x09\xf8\x49\x20\xb6\xc1\xe5\x85\xd3\x78\x93\x51\xd5\x3b\xf3\xae\x16\x85\x14\x12\x3f\x0d\x80\x0d\x80\x15\x91\x44\x24\xe1\x5d\x90\xa5\xf9\x1c\xd4\x1b\x02\xa1\xe1\x32\xba\x73\x08\x70\x53\xbf\xa0\xf4\x5b\xff\x4d\xaf\xfd\xf9\x22\xf0\x04\x77\x17\x3f\xdf\x2e\x1b\xb2\x8d\xe7\x8e\xe7\xfa\xfc\xab\x00\x3f\x6c\xe3\x79\x43\xae\xd5\x4d\x3e\xf0\x33\xf5\xad\x37\xe5\xc1\x02\xeb\xe7\x2c\xdd\xd5\x16\x58\x9f\x97\x75\x5d\xee\x2d\xb0\x5e\xf1\xa4\xb6\x02\x78\x7d\xe9\xc2\xd3\xb0\x69\x18\x58\x45\x59\x70\xa9\x79\x88\x70\x3f\x59\x71\x76\x3c\xe4\xec\xbd\x45\x9a\x66\x66\x98\x0d\x8d\x82\xc4\xe2\xf1\xf9\x1b\xc9\x85\xea\xf0\x03\x0d\x06\x24\x20\xcf\xae\xb3\xfe\x4c\xb1\x53\xd0\xeb\xbb\xc8\x75\x05\x5f\x57\x2c\x45\x3f\x06\x02\x21\x1d\x86\x87\x3f\xbb\xb6\x5c\x7a\x3a\x40\x74\x7e\xa1\xb9\x8e\x3f\x1f\x4d\xc7\x9f\xc7\x0e\x59\xe8\x7c\x31\x0c\xb3\xa7\x62\xe4\x83\xd5\x47\xcb\x1f\xe7\x51\x31\xe9\xe5\x6d\xe9\x66\xf7\x22\x02\x77\x32\xde\xca\x17\x79\x59\x70\x21\xbd\x88\x5f\x34\x9e\x9f\xad\xc8\xe8\xad\x8b\x68\xa6\x43\xb4\x40\x38\xf0\x5e\xd0\x37\x26\xde\x3c\xbd\xbc\xee\x9e\x2d\xb8\x5b\x16\x25\x56\xff\x85\x2c\x45\xd1\x9a\xfc\x42\xcd\x03\xb7\x02\xa5\x97\xfa\xbb\x79\x55\xc7\xe6\x6e\x89\xf1\x72\xb2\xe2\xf3\x87\x30\xcc\xf9\x91\x5a\x65\xa1\x52\xf0\x6a\x60\x2c\xf2\x0f\x7a\xfd\xf6\x8e\xbf\xbf\x86\x5f\xe4\xba\xee\xcb\x87\x23\x6f\x0e\x65\x56\xd4\xbc\x6a\x94\xf5\xd6\x9e\x17\x0f\xa4\x89\xf2\x2c\xba\xbb\x86\x5f\x65\x46\x55\x93\xbc\x81\x16\xff\x96\x0f\x75\x98\x3f\x54\x42\x10\xc1\x6b\x22\xfd\xb7\xcb\xe0\x39\xde\x34\xb9\x74\x96\x73\xd2\x10\xd3\xd0\xfe\x7f\xcc\x98\x90\x5d\xea\x33\xc7\xbc\x98\x4b\xa7\xfe\xcb\x91\x12\x84\x82\xe2\x7c\x18\xe8\x47\x49\x00\x8c\x9c\x5a\xc1\xde\xbf\xe3\x45\x4d\x4f\xf2\x62\x7d\xf7\x74\x6e\x17\x35\x88\x06\x38\xba\x75\x58\xdd\x39\xac\xe9\x3f\xb2\x6b\x15\x39\x45\xcb\x5d\xa7\x6f\x4d\x68\x04\x11\x4d\x74\x0a\x70\xda\x7b\xb6\xe1\x8d\x33\x78\x91\xb4\x23\x1f\xa8\xbe\x50\x9a\x80\x93\xd1\x4a\x76\xee\x48\x9a\xc6\x78\x93\x7e\xfd\x29\xad\x54\x95\x52\x5d\xa7\xdf\xa6\x34\xa6\x0a\x6f\x15\x33\x4a\xff\x8e\x87\xde\xa2\x1e\xad\x03\xe6\x31\x1a\x3b\xd5\xd2\xb2\x5e\x7e\x12\xbb\x1b\xbd\x24\xf4\x1d\x8f\xc6\x49\x83\xe2\x4c\xc4\x86\x44\x4e\xc8\x22\xa6\x1c\x6d\x59\x01\xdc\x8e\x3d\x00\x6f\x17\x0b\xb2\xa3\xff\x94\xc6\xc9\xa1\x7f\x1b\x48\xc3\x8d\x92\xde\xd3\x9d\xbf\x0e\xe0\x40\x9d\x9d\xff\x42\xc5\x8e\x55\xce\x53\x4b\xed\x3d\x45\xa0\xc4\x1b\x97\x75\xdf\xd0\xe5\x84\xe5\x7e\x89\x32\x34\x94\xd4\xe1\x5e\xbe\x14\x1c\x46\xca\x6a\x14\x22\xdc\x7c\x19\x66\x45\x8c\xd2\x69\xd3\x94\x70\xb1\xec\x1d\xed\x09\x38\x86\xbf\x28\xa1\xac\xb2\x14\xeb\xb8\x97\x82\x5b\x0c\x6a\xdd\xdc\x48\xde\x5d\x2e\xd7\x09\xf4\x0a\xba\x7c\x78\xc5\x2a\x1a\x15\x5e\x70\x33\x91\x22\x29\x27\x20\x90\xc6\xf1\xc0\x22\xee\x1e\x94\x67\xd8\xd2\x22\x2d\x24\x04\x9c\x3d\xcd\xfc\x52\xcc\x8f\x7a\xa2\x7e\x00\xfb\x6e\x74\x5f\x94\x0f\x45\x4d\x57\x90\x0b\x2c\xf4\x70\xb0\x6d\xf5\xd0\x7b\x90\x1c\x20\x25\x33\x4a\x67\xeb\xa6\x39\xd7\x5c\xdb\xf6\x84\x36\xbb\x84\x14\x15\xd9\x80\x5a\x71\x31\xd5\xe2\x57\xd7\x78\x27\xd0\x98\x9a\x02\x0d\xaa\xc3\x04\x2a\x67\x84\x10\xe0\xde\x5e\x1b\x43\x8c\xba\x3c\x9f\xc3\x0a\xee\x88\xab\xfc\x92\xef\x90\xed\xc6\x15\x91\xdb\x4e\x0c\x54\xb0\xf5\x93\x4a\xa5\x3f\xb6\xff\x7a\x91\xdb\xb6\x07\xbb\xd1\xb6\xcd\x9d\x24\x78\xe7\xff\x04\x6c\xf1\xba\xce\xff\x3d\xe4\x92\xd3\x87\x00\x37\xfe\x1d\xc0\x95\x20\x80\x2d\xee\x30\x40\xc7\xe0\xd2\x0c\xcb\x79\xdb\x6c\xb7\x4b\x62\xcd\x35\x14\x6d\xb7\x4b\xc7\x73\x97\xcf\xb7\x82\x21\x10\xf2\x89\x23\x9e\x9e\x11\x0b\x19\x7d\xba\x1f\x0e\x2f\x59\x2c\xc8\x1d\xdd\xfb\x49\x00\x33\x2e\xfd\x99\xef\x96\x1a\xfe\xd1\x10\x43\xae\x2c\xa6\xcb\xa5\xdf\xd9\xf6\x6c\x27\xc1\xf8\x6e\xd9\x41\x31\x69\x9a\xd8\xb6\x65\x3e\xc3\xbe\xdc\x7a\xfe\xdc\x92\xb7\xe1\xce\xfa\x74\x84\x6c\x0d\x25\x09\xac\x05\x78\xf5\x65\x46\x60\xb3\x58\x80\x3e\x6b\x12\xa0\x2e\x9f\x7a\xc8\x24\x9b\xd4\xb6\x67\xfb\x5e\xad\x90\x2f\x6b\xce\xaa\xb8\x7c\x2c\x44\x76\xfd\xac\x0b\x1c\xa0\xc3\x98\x6a\x87\x14\xe6\xc9\x94\xc3\xa0\xec\x73\x68\x91\x05\x77\x63\xdb\xa9\x81\xcb\xab\xac\xb8\xca\x88\x5e\xd2\x4e\x42\x28\xe7\x02\x38\x10\x52\x67\x2b\xc1\x63\x0f\x15\x81\x19\x6a\x1f\x64\x8d\xba\x09\x30\x04\x0c\x4b\x42\xa7\x85\xe1\x94\x15\x5e\x1e\x06\x95\x39\xdb\x01\x77\xca\x05\xdf\x8f\x9b\x26\x0f\xe0\x9e\xde\x6a\x3f\x2c\x15\xb5\xcb\x93\x38\xdd\x0d\xa1\x32\xbe\x75\x8b\x86\x19\xba\x37\x03\x76\x5d\x5f\xc6\xab\xa1\x3b\x8a\xd7\xe5\xe6\xf0\xf1\xe0\xde\x13\xdb\xfe\x3f\xa3\xf7\xd9\xaf\x12\x24\xee\xe7\x67\xa4\x45\x8c\xfb\xbe\x97\xfe\x97\x16\xb9\xa1\x2b\xdb\x76\x2a\x7a\x6f\x34\x09\xf7\xb4\xea\xc4\xca\x4a\x6d\x1e\x02\x77\xd4\x28\xea\x5a\xe4\xe5\xca\xb6\xad\xb2\xb0\xe6\xf7\x10\xd2\xd0\xef\x8e\x52\x02\x2f\xc4\xab\xad\x8b\xa5\x5c\xc8\x7b\x38\x53\xcb\x84\xb6\x1d\x0a\x0e\x2d\x3b\xbe\x91\x5d\xa3\xdc\x7b\xe1\x7e\x0c\xc6\x14\xd0\xaa\xc7\xc5\x66\xfa\xbf\x2a\xc1\xbc\x75\xaf\xde\xe4\x0e\xac\x7e\x77\x07\xba\x52\xab\x21\x24\x8c\x87\xbc\xee\xec\xa7\x96\x32\x24\x62\xd3\x38\xfa\x91\xc6\x82\x87\x55\x07\x7f\x9e\x1f\x06\xee\x40\x5b\x00\x7e\x18\x10\x28\xcf\xb0\xca\xbd\xc4\x2a\xbc\x69\x66\xa5\x9e\xff\xa6\xe9\x1e\xbb\x8b\x60\x23\x09\xfc\xd2\x6f\x5a\xec\xfb\x59\xb9\x2c\x4a\xc9\xf0\xd9\x36\xaa\xb0\x7f\xc9\x8a\xb8\x7c\x74\x62\x22\x2d\x19\x33\x5a\x0e\xb0\x54\xd3\xdc\x83\x5a\xf1\x6c\x7e\x2f\xb9\x8f\xd4\x34\xc4\xdf\xa4\x9b\x51\xca\x41\xe2\xfd\x94\xc0\x8e\xa6\x9b\x1d\xa5\xd4\x89\xc7\x5e\x40\x18\x70\x41\xc5\xcc\x31\x6f\x5f\x44\x0b\x41\xac\x4a\xf6\xab\x69\x18\x69\x93\x2e\xea\x82\x93\xd2\x83\xbc\xe6\xc0\xb6\x67\x62\x81\x7f\xaa\xca\x03\x4b\x31\x7e\xe4\xeb\xba\x3c\x1c\x84\x00\x48\xd4\xa5\x9d\xc9\xcd\xda\xcb\xdc\xb2\xc3\xb2\x62\x28\x7b\xea\x48\x7a\x91\xf6\xdb\x10\xb5\xf3\xbe\x2c\x14\x68\x7a\x92\x82\x25\x77\xae\x45\x60\x2f\x70\x95\x0e\xde\x12\x11\xd8\xd3\x3b\xdb\x4e\xfd\xbb\xc0\xf8\x22\x38\x81\xfe\x20\xcf\x49\x31\x14\xbb\x5e\xff\x41\xe9\x2e\x55\x9a\x78\x86\x68\x0a\xcf\x8b\xfa\x4b\x39\x0b\x8e\x11\x24\x45\x8e\xe3\x5e\xac\xb3\x18\xac\xca\xf1\x93\xcc\x2f\x86\x2a\xd6\xfc\x5f\x6a\xfa\x6c\xbb\x7f\x56\xed\x1d\x64\xc0\x55\x0d\x06\x28\xbd\x19\x9d\x8c\x49\xd3\xdc\x8d\xac\x39\x62\xff\x1e\x27\x77\x00\x1a\x18\x10\x2d\x16\x03\x16\x88\x57\x3c\xc8\x73\x61\x38\x43\x01\xf4\x1e\x44\x0d\xce\xd4\x27\xb5\x0b\xba\x2a\x76\xa4\x9f\x8c\x16\x4f\x47\x90\x0d\x1d\x1e\x8f\x74\xa0\x9f\x64\x4f\x8e\x61\x9e\x3b\x30\xce\x3d\x37\xe2\xb9\xd5\xeb\x2c\x3d\x03\x87\x4b\x2d\x43\x21\x06\xea\x72\xf0\xf1\xde\xea\xbe\x9e\x5a\x19\x22\x0b\xdd\xb4\x58\xbf\x2b\xe4\xc6\xc5\x8a\x67\x77\x62\xf5\xbe\x54\x3d\x6f\x9a\xc1\xab\xe9\xcc\xa1\xf6\xe1\x69\xd7\x35\xa7\xb8\xaa\xa3\x99\x0b\x6e\x05\xa3\xdd\x01\x7b\x42\x77\x7e\xa8\x80\x9d\x5d\x02\xf6\x13\x5b\x46\x0f\x95\xd8\x31\xaa\x63\xc9\x92\xe7\x7c\x0f\x91\xb9\x69\x3a\x81\xe4\x88\x77\xb1\xeb\x0a\xbf\xdd\xef\x79\x9c\xb1\x9a\x4f\xd6\xec\xcc\xd8\x00\x31\x0a\x26\xd3\x7c\xd7\x37\x01\xf6\xac\x01\x46\x0b\x56\x4d\xfd\x18\xde\xd2\x54\x4c\x1b\xab\x19\x4d\xf1\x07\x38\x75\x9c\xf1\x74\xa7\x1d\x17\x22\x8f\xc9\x54\xf1\xa6\x49\x75\x9f\x89\x82\x66\x35\xb0\xcc\xd0\x5c\x73\x6c\x50\xed\x27\xae\xad\xa6\xd1\x3c\x6b\xb8\xa7\x40\x5a\x52\x1b\xe3\x74\x48\x6f\x3b\x7c\xb7\x3c\x94\xc7\x5a\xaf\x9b\x6d\x0f\xdf\x07\xeb\x08\xac\x87\x58\x3d\xa7\x97\x4f\x4d\x74\x94\xb1\x70\xc8\xea\xa0\xd9\x87\x24\x00\x78\xdd\xbb\x6d\x67\xe6\x45\xcd\x33\xb6\x94\x41\x40\x9b\xc6\x42\xa9\x5a\x9a\xf3\x63\x60\x0c\x65\x57\x31\xa3\xca\xf9\x98\x66\x03\x87\x06\x74\x0d\x13\x50\xdb\x85\x95\x45\x2b\xa2\x89\x8a\x10\xdb\xc7\x32\xa6\xf4\x6a\xb3\xc3\x40\x98\x73\x92\xd0\xd0\x8f\x82\x81\xd8\x3a\xb7\xae\x2c\xe8\x94\x90\xb1\xcf\xf1\x04\xc6\xe7\x01\x4d\x06\x02\x8f\x57\x38\x5c\xba\xa6\x29\x2f\xac\x4c\x90\x7f\xe5\x9c\xad\x3e\xa9\x9b\x8c\xb2\xee\x26\x23\x02\xb2\xc2\x2e\x44\xcc\x26\xee\x38\x3c\x15\x60\xed\x24\x56\xdd\xcd\xfa\xd9\x8e\xdb\x6e\xe1\x76\x2f\xc3\xe9\xec\xd8\x58\x57\x42\x5b\x12\xef\x48\x4b\x20\x45\x85\xe2\xe1\xe8\x5a\x2c\xaf\xbf\xe3\xef\xaf\x42\xa9\xff\xb8\x8a\x58\x11\xf1\x5c\x4c\xda\x55\x54\x57\xb9\xf8\x34\xd8\x59\x57\x08\x52\x3f\xed\xd8\x91\x5f\xed\x79\xcd\x44\x06\x8c\x82\xc2\x63\x95\x01\xb9\x1a\x91\x2c\xd7\xf6\xaa\xce\xf6\xfc\x75\xcd\xf6\x87\xab\x77\x19\x7f\xbc\x7a\xdc\x65\xd1\xce\xd2\xac\xd0\x95\x45\x20\xc9\x9e\xa4\xce\x5b\xc8\xa7\xfc\xbd\x7a\x56\xdd\x8b\x76\x02\x90\x76\xac\xfa\xa2\x8c\xf9\xd5\x1d\x7f\x2f\xfe\x8b\xe7\x51\x15\x23\x47\x6c\x43\xa1\xa7\xc3\x46\x60\xc3\xb8\x2f\xf0\x49\x47\xb9\x5b\xea\xca\xbd\xfe\xd1\x0d\x97\xaa\x15\x02\xac\x6d\x01\x15\x3e\xc3\x7e\x49\xd8\xbc\x92\x3f\xc7\xab\x28\xcf\x78\x51\xff\xaa\x7e\xff\x79\x55\x26\xc9\x91\xd7\xbf\xaa\xdf\x7f\x5e\x1d\x58\xca\x7f\xc5\xbf\xff\xbc\x3a\x46\x15\xe7\xc5\xaf\xea\xf7\x9f\x57\x75\xa9\xb4\x34\xbf\x3f\x24\xf3\x2c\x32\x54\xfb\x63\x33\x1a\x27\x36\xa5\xc3\x45\x85\x4b\xd5\x33\x0c\xc8\xa9\xf7\xdb\x19\x23\x82\x27\x28\xe7\x77\x42\x47\xcb\xb0\x8c\xdf\x83\xaa\xb3\xaf\x6c\xee\xa0\xa7\xf0\x31\xaa\xca\x3c\x7f\xc5\x93\x1a\x23\x5f\xf1\x41\xc2\x8a\x2c\x64\x2e\x59\xc6\xc8\x65\x26\xe0\x3d\x4e\x38\x2d\x5d\xed\xff\x1c\xd4\xfe\xa6\x3c\x0c\x2a\xc7\xf7\x51\xdd\x7d\x1e\xe3\x7d\x85\xd7\xb6\xe0\x52\x37\x4d\xb7\x73\x93\xa6\xe9\x00\x60\x6d\x27\xde\xda\x7d\x61\x27\xde\xc7\xee\x27\x76\xe2\xbd\x70\x57\x72\xb9\x93\xec\x69\x6c\x73\xc4\x0c\xde\xbb\x0b\x86\x69\xba\xc9\x28\x8c\x02\x09\x65\x5a\xe9\xae\xe1\xda\xe7\xc1\x26\xd5\x86\x3f\x46\x22\x4d\xe9\x2f\x5a\x41\x22\xcf\x50\x0d\x38\xfb\xc7\xf0\x4b\xbf\x2f\x5a\x02\x31\x45\xfb\xcf\xc3\x51\x7b\x15\x96\x87\xa3\xb6\x14\x51\x5f\x88\xdb\x7f\x02\x46\x4d\x59\x21\x11\xe4\x75\x64\xf6\x11\xa2\xf6\x3e\xf6\xc3\x00\x98\x1f\x05\x34\xf1\xa3\xce\x6a\x87\xf5\x0c\xbb\x7e\xa4\x39\x81\x8f\x65\x38\x65\x09\x4f\x06\xde\xee\xf2\x74\x1f\xcd\x68\x4c\xa9\x72\xb1\xf2\xd2\xce\xe3\x11\x12\xe2\xb2\x16\x14\x29\x74\x4f\x79\xc9\x62\xf7\xa4\x19\x74\xbc\xd1\x49\xc6\x34\x3f\x9d\x89\x89\x83\x43\x93\x19\xa5\xff\x72\x88\xf4\x0c\x95\x5a\x5d\xe5\x6e\x9e\xc8\x80\xe6\x78\x25\x79\x7f\xc8\x68\xe8\x20\x2c\xad\xf1\x6d\x21\xcc\x1f\xaa\xdf\x6b\x88\x9a\x0d\x89\x02\xaa\x1d\xf1\xf8\xfb\xcd\x94\x0f\xb5\xd5\x02\x12\xa2\x0f\x34\x64\xe9\xb3\x03\x8b\x4a\x22\xa7\x22\x6b\x49\x8b\x18\x51\x58\xb0\xac\x3a\xac\x8e\x62\xf0\x94\xd2\x5f\x7b\xd9\x8b\x5c\xa3\xfe\x68\xd6\x78\xda\xaf\xaf\xab\x4e\x2f\x1d\x58\xcc\x12\xf2\x79\xc8\x93\xb2\xe2\xf2\xba\x76\xf7\x64\xb2\x05\x43\x83\xf2\xde\xe9\x5e\xb2\x07\xb6\xcd\x90\xb1\xc9\x0a\x96\xab\x4b\xe0\x9d\x51\xca\x52\xb6\x8e\x2a\xfa\xae\x1c\x69\xdb\x16\x8e\xd9\xfe\x21\x1f\x78\x69\x28\xcd\x58\xef\xfb\xa7\x34\x99\x06\x74\x43\x04\x52\xaf\xc9\x20\x3b\xbe\x56\x35\x60\xac\xe7\x41\xab\xee\xa9\x6d\xc9\x26\xf6\x46\xfc\xb9\xc3\xf5\xb5\x8b\xee\x99\x5e\x58\xa9\x13\x38\x01\x3e\x29\x85\xa0\x3b\xfb\x88\xe1\x6a\xa5\x71\x6c\xa7\x70\x39\xb3\x1d\x9d\x34\x14\x16\xb3\x36\x65\x3f\x2c\x06\x3f\x5b\xa3\xc1\xed\x79\x6d\x03\x08\x1d\x04\xac\x90\x99\x3d\x07\x3d\x02\xea\x3e\x0a\xc3\x60\x42\x74\x0c\x06\x94\xb5\x14\x2a\xc3\x84\xf3\xa1\xd2\x2e\x5c\x53\x97\x64\x20\xd8\xf3\x8f\x72\x38\xfd\x22\x0b\xf6\xd4\xfb\x1f\xf7\x99\x42\x51\xb2\x45\x08\xa5\x16\xb9\xb3\x49\x84\x50\x99\x91\x76\xec\x03\x95\x03\xd0\xaf\x4d\x23\x00\xf6\xd1\x91\x8c\xb0\x3c\x2b\xee\x71\x34\x9d\xad\x08\x19\xa8\x48\xa4\x15\x91\x7a\x33\x2d\x4c\xcf\x47\xe8\x3e\x83\x29\x39\x03\x93\x3f\x20\x2d\xb8\xcf\x60\x08\x00\xe7\x4e\x40\xe7\x13\xbf\xb9\x34\xcb\xff\x23\x5d\x38\x86\x35\x9e\xa7\x38\xa4\x85\x11\x53\xff\x9f\x34\x7b\x3e\x0a\xdd\xf0\xa8\xd2\x89\x24\xdd\xf4\xd4\x94\xfc\x27\x7d\xf8\xc0\x94\x9a\x9d\x99\xca\xf6\xa1\x6f\xca\x39\x6f\xa2\xd7\xad\x76\x00\x3a\x21\xc1\x15\xf3\x5d\xb9\x16\x3e\x97\xef\x78\x65\x49\x7e\x2f\xe7\xec\x1d\xd7\xc9\x0f\xb5\x05\xea\xc0\x4f\x65\x57\x6f\xb2\x80\x7a\x51\x45\xf4\x27\xc4\xf4\x63\x5f\xe6\x91\x9c\x1d\xd0\xd3\x80\x48\x84\xa0\x35\x35\x6e\xa8\x78\xf7\x33\xa7\x9d\x08\xa4\x8d\x2b\x48\x8c\x69\x30\xdf\x18\x33\xb7\x13\x3d\x15\x05\xc7\xfb\x75\xb9\x34\x7e\x37\x4f\xae\x75\x0c\x67\xa6\x34\x45\x9d\x0c\x6a\x1e\xde\x4d\xfb\x8e\x81\x2a\x13\x12\x88\xd0\xe2\x7b\x7c\x8e\x2a\x76\xa7\x9c\x62\x49\xbb\x3b\x12\x2b\x29\xac\x49\x0a\xa7\x2c\x48\xcc\x11\x77\x53\xa6\xb0\xb9\x13\x42\x47\x9f\x86\x7a\x11\xb4\x93\xda\x8c\xa7\x38\x0c\xe8\x09\x8f\x8c\xc6\x30\xa9\x0c\x85\x47\xbc\xb0\x9a\xd8\xce\x92\x26\x46\xa3\xe8\xa6\x89\xcf\xcf\x91\x18\xe0\x85\x83\x60\xe6\x05\x87\x0b\xde\x73\x2e\xf0\xb4\x56\xc7\xff\xef\x1b\x5e\xac\x37\xdc\x1b\x54\xcf\x89\x8b\x71\x7a\xcf\xc9\x43\xdf\x1b\xa5\x64\x17\x15\x90\xf6\xcc\x6e\x67\x70\x5f\xc7\xd9\x59\xd3\xd0\xef\xa2\x8f\xd3\x74\x66\x12\x12\xa2\x44\x11\x35\x4d\x08\xda\xbf\xd6\x88\xd3\xcf\xa4\x81\x73\x59\x38\x29\x36\xc1\xfc\x34\x00\x3e\x8c\x46\x94\x25\x2a\x3a\x46\x24\xa5\x15\x4a\x63\xcf\x89\x69\x08\x51\xe7\xb1\x2b\x75\xc8\xd2\x6d\xe3\xdc\xee\x5b\xe4\x8e\x20\xea\xf2\xaa\x57\xa3\x43\x82\x57\x46\x9d\x53\x4c\x9f\x75\xe6\xf0\xb3\x78\x10\x98\xca\x70\x98\xe0\x78\x78\x1d\x43\x3c\xe9\x40\xe5\x48\x3f\x21\x46\x20\x99\xde\x15\x2d\xc4\xf2\x7c\x30\xd1\xe7\x86\xc9\xe8\x88\x5b\xbb\x46\x9c\x99\x09\x49\x90\x65\x71\xac\x95\x60\x31\x44\xca\x36\xb0\x2c\xa6\x58\x20\xd3\x5a\xc8\x58\x48\x01\x76\x65\x92\x5c\xf2\x25\x10\xab\x7b\x81\xac\x74\x58\xa3\xbb\x89\xd9\x44\x25\x50\x38\x63\xe5\x9f\x9c\x8d\xd8\x38\x27\x88\x3b\x0c\x32\xb7\x96\xd6\xdc\xf8\xe4\xf6\x9f\x8c\x30\x6b\x10\x77\xda\x2d\xa8\x75\x8c\xb0\x09\xd8\xc3\x60\xd5\x26\x54\x25\x89\xc3\x21\x04\xe6\xf3\xc9\x00\x57\x78\x45\xfc\x6c\xdd\x34\x13\xb1\x70\x43\x79\x35\x85\x01\x23\xe8\x46\x88\x1a\xb3\x88\x3e\xfb\x9d\x05\x1a\x98\x53\x76\x2b\x74\xc6\xc5\x9f\x85\x96\xb9\x54\x9f\xe6\x3b\xc5\x2a\xa1\xd6\xc8\xa8\x4e\x79\xaa\x5d\x74\xb4\x30\x03\x0a\x9e\x31\xb2\x12\x1e\x66\xab\x8e\xf5\x57\x56\x54\x8c\xd1\xeb\x97\x8e\x37\x63\x15\x67\x4d\x58\x35\x51\x99\x37\x7c\x1f\xf2\xb8\xd9\x55\x4d\xb6\x4f\x1b\x94\x21\x9a\x3c\x2b\xee\x9a\x3d\xaf\x59\x73\x60\x15\xdb\x13\xc7\xf1\xb7\x8f\x6e\x30\x97\xc1\xe0\xc8\xf6\xfa\xe6\x3a\xcd\x20\xc4\xca\xd4\x97\x6b\x88\xc4\x6b\x63\xff\xc9\xdb\x3e\xce\x37\xd7\x10\xcb\xa6\xdc\x63\x54\x65\x87\xba\x39\xd6\xef\x73\x8e\x15\x93\xeb\x0c\x38\xa3\xd7\xca\xee\x67\x7b\x7c\xee\x78\xae\xff\x96\x06\x0d\xdd\x1e\x9f\x6b\x73\xa0\xa5\xc8\x96\x30\x7a\xfd\xf6\x59\xb3\xbd\x76\x3c\xf7\x96\xbd\x63\x0d\x8f\xf6\x8c\xc8\x1a\xaf\x33\x48\xc5\xe7\xba\x7a\xe0\xdb\x6b\x67\xf9\x9c\x5c\xc3\x4e\x24\x6c\x8f\xcf\x5f\xce\x1c\xcf\xdd\xfa\x5f\x7c\xf9\xd9\x9b\xcf\xb6\x7e\xb3\x58\x90\x46\x24\x04\xdb\x40\x3c\xdf\x6c\x8f\xcf\x9f\x5d\xa7\x90\x31\x7a\x92\xb7\x42\xb9\xfe\x1a\xac\x97\x12\x2e\xaf\xf6\x0f\x79\x9d\x1d\x72\x4e\x3f\xd2\x4f\x1f\xdd\x58\x60\xbd\xbc\x96\xdf\x6f\xac\x00\xea\x1d\x67\xb1\x2c\x84\x11\x70\xe5\x77\xf5\x18\x40\x54\xe6\xae\xff\xa2\xfb\xf8\x32\x2a\xf3\xb4\x2a\x1f\x0e\x32\x5b\xf7\x66\x94\xa8\xab\x41\x81\x3a\x2c\xe3\xf7\xaa\x52\x7c\x34\xb3\xc6\xae\xff\xf1\x38\xeb\xcb\xba\x52\xd9\xab\x9b\x89\x32\x9d\xdc\xe7\xaf\xc0\xb2\xc0\xb2\x82\x76\x93\xb1\x65\x79\xa8\xb1\x27\x54\x3e\x67\x65\x01\x19\x5b\x62\x69\x91\x54\x27\x65\x59\x8b\x07\xdd\x63\x7c\x66\x98\x11\xbf\x8b\x59\xc0\x12\x3b\x7c\x8d\x7b\xd3\xa5\x5b\x36\xd4\xc1\x19\xb2\x25\x58\xd8\x2d\x8b\x0c\x24\xd8\xf3\x00\x44\xa1\x19\x94\xc6\xaa\x2b\x8b\xc8\xeb\xce\x95\x7a\xea\xf8\xf9\xfb\x37\x2c\xc5\xb2\x16\xf6\xd8\x22\xfe\x2a\x40\x1b\x10\xc3\x26\x6d\x64\x9d\x37\x36\x93\x53\x05\x89\xcb\x7a\x4b\xaa\xbb\xe1\x2d\x1f\xc8\xe7\x38\x52\x9b\x76\xe9\xb6\xa8\xb9\x75\x6d\xcd\x95\xd4\x64\xd4\x94\xb3\xde\xcd\x3a\x65\x2a\x50\xa1\x54\x3c\x77\xa7\x5b\x9e\xe6\xa4\xfc\x75\xe0\x6a\xb9\xef\xac\x05\xb3\xd6\x3d\x3b\xbb\x01\x0a\xe2\xfe\xb6\x91\x58\x29\xb1\xa5\x45\x3f\xf3\xa3\x00\x2c\x69\x72\xf2\xd5\x3b\x96\x5b\x30\x0b\x9b\x46\x9e\x0a\x85\xe3\x6f\xc4\x88\x97\x5f\xb0\x09\x3d\xbe\x34\x44\xd9\x9c\x5d\xc6\x82\x2a\xb2\xa1\x41\x8a\x93\x18\xf6\xdf\x04\x52\x2a\xfb\x13\x42\x42\xe0\x96\x26\xbd\x71\x8a\xf6\x36\xd2\x36\x02\x69\x6f\xf3\xb5\xe9\x10\xff\xad\x0a\x88\x26\x46\x7a\xeb\xf3\x60\x3c\x58\x93\x80\x86\xc0\x41\xe4\xf1\xa3\x80\xb4\xdf\x0f\x3b\xb5\xa3\xdf\x1b\x9d\xca\xa8\x19\xf6\x66\x47\xe0\x7b\xd5\xc7\x4c\xf0\x4d\xdd\x54\x94\x83\xab\x03\xa6\x61\xf0\x12\x68\xca\x8b\x47\x88\xcb\x96\x18\xc7\x4c\xc7\x5b\xfb\x2c\xcf\xbd\xf3\xa4\x2e\xb7\x3f\xe1\x32\x87\xbe\x6f\x83\x7d\x14\x12\xaf\x8b\xa1\xc4\xd0\x2f\xd4\xb8\xf1\xe5\x30\xba\xef\xe0\xc2\x75\x6c\xfd\xed\x69\x91\x6d\xbf\xd1\x37\xbc\x21\x88\xa2\x3e\x5c\xda\x58\x76\xd7\xe8\xb9\x8e\x51\x40\xdd\x91\x26\x48\x09\xbe\xcb\xd3\x5e\xd3\xe6\x92\x0e\x23\x3b\x13\xc3\xb5\x08\x4d\x36\x2f\xb1\x29\xea\x58\x93\x0d\x0d\x3b\x71\xbd\x3e\x60\x77\x8b\x6e\x9e\xce\xd8\x40\xb4\x69\x86\xc1\xd2\x54\xac\x33\xd3\x17\xb6\x0f\xaa\xec\x30\x22\x0f\x97\x52\x5a\x32\x67\x47\x20\x11\xbf\x8c\xa8\x28\x7f\xc9\xf8\xda\x9d\x03\x73\x12\x3f\x0e\x20\xf5\xe3\x40\x86\x30\xc6\x98\x7c\x58\x45\x42\x93\xa6\x91\xa5\x53\x9a\xe2\xe3\xee\x62\x45\xc5\xa0\x22\xe4\x54\x71\x07\xee\xfa\xab\x74\xb0\x47\x60\x49\xe2\x67\x11\x48\x8d\x8b\x11\xf6\xcc\x49\x61\x96\xd9\x36\xc2\x6a\x97\x87\xc0\xae\x85\xf0\x21\xcb\x63\x6d\x55\x3c\xc1\x49\x6a\x3c\x32\xbc\x59\x2c\xbc\x6c\x96\x9c\xa3\x85\x1e\x5d\x41\xd9\x63\x9d\xf2\x66\xbf\xd9\xcb\x50\x4e\x9c\x32\x7f\x1f\x00\x97\x97\x68\xa2\xb7\xdc\xb9\x23\x37\x27\x44\xc3\x6e\x0e\xdc\xb8\x96\x87\x07\x2e\x27\x1d\xab\x1e\x31\xad\x06\x27\x27\x9c\xcf\xbb\x01\x76\x0f\x2f\x18\x44\xa7\xd4\x09\x15\xbe\xe5\xd2\xd6\x4d\x90\x3c\x72\x7e\x8d\xbe\xa0\x5b\x7e\x1a\x34\x4d\xc6\x3a\xb3\x01\x48\x0c\x3b\xe4\x9d\xbf\x0e\x8c\x9b\xb8\x19\x03\xeb\xe5\xb3\xf5\xcd\xcb\xeb\x67\x2f\x6e\x2c\x32\xdf\xf9\x2f\x02\xb8\xa5\x3b\xc1\x8b\xf5\x16\x74\x89\x58\x5f\x6d\x84\xbc\xe9\xc7\x99\x98\x61\xce\x20\xa1\x77\x26\x85\x4b\xcc\x6b\x58\xa9\x65\x49\x0b\xac\x5c\xc5\xfb\x51\x03\x7d\xc3\x9f\x50\x91\x2e\x26\x64\x73\x37\x2a\x01\xfd\xc5\x1c\x9c\xe6\xdd\x25\x20\xe8\x9a\xb3\x58\xe3\xdc\xeb\x80\x4b\x78\xdf\x04\x9a\x09\x9a\x21\x96\x47\x3b\x8a\x2b\xf0\x1f\xce\x39\x27\x06\x0c\x66\x08\x7a\x09\x81\x88\x90\xd3\xad\xd1\x7c\xe2\xdf\x8a\xe6\x13\xbd\x7e\xfa\x5e\x47\x8b\x74\x61\x3f\x79\x7f\xf2\x2c\x7d\x22\x8a\x33\xdf\x26\xf3\x3e\x20\x79\xe8\x35\x12\xee\x21\xa5\xab\x4d\xa7\x76\x76\x22\x2a\x56\x93\x60\x50\x31\x19\x9d\xdc\x30\xf4\x40\xfc\xc4\x69\xe4\xbf\xea\xb4\x84\xe8\xcb\x13\xd2\x57\x9d\x03\xb4\xba\x5c\x21\xd4\xe4\xa9\xf7\x83\xee\x52\xfc\x38\xf0\x46\xe2\x00\xde\xee\x33\xb4\xac\x13\xfd\x0d\xb5\x65\xdd\xa6\x6f\xa0\x73\x6d\xed\x93\x5a\x95\xf2\xbd\x76\x0a\xf7\xbf\x37\xdd\x5c\xc7\xe2\xfb\xd9\x65\x98\x6a\x12\xc7\xfe\x75\xfd\x97\x5e\x37\xeb\xc9\x78\xf2\x98\x53\xa9\x5f\xe5\x35\xa1\xe4\x4c\x42\x41\x0a\x8f\x39\x7a\x3c\xb9\x9e\x48\xfb\xcb\x38\x89\xe8\x38\xbb\x26\x70\xb2\xde\xcb\x8d\x9d\x79\xfc\x90\x16\x24\x80\x5d\x38\x6f\x59\xc6\xe5\xfe\x7b\x56\x64\x87\xc9\xa8\x65\xb8\x60\xff\xeb\xce\x2a\xee\xec\x96\x69\xd3\x86\xcd\xd0\xa7\x81\x91\xb6\x95\x61\x19\xff\x3f\xd4\xc1\xac\x38\xf2\xaa\xfe\x1c\x0f\x65\x04\x1e\x1f\x84\x61\x14\xdd\x95\xe7\x35\xff\xcb\xde\xca\x83\x43\x23\x08\xf4\x28\x61\xdc\x7c\x27\xb7\xb2\xa4\xbe\x78\x66\xf6\xff\x46\xa3\x83\x10\xc3\xed\x25\xf7\x7c\x33\x52\x2f\xf3\x8a\xfe\xd8\xb1\xdf\x04\xc0\xe9\x6a\xa3\xae\x57\x8a\xd0\xb8\x83\xe0\x95\x58\xa1\xe4\x1d\xa2\x01\xab\xd0\x61\x2a\xa7\x64\xe8\xbe\x18\x0d\x23\x66\x23\x97\xd6\xe1\xd4\x68\x84\x53\x05\x12\xda\xcb\xa2\x26\x99\x36\xeb\x50\x78\x44\xfb\xd4\x0c\x15\x1c\xe7\x01\xf1\xba\xc0\xc6\x68\x34\xa5\x46\x21\xd5\xed\x7e\x18\x10\x0c\x58\x34\x8e\xbf\xec\x8c\x86\xc1\xa4\x39\x3c\x1b\x11\x94\x51\xd3\xe7\x2c\x9b\xe1\x34\xa5\xe3\xdc\xce\xd6\x2e\x53\x11\x53\x28\x0d\x3d\xe6\x4a\xc5\x06\xc6\x2f\x38\x07\x8d\x42\x72\x78\x43\x67\xd8\x5d\xbd\x9f\x0c\xb9\x3a\x81\xe1\xe4\xe6\x50\xda\x10\xb4\x06\x95\x32\x82\xe1\xf4\x36\xf4\xcc\x3e\xbb\xac\xbb\xb3\x32\xec\x68\xfe\x74\xa4\x7a\xdb\x9e\xc5\xc6\xb5\x38\xb3\x8c\xf9\x1d\x8f\xc1\x3e\xc4\x63\x04\xe4\x64\xde\x71\x3e\xe2\x20\x30\x12\x09\x5a\x33\x69\x51\x46\x0d\x27\x92\xc3\x59\x8f\xae\x4f\x1a\xaf\x5c\x28\x57\xce\x74\x9d\x12\x28\x82\xae\x0c\x9f\xff\x36\x54\xdb\x49\xe3\x7a\x89\xe0\xd0\x55\xff\x32\x4a\x56\x1d\x1e\x46\x2e\x3c\x0b\x66\x67\x28\xa1\x7e\x77\x9b\x87\x62\x26\x46\xfb\x1a\x46\xe3\xc1\x4d\xa9\xa2\x97\xa9\x1e\x28\x56\x4f\xe3\x19\xf1\xcd\xd1\x7c\x27\x5a\xe3\xe9\xa5\x34\x3c\x43\x15\x61\x46\x8f\xcd\x9a\x8d\x8e\xa9\xcd\xfe\x76\xf6\xe8\xe8\x62\xad\x7b\x3f\x02\x72\x46\xb9\x52\xf8\xfa\x81\x8e\x8e\x2a\x08\x7c\xc7\x2f\xd3\x15\xe4\x03\x47\xcb\xbd\x3c\x9f\x29\x69\xbe\x58\xc3\x01\x6f\x36\x80\xfb\x61\xf4\xbe\x03\xca\x0b\xf7\x4d\x93\xdf\xac\x27\x82\x9a\x1c\x6c\x7b\x66\x7a\xd3\xd9\x36\x57\xe0\x77\x20\xe4\xb2\x6a\xb1\x0b\x48\xba\x5f\xf2\x7b\x27\x22\x9b\x7b\x31\x5b\xfe\x2a\xa0\x07\xc3\x82\x2f\x82\x78\x29\x76\x99\x43\x08\x81\xd8\x58\x34\xdc\x81\xa2\x5f\x39\xaa\x43\x8b\xe5\x40\x78\x50\x48\xd3\x5f\x05\x23\xac\x36\x53\x31\xfb\xd1\x8c\xc8\xe0\x69\x65\xf0\xf1\x9e\xe9\xed\xfd\x16\x22\x1a\x13\xd0\xe6\xd6\x89\x0a\xe3\x3b\xc4\x8a\x70\x87\x92\x53\x27\x2a\xe5\x37\xb7\x9b\xdb\xf9\x9c\xec\x68\x04\xb7\x33\x4a\x4b\x94\xe7\x35\x06\xd9\xc1\x6c\x85\xc7\x1f\xa9\xc0\xbf\x92\xe3\x4e\x60\x28\x32\xe1\x46\xe9\x66\xc1\xbf\x0d\x60\x07\xb7\x44\x5e\x55\x2b\xcd\xbe\x13\x3f\xe9\xaf\x9d\x18\x0d\x52\xf6\x31\x81\x9c\x11\xb1\xe2\x9b\xb4\xeb\x4f\x22\xaa\xd2\xac\xee\xce\x64\x75\x67\x9d\x0e\x64\x37\xd4\xb4\x0c\x88\x44\x06\x3b\x54\x4e\x2c\x8f\x55\xe4\x15\xcb\x7f\xf1\x77\x2c\xff\x7b\x95\x8b\x3c\xfa\x59\x7e\x14\x5c\x66\x5f\x8b\x68\xaa\xc7\xd7\x1d\x86\xd9\x31\xb0\x2c\x32\x8a\x09\x2b\xdd\xfe\xf1\x40\x4e\xee\xfe\x37\xa5\x6b\xc9\x27\x4b\x73\x37\x22\x49\x3d\x5a\x60\xd2\x5b\xd7\x92\x0c\x85\x4e\xfd\x0c\x09\xbd\x85\xf4\xde\xd2\x88\xe2\xb3\x3c\x77\x2d\x03\x69\x4c\x1c\x7d\x8e\xc2\x38\xb3\x21\x71\xc6\x6b\x0c\x0a\x29\x2e\xf3\x6e\x15\x60\x87\x53\x4d\x65\x08\xad\x88\xee\xf0\xba\xd1\x7e\xa7\xcb\xd5\x17\x0b\x5f\x38\xdc\xdf\x05\xc4\x0f\x03\x27\xea\x8f\x68\x62\x88\x64\xe0\xf6\x01\x31\x33\x82\x33\xc7\x9d\x87\xf1\x3d\x83\x8a\x0d\xe2\x32\x1f\x99\x33\x88\xc4\x54\x38\xd1\x48\xe2\x0c\x89\x46\xa7\x6f\x4a\x47\x9a\xcb\x11\x3c\x84\x4d\xb9\x3e\x5c\xf9\xa2\xdc\x1f\x1e\x6a\x1e\xbf\xae\xdf\xe7\x1c\x43\x72\x5c\xfc\x8a\xf7\x6c\x13\xe2\xc5\x4b\xe5\x6c\xec\x4a\xef\x63\x91\x6c\x38\x20\x6f\xfa\x80\xa4\x88\xdd\x1c\x02\xc9\xf8\x96\x62\x49\x19\x73\x88\x68\xc5\x7c\xd6\x9f\x14\xe0\x95\xd8\xf2\x02\x69\xa2\x9c\x9c\x65\x54\x0a\xf1\xe5\x9e\x51\xe7\x9e\x35\x4d\xe1\x58\x2f\xb3\xa4\x62\x7b\x7e\x85\x7f\xc3\xb2\x8a\x79\x45\x3f\x5a\x7d\x74\x85\xd7\x9b\xe1\x93\xbc\xef\x4c\x3c\x5e\xdf\x58\xe6\x34\x84\x63\x4b\x42\x02\x21\xbd\xc7\x5b\x5b\x47\x41\xc0\x21\x5c\x3e\x56\x59\x2d\x24\x71\x74\xe2\x55\xf1\x72\x74\xf7\xee\x59\x37\x40\x02\x38\x0c\x1a\x11\x88\x5a\xbc\xdb\x8a\xd1\xeb\xb7\x7b\x56\xa5\x59\x71\x0d\xef\xa4\x85\x9b\xf6\x51\x79\xeb\x58\xf3\xff\x9e\x5b\xc4\xf1\x66\x87\x27\xe2\xb3\xc5\x6f\xff\x15\xcc\x9f\x59\x60\x65\x16\x81\x47\x36\xe5\x2f\x3a\xba\xa1\xc5\xf4\xc6\x58\x96\x07\x5e\xf0\x6a\x7c\x89\xcb\x20\x4b\xca\x47\x0b\x19\x82\x8c\x19\xc7\x2e\x7e\x32\xc0\xec\x89\x5d\xd2\x7f\xe1\xa1\x49\xb7\x76\x34\x6a\x9a\x47\x54\x28\x45\xb6\xed\xa4\x14\x21\x5b\x07\x68\x43\x0d\x9b\x13\x92\xa6\x89\xd0\x5f\x46\x64\xb1\xc4\xda\xa6\xc8\xb5\x5e\x56\x9b\xa1\x37\x4b\x21\x9b\x92\x77\x1b\xc0\x3b\x85\xcb\x52\x62\xdb\x0f\x4c\xdf\xa0\x85\xb0\xbb\x5b\x22\x04\x00\xa7\xbb\xe5\x3e\x2b\x7e\xc1\x97\x44\xbc\xb0\x27\xf9\xd2\xa7\x1b\xa9\xba\x1c\x4d\x41\xf4\xfb\x51\xe5\x94\x69\xb1\x59\x86\x83\x51\x2a\x21\x86\x9d\x7b\xea\xa5\x73\xcb\x72\xd3\xf3\x4b\x5d\x55\xec\xb9\xc9\x88\x74\x57\x4c\x5f\x34\x67\x06\x95\x12\x59\xbb\x5b\x1d\x68\x48\x2e\x1c\xe8\xb6\xed\xd8\x61\x1f\x55\x11\x34\x9f\x30\x96\x9d\xf6\xce\x87\xe4\xc2\x07\x0c\x73\x23\x67\x9d\x9c\xd4\xc3\x32\x64\xd1\x5d\x5a\x95\x0f\x45\xfc\x45\x9e\x1d\xa8\xa5\xf6\xcb\x22\x2c\x9f\x2c\x48\x46\x7e\xee\xd3\x45\x2c\xb8\x43\x96\xaa\x42\xb6\x01\x41\x6e\x58\x0f\x46\x1f\x9a\x2a\x0b\x5c\x25\x47\xc7\xe3\x1b\xfe\x54\x53\x4b\xee\x7b\x77\xb5\xc1\x75\x72\x57\x1b\xb9\xe7\xdd\xd5\xa6\x2e\x0f\xee\x6a\x93\xf3\xa4\x76\x17\x7f\xf9\xcb\x5f\xfe\x72\x78\xda\xc8\xcd\xb8\x10\x5f\xd6\x87\xa7\xcd\x41\xdd\xcf\xe8\xb2\xf0\x58\xe6\x0f\x35\xb7\x80\x0f\x44\xeb\xc4\x88\xb1\x99\x3a\xfd\x1c\x74\xad\x2f\x1e\x79\x78\x97\x61\xa7\x17\xc7\xec\xb7\xac\x48\x5d\xd9\x21\x91\xb2\x59\xec\xcb\xdf\x2e\x7c\x9a\x4e\xd5\x28\x35\xcc\xcb\xe8\x6e\xd0\xdb\xff\xda\xa8\x1f\x35\x5e\xec\x3e\x8b\x63\x51\x81\x78\x96\xa3\xff\x64\x7a\x50\xa6\xb6\xd0\xb2\x20\x1e\x29\xcb\x36\x32\xa8\xf0\x04\x1e\x48\x24\x1e\xd8\x84\xd4\x5a\xff\x17\x6e\xd4\x65\x5d\x1e\x20\xa2\xd6\x27\x07\x5c\xa5\x54\x6d\x93\x78\x20\x11\x72\xd2\x9e\x57\x66\x18\xcf\xdd\xc1\xe9\x90\x3d\xf1\x5c\xdf\x8f\x39\xb1\x23\x52\x81\x6f\x5b\x08\xcb\xa7\xd7\x38\x4b\x3f\xf3\x3c\xbb\x10\x3e\xbd\x33\xd0\x10\x65\x22\x21\x15\xc8\xac\xdf\xe3\xf4\x61\x68\x8d\xb1\x74\x10\xa2\xf9\xd0\x1f\x88\x5b\xd1\xe1\xb5\xd1\xc2\xff\x11\x40\x30\x00\xfa\x0c\x12\xcc\x6f\x17\x92\xa7\x60\xc1\x5d\x6d\x3a\x78\xd7\xab\xbf\xb2\x40\xf7\x6e\xdf\x8f\x98\xea\x34\x89\xbe\xac\x95\x80\x82\x41\xca\xfa\xf0\x74\x0e\x0a\x10\xd2\x19\x06\x66\xfb\x3a\x2f\x59\xed\x4c\x80\x44\x24\x41\xc2\x6c\x8b\x9c\x2d\x3f\x24\x23\x0d\x01\x84\x6d\x4b\xda\x16\xdd\xcd\x8e\x8f\xec\x70\x16\x6f\x55\x19\xcc\xa2\x27\x8e\x3a\x55\x4b\x64\x70\xc7\xd4\x4f\x02\x4d\x66\xfc\x24\x80\xfe\x91\x86\x7e\x12\x6c\x38\x8d\xba\x80\x08\x32\x4c\x93\x59\xda\xc8\x2d\x2a\xea\xd8\x12\x19\x9a\xef\x37\x41\xa1\x1d\xc1\x61\x34\x78\xe0\xeb\x78\xb3\x45\xe4\x73\x16\x90\xe5\x9c\x5c\xc3\x67\x17\x68\xf6\xf2\x39\xd1\xa4\xfa\xf3\x71\x16\x7f\xbe\x08\x08\x55\x39\x55\xa6\x2f\x18\x3d\x75\xdb\xd2\xea\xf7\xe5\xbb\xec\x98\x85\x59\x9e\xd5\xef\x5d\x6b\x97\xc5\x31\x2f\x2c\xd0\xcb\x6e\xe1\xba\x5b\x2d\x7c\xc9\xe8\x29\xe7\x75\xcd\xab\xd7\x07\x16\x89\x15\xc7\xc5\x2c\x8b\xfa\x17\x89\xe9\xac\x4f\x56\x2b\xab\x85\xaf\x18\xf5\xad\x5f\x10\x0a\x2d\xb0\x7e\xb4\xc0\xfa\xbe\xfc\xcd\x02\x6b\x7f\xb4\x82\x1e\x8b\x7d\xad\xc8\x51\x96\x38\xa1\x34\x57\xd1\xdc\x85\x0a\x5a\x15\xe2\xd5\xbe\xe5\xdf\x0f\x07\xad\x1d\x98\x6b\xaf\x9c\xb5\x10\x9e\x42\xe0\xf4\x2b\x36\x34\xcd\xe7\xd2\x25\x3f\xa4\x5f\x31\x9f\x07\xf3\x08\xc6\x55\x6b\x73\x9d\x9e\x2c\xfe\x75\xc8\x4f\xd0\xcf\x94\x9e\x22\xec\xaf\x43\xf4\xf0\x16\xf2\x3d\x7b\x72\x56\x10\xfb\xeb\x60\xe1\x44\xe8\x32\x31\x77\x62\xe9\xdc\x7f\x78\xb2\x88\x1b\xf6\x75\x7e\xc3\x4c\x63\x31\xcd\xb7\x27\x34\x42\xcf\x56\x4f\x91\x0a\xcb\xd5\xa4\xc6\x22\xde\x27\xae\x25\x2f\xc3\xc5\xb0\x4d\x6b\x0c\x11\xbe\xda\x7c\x72\x93\x6c\x92\x39\x7d\x41\x2c\x09\xe5\xea\xec\xd1\x49\xe7\x5d\xa8\x9d\x68\xfe\x33\xba\xe8\xaf\xf0\x1a\x96\xd8\x73\xba\x4a\x75\xde\x45\x1f\x96\x47\x6d\x55\x6b\x50\x46\xd7\x3d\x3b\xcf\xaf\x3a\x8a\xd9\xe7\xd6\x2f\xf2\xb6\x5e\x59\x8c\xb8\x66\x2f\xa6\x6a\xee\x13\x67\x67\xbd\xfe\x60\xcd\xdd\x29\x5e\x3f\xa3\xdf\x8e\x56\x49\xe4\xa4\xe6\x8c\xb1\xa5\xf4\x1e\xc2\x9a\x5c\xfd\xf6\x0d\x02\x26\x24\xf4\x51\x1d\x2d\x5a\x3d\x8d\x1b\xc4\x2b\xea\xd0\xbb\x25\xe4\xf3\x04\x19\x8e\xd5\x0d\xe5\x4d\x23\x91\xba\xba\xf7\x8d\x2a\xee\x33\x21\xe0\xac\x6e\x8c\xaf\x78\x5a\xa2\xb7\xb8\xe0\x28\xdf\xf5\x87\x71\x7a\xa7\x6f\x62\x9a\xda\xb6\x73\xb7\x3c\xa3\x25\x0e\x69\x1a\x8e\x6a\xc7\xbe\x02\x4e\x0d\xf4\xc7\x49\xd3\xac\xba\xe0\x82\x73\x0d\x5f\x82\x1b\x9d\x82\x26\x88\x21\x21\x73\x01\x96\xfd\x0c\xfe\x6d\x6c\x09\xa1\x0e\x89\xf0\xfa\xb5\x15\x32\xd0\x6a\x2b\xed\xd4\x4d\x33\x31\x1e\x10\x41\x2c\x3b\x65\xdb\x18\xaa\x4a\x85\xb2\x89\xc1\x2a\xf3\xb8\x13\xb2\x30\x36\xaa\x44\xea\x2a\x0d\x42\x0f\xf3\x37\x4d\x2f\x37\x35\x8d\x33\xca\x45\xbb\xbb\x94\x47\x1f\x6c\xfb\xb5\xf4\x22\x56\x6d\x76\x46\x9d\x66\xb3\x50\x33\x27\xee\x0e\xeb\x09\x91\x71\x5e\x5f\x63\xcc\x50\x1d\x91\x2a\xb2\x6d\xde\x34\xd2\x9e\x62\x54\x9a\x7b\x91\x12\x19\x63\x43\x5e\x24\xea\xa2\xd4\x14\x7d\x1c\x2f\xcc\x44\x68\xdb\xdd\xb0\xce\x7a\x6e\x4d\xa4\x4e\x0c\x3d\xf4\xd4\xfc\x58\xae\xac\x8b\x0c\xaf\x26\xd3\x67\xff\xc7\xa3\x72\x66\x2a\x05\xd6\xad\xdf\xbb\xa7\xf3\x88\xc2\x78\x98\xae\xcc\x17\x10\x44\x2d\x95\xb9\x93\x7f\x55\xe8\x53\x6b\x6d\xb9\x51\xdb\xb6\x2d\x44\xc7\xe3\x0f\x0f\xfb\x90\x57\xee\x29\x2a\xf3\x87\x7d\x81\x7e\xa6\xee\x6c\x05\x49\x96\xe7\x3f\xaa\xb6\xc4\x6b\xce\x9f\xfe\x5a\x95\x8f\xfa\xf9\xf5\xae\xca\x8a\x3b\x7c\xeb\x51\xff\x6c\x05\x79\x56\xf0\x6f\xba\xb7\xb2\xaf\x40\xf2\x09\xf8\x70\xd8\xb1\x02\xef\x6e\x7c\xcc\xe2\xf2\x11\x9f\x7e\xfb\x16\x6f\xc1\x13\x4f\x65\xb9\x47\x0f\xa6\xe8\x88\xa6\xf6\x47\xf7\x64\x25\x02\xfc\x05\x68\x1f\x8f\xb8\x13\xac\x16\x70\x16\x27\x8e\xe6\xa5\xb5\xe6\xc7\x23\xfb\x85\xff\x33\x7a\x67\x5a\x8a\x30\x4e\xf1\xc7\xa1\x81\xb3\xb1\x30\x19\x4a\x44\x81\x9d\xf2\x77\x01\xc6\xdd\x37\xde\xe9\xd7\x0c\xd5\x52\x02\xc1\xe0\x07\xe9\xb4\x16\xe2\x05\x58\xdd\xeb\x2e\x00\x23\xf2\x72\x6a\xdb\x56\xca\x6b\x2b\x2b\xae\x52\x23\xe2\xa5\xc3\x69\xaa\x42\x14\xce\xd6\x10\x13\xe2\x71\x37\xf3\xc3\xc0\x75\x92\x2e\xfa\xad\x11\x10\x97\x26\x88\x78\x3e\x57\x34\x2b\x22\xd2\x60\xd3\xe1\xfe\x3a\x98\xaf\xc9\x73\xee\xbf\x08\xe6\x06\x1e\xd1\xf8\x4e\xc8\xad\x09\xb5\x0a\x04\x00\x8b\x80\x3c\x09\x89\x6c\x3b\x52\x44\x43\x7f\x9a\xa1\x17\x20\x16\x93\xd0\x22\x87\x1f\xcd\x29\x12\xbd\x73\xf1\x49\xc0\xb3\xdc\xeb\x2b\xb4\x51\xeb\x02\x74\xf4\xe2\x93\x85\xf1\xaa\xfc\x30\xa0\x56\x56\xec\x78\x95\xa1\x81\x86\x6d\x5b\xc7\xd1\x7c\x50\x3c\xa5\x4e\x55\x14\x5e\xb1\xc8\x5d\xc9\xa8\x93\x75\x89\x84\xe5\x4b\x8e\x4f\x93\x2b\xfc\x1f\xac\xab\x82\x84\x3f\xb2\xba\xc3\x25\x35\x57\x72\x05\x7d\x7f\xbb\x48\x99\x8a\x94\xc4\x04\xb1\x55\xb5\x67\xb9\x8a\xa2\x89\x3c\xcb\x97\x0c\x33\x7d\x89\xf7\xd6\x48\x14\x19\x35\x4d\xe4\x39\xc9\x90\x2e\x48\x83\xdc\x95\xb4\xcb\xf9\xe1\x61\xcf\xab\x2c\x72\x12\xe2\x25\x4d\xb3\x72\x39\x71\xb9\xa1\xcd\xf4\x2d\x29\x92\x5a\xa0\x28\x67\x70\xa6\x75\x34\x86\x47\xc7\x78\xc6\x34\xa5\x8e\xbc\xdf\x14\x81\x3b\x0f\xf9\x47\x6c\x5b\x3a\x37\x19\x14\xd9\x93\xdc\xb6\xc3\xe0\x0b\xe3\x96\xf0\xae\xba\x6f\xf5\x5c\xb4\xc4\xed\x9e\x3b\x47\xbc\xe3\x44\x3f\xa4\x57\x5b\x6c\xdb\x48\xd9\xf5\x82\x22\x33\x17\x41\xec\x29\x0a\x19\xc3\x1f\x23\xf8\x9c\x00\x27\xee\x4a\x3b\x00\xe8\x59\x18\xc8\x31\xef\x99\x73\xb7\x9c\x10\xe9\x60\xf2\x90\x2f\xec\x47\x7c\xea\x38\xe9\xac\x10\x48\x72\xa1\x19\xea\x27\x06\x3e\xd3\xec\x97\x8c\xbc\x18\x18\x01\xd4\x3a\xbf\x1b\x29\x71\x59\x16\x68\x49\xcb\xb2\x40\x49\x5f\x8a\x73\x3a\x57\x1f\x77\x0b\xc9\xe6\x62\x29\xa5\x8d\x84\x6b\x1e\x7d\x68\x46\x40\x1a\x59\x9d\x5a\x81\x10\xce\x22\x6d\x7b\x91\xe1\x66\xed\xfa\x51\xb0\xf9\x44\x19\x61\x71\x9f\xcd\x7f\xf6\xe3\x40\x54\x9f\xf8\x71\xd0\x34\x89\x1f\x2f\x5e\xe0\xef\xca\x10\x6f\x5a\x78\x60\xfd\xe5\xae\xce\xa8\x67\x62\x6f\xd3\xbf\x32\x32\x36\xdc\x18\xef\xe8\xcb\xe7\x9a\x23\x5d\xa0\x18\x88\x20\xdd\x2a\x92\xbf\x8e\x0f\xaf\x83\x17\x48\x3e\x90\xf7\xa1\xbc\xb8\x22\xf1\x89\x1f\xfa\x69\x10\x74\x00\x22\xde\x24\x0a\xee\x43\xf9\x0f\x4c\x44\x30\xd2\xbd\xa1\x09\x04\x3c\x70\xd0\xe8\xb5\x05\x36\x19\xa2\x98\xb4\x70\xdc\x95\x8f\x13\xca\x83\xbf\x29\xa3\x05\x3c\x5b\xdb\x65\xf1\x94\x82\x41\xe5\x21\x2d\xd4\x65\x9a\xe6\x53\x21\x51\xad\xb0\x2c\x73\xce\x0a\x33\xe4\xb4\x0a\x3a\x2d\x1a\x56\x97\x49\x2d\x45\x03\xfa\x79\x6c\xcd\xf2\x5a\x36\xe2\xc9\x7b\xb3\x89\x2e\xa7\x5f\x65\xd1\x76\x78\xef\xcb\x77\x03\x89\x47\xeb\x43\xf8\xe3\xd5\x77\xac\x77\x1f\xc4\x3b\xd0\x8d\x7c\x6d\xb1\x7c\xf3\xc8\x79\x41\xbf\x63\x60\xe6\xa3\x27\xe3\xaa\x71\xf7\x3b\x06\xa2\xdc\x84\x1f\x0e\x24\xca\x16\x82\xe7\x7c\xaf\x9d\x32\x0f\x55\x79\xa0\x91\xf6\x4c\x38\x66\x05\x5e\xab\x68\x1d\x1f\x71\xaf\x4b\x97\x08\x34\xca\x3e\xd2\x50\xfb\xbc\xb1\xaa\xd6\x96\x24\x8f\xea\x22\x02\xf4\x4e\x96\x95\x14\x31\x8d\xe5\xe3\x03\xde\xe1\xae\xa1\x58\x11\xc4\x28\xf0\x04\x0b\x27\xc8\x61\x0b\xd1\x43\x75\x7e\x00\x2c\xc7\x76\x90\x50\xdf\x75\xb2\xf7\x19\x17\x5c\x49\xca\x6b\x69\x16\xab\xec\x8d\xcc\x32\x7d\x90\x9e\xee\x7b\x0b\xd5\xc3\xc4\x05\x55\x10\xfd\x5e\x63\xe6\x04\x2c\xe3\x87\x0a\xdd\xfc\x94\x6b\x7c\x79\xa4\x82\x22\xca\x59\xf3\x8d\x19\x0c\xb4\x11\xc9\xb8\xe0\x73\x06\x2b\x58\x4f\x7f\xd3\x5e\xf5\x58\xab\x36\x42\x29\x1f\xa9\xa3\x67\x75\xd1\xcf\x3e\x79\x1e\xce\xfb\xb7\x61\x7d\xc7\x9a\x1f\xd4\x99\xbc\x99\xd4\x9f\x4d\xca\x20\x2f\xba\x7e\x7d\xd7\xb5\x6d\x63\x2c\x56\x2f\xea\x02\x88\x5f\x9a\xd4\xee\xbb\xbc\xdc\xa9\x85\x33\x98\x35\x40\xd3\xfc\x06\x66\x7d\xf4\xd4\xf9\x0d\x8c\x08\xa7\x5a\x9b\x71\xe8\x09\xd1\x6b\x5f\x56\x80\x96\xf8\xe2\x5d\x0b\x18\xea\x9e\x36\x23\x4d\xe7\xf4\x9c\x50\xe3\x28\x39\x6e\x99\x0e\x42\x90\x12\x52\x09\x7b\xa8\x4b\xc1\x80\x85\x5e\xe8\xae\x88\x3b\x6c\x66\x4c\x4a\xf1\x9c\xf1\x09\xa7\xb3\xab\xff\x2c\x05\xef\x89\x1f\xf4\xce\x99\xe8\x9e\xc1\x38\xa9\x72\x43\xfe\x48\x25\x92\x1e\x65\x0e\xba\x2f\x58\xf4\xc7\x39\xde\xff\x59\x8f\x7b\x8d\xfc\xfb\x63\xdb\x2d\x8c\x5a\xbf\x2e\xc4\x05\x9d\x48\x7e\xc5\x93\x1a\x3d\x19\x87\xb1\xa1\x64\x8f\x4d\x69\x00\x13\x06\x36\x49\x53\x8d\x6b\x37\x58\x44\x27\x27\x41\xc4\x59\x35\x79\x4f\x67\x0b\x88\x68\x26\xbe\x2d\x3f\x5d\xa0\x1a\x29\x2a\x8f\x0e\x7b\x8e\x8f\x3f\x7d\x4b\xae\x5f\x60\xcd\xc9\x13\x3d\x03\x3a\xe8\x56\x82\x9e\xd4\xfd\x1d\x0c\xbe\x67\xf0\x03\x93\xf1\x72\x25\x09\x68\x04\x76\x6e\x04\x4e\xc6\xfb\x3a\xc6\x4a\x40\xcf\x55\x7a\xc0\x86\x68\x9d\xa1\x3c\xe2\xeb\x15\x87\x3f\x31\x7a\xdd\x07\x9f\x7e\x76\x0d\xff\xcd\xa8\xff\x0f\x16\xc0\xcf\x8c\x9e\xac\xe7\x96\xeb\x5f\x72\xaa\xd2\x76\xb6\x02\x87\xf7\xb1\xe5\x25\xea\xe4\xf4\xc7\x4e\x91\x06\x89\x60\x6b\xb9\xff\x71\x30\x42\x9d\xac\x47\x9d\x90\xd2\xd1\x27\xa9\x57\x9b\xa1\x8c\x33\x8f\x89\x6d\xeb\x0a\x25\xf8\x47\x0a\x7e\x08\x81\x1d\x5d\x43\x46\x5f\x20\xd1\x4f\x6d\x3b\xf5\x3f\x0e\x44\x31\x65\x05\x2d\x5e\x81\x0b\x22\x80\xaa\x8e\x79\xdc\x34\xeb\x4d\x5c\x5e\xed\xe8\xae\x69\xac\xe5\xa7\x16\xa4\xd7\x74\x07\x1a\x2e\x75\xbd\x90\xce\x13\xa2\xd4\x8a\x3b\x21\x99\xed\xf4\xd8\xae\x63\x75\xa9\xf8\xce\xb6\x17\x8b\xac\xbf\xf4\x41\x9d\x33\x4a\x7a\x32\x4f\x9b\x46\xb4\xb5\x82\x48\xd1\x0d\x88\x90\x96\x08\xd9\xcc\x4b\xe7\x03\x19\xcd\x9d\x8b\xbf\x04\xa2\x36\x30\x8e\x3a\x5f\xb3\x9e\xf4\x1b\x17\x95\x99\x41\xe8\x75\x8c\xf1\x96\xc0\x2b\x46\x95\x93\x7f\xaf\xf4\x79\x33\x74\x4c\x91\x9c\x9e\x3a\x97\x62\x52\xb9\x1d\x4a\x75\xa3\xe2\xeb\xe8\x8b\x45\x48\x22\x2a\x18\x3b\xe0\xbe\xd6\x0c\xce\xa3\x80\x72\xbf\xd7\xf1\x45\x01\x65\xc6\x7d\xe8\x0e\x5f\x2a\x71\x9f\x6a\xa5\xbe\x60\xb2\xfa\x6e\xfc\xbd\xd3\xde\x75\x4c\x27\x70\xea\xfc\xcc\x50\x8a\xf2\x03\xa2\x03\xb2\xfc\xcc\x7c\xeb\xb9\x15\x10\xbc\xad\xb6\xb7\x6c\xd8\xa4\xa8\x07\x9d\xcb\xcb\x64\xb8\x9f\x04\x12\xfb\x47\x82\xc7\xea\x14\x6c\x86\x52\xf7\x1f\xd3\x87\xc4\x3a\x32\xac\x34\x38\xda\x53\x0c\xb3\xaa\x25\xbc\xc3\x40\x4f\xf0\x5a\xf0\x89\xf7\xdd\xc5\x0d\x56\xf2\x24\x36\x1a\x06\x09\xc7\xcd\xd2\x34\x68\x4f\x33\xbc\x31\x01\xaf\x7d\x00\x89\xe0\x77\xcb\x87\x02\x3f\xc6\x68\xad\xa2\x5f\xf0\x06\xb7\x9d\x71\x97\x01\x98\x2f\x66\xc8\xf9\xbe\x4c\xd3\x64\x82\xe1\x82\x3e\x65\x3e\x87\x7c\x29\xef\x5e\x35\xc1\x61\x2a\xad\x2f\xb4\x58\x40\x7f\x11\x04\x76\xb5\x33\x0c\xdb\x0d\x2f\x57\xc0\x1b\xd9\xce\xec\x20\xb5\xf4\x98\x15\x57\x61\xd3\x28\x11\x12\xcf\x36\x6c\xdb\x89\x96\xe5\x3b\x5e\x25\x79\xf9\x48\xfd\xb2\x7b\x86\xfe\xf1\x57\xe3\xf9\x9f\x01\xdc\x4e\xc4\x8a\x87\x3b\xda\xe9\xed\x6e\xbd\x6e\xea\x4d\x45\x63\xd3\xd4\x42\x26\xef\x74\x7e\xee\x2d\x28\xa9\x4a\x14\xba\xd3\x6a\x39\x53\xd2\x93\x2a\x24\xd1\xc7\xb2\x57\x3b\x0e\x24\x31\xb4\x29\xd5\x7d\xc3\x7c\xdd\x58\xba\xd3\x90\xa9\xa9\x35\xf2\xf5\xe5\xfd\x55\x60\x8e\xda\xfc\xb2\x36\xbf\xfc\xd3\xfc\xf2\x22\x68\x95\xda\x51\x5d\x24\x86\xca\xe6\x50\xec\xc2\x1f\x3a\xdf\x0c\x54\x71\xa9\x73\x79\xfc\x84\xe8\xcd\x92\x74\x00\x75\x07\xc0\x29\xa5\xce\xc1\x13\xbd\xe6\x96\x6b\x49\x90\xc5\x72\xf2\x59\xde\x4d\x3a\xbb\x37\x62\x90\xdc\xfb\x71\x40\xa2\xb2\xa8\xb3\xe2\x81\x6f\x0e\x74\xb6\x6a\xf7\x7e\x1c\xd0\x7b\xdb\xbe\x47\xb1\xae\x97\x71\x62\x15\xe9\xf6\x56\xdf\x82\x34\x71\x5d\xda\x9e\x10\x63\x41\x1c\x63\x3d\xc7\x0b\x37\x5c\x91\x5b\xe9\xc7\x72\xba\xf7\xf4\x94\x67\xc5\xd5\xbd\x6d\x3b\x07\x7a\xbf\x94\x29\xc4\xbd\x37\xaf\x49\xd1\x5b\x12\x4e\x2d\x81\x04\x03\xc9\xca\x7c\x74\x76\x20\xf0\xff\xe7\xee\x4f\xdb\x1c\xb7\xb1\x43\x71\xfc\x7d\x3e\x85\x44\x3b\x32\x51\x82\x54\x52\xb5\xc7\x99\x50\xcd\xd2\xdf\xeb\x4c\xcf\xf5\x16\x77\x3b\xf1\x44\xd6\xf4\x05\x49\x50\x62\x95\x8a\x94\x49\xd6\x36\x25\xdd\xcf\xfe\x7f\x70\x0e\x56\x2e\xaa\x6a\x4f\x92\x27\xcf\xef\x45\x77\x89\x20\x00\x62\x39\x38\x38\xfb\xd9\x2f\xc5\xdd\xab\x78\x97\x1d\xe6\xef\xb4\x9d\x8a\xc5\x5b\xc5\xca\xd0\xf6\x7b\x24\xd9\xec\x18\xbc\x1a\x03\x00\xd6\x14\xdb\x74\x43\x6c\xfe\xef\x66\x15\xad\xc9\xd1\xda\xc5\x1b\xb2\x09\x7f\x66\xfe\x7e\x29\xd6\x31\x98\xd1\x84\xee\x08\x85\x37\xbf\x1d\x0e\xbe\x28\x0c\x37\x92\xe0\xdd\x8b\xab\x03\x6e\x07\x55\x22\xff\x5a\x3a\x8e\xe4\x70\x50\x27\x10\x12\x04\xcf\x83\x99\xe3\x79\xf7\x1f\x5d\x4e\x88\x30\x9a\x18\x95\x60\x80\x3c\x6d\x41\x58\x0c\x9c\x30\x42\x12\xf8\x3e\x1a\x8e\x39\x45\x8d\x46\x2a\x60\x16\x5f\x86\x82\xad\x27\x34\x96\x79\x21\x99\x18\x7e\xaa\xc2\x20\x8b\x0a\x0d\xf9\x58\x82\x02\x31\x14\x3c\x80\x4c\x4c\xdc\xc7\x1b\xe9\xad\xe1\xa7\xc4\xb4\x4d\xd6\x66\x98\x29\xc1\xd1\x1e\x0e\xbe\x0e\xae\x45\x21\x69\x3f\x97\xd0\x27\x06\x1c\x5a\x97\xcb\x2f\x6d\x5c\x0f\x97\xc7\xbf\x31\x93\xc9\xc3\xce\xf6\xd1\x71\x90\x55\x30\x67\xb8\xfa\x8f\x84\x66\x36\x1e\x16\x47\x91\xa8\x1c\x02\x0b\xed\x65\x13\x7e\xcb\x0e\x07\x71\x43\xd3\x38\xb4\xf4\x83\x57\xb8\x6f\xe2\xae\x1e\x5f\x69\x5e\x68\x82\xb4\xd1\xb9\x29\x11\x84\x41\x1a\xce\x27\x09\x68\x5f\xb2\xf0\x6a\x5a\x0b\x32\xca\x18\x62\x4b\xb9\x84\x2a\x5f\x6d\xd6\xd3\xf2\x36\xf7\x53\x93\xfb\xc3\x4e\xe5\xcb\xe8\xea\x8a\xa6\x54\xec\xc2\xfc\x32\x1d\x8d\xb2\x65\x1c\xf8\x5b\x27\x5f\x89\xa8\xb2\x26\x18\x14\xe9\x2a\xdc\xea\xac\x21\x18\xfe\x90\xc9\x10\x87\xb6\x93\x67\x44\x68\xb1\xaf\xad\xb2\xe1\x8c\x3e\x49\x67\xa2\xaf\x81\x16\x0e\x9e\x8e\x47\x1a\x13\x1d\x2f\xca\xe4\x7f\x0c\x22\x5d\xf8\x03\x72\x6d\x41\x4c\xf5\xd2\x04\x7a\xf1\xd4\x7a\x04\xb1\x5e\x1a\x8a\x33\x0e\x56\x6b\x6a\x11\x98\x4e\xbc\x6b\xa5\x06\x94\x02\x04\x9f\xd1\x2b\xc1\x1c\x56\x20\x19\xc0\x9f\x53\x67\xa0\x40\x68\xc8\x17\x48\xc6\xeb\x75\xd4\x2b\x0f\x8e\x56\x09\xa1\x09\x46\xea\x09\x6c\xcb\x37\xe3\x3b\x1c\x2d\x1b\x5b\x15\x00\x1e\xe4\x4e\x98\x0c\xf0\xc5\x0d\x87\x33\x6d\xa8\xae\xb7\x31\xc6\x6d\x9c\x5b\x4e\xcd\xed\x6d\xa2\xd1\x9a\x04\x5b\x99\xf4\xd8\x29\xa5\xca\x40\xf5\x3a\xbc\xc2\x80\x75\xf0\xad\xff\x60\xfe\x75\xe7\xbc\x89\x4b\x3a\xfd\x1b\xd3\xb4\xd3\x15\x65\x54\xb5\x31\x24\x94\xc9\xb7\x7e\xc3\xf6\xfe\x35\xfd\x19\x22\xcc\x3a\xb6\xd8\xea\x33\xc0\xb7\x8f\x46\xf6\xa3\x0a\xa5\x0e\x4d\xd2\x07\x88\x3f\x55\xfa\x1a\x7c\x32\xaa\x60\x8d\xe5\xd9\x4d\x70\x45\x31\x3f\x90\xec\x01\x1e\x04\xe1\x71\x65\xb2\x3c\xcb\x57\xea\x59\xa6\x61\x96\xa5\xe2\xb7\x9a\xb4\x4a\xf0\x2b\x13\x46\xcb\x52\xf1\x5b\x9f\x77\x59\x86\x4f\xe4\x98\x4f\x3f\xcf\xb3\x1b\x00\x38\xe3\xd9\xfc\x0b\xa3\x4f\xb0\x51\xad\x50\x12\x6e\x32\x6f\xb2\x94\x19\x7e\x90\x5c\x0d\x98\xa0\x22\xb5\x9c\x74\x61\x5b\xea\xce\x20\xf0\x50\xc3\x83\x35\x0e\x05\xd6\xa3\x3f\x01\x8a\x83\xff\x81\x3b\x81\x5f\x3a\x47\x56\x84\xbe\x54\x9d\xb1\x2d\xa3\xe5\xbf\x31\x5d\x91\x91\xe0\xdf\x18\x82\x2f\x93\xa9\xa7\xaa\x3d\xe7\x49\x2b\x82\x1a\x1e\x1a\x36\x1a\x75\xe4\xa5\xb3\x0f\x3e\x23\xc1\x93\x5a\xd1\x20\x3e\x1c\x86\xf1\x68\x14\xa1\x8a\xc1\x5a\x83\xd1\x88\x99\xe3\xcb\x28\x1e\xab\x00\xab\x46\x32\x20\xf4\x37\xe6\x0c\x8d\x46\x91\x95\x61\x5e\x35\x0c\x01\x50\x8a\x34\x5d\xce\x02\xa5\x74\xd2\xa3\x32\xd5\x96\xe6\x67\x60\x7e\x8a\x9b\x02\xb9\x64\x31\xdd\x6a\x69\xfd\x5e\x99\x5a\xeb\xc0\x2a\x37\x9e\xab\x32\x9e\x4e\xa2\xe8\x79\xf9\x03\xd4\x29\x60\xbe\x29\x9f\x91\xa8\x4f\xa6\xc5\x2e\x09\x13\x0d\x68\xd4\xfc\x74\x73\xa4\xd9\x91\xb1\x45\x1b\x32\x1a\xc1\x5f\x23\xaf\x12\x9d\x41\xd7\xad\xbc\x59\xb2\x9c\x1c\x05\x0e\x72\xe4\xe1\x29\x4b\xf8\xbb\xe2\x99\xd0\x36\xd2\x5b\xeb\x2d\x01\xd2\x57\xab\x80\xe9\x4c\xd1\x41\x82\xc2\x10\x17\x20\x00\x3e\xf7\xb5\x46\x39\x3a\x52\x54\xab\x1c\xa9\x7c\x77\x22\x8e\xa0\x4b\xef\x31\xcc\x1c\x07\x8b\x8b\x99\x08\x1a\x59\xe3\xf0\xb2\xfc\x45\x4a\xb7\x5d\x28\xa3\x29\x59\xf8\x5c\x85\x58\x80\x0a\x5e\x9a\xe5\x59\xb5\x05\x2d\x52\x04\xe1\xc8\x20\x3b\xba\x36\x09\x99\xe2\xfb\x70\x43\xf9\xe1\x90\x9a\x2d\x9b\x5b\x89\x15\x37\x52\xf4\x88\x2b\x2b\x2b\xd1\x0d\x69\xe2\x75\xe7\x54\xb4\x3d\xa5\x30\x5a\xda\x42\x91\x29\x98\x9c\x2e\xf2\x63\x3d\x9a\xce\xcc\x5f\x18\x2e\xc7\xce\xfe\x15\x8d\x46\x90\x99\x7d\x2e\xa5\x98\xad\x7c\x65\xdd\x61\x74\x70\x10\x60\xe8\x22\xe5\x6d\xa3\x91\x9b\x27\x0c\x56\x1e\x70\x6c\x05\x31\x23\xb4\x74\x18\x2f\xa4\x0d\xb8\xd0\x8a\xff\x61\xe8\xa3\x51\xe2\x6f\xd0\x5d\x4f\xa5\xab\x80\x70\x11\x9b\x76\xc5\x1f\xb5\xf1\x8a\x69\x84\x57\x9a\xf1\xc5\x9f\x4c\x16\x24\x15\x4d\x04\x4a\x97\xc1\xa5\xd1\x1e\x06\x46\x0a\xaf\x60\xac\xc3\x30\x14\xd4\x1c\x14\x08\xe8\xc2\x4d\x8d\xc1\xc2\x6f\x4e\x53\x95\xec\x83\xd3\x39\x21\x0b\x3f\x12\xd8\x86\xf4\x64\x94\xc3\xbd\xef\x14\xbc\x0d\x55\x20\x6f\x95\x6a\xed\xd4\xaa\xd2\xd8\x5e\x2d\x41\x99\xad\xd4\xca\x7a\x6b\xca\xad\x47\x5c\xe8\xb5\xbb\xd2\xc9\x32\x31\x77\x3f\x50\xae\x0a\x2a\x21\x57\xba\x93\x51\x4f\x6c\x2f\x46\xe4\x85\x95\xc5\xbf\x96\x77\xd1\x50\x00\x88\x59\xd6\x08\x97\x35\xc2\x65\x95\x0e\xae\x62\x35\xa3\xb5\x86\x75\x06\x66\x31\x91\xbd\x9a\xa2\x17\xbd\x92\x11\xac\x24\xca\x76\x66\x8b\xcd\x65\x04\x6e\x8d\xc9\x2a\x5a\x8f\x46\xe2\x7f\x39\x58\xe7\xc1\xc2\x4e\x0a\xe0\xd5\xa4\x74\x1e\x4c\x54\x21\x4b\x76\x93\x22\x43\x49\x91\xd5\x6c\x2a\x92\x55\x72\xc1\x34\x5f\x45\xeb\x85\xfc\x6b\x5f\x47\x8e\x9a\x08\x05\xe2\x87\x43\x97\xee\x2a\xee\x36\x36\xc7\x03\xae\x10\xd9\x3b\xf0\xed\x9b\x11\x8a\x1d\xdb\x0e\x3c\xd5\x2e\x4b\xf8\x57\xc5\x7d\x1e\xbc\x63\x92\x09\x26\x14\x0a\x7f\xde\x43\x11\x8c\x5f\x16\xbd\x43\xad\x9a\x28\x96\xd3\x24\x54\x60\xde\x37\xb9\xb1\xbe\xc1\x3e\x8e\x50\xfe\xc3\x6d\x6d\xbd\x80\x9e\xf0\x85\xec\xc8\xbc\x93\xdd\x1d\x9f\xf7\xf3\x69\xa3\x75\x35\xcb\x48\x21\x69\x98\x1e\x42\x63\xb8\x5a\x2b\x52\x2b\xbe\x6e\xa2\x5d\xf0\x72\xa5\xb1\x06\x5d\x80\x09\x23\x26\x5c\x44\xaf\x63\x0d\x77\xe3\x31\x61\x61\x0c\x31\x8d\x7d\xe9\x16\x81\x07\x37\xd6\x60\x35\x99\xd0\x39\x59\xc4\x5a\x68\x24\xe5\xd3\x90\x2f\xc2\x08\x22\x2d\xca\xaf\x11\x99\x10\x07\xa1\xe8\x14\xf1\x1d\xa5\x6c\x60\x65\xed\x93\xc0\xd4\x10\x5d\xca\x8e\x20\x38\xe4\x1d\xdb\x85\xf3\x57\xd4\xd4\xb6\x67\xfa\x9d\xc0\x2e\xdf\xb1\xb0\xe2\xf5\x1b\x59\xd9\xd7\x4b\xe2\x76\x42\x54\xaf\x62\xd4\x76\x1f\x60\xc4\xa2\x5b\x7f\xc7\x08\xfd\x0e\xbd\x74\x55\x7d\xa0\x1d\xc2\xa7\x6a\x57\xdc\x07\x9f\xcd\x66\x34\x65\x55\x1d\x5c\xcc\x66\x26\x58\xd4\xa7\xb3\x99\xbc\xb3\x13\xbe\x63\x8f\x7d\xf9\x12\x45\x77\x0e\x9d\xc2\xd6\x87\x03\x03\x37\x60\x99\xb3\x95\x5a\x97\x44\x44\xbb\xb8\x1e\x4b\x16\x1c\x51\x06\x79\x0b\xbb\xe6\xa3\xea\x48\x3f\xf7\x96\x5a\xb2\x2f\x0f\x22\x8d\xda\xaf\x30\x9a\x17\x18\xfa\x45\xa7\xcd\xd5\x51\x47\xe7\x11\xb2\x90\xc1\x9a\x4c\x74\x66\x95\xf1\xf0\x87\x3c\xf4\x30\xaf\xc0\x1d\xdb\xdd\x72\x7a\x2d\x28\x73\x0c\xed\xc3\x93\x30\x96\x21\xef\x20\xc9\xa1\xca\x49\x20\x30\x2b\x54\xfb\x4a\x17\xc4\xfa\x25\x3d\x31\x17\xf9\x8d\xd0\xab\x3d\x15\x87\x53\x26\x74\xa4\xd7\x53\xf8\xf1\xef\xea\x7d\xa8\x47\xa4\xd2\x1f\xfe\x95\xd1\xff\x64\xf4\x63\x48\x29\xf2\xb0\x2f\x21\x85\x35\x46\x9a\x5b\x38\xd4\x99\x28\x3f\x69\xae\x90\x43\xd3\x7e\x9b\x00\x13\xc9\xea\x03\xb2\xa5\x9a\x46\x7d\x29\x8b\x5b\xe3\x72\xa5\x24\x46\xba\xbb\x30\xc6\x73\x29\xda\xcc\xa5\xa3\xd1\x05\x28\x51\xdc\x1c\x81\x6e\x4c\xaf\x30\x0c\x7f\x5e\xe6\xc0\x87\x2a\x13\x08\x08\xde\x90\x62\x8a\x18\x1d\x26\xe8\x70\xf0\xa3\x30\x6a\x84\x93\x11\xdc\x3b\x2c\xa8\x36\xa7\xf2\x9d\xd4\x78\xe2\x32\x50\xde\x54\xcb\xff\x64\xc1\x5f\x99\x6d\x43\x15\x2f\x13\x63\x6e\x95\x28\x8d\x69\xe8\xf3\x30\xd1\xb9\x96\xc9\x92\x63\xe2\xff\x34\xcb\x13\xf8\x16\x6a\xa9\xa4\xd1\x2e\x3a\x3a\x81\x95\x94\x6c\x8d\x9d\x56\xba\x53\xdb\x2c\x2f\xd1\x66\x68\xb2\x63\xe6\xa6\xfa\x8c\x68\x3c\xf6\xc4\x01\x91\x16\x3c\xce\xfe\xc0\x68\x7a\xb6\xd9\x91\xd9\x85\x33\x9a\x86\x91\x20\x7d\x55\xf6\x39\x99\xe1\xbb\x91\x55\x5f\x26\x38\x0f\xd3\x15\x1f\x8f\xd7\x44\xac\xa5\xd8\x85\x6f\xb2\x07\xe0\x25\x63\xda\xb3\x94\x10\xd7\x05\x64\x77\xc3\x39\x66\x26\x71\x43\xa8\xc5\x82\x05\x50\x9b\x12\x60\x74\xf0\x86\x1a\x55\xda\x9b\x0e\xed\xe3\x33\x1a\xc9\x43\x85\x79\x9e\xdd\x08\x76\xf2\x28\x9a\x98\x60\x70\xc6\x4c\xc4\xfc\xae\xa4\xab\x32\x51\xb6\x3a\xbd\xe8\xb7\x01\xd6\x59\xff\xc9\x9a\x7a\x5d\x27\xb9\x3d\x46\xb3\x5c\x36\x56\x3f\x26\x41\xe3\x3b\x31\x05\xef\x48\x1d\xdd\xb8\xbd\x5e\x98\x1b\x57\xee\xc3\xf9\xaf\xf7\xe3\xf3\x0d\xe9\x24\x73\x3e\x66\xd2\x18\x50\x83\xd9\x02\x8a\x5c\xf6\xdb\x18\x24\x6a\x26\x58\x50\xc5\xd8\x9a\x62\x03\xae\x69\xfd\x58\xb6\x59\x36\x4e\x0d\xa6\x09\x93\xdd\x13\xca\x95\x3b\xee\x7b\xa9\x14\xc6\x88\x94\x88\x40\x0f\x2a\xe0\xd8\x01\x73\x5f\x40\x4e\x5d\x07\x6f\x09\x90\x79\x06\x6f\xa1\x76\xfe\x34\xde\xfa\xd1\xed\xe6\x34\xde\xb2\x1c\x0b\x57\x06\x68\xe1\x16\x5c\x37\xf1\x97\x7c\x1b\x3c\x79\x69\x51\x7a\x81\xb7\xad\x6f\x76\xdf\x14\xa5\x47\xbd\x78\xc7\xaa\xca\x0b\xf0\xaf\x00\x34\x0f\x73\xb4\x9c\x0a\x92\xd6\x8d\xef\x36\x88\xef\x36\x88\xef\x36\x0a\xdf\xa5\xe1\x1c\xdd\x41\x87\x0e\x26\x03\x45\x43\x64\x9d\x36\xb1\xf3\x11\xe4\x93\x36\x56\x37\x60\xff\x6f\x8c\xc4\xb8\xc1\x29\xdc\xc6\x29\x49\xc8\x1d\x9c\x92\x04\xb0\xad\x71\xc0\x0d\x66\xe3\x06\xb3\x89\xea\x06\xb3\x61\x65\x9c\xb4\x3a\xac\x2c\x42\x5b\xea\x96\xfd\x89\x3e\x6a\x5b\x56\xd9\x47\x8d\x45\x60\x9e\xeb\x91\xc3\xe1\xbd\x32\xd2\x33\x2a\x9a\xc3\x81\x4d\xb7\x25\x4f\x97\x6c\xaa\xbb\x9e\xcc\x8f\x32\x84\xb5\x75\x65\x03\xe6\xb6\x2c\x30\xd4\x4d\xde\x6d\x07\x03\x59\x57\x94\xbd\x85\xa5\x45\x8e\x1c\x33\x0c\xfb\x49\xf7\x08\x63\x00\xf4\xed\xb2\x24\x72\x74\x1e\xf5\x4a\xce\x92\x1f\xf2\xdd\xa3\x47\xbd\x1b\xf6\xf0\x2d\x40\xaa\x00\x17\xbe\xdb\x49\xa7\x25\xf9\xf4\xa3\xd4\x65\x53\xaf\x2c\xee\xdf\xee\x59\x2e\xca\x8b\x9d\xfc\x75\x5b\xf1\xef\xd8\xde\xa3\x1e\x78\x74\x7f\x81\x0e\x16\x54\x39\x58\x7c\x9d\x64\x18\x95\x73\x4d\x9d\x0b\x59\xc1\x04\x46\x74\x72\xe2\x9a\x00\x1f\xa7\xc2\xca\x46\xe1\xf9\xea\xd7\xfa\xd7\xf2\xd7\xfc\xd7\x74\x7d\xbe\x69\xd0\x12\x49\xf2\xa5\x00\xea\x2e\xe3\x2e\x13\x5a\xb2\x6d\xaa\xc9\x46\x23\x46\xb3\x70\x46\xaf\x9a\x01\x5d\x1a\x62\xbb\x13\x01\x31\x04\x43\x22\xad\xfc\xd4\x30\x7c\x66\x31\xab\xd2\x60\x4e\x1f\x3a\x22\x03\x60\x6c\x09\x72\x9b\x20\xd4\x70\x33\xa7\xae\x17\x57\x97\xd9\x22\x43\x01\xb4\x8c\xc5\x9b\xad\x69\x12\x62\xb8\x0b\x4b\xbd\x1c\x9b\x7e\x97\xbe\x37\xf0\xc6\x56\xc1\xd8\x1b\x78\xc4\x84\x85\x89\x28\x98\xa3\x8a\xff\xc8\x53\x6a\x45\x52\x8b\x30\xd5\x5f\x62\xcc\xce\x07\xde\x18\x5b\xbf\x9e\x41\x2a\xf5\x10\x9f\x16\x1b\xc1\x15\x95\xd9\x8d\x9f\x10\x6a\x7d\x08\x31\x81\x3d\x96\x70\xe3\x06\x87\x90\x38\xef\x25\x7b\x04\x56\xd0\x0d\xb4\x79\x38\xfc\x77\xef\x9c\x35\xbe\xff\xd5\x9b\xd7\xb3\x77\xf8\xd8\xb5\x83\x97\xe1\x8c\x24\x61\xa2\x7b\xd2\x6f\xa8\xdc\x51\x08\xd9\x86\x7b\x1a\x78\xde\x07\x6e\x2b\x72\xe8\xcd\x6d\xb5\x0c\x9e\xe4\x66\x2d\xfa\xec\x6c\x23\x3b\x30\x4d\x18\x2f\x23\x94\x48\x9a\x83\x44\xec\x70\x3b\x6e\x99\x24\x41\x5c\x15\x83\x6d\xac\xad\x36\xd7\x1a\xa5\xb3\xb9\x71\x63\x73\x05\x01\x15\x91\x63\xe0\xea\x31\xed\xf1\x29\x80\x45\x0d\x85\xec\x1f\x98\x02\x07\x00\x64\xca\xa3\x30\x5d\x25\x62\x77\xb8\xb8\x42\xf0\xf3\x11\x59\x72\x67\x32\x11\x09\xb8\x99\x6e\x84\xea\x5a\x3f\x16\x4c\x82\x23\xdb\xc1\xe0\xa7\xee\x78\x47\xa3\x6f\xb5\x1d\x26\xf5\xde\xbf\xd7\x2f\xde\xbf\xf7\x9a\x70\xdb\x78\x0e\xdd\xc7\xc3\x81\x21\x09\xe8\x79\x81\x2d\x57\x76\xfb\x24\x00\xeb\x10\x40\x4b\xce\xa7\x3b\x96\x62\x28\x80\x8c\x01\x90\xb5\x83\x65\x29\xe5\x9e\x15\xb2\x6e\x15\xaf\x1d\x93\x99\x81\x37\x56\xc5\xa7\xcf\x83\x86\xf7\x08\xe0\x5c\x65\xb2\x5f\xe8\xe4\xf5\xf2\xf2\x88\xa2\xf0\xfc\xd7\xb2\x79\x69\xdc\xb1\x5d\x1f\x2e\xd2\xe1\xcf\xc1\x41\xaa\x19\xba\x4a\x87\xaf\x6f\x00\x5f\x97\xf0\x54\x82\x0c\x5f\xb4\x62\xf1\x81\xad\x40\xb2\x74\x01\x52\x81\xec\x1d\xdb\xf9\x84\x04\x4c\xb3\x5d\x3c\x04\x97\xb7\x86\xae\x87\x2f\xf9\x58\xbc\x30\x36\x08\xd2\xab\x12\x55\x91\xbc\x2b\x58\xa3\x8a\xa3\xe6\x79\x01\x1b\x7b\xde\x91\x10\x2a\x68\xb3\x3b\xb6\xb3\xcc\x9f\x65\x6e\xce\x66\x71\x77\x8c\xdf\x35\x18\xd1\x4a\x6a\x2d\xb2\xa8\xb5\xc8\x80\x27\xa7\x1e\x70\x25\xe0\xc7\x04\x7d\x21\x93\xa2\x31\xaa\x09\x94\x66\x0f\x86\x77\x8c\x84\x9f\x1c\xc6\xa6\x3d\x0c\x3f\x0e\x23\x00\x6a\x33\x08\xb2\x8c\x03\x3f\x0e\xb9\x14\xa6\x74\xfa\x70\x28\x60\x8b\x22\xea\x79\x2a\x4f\x44\x2c\xd6\x2d\x56\x3e\x2f\x16\x28\x69\x7f\x43\x50\xb7\xf5\x50\x71\x2e\x57\xad\x06\x63\x1b\x39\x0f\xc1\x08\x59\xa2\x64\x19\x4c\x93\x41\x0a\x6b\xa4\xe7\xda\x3d\x3b\x21\x4c\x43\x15\x66\x1d\x53\xb7\xb8\x34\x60\x1a\x4a\x91\xd4\x44\xda\x17\x31\x19\x49\x6a\x76\xc9\xe9\x26\x4c\x97\x62\x00\x01\x64\xd2\x4c\x97\x7c\x3c\x0f\x94\xc4\x5e\x5c\xb4\x97\x7c\xb9\x0d\xd2\x25\x0f\x66\x8b\xad\x7d\xbf\x25\xe2\x72\x1b\xfa\x43\x23\x81\x1a\x8d\x32\x34\x99\xf2\x1d\xe1\xd3\xd2\xc8\x9e\xb4\xe8\xa0\x11\xec\x5c\xbd\xf7\x08\x39\x1c\x9c\x88\x85\xea\x8d\xc3\x26\xdb\x35\xa8\xa7\x42\xcd\x7b\x2a\xc4\x6a\x28\x4e\x1f\x9e\x24\x9a\x1a\x6f\x76\x99\xc0\x32\xd2\x57\xd9\xa6\xe5\x2c\xe5\x08\x17\xcc\x8a\x62\x14\x31\x95\x35\x3a\xb2\xc3\x48\x49\x94\xbf\x99\x4c\x48\x12\xf2\xd5\x66\x4d\xfd\xc4\xd0\xf4\x26\x2c\x6e\x22\x01\x2e\x05\x84\x05\x9a\xaf\xe1\x8c\xd8\xb1\x93\x1a\x9b\x16\x4e\xe6\x84\xa6\xc7\xa3\x43\xbb\x4b\x59\x9c\x11\x12\x36\x68\x6a\xe7\xd0\xae\xdb\xac\xbf\x15\x1d\xd1\x78\xfb\x2c\x75\x0c\x6e\x6b\xbc\x60\xf1\x85\x4b\x08\x38\x56\x27\x7b\x30\x62\x49\x60\x64\xdc\x2f\x42\xc8\x9b\x5e\xd4\xd3\x8a\x71\x2f\x8f\xc1\xd2\x2b\x72\x2f\x50\xd2\x44\x62\x26\xec\x45\xbb\xdb\x72\x00\x09\x7d\x06\x32\xcb\xcf\x40\xa5\xf7\x19\xec\x0a\x96\x0c\x4a\x5e\x65\x7f\xe7\x03\x34\x63\x1f\x60\x1a\xb9\x01\xa4\xa7\x1b\x24\xd1\x0e\x7f\x40\x9a\xa5\xa4\xb8\xcf\xf1\xd7\xed\x1e\xff\x8a\xab\x78\xa0\x33\x33\x0d\x54\x32\xa6\x81\x49\xdc\x34\x30\xc9\x9a\x06\xf1\x96\xe5\x1b\x3e\x90\x79\x1c\xaa\xdb\xe8\x26\xab\x07\xd7\xfc\x11\xfa\xbd\xe6\x8f\xfb\x92\x57\x95\xf8\x71\xbb\x1f\xf0\xb2\x2c\xca\x41\x8c\x69\x5b\x6f\x78\x7e\xeb\x66\xdf\x6c\xab\x34\x5c\xe9\x87\x11\xcf\xb4\xa4\x08\x33\xa4\x92\x40\xc0\x2d\xe3\x2b\xc6\x2a\xd9\x99\x4c\xcf\x11\x91\x56\x5c\xdf\xad\x98\xe0\x89\x14\x22\x66\xc6\x62\xd3\xcd\xa4\xfd\x08\xd2\x83\x43\xda\xa8\x3e\x09\x52\xad\xb3\xc4\x60\x7a\x3b\x1a\x93\x23\xbd\xcd\x5b\x4d\x1a\x0d\xd2\x54\xb7\x20\x26\x97\xe1\xf3\xc9\x68\xb4\x56\x87\xde\xe6\x3d\xad\x74\x9b\x79\x07\x43\xb1\xb4\x3e\xef\x9d\x9d\x79\x72\xf1\x44\x41\x44\x05\x49\x7f\x76\xe6\x89\x29\x48\xfa\x21\x8e\x94\xfa\x87\x26\x82\x94\x58\x9e\x2f\xf2\x29\x78\x94\xfe\xe5\xed\x0f\xdf\x77\x41\xba\x28\xc7\x1a\xbe\xb8\x64\x41\x85\x02\x8f\xbf\x7c\xf7\x6d\x5b\x6b\x4e\x63\x88\x2c\xcf\x0c\x9f\x63\xb4\xe3\xc4\x3a\x3b\x10\xcb\x33\x06\x6f\x85\xaf\x7e\xf8\xee\x47\xd1\x5f\x49\xa3\x30\xc6\xae\xbf\x29\x8b\x9b\xb7\xd0\x1c\x52\x60\xf0\x87\xfa\xfc\xe1\x66\xe7\x11\x19\xa8\x33\x21\x4f\x2a\x23\x8d\xca\x62\x33\x8c\x0e\x87\xa8\x27\xe3\x05\x74\x59\x02\x0c\x6b\x9b\x67\x50\x31\x43\x91\xef\xbd\xc9\xef\xd8\x2e\x4b\x06\xbf\x7c\xf7\x6d\x20\xc8\x3d\x42\x23\x74\xb8\xe0\x51\x78\xfe\xd1\xf4\xec\xe3\x73\x9a\x46\xe1\xb9\xbf\x5a\x8e\xd6\xe4\x7d\xb8\xfa\xdb\x68\x7d\x76\x4e\x37\x51\x78\xfe\x37\x7f\x7a\xb6\x24\xc1\x6a\xf0\x6b\xbd\x3e\xf3\x57\x7f\x13\x3c\xfd\xfa\x8c\x7c\x7c\xbe\xb9\xa1\xdb\x08\x45\x72\x2c\x2a\x6e\xeb\x03\xdb\xef\xc5\xbf\x49\x55\x17\x25\xdb\xf0\xc3\x74\x3c\x01\x60\xae\xb2\x22\x3f\xa4\xd9\x8e\x1f\x4a\x5e\x1d\xee\xb3\x64\xc3\x6b\x12\x7c\x7c\x4e\x33\xd9\xfc\x4f\x5f\xbf\x3b\xfc\xf9\xeb\xcf\xbf\x22\x1f\x9f\xd3\x2b\x51\xf6\xeb\xf9\xaf\xe7\xe7\xf4\x1a\x5e\xaf\x7e\xbd\x9f\x8e\x27\xeb\x71\x40\xfc\x65\x20\x5e\x40\x72\x98\x5f\xcf\x97\x1f\xad\xcf\xfe\x7f\x07\xe2\xe3\xef\x60\x7d\x26\xde\x07\xfe\xaf\xc9\x98\x1c\xc8\x81\x9c\xd3\x5d\x14\x3e\x1d\xe9\x0d\xfc\x9f\x47\xa1\x77\x76\xee\x29\x1b\x7c\xef\xcc\x23\xb4\x88\x42\x36\xdd\x15\x31\x18\xd0\x80\x14\x88\xee\xa3\xf0\x3a\x42\x5b\xe4\xa2\x21\x95\x44\x56\x41\x5b\x64\xfe\x16\x59\xe0\xe3\x2a\xb0\x7a\x32\x63\x45\x54\x8c\xc1\x43\x10\xd5\x62\x70\xf7\x23\x2e\x5f\xd2\xe4\x8e\x63\xa2\x38\x47\x25\x13\xf7\xc6\x60\x27\xbb\x9a\xad\x97\xbe\x60\x1b\x55\xe8\x18\x48\x1b\x41\x51\x08\xce\xc0\xc2\x79\xb5\x26\xda\x96\x2a\x26\x24\x68\xbe\x83\x4b\x36\xb6\x6d\x6d\xcb\xa8\x69\x17\x03\xfe\xb3\x82\xf3\xb8\x89\xec\x48\x5d\x5b\x7c\x9f\x69\x7f\xd8\xd5\x76\x8d\x56\x02\x70\x1d\x30\xf0\x3a\x5f\x39\xea\x73\xd9\xe4\x2a\xdc\x4a\x7b\x9a\x3e\x6b\x93\xab\xc3\x21\x3d\x1c\xf8\xea\x6a\xbd\x4c\x97\x43\x3f\x0b\xaf\x94\xf3\x70\xe0\x47\x90\x3e\x5d\xd0\xe6\x95\x9e\xda\x15\xa1\x1b\xf1\xdf\x70\x2e\x2e\xa4\x4c\xd3\x0c\x76\xe5\xd5\x6c\x4d\x0e\x87\x21\x07\xbb\xb6\xd1\x68\x03\xd0\x60\xe6\x5d\x45\x4d\x92\x22\x9f\xb2\x2b\xf6\xf0\x96\xd7\x75\x96\x6f\xaa\x69\xba\x63\xb5\xb4\xf7\x84\x74\xf8\xda\xae\x37\x22\x86\x94\x5e\xc5\xeb\xd1\xc8\xf7\xf9\x2a\x5e\x2f\x59\x90\x1c\x0e\x7e\x12\x3e\x1d\x09\x59\xc5\x6b\x78\x69\x22\xef\x58\xa1\xba\x86\x33\xca\x68\xe2\x24\x77\xa9\xa3\xde\x54\x18\x28\xa8\xab\x20\x94\x83\x9e\x9c\xa4\x6c\xbc\x33\x01\x18\x99\x98\x6a\x36\xc5\xa5\xb1\x14\x4b\x89\x8c\x3a\x79\x93\xdd\xc8\x30\xd6\x80\x56\x7e\xe2\xd5\xbe\xc8\x2b\xfe\x67\xce\x12\x5e\xfa\x9e\x0c\x24\x3a\x79\x87\x49\x6d\x04\x3c\x26\x44\xdb\xd4\x6c\x05\x41\xb9\x05\xb3\x1a\xf1\x3f\x8a\x56\x13\x41\xcc\xe9\xdd\xe0\x64\x11\x95\x9c\x5d\x1f\xb3\xd4\x17\x63\xc9\xf2\x41\x4c\x52\x18\x16\x5a\xc2\xeb\xce\x62\xd4\xb7\x64\x32\x63\x4f\x5c\xe4\x77\xbc\xac\x79\x59\xad\x80\x95\x1c\x8b\x17\x6b\xf2\x94\x86\x5c\xf6\xb8\x81\x28\x85\x9c\x1c\xd1\xff\x49\x6d\x74\xba\xf4\xd3\x21\x4e\x7c\x34\x32\x03\x49\x09\x8d\x57\xa9\x71\x3c\xd7\xcb\x7b\xdb\x04\x72\x2b\x86\xef\xd3\x91\x5e\xdb\x4b\x2b\x4f\x17\xac\xc3\xf5\x6a\xbe\x26\x26\xb9\x9d\x35\x60\x72\xb5\xda\x34\x05\xa3\xce\x84\x36\xeb\x45\x1a\x5e\xab\x4d\x91\xfb\x95\x8a\xc5\x84\x6c\xb7\xb0\x03\xdf\x64\x7c\x97\x54\xab\x54\xc0\x50\xbc\xea\x28\x5f\x87\x11\x81\xfc\x1e\x90\x4d\x55\x0c\xf1\x1b\x30\x8c\x03\xc9\xbd\x5d\x00\xc9\x11\xd5\x14\x08\x98\x7d\x53\xeb\xf3\x90\x8c\x03\x60\x25\x15\x1b\xa3\xf3\x6c\x78\x67\x9e\x58\x46\xe4\x0d\x52\xd8\x9c\x4d\x78\xb5\xca\x60\x33\xd2\xf5\xe1\x70\xb5\xf2\xce\xe0\x27\x1d\x6e\x88\x95\x96\x47\xc0\x44\xc8\x6d\xca\x69\xbb\x9a\xaf\x65\x14\x0f\xd3\xc5\x56\xec\xa7\xee\x05\x9e\x08\x79\xda\x80\x61\xe2\x72\x03\x29\x7d\x02\xf1\x1f\xe4\xe9\x87\xe4\x41\xa2\x0e\xbd\xd6\x3b\x2a\x7a\x25\x16\x78\x6d\xa0\x26\x41\xef\x38\xb6\xf2\xea\x6d\x59\xdc\x57\xde\x9a\x44\xe1\xc6\x8f\xa4\x3d\x98\xb8\x8f\xf1\x59\x5e\xb2\x3b\x1d\x2a\xb2\xaa\x05\x4d\xe2\x5c\xa3\x14\xfe\x04\x9b\xe5\x2e\xf0\xbe\x2f\x06\xb8\x85\xe2\x2e\x1b\xa4\x65\x71\x23\x80\x72\xec\x0d\xea\x42\xac\xc2\xf1\x78\x74\xfb\xa9\x6e\xc1\x85\xc3\xa3\x62\xe9\x83\xe8\x68\x05\xbb\x61\x71\x9d\xdd\xf1\x60\x46\x77\xac\xaa\xbf\x2b\x92\x2c\xcd\x78\x12\x3c\x1d\x29\xaf\xd9\x46\xfc\xb5\x91\x4d\xf0\x74\x5b\xee\x82\x22\xa2\xa0\xa5\xf4\xfe\xf4\xf5\x3b\x8f\x66\xd5\xb7\x45\xcc\x76\xc1\x36\x92\xf1\x9f\x23\xb1\x16\x14\xe3\x00\x07\xc3\x19\xdd\x97\x85\xf8\x38\x64\xcf\x10\x28\xa5\x7a\xcc\x63\xf1\x43\x62\x0c\xcc\x3d\xcd\xf6\xfb\x5d\x86\x77\xdf\xf9\xc3\xe4\xfe\xfe\x7e\x92\x16\xe5\xcd\xe4\xb6\xdc\xf1\x3c\x2e\x12\x9e\x2c\x20\xcb\x7e\xc5\xeb\xf0\xe7\x77\xdf\x4c\xfe\xe8\x51\x4c\x9d\x51\x05\xe0\x30\x99\x47\x14\x12\x4f\x20\xe1\xb2\xdf\xb1\x2c\xf7\x30\x50\x3b\x96\x88\x9f\x1e\x7d\x10\xcf\xce\x97\x6e\x76\x74\xa0\x69\x1d\x7a\x55\x41\x8c\x36\xab\x82\x28\x91\x35\xae\xd8\x1d\x93\x91\x9a\x8f\x6a\xec\x55\xf0\x24\xfa\x14\xad\xcf\xf1\x73\xf0\xa5\x73\xec\x09\x5a\x9f\x1f\xa9\x7b\x5c\xb0\x89\xa7\x0a\x7f\xf9\xee\x5b\x4f\x8e\x5d\x15\xbd\xe3\x0f\xb5\x1a\x8c\x2a\x13\x24\x21\x7e\x57\x1e\x5c\x31\x6f\x18\x98\x17\x20\xd9\x86\x44\xdb\x00\x66\x2a\x96\x17\x1f\x45\x2f\x5e\x60\xd1\x9b\xb2\x5c\xcc\x37\x30\x54\xe5\x91\x5a\xd7\x08\xee\xb2\xda\xa1\x87\x3a\x18\x0a\x96\x4d\xc2\xc1\x6d\x8f\xfa\x32\x5a\x56\x91\x0f\x97\x95\x7b\x3f\x09\xd6\x2f\xa8\x22\xdf\x2d\xa5\x82\x25\x10\x05\x3f\x6a\x6b\xeb\xdf\x22\x7f\x17\x11\x28\x7c\x57\xb2\xbc\xda\x17\x65\x2d\x0a\x6f\x64\x61\xe3\xb3\x6d\x7b\x6a\x44\x36\xb6\x15\x68\x18\xc1\x8d\xd8\x91\x23\x8c\x5e\x9b\x6b\xf4\x76\x2f\x3d\x2f\x76\xe1\xf5\x54\x4e\xf9\x70\xb8\xa6\x37\xe6\x71\x34\xf2\x77\x56\x96\x85\xdd\xf4\x0a\x72\x63\x91\x65\xee\xef\x74\x2e\x6e\x5a\x38\x4e\x2f\x74\x1f\xe6\xd3\x2f\xd9\x6e\x17\xb1\xf8\xba\xf2\xbd\x22\x8f\xf9\xe0\x86\xdf\x14\xe5\xa3\x47\xe8\x6f\x02\xe9\xd5\xac\xbe\xad\xbe\x2c\x12\x0e\xb1\xf4\x4b\x81\xe2\x2b\xf1\x5f\x1d\xce\xe8\x6d\xe8\xc5\x2c\x8f\xf9\x8e\x27\x1e\xbd\x0b\x9f\x4a\xce\x92\xc7\xb7\x70\x9c\x67\xb4\x75\x3b\x76\xf8\xbe\x67\xa9\x7f\x11\x86\x61\x8d\x57\x19\xb8\xe6\x3e\x1d\xb5\x70\x79\x13\x69\x1f\xb7\x74\x15\xb5\xb3\x02\x84\xd1\xea\x62\x7d\x8c\xc2\x74\xc5\x1a\x6f\x8e\x0e\x3b\x1e\xa1\xd8\x27\x3a\x8a\x31\x7d\xbe\xdb\xb9\xc3\xaa\x3a\x22\x6a\xc0\xa0\x96\x3c\x40\x5b\xaf\x4a\xcc\xe4\xb7\x5b\x5e\xd5\xad\x89\xd8\x39\xcd\xdc\xac\x60\x8a\x9f\x3b\x1c\x7c\x16\x56\x82\x86\xc1\x84\x04\x8c\x96\x2b\x06\x77\x11\x2a\x18\x04\xcb\x5a\x66\x09\xff\x4e\x12\x16\x9d\x1a\x73\x90\x34\x29\xd2\x23\x64\xaa\xad\xd9\x9c\xee\xb5\x05\xe7\xae\x8b\xcb\x9a\x68\xdf\x34\x46\x7e\x13\x4c\xf8\xea\x37\x30\xe9\x5b\x45\x6b\xa4\x2a\x06\x77\xca\x1d\x82\xad\xee\xe4\x9e\x37\xd2\x82\x52\x16\x09\x60\xef\xd0\xdb\x1e\x0e\xb7\x5a\xbc\x33\x1a\xc5\x53\xa8\xe8\x47\x84\x3e\xf8\x33\x95\x82\xfc\x78\x14\xe3\x29\xb4\x77\xd1\x1d\x31\x76\xf2\xfb\x29\x4b\x12\x7a\x37\x95\x17\x40\x78\x87\x2e\x1c\x77\xc8\x87\x85\x77\xe0\xaf\x21\xee\xb1\x72\x17\xfa\x3e\x3b\x1c\xe0\xe7\xe1\x50\x44\x44\x30\x9e\x5a\x8a\xc9\x41\x8a\xa9\x1f\xaf\x22\x0a\x68\x7e\xec\x9d\x9f\x43\x48\x2a\xcc\x11\x38\xbd\xe1\xf5\xb6\x48\x04\xfd\x86\xa2\xc1\x6b\x5d\x82\x55\xe8\xb5\xa1\x5f\x94\x36\xd0\x14\x61\x76\xb9\x7e\x16\xc4\xf3\xd6\x52\xa2\x7d\x3d\x8d\xcb\xa2\xaa\xbe\x2a\x6e\x58\x96\x43\x9c\x7d\xc5\x27\xc1\xf8\x1b\xac\x12\x75\xaa\x87\x43\x7f\xb8\x3d\x1c\x24\x1d\x00\xd3\x10\x24\xe3\x85\x7c\xba\x10\x44\xce\x16\x1d\xe7\xbd\x6d\x5d\xef\x03\x41\x8e\x88\xda\x4b\xef\x8f\x33\x2f\xf0\x3e\xfd\xf4\x95\x47\x08\x78\x7d\x46\xcd\x6a\xd0\x9b\x53\x0f\xbe\x2e\x26\x38\x1a\x5d\x4f\xad\x9b\xd0\x68\xae\x34\x73\xa1\xea\xc9\x15\x09\x01\x3b\x33\xb5\x40\x62\x91\x4b\x96\x40\x1c\x51\xb6\x23\x84\x96\x02\x5f\xd2\x6b\x1a\xd1\x3b\x42\xf1\xa4\xab\x68\x39\x8b\x4c\x25\xa2\x12\x5f\xc5\x9b\x98\x66\x18\x23\x2a\x9f\xe2\x8d\x3f\x1e\x03\xa5\xef\x64\x65\xf5\x00\x23\xd6\xac\xac\xcd\xa6\xe2\x1f\x37\x2a\x28\xbd\x06\x9d\x94\x4c\xc4\x32\xcc\xe4\xcd\x8f\x55\x09\x4d\x42\xd8\x05\xa7\x16\x9c\x32\x39\x3f\xf9\x7e\x1c\xfa\x49\xa4\xe8\xf4\xa5\x37\xf2\x02\x6f\xe9\x91\xb1\x9c\xae\x34\x5a\xc1\x27\xd8\x42\x16\x6f\xb9\x4a\x85\x8b\x10\x9b\x9a\xe6\x46\x47\x99\x46\xd4\xfb\x78\xfe\x3e\xf4\xc6\x71\x34\x1e\x93\x20\x19\x77\x7e\xc6\xd3\x35\x44\xe7\x59\xaa\x48\x1f\xc8\x61\x62\xd3\x42\xab\x64\x3d\x1a\xdd\x4d\x9b\x88\xca\xf7\xde\xa4\x13\x55\x67\xf2\x36\xcb\x63\xee\xd1\x56\x4b\x90\x42\xd6\x6c\x73\xaa\x93\xef\x8b\x9c\x4f\xbe\x13\x60\xee\x99\xda\x84\x50\xdf\x00\x8e\x59\x47\xf1\x64\x11\x4e\x43\x4c\x24\x1c\xd9\x65\xa4\xfb\x4b\x0e\xfb\x44\x9d\x5e\x08\xed\x6a\xf0\x39\x10\x58\x9e\x7d\x66\x81\x8f\xb9\x96\x59\xcb\xaa\x95\xfb\x66\xbd\xec\x7d\x33\x96\x14\xbc\x5b\xbc\xf4\xe8\xc0\x1b\xe7\xd1\xd8\x5b\x0c\x7e\x0b\x67\xd3\xd9\xdc\x0b\x3c\x8f\x04\xa6\x1b\x70\xf5\x02\x8e\xf6\x4a\x60\xd8\xeb\xe9\x16\xaf\x15\xd2\x31\xde\x2b\xaa\x5f\xaf\xae\x30\xdb\xe1\xf5\x14\x13\x43\xbc\xe5\x79\x82\x61\x40\xf5\x23\xea\xcd\x76\xf4\x8e\x5e\x13\x99\x8d\x19\xcf\x90\x3e\x44\x12\xd7\x92\xc5\x6d\xe8\xc1\x4f\x4f\x0f\xe4\x49\xa2\xd3\x60\x2e\x89\xf2\x39\xd5\xbe\x5b\xf3\x23\xb9\x5b\x5d\xad\xfd\x6b\x35\x88\x38\x2c\x05\x11\x23\x4f\x2a\x79\xba\x9b\x9a\xab\x3c\x9c\x43\x8a\xba\xc6\x01\x84\x04\x17\xab\x3b\x7a\xbd\x16\xa0\x09\xf4\xb2\x58\xf5\x1a\x8d\x8b\x2f\x67\xc0\xba\x74\x47\xa7\x50\xa3\xf6\x64\x65\x8f\x1c\xa9\x6e\x49\x30\x9d\x4f\x1d\xce\x69\x3c\xad\x04\xf5\x5f\xd2\x07\xc5\x7b\xdc\x23\x9d\x00\x57\x1a\x01\x76\x65\x70\xbf\x78\xf0\x27\x73\x7a\x4f\x8e\xe8\x06\x0c\x4f\x82\xf7\xd0\xf4\x99\x67\xc5\xa3\x7a\xc0\x30\xad\x5a\x98\x42\x4b\x5a\xd1\x5b\x7a\x4f\x1f\xc2\x68\x71\x31\x0c\x43\x41\x45\xd5\xe1\x05\xdd\x8c\x46\x8e\xb1\xf4\x86\xe8\x1c\xe9\x94\x43\x84\x10\x8f\x3a\x8b\xc4\x2e\x67\xcb\x4f\x83\x19\xbd\x0a\xd9\x65\x78\x31\x9b\x8d\x46\xaf\x66\xb3\x4b\x76\x38\xbc\x9a\x7d\x1a\x86\x21\x03\x0b\xb1\xdb\xb0\x8e\xfc\x6b\x7a\x47\x53\x42\xe8\x6d\x78\x2b\x1e\x6e\xe9\x1d\xbd\x22\xf4\x6a\xe9\x37\x4e\xf8\x7d\x78\xd7\x25\x61\xf8\x96\x55\xb5\x3e\xd3\x1e\xa1\xf7\x5d\xc8\x20\xbc\x27\xb4\xa7\xbd\x38\xbb\xba\x99\x3c\xc8\xe1\x3d\x21\xf4\x02\x07\x7a\x38\x78\x7f\xfe\xfa\xf3\xaf\x20\x6e\x02\xe0\xca\xe5\x43\xe8\xe5\x85\x0a\x22\x1b\xc8\xf9\x60\x69\x7d\xa3\x06\x12\xf8\x0f\xe1\x2d\x50\x0e\x9c\x96\xe1\x2d\xe2\xc7\x2a\xbc\xc5\x4b\x9c\x5e\x85\xc3\x8a\x90\xc0\xaf\xc2\x07\x2a\xae\xf0\xe1\x03\x19\x8d\xfc\x87\xd0\x93\x7c\xe3\xec\x12\x52\x12\x85\x33\x71\x19\x29\x0a\x24\x64\xfa\x27\x04\x31\xf7\xa3\xc3\xe1\x41\xdc\xf9\xf4\x6a\x59\x38\xde\xb1\x3b\xba\x2a\xe9\x03\xbd\x5b\x93\xa0\xb0\xfd\x63\x77\x02\x44\x1f\x68\xb5\x36\x9d\x0a\x6a\xc9\xff\x4d\x10\xb7\x72\x3b\x1d\xe0\xbe\x5a\x22\x78\x4b\x5e\x34\x80\xa7\xaf\x71\x8c\x02\xda\xe9\xd5\xb2\x0c\x44\x77\x7b\x08\x8a\x61\x7d\x64\x0d\x99\x1c\xfd\xc6\x39\xf9\x52\x1e\x39\x7d\x56\x26\x13\x75\xb9\x1d\x0e\x3d\x57\x5b\xb1\xb7\x53\xcf\xdc\x01\xd5\x2a\xb8\xa2\x3e\xf1\x7f\xae\xec\xff\x68\x4c\x3d\xe0\xa5\x08\xb4\x79\x0b\x8c\x60\x9f\x5a\x0c\xdb\xc8\x35\x88\x4c\x82\x1f\x47\x0d\xb7\xe1\xb5\x47\xbd\x7d\x51\xd5\xed\xa0\x90\x4d\x65\x8e\xeb\xbc\xe3\x0a\x61\x41\x63\xcf\x0f\x87\x84\x26\x61\xac\x4f\x12\x91\x6c\x98\x0f\xbc\x1c\x43\x86\x3d\xa2\x0a\xfd\x06\x1c\x45\x01\x31\x55\xa8\x2c\x51\x96\xa0\x2a\xa5\x4f\xa7\x0a\xae\xdd\x27\x0a\x01\x74\xbf\x6a\xae\x8a\xcd\x9f\x6b\x41\xc0\x9c\x2a\x29\x88\xe0\x27\x49\xc3\xdb\xf2\xbe\x64\xfb\xcf\x77\x1d\x26\x15\x8b\xae\x59\x33\xb2\x3c\x6d\x91\x25\xbb\x73\xad\xb1\x08\x39\x12\xcc\xaa\x01\xf7\x18\xe8\x78\x7b\x52\x46\x91\x29\xff\xcd\x9f\x11\x2b\x7d\x8f\xaa\xe6\x5a\x4c\x3a\x69\xff\x64\x15\x42\xa3\x66\x3a\x39\xf4\xfe\x00\x3f\x75\x64\xc0\x18\xa6\xa1\x92\x9a\x13\x4c\x8d\xc8\xc2\x8e\x52\x13\x9f\x58\xe7\x45\xab\x31\x07\x99\x0c\x4a\x27\x66\xfa\x26\xcf\xf9\x33\x6e\x0c\xbd\x96\x4e\x8d\x45\x83\xae\x5a\xcb\xd6\xca\xa1\xa0\xad\x97\xe2\x50\xd3\x1e\x95\x6f\x5c\x95\x96\xb1\xd9\x02\x12\x44\x56\x4a\x37\x39\xe4\x4e\xf3\x06\x67\x88\x8b\x93\x59\xc4\x9a\x1b\x1d\xb9\xa6\x30\x24\xc0\x4f\xdd\xe6\xee\xc7\xdc\x95\xc1\xbd\xec\xc8\x2e\x6a\x99\x09\xa0\x29\x13\xe6\x61\x3f\x1c\x8c\xc5\x9f\x4e\x24\x25\xcd\xaa\x4c\xe6\xdc\xa3\x74\xfa\x55\x46\x1e\xfb\x52\xba\x09\x57\x2a\x5a\x4a\xa7\xa1\xb0\x15\xba\xf5\x75\x38\x1b\x8d\xdc\x80\xea\xaf\x43\xf0\x75\x72\x7a\x83\x14\x02\x3b\xde\xd1\xdd\xb0\xf3\xbb\x62\xf9\x41\x18\x72\x17\x85\xe7\xff\x7c\x31\x3b\xdf\xd0\xfb\x28\x3c\xff\x75\xf5\xeb\xfa\xe3\x73\xfa\x00\x66\x4e\xcb\x5f\xf3\xf3\x0d\x7d\x94\x9a\x30\x54\x51\x4b\x63\xf6\x43\x76\xc3\x36\xa0\x34\xe3\x35\xe8\xcf\xc8\xc7\xe7\x19\xfd\x7b\x74\xca\x0c\xfe\x9a\x3f\x6e\x78\x4e\xce\x33\x43\x27\x7c\xde\x94\x71\xb7\x02\x87\x4a\x14\xe9\x78\x62\x71\xf2\x14\x1f\x0e\xf7\x91\x8a\x6b\xba\x4c\x7c\x46\x39\x09\x44\x6f\x63\x6f\xe5\x8d\xfd\x96\x40\x88\x2f\x23\x41\x4e\x8e\xbd\xb5\x47\x39\x2a\x7c\xad\xcc\xcd\x87\x83\x6a\x30\xd4\x59\x9f\x23\x42\x12\xc0\xc0\x0d\x7f\xdd\x88\xe8\xcf\x70\xe8\x2e\x5a\xf1\x35\xf6\x28\x99\xb4\xb0\xd3\xfe\x03\x73\x86\x35\xc2\x08\x84\x0d\x27\xfd\x65\xe4\x2b\xf3\xa0\x68\xe9\x79\x02\x49\xaf\x94\xe9\xcc\x3a\x44\xe9\xe7\xcf\x3f\xbd\x11\xb7\x5d\x91\x43\x96\x3b\x32\xf6\x42\x6f\xdc\xf1\x26\x22\x47\x27\x9d\x64\x24\x2d\xe7\x6d\xc9\x9b\xe0\xfa\x1c\xfd\x91\xcd\x55\x5a\xe1\x68\x18\x18\xa3\xa3\x9c\x4b\x46\x16\xf8\x71\xc7\xb2\x5c\x3b\xa1\xab\x6d\x72\x82\x0b\xe3\x79\x99\xe6\xec\x86\x53\x63\xa7\xa5\x17\xde\x0a\x8d\xf3\x79\xe4\xc7\x14\x42\xe0\x88\xcd\x35\x51\x0a\xae\x8a\x2c\xf7\xbd\x91\x25\x6c\xb8\x8b\xa8\x37\xf6\x9a\x17\x46\xc5\xcb\x8c\xed\xb2\xbf\x77\x66\x85\x91\x9c\x33\xc6\xb7\x54\x15\x71\x5e\x84\x1c\xa9\x5b\xd4\x87\x1d\x3a\x71\xb8\x74\xbd\x42\xac\xc0\xa5\xe2\xdb\x18\x61\xb1\xa5\x6d\xe4\x23\x6d\x4d\x8f\x44\xc5\x09\xe8\xbc\x12\x00\xf6\x1c\x6c\x97\x83\x79\xe6\x50\x21\x9b\xac\xf2\xbd\xc0\x58\x37\x8d\x46\x7f\x97\xc7\xc0\xb1\xaa\x23\xa3\xd1\xf0\x31\x32\x29\x40\x15\x5e\x92\x59\xe6\x87\x2a\x7b\xbe\xb8\x05\xdd\xb9\xd9\xfe\xc3\xb6\x05\xa1\x1b\x3e\x33\x46\x49\x9f\x81\x90\x18\xf2\xfb\xb3\xbd\x1f\x77\x18\x0a\x3e\x89\x39\x04\x11\x42\x02\x00\x41\x60\x92\x8c\x3e\x44\xd4\xfb\xb5\xfc\x35\x07\x8a\x28\xe8\xa8\x1a\x77\x57\xc5\x4c\x79\x88\x57\x1d\x18\x7e\xd8\x96\xb6\x2f\xa6\xe0\x72\xac\x80\xb8\xbf\x7c\xf7\xed\x9f\xeb\x7a\x2f\xd9\x45\xc9\xef\x30\xf2\x74\x44\x6c\xf8\x45\x14\xce\xe8\x97\xa0\x97\xff\x2a\x0a\x9f\x66\xe0\x64\x3a\xbf\xb8\x78\x15\x5c\xcc\x3e\x3d\xd2\xaf\x9b\x27\x48\x7c\xcd\x27\x0b\x36\x65\x75\xcd\xe2\xed\xd7\x28\x67\x71\x1e\x7d\xaf\xc8\xd1\x8e\xc8\xb3\x4f\x87\xce\x85\x2b\x8e\xc0\x97\x11\xf9\x32\x5a\xb1\x35\x44\xc3\x12\xec\x78\x59\x85\xc3\xe1\xd7\xd1\x68\xe4\xdd\x67\xf5\xf6\xcb\x92\x27\x3c\xaf\x33\xb6\xab\xbc\x2c\x1f\x7c\x1d\x09\x56\xf0\x8a\x3d\x84\x5f\x47\x50\x4d\x2e\x81\x66\xc5\xfc\x5e\xca\x09\xfb\x3e\x1c\x44\xd7\x43\x66\x8b\xc2\x96\x4f\x95\x93\x35\xda\xd6\x3b\x86\x0c\xe7\x49\x37\xe1\x78\xfc\x45\x84\xe9\xc0\x8a\xbd\xb8\x45\x50\x94\xc7\x40\xc6\xc3\x90\x3f\x15\x4f\x15\x2f\x61\x0b\xd9\x74\xcf\xaa\xea\xbe\x28\x13\x42\xa1\x13\xd4\x7b\x18\xb5\x9c\x53\xb8\xe2\xeb\xd0\x2a\x58\xf1\xf5\xc2\x68\x82\x47\xa3\x74\xda\x14\xe2\x76\x95\xf9\xa6\x89\xf8\xa6\x35\xc5\xc3\x21\x5e\x79\xbf\x4c\xe4\xde\xf3\x64\x02\xb9\x1f\x21\xa0\x7e\x57\x79\xe8\xb9\xc0\x22\x23\xcb\x48\xa5\x70\xda\x96\x3a\x70\x1a\x43\xac\x86\xa8\xeb\x52\xb7\xb6\x5e\xa0\x62\x29\xd2\xfa\x12\x02\x5d\x47\x61\x3a\x2d\x00\x44\xe0\x07\xca\x63\xc1\x98\x49\x4a\x1b\x80\x13\x4c\x95\x14\x22\x90\xdc\x1c\x94\x26\x90\x99\x4d\x70\x5c\x34\xb5\x98\x38\x12\x24\xfe\x57\xd1\x4a\x15\xad\x0f\x87\xce\x6a\x6d\x7b\xd5\x74\x6a\xab\x9e\x96\x32\x87\xbb\x53\x78\x94\xba\x6a\x9a\x4e\x3b\x05\xfd\x3e\x01\x33\x53\x3d\xa7\xc8\x27\xd4\xcc\x2b\xf2\xe5\xf0\x09\x8d\x42\x98\xbf\x28\xc2\x79\xca\x1c\xc3\x28\x90\x60\x8e\xa8\x0b\x55\xc5\x18\xe2\x42\xc9\x29\xb6\x32\xf5\x06\x8a\x28\xb6\xc7\x96\xf0\x1c\xd6\x3a\x12\x68\xc2\x8e\xeb\x6e\xe9\x7a\xb4\xe2\x10\x59\x15\xa9\x21\x34\xea\x3d\x3a\x70\x34\x80\x3d\xe5\x3c\xbe\xe9\x2c\x7f\x98\x98\x37\x8e\xa2\x50\x7e\xed\xdc\x5f\x06\xa2\xcf\x83\xa8\x46\xb0\xf0\xbc\xa1\xd8\x03\x0d\x9d\xec\xa2\x8b\xac\x77\xb2\xac\x32\x42\xd9\xd1\xe0\x44\xad\x50\xf3\x35\x2b\xe6\x60\x06\x9d\x6a\x1a\x05\xaa\xe0\xf1\x89\xa2\x55\x74\x4f\x75\x05\xeb\xca\x7f\x5b\x30\x79\x44\x7f\xc3\x20\x9d\xce\x6f\x80\xed\x80\xd5\x8f\xb1\x53\x53\x5a\x69\x07\xeb\x00\x6f\x2b\x38\x0a\xef\x35\xf6\x76\xe9\x11\xbc\x65\x9f\x8c\xae\x18\x75\xbf\x01\x9b\x62\x95\x2f\xf1\x99\x56\x65\x1c\x00\x22\x3a\x92\x69\x91\xfb\x1e\x98\x6e\x4a\xb9\x47\xec\x1c\xc9\x48\x27\x5d\xa6\x31\x9e\x33\x36\x1a\x71\xdf\x3a\x56\x28\x91\xf9\x74\xf6\x29\x5c\x00\xf8\x88\x91\x0a\xb7\x9c\xb9\xc9\xd2\x22\xc1\xe6\x75\x40\x5e\x3c\x1a\xc5\x02\xf2\x94\xe9\xdf\x37\x91\x20\x01\xff\x14\x85\xe7\x7e\x48\x7e\x5d\xfa\xcb\x70\x74\xf8\x98\x1c\x7e\x5d\xa2\x11\xa0\x05\x94\x57\x55\x91\xef\x03\x2f\x96\xfa\x42\x54\xff\xee\x95\xfa\xb0\x1d\xe0\xfc\x9b\x08\x63\x36\x80\xa4\x03\xe2\xfb\x15\x63\xef\x3d\x4a\xb4\x6d\x5a\x62\xc5\xc0\xf8\x89\x75\x02\x88\xf8\x06\x68\x88\xf7\x9e\x13\xf5\xa0\x99\xca\x23\x9a\x42\x25\x15\xf0\xe5\x4f\x92\xca\x88\xc4\xc2\x93\xa5\x77\x5b\xee\xbc\xa0\x85\x54\x22\x29\xbd\x1e\xfa\x8e\x74\x1a\x3d\x9e\xb4\xab\xd1\xb3\x7a\x7f\x41\xef\x98\x0f\x82\x32\x60\x34\xf2\xc4\x5f\x43\x75\x6d\x0f\x07\x0f\xa7\x01\xe9\xc8\x1d\x19\xb3\xcf\xd5\xf0\xd5\x62\x36\x08\x70\xf7\x25\x59\x36\x0a\x7c\xc1\xbe\x3a\x25\x74\xbb\x8c\x56\xdb\x75\x28\xfe\xd3\x74\xca\x9f\x40\xeb\xe0\x8d\xb9\xae\xae\x56\x2b\x6a\xe8\x3a\xd4\xaa\x29\x45\x84\xac\x8e\x34\x3d\x24\x9a\x35\xc6\x39\xf2\x78\xa1\x16\x7f\x1d\xb6\x09\x55\x48\x9e\x8a\x36\x95\x7c\xec\x0d\xee\x59\x35\xc8\x8b\x7a\x20\xc0\x08\x24\x98\x9b\xd5\x6c\x7d\xa4\xee\x92\x84\x28\xc8\x82\x20\x93\x7c\x4d\xc5\x7f\x76\xcf\x1b\x63\xef\x7a\xa4\x49\x47\xe8\x46\x6c\x00\x3c\x10\x4c\xcf\x5d\xdc\xb8\xb1\x58\x02\x50\x6f\xab\xad\xcf\x89\xcc\x7d\x6d\xad\x7d\x4a\x46\xa3\xd4\xdf\x80\xcc\x64\x13\xa6\x26\xb0\xb2\x96\x98\xd9\x28\x1c\x6c\x15\x20\x8f\x65\x53\x58\xf7\x32\xf3\xd7\x4e\xff\x31\x69\x09\x29\x70\x1f\x98\x0b\xec\xd0\x1e\x32\xbc\x53\xa9\xf3\x29\x0f\x87\xf1\x68\xb4\x5a\x9b\xdc\x74\xab\xa8\x11\xfa\x22\x59\xcd\xd7\x64\x1d\x40\xac\x4f\x37\x23\xf9\x8a\x21\x7f\x83\x01\x89\x54\x7a\xf1\xdc\xe7\xc4\xa0\x23\x95\x0e\x7c\xb5\xa6\x89\x2d\x47\x90\xcc\xfa\x9f\xc1\xf1\x23\x9f\x0a\xd4\xb6\xd0\xbf\xba\xd6\xa0\x2b\x38\xd6\x9f\x23\xb5\x06\x7f\x8e\xba\xe3\xfa\x2c\x6c\x7f\x6d\x78\xb7\x0d\x99\xed\x0b\x68\x8e\xd9\x65\x08\x1e\x9d\x4a\x73\xcb\xa4\x09\xda\x96\x10\x0a\xe1\xf8\xe0\x69\x06\x89\x7b\x9a\x4c\xae\x5c\x67\x29\x9c\x0c\xa2\x8e\x80\x78\x10\xd6\x3a\xf4\x7e\xfc\xe1\xed\x3b\x01\xb9\xda\x5c\x5d\x71\xac\x8e\xd8\x91\x5b\x22\x47\x34\xee\x91\xa6\x4d\xa4\x11\x57\x96\x91\xa7\xd4\x40\x34\xdd\x60\x62\xf9\x64\x29\xae\x9b\x24\xbb\x13\x77\x8d\x14\x4e\x59\x10\x26\xb8\x24\x70\xb6\xf1\x13\x94\x24\x69\x8d\xba\x1f\x8f\x46\x2e\xe3\xb4\x41\x36\x38\xa6\xe9\xe1\x60\xd9\xc6\x01\xa5\x15\x51\xb6\x16\x57\x08\x6a\xf9\xb5\xe8\xd7\xa8\x59\xa9\x91\x4b\xd3\x86\x50\xdb\x16\x8f\x3b\x82\x73\x6a\xb4\x44\xed\x6c\x42\x4d\x47\x80\x2e\xe3\xf7\x2e\xc9\x94\x8c\x78\x94\x74\x4b\x7d\x37\x25\xdf\xfb\x3a\x1c\x97\x2d\x3b\xd4\x51\x76\x04\xe2\xc5\x58\xae\x72\xe3\x10\x7a\xdf\x80\xfd\x9f\xce\x49\xed\x66\x25\x36\x42\xa1\xbf\x44\xce\xf7\xb2\xea\x3f\xb2\x3c\x29\xee\x7d\x46\x96\x2c\xf8\xd7\xb0\x99\x50\xcc\xca\x6d\x7d\xcc\xa5\x9c\x0c\x1c\x55\x7e\x80\x9f\xa7\x42\x12\x58\xf6\x3f\x2a\x8f\xa2\xcc\xce\xe9\x11\xba\xc3\x04\xef\x37\xe1\xd3\x71\xe1\x09\x8a\x39\x8b\x65\x90\x6b\x95\x95\x6a\xaa\x6a\x87\x5e\xc9\x77\xac\xce\xee\xb8\x47\xe8\x36\xdc\xc9\x51\xf8\x18\x9c\x4f\x76\x0d\xfa\x06\x9a\x99\x82\x1d\x4f\x6b\x8f\xd0\xab\xd0\x37\xa9\x40\xc5\x07\x0e\x07\x2f\xcd\x1e\x78\x02\x0f\x90\x84\x6f\x9c\xd9\xb7\xe4\x6d\x5d\x78\xe4\x72\x32\xa7\x57\x4b\x3f\x09\x77\x7a\x14\xc0\x9f\x25\x90\x98\x97\x87\xc9\x54\x74\x4f\x02\x7f\x63\x27\xac\x4a\xc9\xe1\x30\x73\x73\x1b\x66\xa2\xa8\x75\x46\x41\x58\x14\xa9\x80\xa2\x31\x1e\x63\x74\x2a\x9b\x42\x24\x35\xff\x46\xfc\xc5\xa7\xc9\x56\xfc\x3f\xde\x98\x2a\xe2\xdb\x50\x47\xfc\x90\xcf\x93\x2d\xfc\x11\xf7\x9a\x77\x5b\x09\xdc\x94\xe5\x83\x68\x19\x4d\xe1\x41\x7d\xea\x86\x04\x3b\x58\xa0\x1b\x4c\xfa\x60\x49\x79\x8a\xe6\x7e\x92\x53\x3e\x95\x86\xb8\xb5\x32\xf0\xb7\x75\x04\x72\xab\xa6\x1a\x5e\x54\xe4\xb8\x88\x28\x97\x4f\xf0\x86\x93\xf2\x7c\xca\xc3\x27\xc8\x27\x4d\x21\x9f\xf4\xec\x48\xd3\x30\x81\x10\x93\xb6\xc6\x00\x18\x64\xe3\x85\x98\xb6\x32\x70\x5b\x49\xce\x21\xcc\x88\xaf\x23\x6e\x6e\x78\xfd\x45\x71\x9b\x27\x59\xbe\xf9\x72\x97\xf1\xbc\xfe\x89\xc7\xf5\x30\x0c\x7f\x46\x27\xcf\xee\xf7\x3e\x11\x84\xec\x5f\x22\x3f\x25\x14\x86\xc7\x61\x43\xe2\xe9\x9e\x6d\xf8\x5f\x71\x5e\x93\x68\x1a\x43\x83\x77\xc5\x1e\x07\xcf\x71\x3f\xb0\xd6\x2f\x8d\x5a\xdf\xf2\xb4\x3e\x92\x80\x1f\xe9\xbe\x23\x39\x73\x96\x6a\x05\x87\x0a\x75\x46\x63\xbd\x46\x49\x63\x8d\x94\x05\xbd\x86\x6a\x99\x42\xc2\x3e\x6e\xcb\x08\x7d\xf8\xba\x26\x17\xf8\x52\x38\x86\x7b\xf5\xa3\x94\xd4\xd3\xc8\x2e\x85\xcb\xd3\xc4\xbd\x11\xe3\xc0\xcb\x80\x80\x81\x3b\xd3\xd5\x08\x85\x33\xa2\x93\xa1\x42\x4d\xcc\xe7\xf5\xae\xd8\xeb\x54\xa8\xa2\x1a\xac\x4f\x47\x3d\xb1\x38\xa6\xa2\x5c\x73\x3c\x0a\xd0\xf7\x44\x4f\x10\x33\x38\xbc\x13\x28\x5d\x74\x09\x0b\x22\x8f\x03\x76\xdf\xac\x2a\xba\x86\xba\xc7\xe3\x91\xda\xf3\xfd\x20\xc9\x64\x6b\xb5\x0e\x87\x37\x91\x52\x37\x81\x04\xd7\x8e\x10\x84\xcb\x04\x56\x48\x0a\xcb\x75\x20\x44\xd0\x49\xd9\x7d\x6a\x39\xa7\xe8\xfc\xe8\x86\xfd\xd3\x59\x60\x02\xcf\x82\x2e\x8f\xea\xac\x31\x58\x2e\x61\xd3\x4e\xa0\x66\x05\x5a\x73\xaa\x84\x61\x18\xb7\x43\x19\xf2\xde\xcc\x64\x11\x26\xa8\xc2\x94\xe6\x7f\x89\xac\xb4\x83\x1a\x33\xa4\xcb\xcd\x72\xb3\x8a\xd7\x81\x20\x5f\x81\xba\xf4\x37\xcb\x8d\xce\x6c\xe3\x27\x4b\x66\x9f\x8d\x20\xa5\xc9\x32\x0d\x98\x7d\xaa\x08\xb4\x0d\x53\x72\x14\xa4\x5d\x2b\x4a\x0f\xe6\xc8\x6e\x04\x70\x14\xd7\x3b\xe0\xfe\xd3\xf9\xff\x20\xe1\x9d\x93\x1e\x9d\x76\xfa\xf4\xc5\x82\x9e\xc2\x6c\x86\x26\xef\x6d\x4c\x30\x00\xbf\xb9\x1b\x56\xd1\x1a\x52\xd2\x06\xb1\x21\xa4\xad\x1d\x93\xa9\x43\x75\x8a\x42\x4c\xe4\x2b\xc3\xdf\xb7\xc3\x26\x62\x23\x9d\x10\x0f\xd2\xca\x7b\x63\xa6\x44\x1c\x41\x44\x3d\x2f\xf0\x8a\xdb\x1a\x8a\xad\xf6\xc0\x4f\xc2\x36\x26\xd6\x36\x02\xdb\x8f\x49\x9a\x9b\x4b\x28\xc8\x72\x2b\x7e\x81\xa6\x67\x21\xd0\x2d\xe4\xb4\x95\x19\x18\x31\x74\xf0\x52\x25\x4d\x09\x54\x62\x5e\xbd\xef\x6d\x08\xb1\xf4\x4e\x6d\x72\x23\x12\xec\x5f\x1f\xb5\xb2\xf2\x10\x4d\x7a\x63\xb6\x06\x9a\x24\xd2\x34\x09\x72\x99\x4d\x8c\xaf\x63\xd4\x47\xd3\xa8\x48\x1e\x81\x9b\x2b\x76\x3b\xd1\x9e\x72\xe7\x49\x55\xc0\xa3\xa6\x2a\xb8\x4f\xe6\xe3\x44\xed\x26\x24\x25\xc0\x63\x2b\x26\xb6\x21\x81\xca\x8e\x80\x91\x08\x36\x00\xa2\xe9\x32\xd1\xc2\x3b\x0d\x9c\xca\xbd\xb3\xca\xfe\xce\x3b\xf8\x4a\x2b\xe6\x82\xbc\x91\x59\x9e\xbc\xe5\xbb\x14\x79\x11\x96\x24\x5f\x08\xe6\xce\x53\x2d\xad\x00\xd2\x3c\xcd\x72\x3e\x1a\xe1\xdf\x29\xbb\x49\xd4\x6f\xdf\x43\x6d\x92\x47\x57\xeb\x8e\x84\x94\xb9\xbc\x7b\xff\x8f\xa0\x18\xaf\xfe\x4d\xd4\xa4\xdf\x8a\xdf\x1f\x9b\x8d\xca\x8b\x2f\x8b\x3c\xdd\x65\xb1\xe5\x20\x6c\x11\xa1\xd3\x8f\x05\x1a\x03\x62\xed\xe3\xf0\xdb\x08\xe3\x00\xcb\xbe\xf4\x1b\xf9\xf8\x7f\x22\x42\xf3\x23\x55\xbc\x47\x88\xd7\xad\x7e\x2d\x7a\xc8\x45\x0d\xb2\x38\x3f\x1b\xfe\xd3\xd9\xe0\x8b\xa2\xa8\xab\xba\x64\xfb\xc1\xdd\xab\xe9\xab\xe9\xbf\x0c\x7c\xb0\xfa\x3c\x3f\xdf\xf0\x3a\x52\xef\x04\x9b\x40\xfe\xe9\x6c\xf0\x65\xb1\x7f\x2c\xc5\xa1\x1a\x5c\xcc\xe6\xf3\xc9\xc5\x6c\xfe\xd9\xe0\xdd\x7d\x56\xd7\xbc\xa4\x83\x37\x79\x3c\xfd\xa7\xb3\xc1\xb7\x59\xcc\xf3\x8a\x27\x83\xdb\x3c\xe1\xe5\xa0\xde\xf2\xc1\x77\x6f\xde\x0d\x76\x58\xfc\x4f\x67\xe7\x82\xa3\x13\xef\xc4\xda\x25\x66\x81\x71\x80\x52\xfe\x99\xf3\xfb\xc1\xd7\xe8\x52\xa9\x07\xf8\x49\x35\xf8\x0b\xbb\x63\x68\xa2\x32\x28\xf9\x6f\xb7\x59\xc9\x2b\xd9\xce\x23\x8b\xb1\x4d\x4d\x79\xb7\x15\x1f\x08\xbe\x31\xae\xbd\x85\x0a\x16\x95\xe6\x52\xf1\x67\x39\xce\xac\x66\x6b\xf5\x34\xf5\xc0\xb0\x2d\x5a\xcd\xd6\xaf\x2f\x46\xa3\x68\x35\x5f\xbf\xfe\xd7\xc3\x61\x1e\x42\x02\xf9\xd1\xe8\x5f\xc5\x8f\xf9\x5a\xbc\xb9\x58\xbf\x9e\x1f\x0e\xa2\xf8\xf2\xd5\xef\x1d\xf2\x40\xf9\xb9\xcc\xa7\xff\x3a\x9d\x0f\x8a\x72\xb0\xcd\x36\x5b\xb1\x92\x11\x78\x70\xdf\xc3\xea\xb1\x5c\xd7\xfb\xd4\x23\x47\x5f\x2e\x13\xed\x9f\xad\x66\x3e\x22\x7d\x87\xea\xa3\xdf\x08\x6d\xa9\x37\x18\x04\xd8\x4f\x98\x69\x1f\xa4\xa0\x32\xaf\xff\x7d\xa3\xe4\xeb\x3c\xf1\xe8\x77\xc5\xdf\xed\x3a\xb5\xfe\x0d\x06\x7e\x3f\xd8\xef\x0a\xa7\xe9\xa0\x68\xd4\xad\x7b\xbb\x39\x9a\xc8\xf7\x3a\x8d\x8d\x76\xfb\x53\xc9\xcd\xe3\xb5\x24\x4c\x9f\x78\x9e\x04\xd1\x2a\x5e\x1f\x4d\x94\x13\xd8\x6e\x7e\x73\xbb\x63\x35\x77\x46\xe1\x1c\x31\x54\x0f\x0e\xe7\x92\x2c\x5e\xc8\xb4\x98\x53\xc1\x6b\x7b\x51\xd5\x98\xb9\x2d\x12\x0d\x87\x33\x79\xb2\x1d\x44\x13\x1f\x0e\xcc\x4f\x88\x36\xd0\x62\xd3\xea\x76\xbf\x2f\xca\x7a\x6a\x26\x38\xe5\x79\x62\x02\x91\x5b\x16\x8f\x5c\xdb\xbe\x53\xe6\x88\xa6\x3a\x3a\x01\x55\x44\xd7\x0b\x4c\x3c\x07\x56\x62\x32\x81\xc3\xb4\x31\x91\xf0\x29\xca\xf2\x04\x84\x0c\x7d\xc3\xd3\x6e\xe7\xa7\x6b\x6d\x21\x84\xa9\x93\xdf\x42\xf0\x31\x7e\x34\xad\x59\xb9\xe1\x35\x28\x79\xd1\xb0\x47\xb1\x10\x53\x6c\xf3\x43\x74\x25\x7f\x95\xdd\xf2\x1b\x40\xe6\x1f\x08\xef\xd1\xe9\x80\x81\xd2\xeb\x42\x9a\xf8\xf0\x30\x06\xf9\xa1\xd8\xe7\x29\xdb\x71\xd0\xd9\xf0\xc3\xa1\x55\x4a\x39\x38\x97\x6b\x0b\xa5\xb6\x48\x78\x34\xe2\xab\x48\x65\x12\x13\xc3\xc6\x2f\x7d\xb2\x12\x3d\x4d\x92\xac\xba\xc9\xaa\x2a\xf4\xb0\xbb\xf5\x27\xd4\x85\x41\xe6\x47\x28\xe5\x87\x90\x0c\x9e\x89\xc0\x54\x54\x9c\x1c\x17\xc9\xf4\xdf\xbf\xfe\xe9\xed\x9b\x1f\xbe\x0f\x3d\xc0\xd0\x1e\x4d\xa6\xef\x7e\xfa\xfc\xfb\xb7\x6f\xde\xbd\xf9\xe1\xfb\xf7\x5f\xfd\xfc\xd3\xe7\xe2\x47\x38\xff\xc3\x8c\x26\x56\xe6\x3f\x68\xef\x7c\x48\xaf\x54\xec\x93\xa7\xcd\x34\xe1\xb5\x58\x20\x03\xab\x1e\x34\x49\xa6\x66\x3d\xb4\x34\xef\x88\x80\xce\x74\x70\x27\x8e\xf1\x5a\x40\x62\x3d\xc1\xcd\xf6\xc8\x22\x85\x40\x94\xea\xdd\xb6\xe4\xa9\x27\x2a\xa7\xa3\x51\xaa\x45\xca\xe7\xd3\x33\x7f\x19\x7e\xb4\xfa\xdb\xaf\xd5\xfa\xec\x63\x72\x4e\x3d\x8f\xe0\x41\xda\x84\xcc\xf7\x3e\x02\x37\xc9\xe5\x6a\x1d\xa4\x64\x81\xc1\xfc\x4a\x80\xe6\xaf\x50\x38\xe2\x1b\x19\x1a\x3a\xa7\xe2\x44\x2b\x81\xc0\xe5\xa8\x45\x0d\x1d\xf2\x21\x64\x53\xa9\xbb\x86\x7a\xd6\xe4\x08\x8d\xa6\x59\x25\xbb\xfd\x11\x3f\xc2\x13\x5f\x30\x59\x1b\x27\x1c\x95\x97\xe5\x5e\xdf\x59\xdb\x98\x30\x56\x5e\xca\x12\xee\x91\xe5\xa6\x07\x7b\xc4\xa4\x13\x1f\xf9\x9d\xdb\x49\x82\xd8\x57\xa2\x52\x8e\x77\x17\x0c\x7b\x61\x7e\x86\x11\x35\x0f\xd3\x2f\x4d\xa2\xdb\x30\xb1\x5f\x74\x11\x17\x16\x6d\xa1\x7b\xe3\x1a\xf3\x24\xda\x5a\x50\x43\xa5\x5e\x36\x38\x1c\x13\xb6\xcf\x04\x9c\xb6\xc0\xed\xbf\xe1\xc0\x26\xd6\x81\x4d\xcc\xd1\x44\xdb\x2d\x80\xae\x2e\x89\x6b\xb4\x80\x3c\x1c\xcd\xea\xf2\x28\xc7\x92\x7c\x16\x87\x59\x27\x3d\x8b\x96\x5c\x06\x45\xf3\x41\x90\x0b\x21\x35\xc1\x52\xdb\x8f\xcc\x99\xb6\x48\xee\x44\xe6\x0c\xfe\x58\xda\xcb\x84\xe2\x20\xbb\x79\x81\x99\x95\xa4\x22\x9e\x7e\xf5\xf5\x37\x9f\xff\xfc\xed\xbb\xb7\x34\x91\xd5\xb2\xea\xdb\x82\x09\xb6\x23\x1c\xce\x8f\x8b\xb8\x75\xd0\x4d\x93\xf0\x69\x87\x35\xdf\x81\x4b\xa5\x7c\x98\x4e\xa7\x9e\xe8\xd8\xec\x82\x1a\x72\xc7\x25\x67\x02\x09\xa9\xe0\x63\x6a\xe0\xb0\xb2\x59\xa5\x43\x5d\x2f\xbd\x3b\xb6\xf3\x94\x00\x3a\x55\xcb\x4e\x16\xd1\x38\xf4\xd0\x8b\x13\x6d\x67\x40\x97\xce\xeb\x77\xe0\x4a\xa8\x56\x5b\x17\x79\x34\x59\xf1\xb5\x4f\x08\xb5\xae\x38\xc8\x4d\xfa\xf0\xe8\xc4\x71\x15\xb5\x64\x87\xab\x68\xbd\xb4\x57\x70\x15\xad\x83\x14\x13\xd7\x5b\x0b\x00\xbb\xe5\x37\x97\x50\xa0\x3f\x1d\x34\x2e\x26\x88\x84\x62\x71\xec\x40\xeb\x1a\x83\x80\x23\x70\x5b\x29\x7b\x22\x7b\x27\x68\xe2\x9c\xfe\x98\xd8\x11\x80\xad\xde\xe6\x84\x1c\x65\x8e\xe0\x19\x71\xb7\x01\xe1\xa8\x15\x45\x5f\x8c\x31\x72\xd7\x5e\x63\x2f\x79\x59\xc8\x96\x1e\x02\x6c\xe5\xad\x3f\x41\xa2\x54\x89\x04\xed\xa4\xa9\xba\x0f\x10\xe9\xab\xdd\x5b\xe8\x00\xca\x31\x0e\x15\x03\x21\x93\xa5\xaf\x9e\xa5\xf1\x14\x64\x32\x64\xa8\x23\x92\x5d\x48\x3b\x73\xcf\x8d\xfd\xe8\xa9\x52\xea\x7e\x56\x2f\xb6\xae\x40\x02\x13\x7e\xa9\xf9\x7d\x88\x9a\xd8\x18\x80\xcc\xf6\x61\xba\x34\xc8\x54\x75\xa9\xc7\xe8\x56\xb4\xc3\x17\x9a\xcf\xd3\xe6\x17\xe8\x73\xdd\x13\xca\x46\xa3\xd8\xba\x02\x21\x96\x91\x27\x33\xc4\x35\xe6\x0b\xb7\x1a\x2b\x33\x36\x81\x90\x46\xa2\xff\xe1\xf3\x1f\x78\xc1\xc0\x8f\x52\x3d\x07\xe8\x18\xb7\x7e\x61\xfd\x56\x98\x1e\x9f\x1c\x54\x1f\x3b\x6f\x9e\xc7\xf5\xb2\xc3\xe4\x39\x64\x2f\x3b\x34\xd8\xde\x81\xcf\xbf\x29\x00\x15\xd4\x8c\x6d\xbf\xac\x30\x76\xac\x09\x40\x73\x3b\x47\x75\xee\x91\x85\x94\xc4\x27\xd4\x24\xc6\xb0\xab\x67\x95\xff\x09\x00\xf2\xca\x8e\xb0\xbf\xa6\x03\xbb\xd0\x84\xf8\xfa\x44\xdc\xd6\x71\x9b\x44\xb0\xf0\x19\x55\x57\xc5\x32\x31\xdb\x0c\x91\xb2\x3c\x12\x24\xf6\xd9\x09\xa4\xe5\xb1\x6c\xa1\x1e\x3d\x82\xf6\xeb\x36\xa5\x24\xdb\x13\x69\x9f\x01\x8f\x1d\xcb\x36\x88\x76\xb7\xe5\xef\x5d\x4e\x24\x0d\xfb\x16\xd2\x05\x24\x1c\x0f\x3d\xff\x1b\xfc\xf0\xb3\x9c\x2c\x3f\x3e\x57\x8a\x79\xb0\xf8\xf8\x6f\xa1\xa6\x7b\x2e\xe7\x98\x95\x10\x28\xcb\xc3\x30\xa0\xdd\x77\xa0\xbc\x54\x68\xe7\xf5\x4d\xe8\xa6\x1d\x98\x38\x5a\x46\x41\x3a\x85\xfc\x2a\x8d\xeb\x5d\x7f\xb0\xe3\x82\x6f\x86\x87\xc4\x7b\xde\x8f\x48\xb0\x59\xf2\xd5\x66\xed\x93\x20\xd5\x79\x3d\xc4\xb5\xbf\x67\xb7\xe0\xa2\x1b\x3f\xc6\x3b\xcc\x61\xdb\xba\xfa\xe3\xfe\xab\xff\xe3\x2c\x4f\xb2\x98\xd5\x45\x59\x75\x62\x69\x3d\xd6\x89\xa9\xe8\x35\xc8\x06\xc9\x01\xc0\x40\x12\xb4\xea\x41\x9b\xdf\x5d\x06\x77\x94\x29\xd1\x49\x4d\x4c\xd1\xc7\x88\x54\xec\x92\xac\xe6\x37\x95\x55\xa0\xb2\xdf\x5f\xf3\xc7\xa8\x60\x65\x22\xd3\x49\xe9\x91\x0a\x90\x96\xf1\xdb\xa6\xce\xea\xaa\xdb\x1b\xaa\xcb\x1a\x54\xb1\x45\x10\x4a\xcd\x93\x18\x5d\x7d\x02\xe6\x30\x1a\x0d\x7d\xaf\xc8\xeb\xe2\x36\xde\x42\xd6\x15\xc8\x8a\xd0\x23\x8f\x24\x5d\xa3\x31\x61\xd8\x4e\x0c\x08\xbe\x25\x87\x63\x5a\x41\xb8\xb6\x13\xad\x60\x9b\x65\xab\x6e\x22\xac\x8b\xdb\xfa\x6c\x36\x73\xc8\x33\xb5\x11\xc1\x1f\xf8\x2b\x0a\x03\x09\xe4\x82\xa0\x5f\xc8\x70\x46\xd5\x6a\x07\xc3\x99\x4b\x2d\xc8\x85\x0c\x1b\xea\xc0\xe1\x39\x3a\x1f\x28\xaf\x83\xf3\x4c\x05\x56\x47\x94\x30\xad\x31\x2c\x19\x21\x4f\xd5\x7d\x06\xc6\xbf\xd3\xfb\x6d\x16\x6f\xc9\x53\xcc\x2a\x3e\x78\xf5\x2f\x48\xec\x08\xe4\xe8\xcb\x20\x2e\x0b\x7c\xf3\xaf\xf8\x26\xe7\x0f\xb5\x7e\xa3\xd2\xcf\xe0\x99\x3f\xb2\x16\x52\x3d\xba\xa3\x86\x75\xeb\x92\x57\x46\x2a\x98\xa9\x84\x5f\x7d\x79\x9b\x43\xe6\x66\xc9\x71\x5e\xba\x47\xc1\x6a\x33\xb4\xfa\xd4\x64\x9b\x02\x7f\x3b\x65\x8f\xb3\xbb\x62\x8a\x92\x48\xeb\xec\x97\x28\x81\x8b\x3d\xb5\x0d\xaf\xdf\xd4\xfc\x06\x63\x4d\xf6\x19\x1d\xc8\x53\xc5\x8c\xbb\x0d\x18\xb9\x94\x3c\xf7\xbd\xa9\x78\xa7\xe9\x25\xa8\x88\x5a\x6f\x9f\x1d\x0e\xf6\x29\x25\x9d\x1f\xfe\xa6\x28\xbf\xca\x4a\x0e\x9f\xed\x72\xc1\xc0\x23\x66\x8f\xd2\x87\xb4\xb0\x9e\xd8\x32\x0f\xf2\x7a\x41\x66\x93\xc3\xc1\xcb\x91\x5c\x16\x44\x8e\xa2\xb5\x70\x38\x48\x4f\x4e\xe6\x10\x6f\x4a\xad\xae\x5a\x1d\x01\xb2\x26\x38\x28\xf2\xa0\xba\xf3\xe5\x64\x1e\xcc\x69\x1a\xfa\xf1\x98\x93\x7f\x6e\xf7\xb9\x68\xaf\xd2\x94\xff\xe6\xa7\x2d\x1a\xb9\x23\x53\x1e\xba\x39\x75\xcc\xcf\x41\x6d\x9d\x78\x55\x7c\x48\xd3\xaf\x40\x34\x0f\x7d\x76\xd9\x35\xe5\xc3\x81\xbd\x9e\xb9\x31\xd0\x25\x66\x5d\x36\x31\x0f\xf7\x3d\xf1\xca\x45\x1f\xb6\x4d\xae\xb8\x4a\x18\x39\x92\x20\x56\xea\xf9\xe6\xfd\x11\xe8\x0f\x70\x9f\x5d\xc6\x4b\xdc\x92\x00\x97\x93\x36\x16\x89\x91\xc6\x2a\x41\x67\x2f\x3a\x65\xb3\x26\xa5\x29\xd7\x05\x4e\xc0\x00\x4e\xb3\x8e\x59\x38\x1a\xf5\x48\x0e\x1b\xb4\xea\x73\x42\x4c\x6a\x30\xa8\x0f\xea\x63\xf7\x54\x3e\x7b\xcc\xdd\xb9\x8a\x91\x36\xf2\x25\x0f\xed\xdd\x69\xed\x18\xf7\x71\x31\x9b\x6b\x56\xf2\xbb\x0f\xed\x07\x97\xa7\xc1\x4c\x8b\x57\x0d\x8e\x1f\xcf\xc2\xf3\x00\x28\xd8\x66\x79\xd4\x3b\x0e\x35\x78\x7e\x49\xbb\x34\xbd\x24\x74\x1b\xaa\xe3\x1a\x2d\x51\xad\x1a\x78\x25\xea\x30\x33\x14\x4f\x83\xb7\x42\x07\x8f\xd1\x01\xca\xe1\x70\xbe\xc0\xe8\x7f\x29\xc4\xf4\x32\x72\x30\x98\x96\x0b\xd1\x4f\x60\xf4\xc3\x93\x77\x70\xb1\x04\x57\x34\x51\x23\x0d\xb6\x18\x89\xba\x1b\x30\xae\x09\x1d\x5e\x77\x0a\xd1\xb4\x61\x85\x19\xcf\x8c\x6e\xe4\xd5\x2e\x4f\x48\x8b\x60\xd2\x4c\x6e\xeb\xc5\x8b\xd8\x53\x98\xef\x4e\x92\xa4\x4e\x73\x8d\x99\xc9\xaa\x8d\x5a\x52\xb2\x26\x8b\xdd\x68\xb4\xeb\x60\x68\x81\xf4\xbb\x71\xd7\xee\x83\x96\xce\xe4\x26\xea\x38\x6e\x7d\xbc\x23\xec\x90\xe0\xd8\x53\x3b\x0a\x3e\x4d\xc1\x9f\xd7\xf8\x53\x52\x2b\x48\xfe\x96\xd0\xd4\x79\xe2\xcf\xeb\x30\x52\x67\x19\x57\x11\xdd\xae\xa5\x9f\xda\xc0\x23\xa4\x63\x35\xa8\x1b\xa6\x7f\xa5\x5e\xb8\x0d\x69\x66\xc1\x20\xed\x0e\xe8\x90\xb5\x61\xe9\x86\x1c\xe9\x0c\xbc\x4c\xbb\x84\xa4\x9d\x54\x18\x21\x81\xcf\x7b\x44\x15\x69\xd7\xf8\x1b\x07\xa4\xc9\x9a\xeb\x91\x10\x0d\xaa\x12\x89\xab\x88\x44\x16\x9b\xae\x40\x60\xe1\x3c\x29\x56\x5d\x3d\x77\x31\xeb\xfa\xdd\xf3\xec\xba\xee\x56\x32\xec\x4d\x85\x93\x31\x02\xb4\x64\xf3\xcc\xef\x94\xce\x83\x81\x81\x2b\x9b\x87\x94\xc2\x5d\x82\xf9\xb1\x16\xcc\x37\x50\x8e\x61\xed\x94\x41\x8a\xcd\xdf\xa5\x8a\xa9\xe3\xf2\x07\xa1\x5b\x57\x55\x00\xa0\x3d\xa9\x0b\x8f\x2c\xb6\xa3\x91\xbf\x31\x97\x05\xca\xa1\x40\x38\x90\xd2\x0d\xa1\xdb\xd1\x28\xed\x62\x29\xc5\x8d\xbb\x45\x49\x4f\x93\x3e\x5d\xf4\x8a\x33\xf4\x92\x1b\x0e\xdc\x5b\x99\x01\xad\x3d\xca\x3f\xac\xc5\xa4\x2e\xa0\x11\x65\xfe\x3d\x18\x59\x18\x47\x0d\xe7\x8c\x31\x25\xd8\x2b\xc5\x5d\x62\x96\x6f\xfd\x49\xdb\x3d\xdb\xd1\x4f\x29\x41\x49\x4c\x63\xb5\x96\xbf\x4f\x23\xa6\x9c\x76\xa3\x1e\x98\x88\xf5\x1b\x0d\x13\xf1\x49\x98\xd0\x38\xcd\x4f\xac\x80\xae\xf1\x3f\xa0\x7d\x8b\x8b\xdd\x8e\xed\x2b\xde\x92\x17\x24\x46\x5e\x10\x9f\x96\x17\x2c\x86\xe0\x41\x87\x42\x91\xd1\xe8\xbc\xda\x16\xf7\x87\x6d\x96\x70\x25\x05\x01\xeb\x53\x25\x98\x15\xb0\xe6\xaa\xfa\xf4\x10\x1c\x6d\x1f\x4a\x10\x7a\xf4\x7d\x5a\x34\x90\xbc\x50\x34\xd0\xa5\x15\xb0\x67\xa8\x2e\x44\x89\x87\x42\xd6\x14\x0a\xeb\x41\xae\x57\x62\xaf\x42\xef\xa3\x4f\xc6\xd1\x34\x4b\xc6\x9f\x78\x6b\xda\x5b\xd5\xda\x70\xa7\xc5\x27\xf2\x7b\xe6\x46\x72\x65\x0b\x86\x85\x17\xfc\x8d\x24\x8d\xf1\x41\x13\xe8\xca\x80\x51\x66\xd1\x4d\x92\xcf\xcb\x8c\x7d\x9e\x27\x5f\xca\xcf\x4b\x0c\xec\xaa\x1b\x9c\x59\x36\xf8\x32\xb5\x81\x38\x32\xa9\x8e\x79\xb9\x12\xf4\x15\x28\x41\x0d\x5b\x8e\x3d\x00\xc7\x6d\x2b\xab\x92\xec\x06\x03\x66\xb7\x45\xf4\x7d\x77\x32\x9a\x8f\x59\x1e\xd1\xb2\x44\xdb\x99\xb9\x5f\x10\xf0\xd7\x49\x83\x3a\xab\xad\xf8\xae\x8e\xef\x65\xb9\x42\xb1\x11\x55\x04\x27\x2e\xbe\xa2\x1b\xf0\xc9\xe6\x3a\xf7\x2c\x07\x0c\x69\x33\xa2\x39\x1d\x28\xe0\x16\x40\x2c\x19\x23\xc7\x6f\xc3\x8f\x42\xde\x79\x18\x41\xfd\xea\x0c\x98\x10\x6d\xdc\xa6\x49\xa2\x6d\x71\x3f\x75\xda\xf5\xd3\x8b\x29\xa1\xc3\xb4\x87\x5e\x74\x87\x14\x23\xf6\xe3\x54\xa5\x55\x8e\x0e\x87\xae\x41\xa2\xe5\x97\xd2\x1f\xc3\x57\xf5\xe6\xfa\x64\xe1\x0e\xc3\xa1\x14\xcc\x78\x2d\x4a\xc1\x5e\xa9\xd5\x66\xed\xcf\x88\x2d\xf5\x47\x8f\x34\x10\xfb\xcf\x1a\x87\xb5\xbb\xef\xc4\x7b\xae\xbd\x7b\xf8\x90\x64\xdf\x3a\x4e\xdf\xcf\xce\x00\x06\xdb\x9e\x03\x1f\x08\x10\x12\x93\xf0\xbc\xce\x8f\xcd\x7a\xc8\x1f\xd8\xd1\xdc\xdd\xd2\x23\xc6\xe2\xef\xa0\x62\x15\xef\xe1\x24\xfe\x86\x48\xe5\xe0\x8b\x79\xc3\x77\x10\x5c\x4f\xdb\x05\xd2\x8d\xa2\x15\x27\x82\xbc\xe8\x60\xb8\x5b\x24\xab\x12\xe8\x6c\x95\x6c\xef\x03\xd4\xe8\x62\xfe\xce\x37\x56\xb3\xf5\x2a\x5b\x83\x33\xa3\x73\x60\xb7\x0e\xaf\xd7\x7f\x60\x5f\x70\x5e\xcd\xd9\xd8\x2a\x4e\xeb\x05\x67\x23\x22\x74\xd8\x6d\x90\xe0\x48\x7d\x7a\xa1\x7b\x15\x37\x67\x1a\xaf\x7d\x42\x0c\xcf\x80\x76\xb1\xbd\x3a\x3c\x07\x9a\x3a\xa1\x19\x00\xaa\x07\x9e\xe7\xcd\xf3\xd0\x86\xc7\xfe\xc3\x30\x3f\x71\x18\x78\xeb\x30\x9c\x86\xe2\x0f\x39\x21\x9e\xa5\xd1\xc1\x58\x32\x4d\xa8\x3f\xc1\xbe\x61\xd2\xdf\xd6\x8a\xcf\xfa\x8c\xc7\x14\x14\xf3\xdf\x01\xc5\x01\xb7\x4e\x57\x13\x72\xdb\xca\x66\x51\x6d\x75\x0a\x50\x97\x88\x55\x65\x0a\x7a\x41\xc9\x38\x3d\xea\x8b\xbd\x8b\x2d\xf1\x3b\x88\x03\xe9\x55\xd6\x4f\xae\x40\xb9\xa4\x1d\xbc\x4f\xc6\x1d\x5d\x20\x45\x22\x63\xaf\x34\x8d\x04\xac\xf4\x08\x82\xea\x5c\x9c\xa6\x36\x22\x9f\x13\xca\x95\x72\x5e\x85\x2d\x72\x66\xd8\xd7\xb6\x53\xda\xca\x1a\xab\x87\x31\x32\xda\x70\x1c\x0b\x06\xc6\x51\xcb\x19\xd0\xa7\xc3\xb8\x07\xfa\x63\xd7\xca\x47\x35\x59\x38\x4f\x9a\x75\x94\xcf\x5d\xe6\x3e\xfa\xdd\x0b\xd8\x4a\xd5\xed\xb3\x46\x3f\xba\xd3\x1e\xd5\xa5\xbd\xcb\x96\xee\xd2\xda\x2e\xbc\x11\x7a\x38\xd2\xa4\xc5\xc5\x2d\x90\xbc\x80\x3d\xdc\x84\x69\x27\x5d\xb2\x0d\x37\x4b\xa5\x3e\x0e\x14\xab\xb9\x88\x15\xf3\xb8\xfd\xfd\x7c\x52\x37\x97\xb4\x88\x3b\xf8\x24\x1a\x87\xf1\x68\x74\xfe\xd1\xea\xf3\xc9\x7f\xb2\xc9\xdf\xd7\xe7\x26\x2f\x76\x37\xff\xe4\x1a\xbb\x25\xa2\x35\xf3\x63\x3b\x45\x85\x8a\x8f\xb4\x4c\x82\x48\xab\x15\x6c\x16\x2b\x06\x5f\xfc\x57\x90\x33\x13\x54\x3d\x87\x83\xcf\x1c\xaf\x5b\xe6\xa7\xdd\x8c\xa5\xad\xaa\x8d\xfc\x44\x70\x5a\x0d\xd1\x15\x0a\x18\xac\xbc\x8c\x5e\xb1\xe7\x39\x1a\x6e\x8c\x46\xd2\x3a\x51\x7c\xb9\x06\x77\xc5\x1e\xed\x54\xdc\xd4\x4e\x8d\x46\xcc\xb8\x88\xf1\xd5\x6c\x4d\xb5\xb6\xff\x70\xf0\xb9\xc6\xc0\x71\xfb\xda\x4c\xca\x62\x9f\x14\xf7\xb9\x07\x7c\x58\xdc\x67\xad\x97\x74\x1f\x2c\x2f\x65\xbb\xaa\x2d\xb5\x92\xb3\xb2\x84\xdb\xe6\xab\xf2\x06\x70\xbe\x4b\x04\xe3\x6d\xed\x42\xf2\x61\x8c\x6e\x62\x33\xba\xba\x63\xb2\x48\x1c\xf6\xd3\x7c\x31\x01\xf6\x73\x73\xca\xd8\x34\x69\x1b\x9b\xf2\xd0\xd3\x7d\x4c\x22\x16\x5f\x8b\x07\x8f\xa6\x61\xe3\xb0\xea\xef\xac\x3f\x11\xa7\xab\xd7\x0a\xd5\x5d\x05\x8b\x19\x23\xc7\xc5\xa6\xc5\x8b\x6d\x4e\xdc\x46\x2d\x4c\x20\x08\x2b\x0e\xe6\x19\x3a\x81\x1d\x1d\x58\x71\xa0\x14\x83\xa1\x31\x40\x13\x1e\x21\xfa\xac\x4f\xe8\x70\x43\x9e\x5e\xac\x55\x1e\x8d\x86\xa9\x65\x42\x91\xb3\xbb\x88\x95\x93\x9c\x39\x3a\x11\xbf\xcf\x50\x3e\xc9\xee\x5c\x89\x68\x7b\xad\x89\x0c\x9a\xf8\x79\x0a\xb9\xc2\x7c\x4b\x0d\xad\xec\x7a\x89\xa4\xee\x3b\xcf\x1d\xc8\xd9\x14\x4c\x26\x6d\xf6\xca\xec\xc6\x96\xa0\x7d\x4b\x07\xa1\x88\x60\xb9\xe0\x2d\x43\x95\x9e\x13\x52\x97\xb7\x28\x2b\x75\x6e\xad\xbe\x03\xa2\xf9\x02\x67\x2c\x47\x93\x58\xd4\x01\x84\x96\x56\x1b\xbd\xf9\xcf\xfd\x57\x7f\x3c\x7c\x3a\x3b\x5c\xfc\xcb\xe1\xd5\x05\x51\x48\x53\x2a\xae\x47\xa3\x3e\xa5\x77\x0b\xad\x34\xb0\x1a\x00\x45\xdb\x0e\x28\x9e\x56\x75\xb1\xff\xb1\x2c\xf6\x6c\xc3\xf0\x7c\xd2\x61\xf2\x2c\xf4\x49\x14\xb9\x09\xdb\xd8\x10\xe0\x77\x33\x1a\x5d\xfc\xcb\xd0\x20\x61\x78\xd6\x48\x59\xb1\x44\x56\x91\xe0\x6d\x81\x44\x4a\xdb\x46\x44\x34\xb1\x2d\xb0\x05\xa8\x28\x40\xf1\x06\xbb\x2c\xc8\x8b\xda\xd7\x63\x25\xca\x28\x69\xc0\x3c\x9a\x85\x5c\x29\x46\x34\x3c\x42\x4a\xbd\xf1\x16\x86\x99\x39\x46\x83\x57\x61\x26\x75\xd0\x1a\xff\x2e\x5e\xfd\xd1\x1a\xe1\xd5\xe5\x6c\x34\xba\x9a\x4c\xe8\xa7\x33\xbb\xf4\x75\xa6\x15\xa7\xa3\xd1\xd5\x78\x4c\xff\xdf\xd5\xe1\xe0\x5f\x85\x33\x42\xb3\x29\xff\xcd\xbf\x6a\xcf\x48\x30\x57\x72\x0a\x40\x6e\xa8\xd1\x2d\x9c\x27\x45\xb7\xa8\x67\x87\xa6\xd9\x34\xde\x3d\x4f\xd3\xe8\x6e\xb7\xcf\xd1\x34\xba\x53\xcb\x96\xf9\xf9\x2a\x66\x91\x07\x69\x51\xde\xb8\xb1\x81\x58\x1b\xce\x8e\xcf\x77\x99\x76\x60\x4e\xd2\xb4\xbe\x79\xb6\x9d\xac\xfb\x92\x86\x4d\x40\xe9\xec\xe7\x43\x49\xa7\x66\x2a\xc2\xae\xfb\xd0\x75\x1d\xd0\xd7\xde\x4d\x91\xb0\x9d\x27\x0e\x5a\x8f\x95\x18\x7f\x46\xea\x9b\x3a\x52\x21\xec\x8e\xa6\xb6\x0d\xd8\xa6\xf3\x12\x5d\xa6\xab\x68\xed\x27\x24\xd8\x80\xa4\x6e\x34\x4a\xe1\xaf\x9f\x9c\x34\xf7\x6a\xd8\x67\x7d\x1c\x15\xc9\x63\x68\xdd\x1a\xe2\xb9\xa1\x85\xb7\x2d\xc3\x92\x8c\xed\x8a\x4d\xb7\xf2\x18\x86\x3e\xc1\x1a\xda\x70\x44\x5d\x2e\xb6\xc1\x57\xf5\x56\x60\x61\x5b\x4c\x5b\x66\x9b\x2c\x67\xbb\x2f\x8a\xe4\xf1\x47\xe6\x98\x8b\x81\xc4\x25\x62\x25\x68\x0b\x15\xa7\x9c\x6d\xf2\xa2\xe4\x5f\xc8\xae\xbf\x14\xe0\xa9\x55\x61\x8a\x25\x13\xf4\x52\xcd\x9b\xc2\x0e\x67\xa8\x2a\xba\x37\x81\xb8\x2d\x7e\x47\x73\xda\x61\xeb\xdd\x23\x71\x12\x5d\xa0\xe3\x89\x84\x88\xe3\x07\x1b\x64\xbd\x02\x83\xac\x2f\x3e\xff\xf2\xff\x7c\xf5\xd3\x0f\x3f\xbe\xef\xf3\x90\xb1\x6d\xb6\xd4\xf2\x36\x8c\xb3\xa8\x80\x84\x96\x91\x56\x93\xae\x69\x58\x03\xc9\x7d\x41\x29\xb9\xa0\x5f\xb5\xe1\xc7\x16\xe2\x7d\x34\x2c\x0b\x1c\xe9\x70\xa4\xee\x32\x00\x58\xde\xbe\xfb\x25\x5c\x37\xe8\x86\xe8\xd8\x14\x9f\xa9\xf5\xe4\xc4\x01\x16\x71\x46\x7a\x48\x67\x07\xa6\x86\x12\x42\xc0\xbc\xf6\xad\x02\x1e\xa5\xa7\xaf\x20\x3c\xb8\x5b\x06\x27\xc0\x22\x8b\x10\x34\xf0\xa2\x94\x89\xbf\xab\x98\xed\xb5\xae\x1f\x53\xd2\xfa\x4d\x4b\x15\x83\x27\xa5\xaf\x94\x35\xe9\xa6\x13\x15\x16\xaf\x3f\x71\x8d\xf8\xc4\x8a\x2b\x43\x44\xfb\xb0\x19\x33\x40\xc4\x84\xad\xee\x6d\x3f\x84\x86\x1c\x52\x66\xc4\x3d\xd5\xa8\x61\xa2\x9b\x55\xbe\xe9\x44\xf0\x4d\x49\xf7\x69\x9b\x81\x2a\x0f\x07\xaa\x80\xb0\x03\x63\x76\xda\x0c\x24\x5d\x32\x1d\xf4\x3c\x5a\x58\xef\xb4\x51\x9a\x72\x95\xb2\xde\x61\x60\xa0\x77\x85\x18\x2c\xa2\x2c\xeb\x25\xc0\x2b\xd1\x91\x03\xf6\x3e\x84\x8f\x60\xc9\xd5\x6d\x55\x7f\x05\x6b\xea\x43\xd8\xa7\xc4\x96\xa8\x3a\x56\x09\x49\x97\x74\x11\x5c\xa8\x92\x29\xcf\xd3\xa2\x8c\xf9\x37\x60\xa5\xac\x78\xfd\x36\x81\xd9\x0f\xf0\x7c\x99\x58\x7b\xfb\x8c\x81\x43\xd2\x81\x6a\x14\x41\x6c\x54\x12\x1f\x66\x72\x10\xbc\xb4\xd3\xc6\x91\x77\xe5\xcb\x11\x86\x73\x6c\x13\xac\x1d\xc2\x63\x75\x49\xf6\x8a\x8d\xed\x43\x3c\x1a\xf5\x08\x91\x8d\xa7\x8b\x3c\xec\xf3\x93\x07\xd4\x21\x9e\xd2\x54\x4e\x31\xcb\xfb\x07\xd4\xf2\x98\xc3\x76\x3d\xe7\x5a\xbe\xed\x3d\x63\xcd\x63\xac\x2b\x77\x9f\xe3\x3e\xf7\xbc\x3e\x21\xa8\x74\xd5\xfb\x10\xed\x83\xc6\x33\xdf\x89\x2f\x9e\x14\xe2\xf6\x40\x8e\xdb\x83\xdf\x84\x10\xfb\x6c\x84\x8e\x09\xc1\xb3\x5b\x61\x9c\x10\xec\xe2\xf6\x05\xcc\xc8\x93\xea\x0b\x43\x43\xc2\xc1\x52\x26\xa9\xe6\x3c\xf7\xbf\x14\x6b\xa8\x2d\x90\x0d\x76\xe9\xb9\xd7\x15\x3f\xa0\x6e\x73\x77\xbe\x00\x79\x2d\xf1\xbe\x06\x64\x87\xa4\x50\xf7\x73\x6b\xcb\x0c\xc9\xdb\xc6\xd3\x5d\xf3\x17\x4c\x19\x53\xcc\x8d\x75\x5b\xab\x31\x06\xee\xcd\xd9\xf8\x9c\x58\xfe\xde\xef\x35\xe6\x87\x67\xa9\x6f\x7e\x4b\xd7\x70\x04\x2b\x77\x8c\x1d\x87\x08\x9e\xd2\x3f\xef\x13\x56\xab\x6b\x2e\xb0\xda\x8b\x51\x35\x3b\xe8\x40\x3f\x00\x76\xdd\x1a\xef\x06\x21\x81\x4b\xd2\x7f\x41\x31\x79\xf3\x3b\x67\xde\xb9\xfc\x19\xba\x06\x7e\x0e\xf7\xc6\x0d\xa6\x51\x50\x85\x36\x19\xc1\x3a\xa0\xc6\x08\xe2\xd4\x54\x5a\x2b\x2b\x3e\xab\x2e\xd5\xb6\xb6\x54\x0d\x59\x9d\x7f\xf5\x6c\xc4\xa4\x1d\xf4\xb5\xfb\x89\xa8\xd5\x79\x93\x4a\x7b\x06\xb5\xe0\xdf\xc0\xf3\xb4\xc6\xaf\x1b\xb0\xd5\x87\x8c\x5e\xbd\x0b\x8f\x71\xa3\x37\xd4\x23\xfb\x00\x71\x15\x6e\x8d\x6a\x39\xf0\xc6\x9c\x18\x2a\xc0\x50\x72\x1f\x42\x97\x75\x9d\x2d\x87\x20\x6e\x13\x3e\xa0\x31\xf3\x4f\x30\x21\x18\x00\x46\xa3\x17\x0c\xe7\x7b\x5b\x0a\x4a\x06\x49\x80\xd1\xc8\x37\x91\x9d\x3a\x97\x71\xd9\x44\x65\x53\xf4\x88\xb2\xb0\x2f\xc4\x74\x56\xc4\x62\xda\x84\x91\x26\x35\xd3\x80\xa0\x06\x45\x33\x54\x71\x28\x17\xe9\xb2\x51\xb3\xfb\x36\x89\x7a\xaf\x8c\x53\xac\x0b\x09\x22\x5f\xba\x24\x6a\xbd\xb4\x0b\x4e\x1f\x1b\x38\xea\x84\x79\x5b\x7d\x85\xb6\x12\x0e\x9d\xe4\x9e\x28\x1f\x4d\x3f\x7c\x72\x5c\xfc\x03\xd7\xea\x33\x2b\xb1\xf9\x9d\x2b\xb1\x51\x2b\x21\x87\xe8\xa2\x39\x0b\x51\xb6\xf0\x82\x4b\xc4\xba\x0d\xed\x77\xcf\x18\x05\x41\xc8\x18\x40\x61\xa8\x51\xbf\xec\x93\x39\xcb\xf8\x73\x58\xab\x81\x61\xe3\xaa\xd2\x41\xa7\x20\xb8\x18\x6e\xaa\x38\x85\x6f\xaa\x1f\xee\x78\x99\xee\x8a\x7b\x30\x38\x90\x5e\x05\x2e\x33\x1f\x78\x1e\x95\xad\x7f\x82\x68\x57\x7d\xad\x87\x7d\xcd\xdb\x38\xd5\x45\xd7\xfd\x36\x28\xad\xa1\x37\xc7\xd2\xee\xdc\xe5\x28\xdb\xeb\x8b\x37\xd9\x14\x62\x6f\xc1\x00\xd1\xdc\x44\xd9\x53\xf4\x2e\x70\x4f\x94\xbd\x05\x0b\xa3\x29\x58\xce\x4f\x20\x58\x15\x8b\x2a\x1f\x43\xd5\x91\x63\xf7\x42\x85\x8e\x0c\x47\x6e\x1c\x26\xad\x61\x9d\xc2\x14\x28\xbb\xe1\xac\xba\x2d\xb9\x75\x9f\xb5\xbd\xf1\xfb\x27\x0d\x91\x2b\xdf\xe4\xb5\x85\x80\x61\x6d\x3d\xb9\x98\x13\xb4\xfd\x87\x38\x97\xf3\x99\xe4\xf5\x9b\xd2\x1e\x77\xdc\x32\x96\xa7\xb5\x19\x90\x76\xae\x0f\x38\x4e\x7f\x98\xb2\x71\xc7\xcc\xbb\xc0\xa6\x73\x92\xcf\x74\xde\x35\x9b\x46\xdf\xcd\xe5\x6d\x2f\xe1\xc9\x0b\x70\xc1\xa6\xb1\x40\x4b\xdf\xb3\x1b\x2e\xe5\x06\x13\x3d\x97\x89\xec\xdc\x73\x04\x19\x2a\x9d\x93\x0e\x19\x65\xdd\x04\x13\x66\x83\x85\xeb\xe4\x04\x61\xce\x66\x6b\x85\x6b\x21\x98\x3a\x23\x34\x72\x0c\xc6\x61\x04\x0b\xf3\x53\x99\x8a\xc3\x43\x97\x9d\x38\xbe\x78\x5e\xf2\x8d\xbd\x3d\xeb\xd2\x8d\xdd\xf5\xea\xf1\xb5\x60\xa5\xcb\x9f\xbb\xd6\x4e\xbe\x8d\xd0\x2e\x4c\x6b\x5f\x1b\x9a\x7d\x30\xe7\x3b\x69\x5a\xee\xaa\xf7\x25\xa9\x67\xf4\xfa\x46\x22\x8c\xe2\xc4\x60\x78\xfe\x91\x54\x17\x71\x32\x1a\x71\xcb\xda\x5c\xf9\x12\x93\x05\xaa\x76\x98\x07\x4a\xf8\x16\x73\x9d\x4a\x8f\x2e\x57\xac\xe6\xca\xf1\xbb\x05\x65\xb2\x65\x93\x32\x75\x85\x0d\x90\xd0\x46\x3b\x8d\x8f\x46\x6d\x7f\x73\x10\xfb\x18\x23\x77\x99\xec\xec\x7f\xce\x31\xbb\x2e\x8a\x5d\x9d\xed\x4f\x84\x4d\x19\xf2\xd1\xe8\x3c\xe1\x55\x5d\x16\x8f\xae\xfd\xf4\xe1\xe0\xbb\x4e\xd7\xaa\xb3\x0e\x9f\xeb\x5e\x8b\xe9\x0e\xf1\x3a\x18\xda\xa0\x86\xf9\x71\xcf\xdb\xf6\xc7\x56\x09\xcf\x41\x09\x66\x95\xc8\x14\xa0\x56\x09\x38\xdd\x62\x0c\x14\xcb\x03\x5a\x49\xe3\x6d\xcf\xe9\x66\xa5\x2c\xcf\x6a\xdf\xd3\xb3\x82\xb8\xb9\x2f\x16\x3f\x37\x65\xcb\x18\x78\x3a\x2b\xf2\x60\x38\xa3\x70\x08\xc4\xf7\x03\x8c\x99\x89\xe9\xc4\x8a\x32\x18\xce\x69\xcd\x6f\xf6\x82\x08\x0a\x3e\x79\x9d\x64\x77\x03\xc0\x58\xa1\x1e\xc5\xa0\x2c\xc4\xd9\x54\x8f\x97\x1d\x75\x26\xac\x2c\x8b\x7b\xef\xf2\xf5\x79\x92\xdd\x75\x56\xc0\x90\x96\xaa\x02\xfc\xff\x09\x95\xa0\x29\xbd\x94\x07\x32\x80\x40\x9d\xd5\x3b\x2e\x2e\xf4\x84\xef\xd8\x63\x30\xc3\xec\xff\xc3\x39\x95\x16\x1c\x1c\xc6\x7c\x97\xf1\x7b\xc8\x63\xff\xa4\x67\x82\xa9\xe4\x14\x1d\x10\xcc\x1a\xce\xc2\x62\x6d\xc3\x66\xb8\x4a\xc5\xd2\xa8\x6d\x55\xf2\x67\xcc\xba\xdd\xd2\xa3\xc4\x0d\x33\x7a\x78\xd8\x70\x95\xde\xdf\x57\xee\x88\x1f\xab\xe1\xb9\x1c\x82\x2a\x1d\x8d\x98\xcf\xec\x10\xd1\x9d\xb5\xc8\xb2\xb3\xd8\x4a\xc6\xe7\x0c\x4f\xb2\x17\xad\xea\x6a\x7d\xa4\x20\xa1\xf5\x15\x17\x16\x9f\x00\x57\x8b\x15\x86\x4d\x11\x3f\x60\x5f\x82\xe1\xfc\x48\x9b\x34\x68\x96\x57\x35\xcb\x63\x08\x4e\xa9\xaf\x41\x73\x89\x34\x5d\x7a\xd5\x48\xda\xe1\x0a\xff\xaf\x7a\xf5\x7f\x07\x58\x79\x70\x73\x5b\xd5\x83\x88\x0f\x20\x7e\x5c\x9a\xf1\x64\x70\xbf\xe5\xf9\x40\x6c\x22\x24\x18\xcb\xf2\xcd\xc0\x1b\xeb\xbd\x1a\x7b\x83\x22\x87\x48\x8f\x92\x8e\x53\xe3\x19\x20\x8a\x19\xca\x74\x43\x96\xef\xa4\x36\xf7\x97\xd6\xa2\x26\x20\x23\x28\x08\xa5\x23\x71\x3a\x99\x2c\x94\x9b\x11\x5f\xa5\x6b\x41\x15\x6a\x3b\xa4\x0d\xe9\x63\x56\xad\xa1\xd1\xce\x35\x70\x85\x2b\x78\xe1\x48\x86\x50\x67\xd2\xf3\x6e\x58\x7e\xcb\x76\xde\x30\xdc\xe0\x10\xb6\xa1\x8e\x70\xb0\x59\x5a\x01\x09\xbc\x40\x49\xde\x3c\x9a\xb5\xeb\x40\xf8\x01\x55\xa7\xb8\xad\xbd\x96\xc9\xb3\xbf\x1d\x7b\x1f\x3a\x66\xf8\xb2\xab\xf0\xb0\x3a\xcc\x3e\xbc\x43\x18\xa6\x12\xd3\x1d\x3b\x1b\xe0\x89\x78\xdf\xe5\xc5\x62\xd7\xa7\x4f\x1a\xb5\xc8\x25\x34\xf8\x4e\x70\x06\x78\x52\xd2\xec\xe1\x9d\xc0\x35\x4d\x92\x79\xc3\xd5\x7d\x5d\x75\x90\x3b\x06\xc3\xb6\x5a\x49\x2c\xd0\xe9\x2a\xdd\x1e\xab\xf5\x99\x96\x36\x4a\x12\x15\x91\xb8\xa9\x01\x0d\x8e\x46\xed\x20\x22\xea\x8d\x2f\x7f\x85\x4f\xa0\x35\x94\x4f\x54\xdc\x9c\xea\x41\x5c\xf9\x1d\x93\xc4\xf8\x8a\xad\x61\x2b\x9e\xe7\xe9\x68\xf9\xc1\x9b\xb1\x3a\x74\xa7\xda\x8b\xd1\x88\x21\x15\xe0\x94\xda\x91\x8e\x13\xf2\x14\xaf\xd8\x7a\x18\x26\x62\xc8\x2b\xb6\x0e\x13\xd2\x1e\x17\x40\x55\x47\xe8\xb0\x68\x60\x21\x1b\xf8\x86\x85\x68\x96\x51\xc0\xfc\xc8\x95\xd3\x10\x43\x25\x58\x70\xa8\x07\x8f\xe6\x94\x02\x05\x35\x3b\x6b\x76\x64\xed\x96\xb3\x5e\x3e\x21\xf4\x85\x5f\xa5\x31\x21\xd4\x99\x81\xd4\xb0\x80\x97\x89\x44\xbd\x2b\x7d\x86\xc3\x10\x03\xe6\x2c\x25\xcd\xa6\xc2\x78\xac\xc1\xc3\x3e\x9e\xd6\xd9\xde\x27\x0d\x83\xe0\xc3\xc1\x83\x96\xb1\x45\x7d\xa0\xb0\xcb\x2e\x09\xa1\x6e\xe0\x3b\x59\xc2\x63\x9d\xc5\x9c\xb6\xea\xd2\x58\x9f\x41\x09\x6d\x8d\x02\x50\xd6\xa9\x0f\x29\x52\xa8\xdb\xe1\xb6\x3d\x40\xd1\x1b\x2a\xfb\x8e\xcd\x0f\x41\x39\x21\x81\xaa\xd0\x38\xa3\x59\xf5\x06\x57\xed\x5d\x79\xeb\x48\x59\x9c\x44\x80\xf6\xcd\x46\xb4\x0c\x54\x2e\x37\x53\xa1\x5b\x87\x33\x13\xb2\xd5\xf9\x08\x20\xa4\xff\x4e\x58\xc4\x6c\xa9\xff\x3b\xe1\x50\xdc\x13\x27\x00\x71\x4e\xe8\x30\x76\xb7\x41\x1b\xff\x0d\x5e\x06\x5e\xe2\x0b\xcf\xc3\x97\x40\x63\x2f\x84\x2f\x1c\x72\x13\xc0\x94\x6e\xa5\xab\x63\x00\x30\x53\xa1\xdf\x77\xae\xe1\x54\xa3\xd8\xb7\xe6\x6e\x4a\x4d\x89\xca\xb3\xe7\xab\x40\x42\x92\xbc\xec\x33\x3e\x89\x88\x66\xd2\xb5\x99\x72\x4b\xde\xe7\xe4\xc4\x68\x45\x44\x6f\x56\x97\x21\xfb\xba\x59\xc9\x61\xa2\x44\xc6\x86\x1e\xa2\xa9\x4c\x99\x2a\x90\x8b\x8a\x0b\xb1\xe1\xf5\xcf\x6f\xbe\xf2\xad\x49\xa2\x38\x86\xd7\x7a\x86\x34\x95\xcc\x77\x06\x02\xd5\xa6\x6f\x8f\xb1\xf9\x4c\x78\x15\x97\x59\xc4\x93\xe8\xd1\x54\x54\x5b\xa2\x79\x95\xd1\xc8\xf6\x9a\x97\x46\x05\x92\xf6\x69\x87\x44\x77\xfa\xd0\x2c\xce\xb2\xbb\xd8\x22\x9c\x21\x1e\x45\x6b\xc9\x82\xee\x76\x34\x0b\xcf\x7f\xad\x96\xec\xb6\x2e\x96\xbf\x56\xcb\xf3\x8c\x5e\x85\xd2\x24\x74\x4b\x16\x57\xa3\x91\xbf\x0d\xb7\x5a\xce\x90\x51\x0f\xb0\x31\x26\xa8\x49\x4d\x88\x5b\x90\x59\xda\x99\x3c\x68\x92\x55\x7b\xc1\xe2\x78\xd1\xae\x88\xaf\xbd\x23\xb1\xa3\x27\x74\x1f\xe0\xba\x1d\x46\x48\xb3\x45\xcb\xb4\xa1\x50\x69\xd5\xc0\x30\x63\xc6\x44\xd8\xe5\x1f\xfa\x7c\xf1\xb0\x05\xda\x46\x39\x00\x2f\xb6\xe5\xda\xf8\xe1\x9a\xc4\x39\xbb\xb0\x15\x27\xe2\xc6\x2e\x92\xe2\xe8\x2c\xf5\xaf\xf0\x68\xe5\xe1\x96\x16\xed\x9e\x5c\x5e\x8a\x2c\xb6\xa1\x17\x15\x75\x5d\xdc\x78\x61\xb8\x1d\x8d\xae\xa7\xf8\x34\xbe\xb9\x2c\xe4\xcf\x25\xac\x3b\xf2\xb8\xb2\x4e\x5d\xec\x27\x37\xaf\x0b\xf1\x77\xa9\x9a\xab\xa0\x26\xb2\x0a\x3c\x8c\x77\x97\xc5\x14\x1c\x6a\x75\xe4\x13\xf8\x23\xeb\x40\x7a\x91\xdd\xeb\x02\x7e\x2c\x65\xfb\x60\x4b\xdd\x08\x16\xb9\xb3\x87\x20\x67\xd8\xeb\x79\x7d\xc9\x76\x31\x68\x1b\x12\x99\x1c\x67\x4b\xaf\xe9\x8e\xde\x28\x67\xa2\xfd\x7e\xf7\xf8\xa3\x82\x3a\x7f\x4f\xb7\xb8\xc4\xbf\xb5\x85\x8e\xdc\xc2\x71\x0b\x7e\xca\x7f\xd2\x1b\x73\xdc\x2d\xca\x5b\x72\x09\x89\x30\x19\x7a\xbd\xb2\x3b\xee\xf3\x67\xd4\x2d\x75\xb6\x6f\xab\x5a\xd2\x1e\xed\xca\x6f\x1f\x66\x9a\xf0\x5b\x2b\xbc\x97\xbb\x20\x0d\x6b\x48\xa3\x08\x95\x28\x8b\x87\x49\x13\xe8\x52\xbb\x48\xfa\x1e\x6e\x8c\xd0\x3b\x41\xa9\x30\xa6\xb8\x98\xe0\x81\x9d\xcf\x08\xdd\xf6\x55\x91\x39\xa6\xe6\x33\xb2\xc8\xaa\xef\xd9\xf7\xfe\x86\x8c\x46\xfe\x06\xec\x90\xe1\x79\x4b\x00\x1b\xcc\xd0\x0b\x6b\x3f\x0e\x37\x34\x92\x79\x6f\xb6\x94\xb5\xb3\x23\x89\xe1\x51\xc3\x19\x40\xee\x26\x27\x25\x53\x62\xd0\x06\xa8\x11\xca\xe2\x16\x72\xb9\xd6\xc5\x5e\xe6\xbf\x71\x8a\x51\xbf\x20\xd6\x31\x22\x54\x5a\x4d\x25\x4d\xbd\x5b\xd6\x5e\xa8\xab\xf6\x42\x2d\xe4\x19\x8a\x47\xa3\xab\x61\x98\x02\x9b\xa1\x73\x54\x8d\xd3\xc9\x55\xf3\xfc\xff\xbb\x3c\xa6\xa8\xc0\xe1\xc9\x57\x7c\x57\x33\x3f\xa6\x11\xcd\xe8\x15\x59\xe0\x09\x5a\xaa\xe5\xc0\xc7\x40\x2e\x13\x9c\x52\x19\x3b\xe7\xbc\x2e\xf6\x07\x3c\xa7\xda\x9f\x89\xde\x84\xbb\xe5\xc5\x99\x3c\x85\x7c\x9c\x05\xe2\x41\x9c\xec\x74\x7c\x45\xf3\x70\xb7\xf4\xac\xe9\x78\x81\x67\xcf\xc4\x5b\x24\x2a\x5d\x51\xa4\x6d\x8c\x00\x59\x7f\x5e\x96\xc5\xbd\x7f\x43\xc5\xe4\x57\xf9\x9a\xee\x5a\x9a\x05\x53\xad\x95\x16\x10\xcf\x2c\xf4\x80\xc8\x3d\xd6\x78\x03\x24\x6c\x7f\x98\x9d\xf9\xf3\x09\x3b\x8f\xc8\xd8\xfb\x67\x4f\x57\x41\xfc\x04\x15\xc5\x4d\xd1\xd2\xd6\xc8\x8b\xb5\x47\x01\x88\xa0\x1e\xe9\x45\x97\x0c\xec\x82\x29\xcb\x58\x57\xe0\x26\x63\x0d\xa9\x8b\x60\x5b\xdf\xec\x96\x18\x53\x19\x73\xf3\x7a\x6b\xb1\x24\xcc\x55\xd0\x8a\x63\x0d\xd4\x73\xb1\x1f\xe0\x3e\x0c\xc4\x70\x07\x52\x17\xf4\x8c\x4d\x99\xe5\xa4\x84\x24\xff\xd0\xc1\x56\x10\x51\x45\x5e\x89\xd4\x60\x2e\x81\x82\x1a\x66\x5c\x9f\x77\x93\x0e\x9d\xfe\xb2\x06\xcb\x49\x8d\xac\x43\xd7\xa8\x68\x4c\x75\xb6\x47\x3b\xef\x86\x75\x5b\x27\x15\xd7\xc2\xa9\x1b\x42\x87\x9b\x53\x3e\x2f\x83\xf4\xc5\x21\xdb\xd3\x97\x63\xd1\xe4\x03\x4d\x03\x95\x2c\xa1\x4b\x08\xed\x6e\x9d\x92\x7f\x3c\xa3\x6b\x5e\xf8\xca\xd7\x14\x24\xb3\x40\xdc\xb4\xd2\x61\xda\x0a\x18\xa5\x51\x9b\xc8\xfa\x44\xa6\x70\xef\x79\x4f\xdb\xdd\x6b\x67\x21\x59\xa3\x75\x4e\x0c\x89\xdd\x97\x61\xc7\x9c\x8d\x96\xdc\x43\x91\x17\xae\x29\x64\x18\x35\x2c\xad\x16\x92\xd9\xc3\x1c\x6c\xde\x17\x3f\x7c\xf5\x57\x74\x3d\x44\xef\x1f\x08\x1f\xd3\xa7\xfc\xc5\x50\xe2\x1c\xc9\x09\xc8\x35\x67\x8b\x7f\x38\x7d\x82\x17\x01\x97\x1a\x62\xcc\x1d\x47\x31\x8a\x47\xc0\x25\x2d\x33\x81\xbc\x73\x47\xa2\x6c\x54\xa5\x64\xf3\xed\xbf\xff\x49\x3b\x94\xc5\x36\x2f\xd7\x7a\x4f\x37\x61\xb2\x74\x93\xc7\x05\xe9\x52\x8c\x2d\x88\x4c\x9e\xb7\x6d\x28\x13\x8c\x05\xc9\xb2\x57\xcb\xad\x6d\x71\x0f\x87\x86\xba\x57\xa7\x20\x8b\x2c\x83\x5d\x72\xa4\x99\xf8\x36\x4e\xd3\x98\x89\xc1\xb3\xf8\x26\xce\xd4\xbc\xc0\x02\x9f\x1c\x03\x48\x28\xab\x55\x8b\xf6\xa2\x6d\x69\x06\x79\x97\x1a\xdb\xd9\xa4\xaa\x1a\x88\xda\xb8\x86\x18\xda\x91\x2d\x4d\x8e\xb9\x71\x24\x3f\x6e\xa7\x93\x1b\x47\x38\xd4\xf3\x8b\x49\x7c\x7e\x71\x54\xf4\xa4\xdd\x6e\x92\x9c\x6c\x20\x49\xc7\xce\x2f\x9d\x5f\x4c\x92\xf3\x0b\x27\x7d\x5d\x7c\x0c\x5e\x54\x51\x7d\xe7\xd8\x5a\x86\xce\xeb\xb7\x63\x2d\x10\x33\x36\x52\x0a\x6a\x8b\x1e\x43\x6c\xcb\x2d\xe0\x12\xf8\x7a\xf4\x18\xdd\x2a\x07\xa9\x82\x39\x1c\x66\x16\x23\xd9\x4b\xd5\x67\xa9\x7f\x0e\xe7\xe0\x20\x86\x23\xef\x7c\x46\x94\xc8\x1b\x57\x3b\x9d\xa8\x54\x72\x34\xd3\x34\x88\x2a\x1a\x27\x8b\xed\xeb\x0d\x50\xf8\x70\x66\xc2\x0d\x26\xd2\x0c\xb2\xcb\x0d\x26\xd3\x94\x0b\x2a\x8e\xa2\xa9\xa0\x8b\x27\x19\xda\xf3\x48\x27\x35\xb9\x27\x29\xbd\x96\x3f\xc7\xe9\x38\x5e\x5c\xbd\xde\x20\x09\x83\xa7\x35\xc4\xa7\xc9\x55\x70\x7d\xb9\xc1\x73\x0c\xbd\x5b\xef\xc6\x1b\xdc\xac\xc9\xb5\xf2\x50\x1c\xf0\xd6\xbe\x75\xa3\xe0\x66\x8c\x7e\x25\x88\x95\x4b\xad\x0f\x88\xeb\x2c\xde\xc4\xbc\x87\x83\xdf\xc1\x34\xc7\x53\x78\xbd\x94\x7f\x91\x2d\x86\xbc\xeb\x81\x2c\x6a\x1f\xb2\x9f\xdf\x7c\x15\xba\x26\xbc\x03\x36\x0e\xff\xdf\xff\xf3\xe7\xfc\xb3\x33\x24\x41\x59\x9e\x14\x37\x3e\x21\x32\x31\xa2\x46\x13\x1b\xae\xb0\xc8\x17\x8f\x6f\x12\xb1\xb1\x7a\xf4\x0d\xf7\x96\x6c\xdf\x19\xfd\x44\xdc\xdb\x3a\x2e\xa8\xa8\xd4\x88\xff\xa0\xd4\x97\x84\xce\x87\xa1\xe1\x53\xa4\xe3\x61\x4b\xd9\x64\xeb\x8c\xfe\xaf\x6a\xeb\xea\x9d\xe2\x22\xaf\xb2\xaa\x1e\x14\xe9\x80\x3f\xb0\xb8\xde\x3d\x0e\xe6\x82\x1c\x9a\xec\xf8\x1d\xdf\x0d\xe4\x9e\x0c\x3d\x57\x14\x2e\xbe\xda\x60\x60\x5c\xc2\xb1\x11\xbc\x17\xdf\x5a\xbf\xe5\x05\x84\xe2\xdd\x06\x3d\x87\x1a\xd6\x96\xb9\x36\x8b\xda\x61\x37\x2c\x65\xa6\x5b\x5d\x7a\x70\xf6\xd7\x9f\x77\xf9\x1b\x7d\x2d\xdf\xf6\xb6\xb2\x9f\x4e\x3b\x2c\x39\xc1\x83\x17\x98\x23\xfc\xa5\xc2\x52\xfa\x3f\x2e\x29\x25\x34\x5a\x1a\xb1\xe8\x34\x46\x0b\xd1\x46\x01\x6d\x09\x41\x97\x31\x2a\x31\xfc\x58\x9c\x27\xe4\xab\x63\x82\x67\xab\x2d\xb7\x5f\x9a\x2a\x81\x69\xd8\xd8\x37\xb4\x85\xe8\x31\x9b\x76\x84\xad\xb5\x65\x91\xa0\x08\xc1\x2c\xe1\x0d\xc3\x69\xc7\x96\x7c\xea\x8d\x19\x2e\xb1\x24\x5f\xbf\x32\xeb\x21\x5f\x50\x26\x0f\x21\xfe\x35\x04\x3c\x3e\x23\x81\xc9\x14\x44\xab\x27\xad\x03\x57\x05\xb6\x05\xc4\xd1\x4d\x38\x21\xc1\x7c\x61\x3f\x28\xe3\x24\xf9\xd8\x65\x9e\xa4\x5e\x3d\x6f\xa0\xa4\xfa\x94\x26\x4a\xff\x63\xe6\x2e\xfb\x62\x0f\x22\xf3\xff\x12\x73\x17\xd5\xd9\x7f\x99\xb9\x0b\xda\x9b\xe8\x6e\xd1\xde\x04\xc3\x6c\x99\x35\x6b\xab\xeb\x7f\xc4\x06\x26\x9d\xa0\xda\x87\xab\xca\x23\xa7\x93\x08\xd9\x24\x5d\xdf\xee\x1a\xdf\xdb\x27\xcb\x6c\x45\x19\xed\x29\xcd\xae\x0a\x69\x20\x73\xa4\x7a\x5e\x8f\x1d\x8b\x9a\xdd\x29\x3b\x16\xd7\x7e\x65\xfb\xaa\xd1\x56\xde\xa7\x97\xaf\xcf\xb7\xaf\x2e\x3b\xfa\xd6\x9e\xa8\xae\x81\xcb\x91\xd8\xc7\xf8\x65\x53\xd7\xd5\x89\x6b\xbd\xea\xc0\xfe\x3f\xae\xad\xfe\xbd\x82\x06\x4b\x21\xac\x35\x00\x46\xf8\xe0\x2e\xd7\x4b\x85\x0f\x8d\xc6\xc6\xab\xd7\x84\x4c\x36\x52\x74\x08\xa4\xd4\xd5\x71\xf3\x00\xc4\xfa\x5b\x28\x14\x37\x1f\x8d\xbb\x25\x1e\x9d\xe2\x8e\x81\x64\xe2\xbb\x27\x08\x9f\xf6\xc9\xe1\xd0\x5f\xa1\x43\xb7\xf4\x21\xcc\xab\x89\xdf\xad\x97\xbb\xcd\x00\x9d\xdc\x48\x4d\x41\x46\xdd\x14\xa4\x4d\x3f\xea\xa5\xef\x26\x1c\xa3\xa9\xac\xb0\xd4\xbf\x64\xa2\x79\x20\x1e\x75\x61\xd3\xae\xfd\x1f\xa7\x82\x14\xf5\x63\x5f\x19\x72\xa9\x17\xf6\x83\xba\x32\xe4\x63\xd7\x95\xa1\x5e\x3d\x7f\x65\xa8\x3e\x7f\xdf\x95\x11\x9b\xe4\x6c\xa7\x7c\xf4\x91\x81\xf9\x5a\x5b\x98\x31\x3f\x46\x27\x5e\xa7\xf2\x12\xf9\xe4\xa0\x69\x7f\x66\xa3\x94\xa8\x9d\xdc\x4d\x19\xbd\x84\x0d\x82\x59\x7a\xd5\x79\x1e\x19\x7b\x83\x69\xce\xee\x06\xbb\x6c\x70\x39\x60\xca\x24\x1a\xf8\xe8\x2a\x5c\x49\x1d\x19\xd6\x37\xcf\x18\xcb\x1a\xc9\xa7\x96\xaf\x3f\xca\x5c\x75\x4c\x3c\x67\x7e\x60\x20\x85\x25\xd3\x48\x35\xa8\xf6\x8f\xcd\x24\x2a\x65\x11\xf3\xaa\x72\x6c\x8b\x4a\x9e\x96\xbc\xda\x2a\xe9\x96\xac\xd2\x0a\x4d\xf5\x3b\x6f\x69\x33\x92\xce\x7b\x3a\x1e\x8d\xe2\x46\xba\x1f\x6b\xec\x78\x19\x47\x27\x2e\xe3\x58\x5c\xc6\x31\x46\xeb\x8d\x5a\xb7\x63\x64\xd9\x6c\xe2\xd2\x07\xf3\x99\xd8\x4f\xe7\x94\xbf\xb5\x57\xb7\xef\x30\x39\xab\xdd\x74\x12\x39\x1c\x74\xda\x6c\x03\x97\xcd\x4a\xf4\x19\x11\x10\xd6\x22\xee\xf0\xe4\xe6\xb4\x15\xe6\x35\xe6\xd2\x50\xf9\xb6\x69\x12\xce\x16\x2f\x02\x31\x07\x96\x14\x0a\xb4\x97\x00\x88\x4f\x9d\x5d\xbc\x7b\xf6\x18\x5a\xda\x24\xdd\xd7\x49\x07\x5d\xa0\xb4\xc4\x56\x4e\x4c\x01\xc0\x3d\xce\x39\x22\xd3\x1b\xd6\xf2\x92\x8f\xec\xa8\x66\x12\x40\x8c\x0d\x7a\xd4\xb4\x56\x3f\xff\xdb\x47\x53\xcb\x86\x9c\xf9\xc6\x26\x09\x72\x94\xaa\x48\x50\x69\xcb\x96\x7b\xb5\x4a\x01\x88\x40\x74\x91\x50\xbe\x5e\x1f\x0e\x48\x4a\x4f\xab\xa2\xb4\x4c\x21\x80\xbe\x53\x98\x6c\x35\x5b\x4f\x04\x73\x7f\x6c\xc7\x64\x53\x42\xc0\x6a\xba\xbf\xad\xd0\x72\x4b\xac\x1a\x55\xd1\x04\xec\xf2\xf9\x1a\x5c\x20\x23\x27\xc7\x05\x9c\xc1\x7e\xd9\x45\xef\x32\xbb\xc1\x17\x71\x10\x16\x65\xd1\xd8\xe7\x24\xec\xa8\x3e\x8e\x27\x5d\x1f\x51\x72\x44\xe5\x1c\x29\x27\xa8\x8d\x1b\x70\x5e\x4a\x2a\x65\x23\x32\x2d\xf8\xb7\x41\x6f\x18\xc6\x52\xc6\x65\xf0\x4f\x74\x19\x2a\xf3\x89\xc1\x66\x18\xfa\x2c\x4c\x57\xa9\x8e\x4f\xb4\x56\x26\x1f\xd0\x37\xab\xb9\xcf\x40\xc2\xb5\x19\x8d\xa2\xd7\x5c\x2c\xaf\x7d\x60\x7b\x30\x29\xb0\x74\x3e\x5a\xac\x32\x63\x8b\xca\x26\x93\x05\xd9\x0c\xc3\x74\xc5\xd6\xa3\x51\x74\x19\x72\xf8\xe1\xeb\x94\xf5\x7c\xc5\xc6\xf3\xf5\xe1\x20\xbe\x24\x7e\xb5\xc6\x22\x5a\x36\x76\x51\xbd\x73\xb8\xf4\xf6\xe0\x22\x77\x64\x56\x34\x58\x75\x38\xc6\x9f\xb8\x61\xbe\x3f\x19\x47\x10\x14\x5c\x86\xda\xb4\xaa\x61\xe0\x70\xf9\xfe\x13\x0a\xc9\xfa\x88\x0c\x17\x51\xf9\xde\x2e\xf3\xba\x32\x3f\x2c\x12\x15\x51\xa2\x19\x42\xc8\x84\x4f\xf3\x93\x30\x31\x21\xd6\x76\x99\x15\xed\xae\x2b\x55\xa4\x1d\xf6\x4a\xad\x83\x7b\x31\x35\x16\x0b\xa6\xef\x3a\xc6\x37\x10\x84\x9c\xc5\xcf\x79\x9d\xed\xba\x6e\x5d\xfa\x5c\x06\x11\x87\xc6\xd1\x03\x59\xb8\x8f\x8a\x98\xd1\x05\x0e\xa5\x13\x35\x5f\x3e\x4f\xeb\x98\x9e\x8d\x0f\x4f\x33\xa9\x80\xb3\x32\x76\x28\xa8\x8e\x54\x03\xa2\x27\x15\x6e\xb9\x2f\xcf\x80\x46\x9c\x2a\x6c\x66\x44\xa3\x7f\x2c\xcf\xc0\xef\x75\x49\x61\x11\xe6\xdd\x6e\x94\x39\x6c\xf6\x4b\xa2\xf0\xc7\xed\x43\x64\xc7\x60\xfa\x50\x57\x8e\xe7\xcc\xd1\xec\x0f\xd0\x38\x8c\x0c\xe4\xdf\xee\x64\xcc\x36\xfb\x9c\x10\x8f\x40\x0e\x06\xf7\x8a\x82\xe4\x5b\x90\x97\xa3\x71\x55\x25\x61\xd2\x97\x9a\x43\x87\x11\xa5\x43\x1d\x24\x14\x8f\x6d\x47\x62\x20\xa9\x71\x88\xdd\x04\x3a\xc1\x8e\x55\xf5\x80\xc9\x74\x0b\x0d\x85\x2c\x2c\x7e\x33\xf2\x0a\xdc\x61\xb6\xfa\x56\x19\xe1\x75\xd5\xe6\x50\x5b\xcc\x8d\xdb\x91\xdf\xa3\x17\x68\x73\x21\x4c\x63\x7f\x0c\xec\xad\x1d\xfe\x57\xe1\xd5\xc8\x46\x3a\x1e\xd1\x79\x14\x74\x85\x2d\xdd\xea\x78\x38\xf6\x81\x31\xa3\x7b\x12\x1b\x1d\x58\x3a\x6d\x98\x56\xe7\x1a\x44\xcd\x46\xda\xda\xa7\xa3\x0d\xae\xc4\x11\x42\x36\xc7\xa7\xf1\x3e\x4d\x28\xb7\x14\xf8\x29\xa4\x68\xef\x44\x52\x72\x2f\x2f\x07\x2e\x84\x0d\x2e\x07\xcf\x60\x37\xe4\xdf\x3b\x43\x35\x8b\xb1\x0b\x54\xd1\x1b\x9f\x3b\xea\x40\xe1\xbf\xa3\xa7\x19\xa1\xdb\x25\xe8\x3b\x1c\x13\x98\xa8\x61\x2a\x23\xf8\xd9\x96\x90\xc0\x13\xa3\x78\xf6\x16\x8a\x5e\x7e\x05\xfd\xee\xf5\x98\x41\x04\x24\x95\x16\x7f\x13\x26\x66\x4b\x74\xaa\xa1\x6d\xc8\x7b\xb3\xac\x6d\xf4\x68\xdb\xe9\xe3\x0f\x87\xe1\xd0\xea\x0f\x0b\x95\x3e\x65\x61\x5a\x6e\x7b\xf3\xcc\xa7\x1f\x66\xb4\x90\x42\x46\xfd\x96\xf1\x84\x2b\x21\x66\xd1\x42\xfd\xd0\x92\x61\x16\x75\x4a\x85\x59\xf4\x12\x89\x30\x8b\x4e\xa4\x34\xea\x70\xdd\x94\x4e\x93\xea\x0a\xc1\xc0\xe5\xe4\x44\xc6\x1f\x31\x8e\x5e\x5f\x57\xdc\xde\x56\xce\x9f\x93\x6d\xf6\x19\x5c\xa7\xf4\x7f\x30\xc9\x3d\x4b\xd3\xec\xe1\xc5\x39\xee\xb1\xf6\x87\x88\xa7\x4f\x65\xb5\x7f\x61\x0a\xfb\x8f\x25\xc5\xd9\x54\x0b\x4a\xf5\x8e\x2b\x73\x80\x11\x5a\x2b\xec\xe6\x61\xdd\xf2\xf8\x5a\xe9\xa9\x55\x78\x25\x67\x7b\x5e\xde\xfc\x3f\xb2\x7a\x0b\x17\xd5\xb7\x45\xb1\xef\x74\x93\xb2\xe2\x32\x42\xb7\x8e\x57\xe9\x6d\xbe\xcf\xec\x10\x8b\xfb\x2c\xcf\xb5\x85\x83\xc5\x29\xd8\x9f\xf4\x7b\x28\x8c\x9f\xbe\x7e\xfb\xf5\xbb\xd0\x83\x8f\x0c\xe0\xff\x49\x5d\xec\xe5\x2f\x69\x14\xe1\x78\x8e\x4a\x29\xc4\x8c\xe2\x1a\x06\x48\x09\xb6\x04\x8f\x8d\x34\xff\x0d\x13\x03\x7b\x6f\x6c\xe6\x4f\xf1\x62\xb6\x16\x0a\x2d\x51\x36\x6e\x1b\xc5\xcb\x89\x5b\x5c\xcc\x18\x98\x31\x69\x89\x61\xaf\x9a\x36\x55\x78\xad\xde\x83\x93\x9e\xb6\xf6\xe8\xaa\x2b\xfb\x5b\x0e\x7d\x3e\x36\xeb\xfd\x3a\x4c\xc1\xb2\x72\x34\xd2\x86\xc2\xa2\xc2\xe6\x75\xc8\x26\x89\x55\x2a\x0d\xd2\xd1\xca\xc7\xee\x9e\x66\xe1\x76\xc9\x03\xe8\x85\x5e\x85\xdb\xe5\x26\x88\x16\xee\x27\x47\x23\xfe\x3a\x54\x76\x80\x58\x96\x8c\x46\xd9\xf8\xea\x52\x7c\xc4\x7c\xa3\x6d\xb6\x64\x43\x80\xab\x27\x6f\x41\x88\xc3\x64\xda\x2f\x4e\x64\xa3\x91\x70\xe2\xdc\x52\x78\xf8\x17\xb6\x38\xb9\x63\x43\xa3\x9e\x0d\x5d\xf4\x8d\x42\xda\x74\xb0\x8e\x08\x1d\x9d\xc7\xc7\x9e\xae\xe5\xfb\xf1\xdc\xd9\xa5\xf3\xae\x18\x20\x6d\xf3\x2f\xb3\x86\x7a\x0a\xae\xec\xc5\x21\xb8\x4d\xcc\x99\x93\x02\x0a\x40\xa3\x02\x0c\xd2\x30\x91\x06\x5d\x74\x13\x6a\x09\x9c\x7d\x69\xe8\x8e\x9a\x32\x62\xfd\x86\x2c\x14\xf6\xd5\x26\x77\xc9\x68\xe4\xa7\x21\x0f\x13\x42\x3b\x44\xf5\x1c\x8c\xce\x60\x00\x0d\x2b\xff\xce\xea\x29\x74\xa6\xc6\xd9\x6c\x21\xc1\x5d\x8b\x67\xc4\xb1\xf7\x37\x34\xa2\x9c\xa6\xc6\x60\x52\x1e\x81\x61\xb8\x25\x4f\x08\xd7\xe6\x60\x35\xc3\xf5\x80\x51\x35\x58\xc9\x7a\xda\x28\x59\x42\xdb\xd8\xdf\x2e\xbd\x89\x37\xde\x06\x9e\x47\xe8\x95\x26\xf7\xb3\xb1\x37\x35\xf7\x51\xbf\x99\xe6\x15\xa1\x57\x27\x23\x93\x3b\x08\x77\x6b\x63\x5b\xcb\xb9\x60\xa9\x26\x6b\x9f\x3a\x9f\x04\x6d\x7f\xfe\x67\xce\x50\x66\xec\x55\x33\xcd\x4b\xc9\xa9\x52\x4f\x0e\xc3\x23\xce\xe4\x8e\x8e\x97\x43\xe7\xd9\x02\xfb\xad\xcd\x24\x9a\xa4\x82\xb2\xb7\xe9\x24\xe8\x63\x61\x7e\x2a\x5a\x09\x6f\xae\x0e\x6a\x09\x5f\x3c\x4f\x2f\x61\x6f\xfd\xe2\x81\x13\x82\x00\x9c\xd7\xb3\xf9\x06\x4d\xa2\x02\xa2\x4d\xb6\x43\xf5\xe3\x70\x78\x3a\x52\x89\x2f\x65\xd1\x17\xb0\x4a\x10\xe3\x54\x5a\xd6\xe3\xba\x35\x2a\x90\x46\xb3\x77\xc5\xde\x6e\x53\x17\x7b\xfb\x95\xa6\xf3\xc4\x55\xe6\x88\x21\x0c\x41\xb5\xe5\x0f\xef\x8a\x9f\x36\x91\xcf\x95\xaa\xed\xfc\x6f\x1f\x2d\xfd\x15\x9b\xa4\xbf\x26\x6b\xd2\xfe\xf1\xf1\x79\xb6\xe0\xa1\x09\x46\xc2\xcc\x5a\x71\xca\x68\x4d\x33\xb3\xd6\x63\x36\xae\xc7\xf5\x38\x1b\x67\x47\x3c\x1a\xb5\xd3\xfb\xd3\xc5\x91\xf4\xfd\xfe\xf8\x3c\x9b\xf2\x07\x1e\x5b\x32\xe5\x7a\xf9\x54\x06\x26\xcc\xcf\x6a\xbe\xa6\xf3\xcf\x08\xdd\xd8\x65\x17\x58\x16\xd9\x65\xaf\xa0\x0c\xcd\x31\x2d\x1d\xcb\x8e\xdd\xec\x71\xc8\x7a\xc0\x88\xd2\xb2\xdc\xd7\xb8\x8d\x53\x46\x68\x6d\xa9\x66\xb2\xea\x4d\xfe\x79\x59\xb2\x47\x78\x65\xa0\x0a\x62\xc1\xff\x90\xfa\x9c\x5c\x4e\xe6\xe8\x2c\xf3\x97\xb7\xa1\xbd\x34\xb8\xbe\xb5\x89\xb2\xf3\x9b\xd8\x8a\xb7\x52\xdc\xe6\x7b\x1f\x79\x63\x3e\xf6\x04\xdf\xb9\x67\x65\x9d\xc5\x3b\x5e\x4d\xae\xaa\x49\xcc\xf2\x3b\x56\x4d\xf8\xce\x93\x9c\xba\xe8\xf7\x09\x4b\x83\x27\xbe\x0b\x6a\x7a\x1f\xd4\x0e\xff\xb7\xd5\xcf\x28\xfa\x3d\x52\xdd\x63\xf0\x84\xbe\xd7\xc1\xd3\x1d\xdb\xdd\xf2\xe0\xd3\xd9\x8c\x26\x5c\xb0\x35\x8f\xc1\x13\x1a\x3e\x05\xc3\x19\x85\x97\xef\x59\xc9\x59\xf0\xc7\x19\x44\x9f\x28\x76\x85\x6e\xe4\x7d\x94\xa6\xa9\x77\xa4\xd5\x96\xed\x79\x20\x19\xf7\x38\x2b\xe3\x1d\xf7\x68\x55\x97\xc5\x35\x0f\xa4\xbd\xec\x4c\xb6\x14\x4d\x66\xb3\xd9\xcc\x3b\xd2\x7d\xb1\x7b\xdc\x14\x79\xf0\x94\x47\xef\xab\x2c\xe1\x55\xf0\x87\x23\xcd\x6e\xd8\x86\x07\x4f\x55\x19\x07\x9e\x47\xb1\xed\x7c\x36\x53\xd6\xb5\x73\x18\x44\xb1\x67\x31\x0c\x14\x87\x31\xa7\x68\xa8\x17\x0c\xe7\x94\xe5\xd9\x8d\x99\xc0\x9c\x56\x7b\xce\x93\xe0\x42\x35\x79\x7f\x93\xe5\xc1\x8c\x56\x8f\x79\x1c\x40\x6a\x85\x2a\xfb\x3b\x57\xfd\x5c\xcc\x9e\xef\x68\x06\x2d\x5a\xdd\xec\xb2\x9c\xbf\xdf\x65\xf9\x35\x4f\xec\xe5\x4b\x32\xb4\x64\x86\x29\x98\x05\x48\x3d\x3d\x85\xb9\x9a\xe3\x91\x0a\x94\x6b\x37\x56\x43\x37\x99\x8f\xbd\xbc\xc8\xb9\x67\x0d\xb2\xaa\x4b\x06\xeb\x32\x9c\xd3\xe2\xb6\x7e\x7f\x53\x24\x3c\x40\x27\xd4\xa8\xb8\x15\x1f\x16\x33\xa9\xeb\x92\xc5\xb5\x3d\x99\xb2\x10\xf7\xdd\x2f\xc1\x2b\xfe\x4a\xfe\xfe\xab\xf8\x7d\x3c\x52\x26\x40\x3a\x58\xad\x8f\x14\x32\xc8\x02\xdf\x0d\x4b\x9d\xf0\x9a\xc7\xf5\x7b\x31\x0a\x84\x39\x8f\xc2\x35\x54\x05\x4f\x45\x8e\x71\x35\xac\xb1\xe3\x40\x36\x25\x8b\xbc\x23\x2d\x72\x0c\xc0\xd1\x7a\xbf\xbf\xad\xb6\xde\x91\x62\x8c\x4d\x08\x0d\x2e\xca\xab\xe0\x49\x34\x0c\x9e\x9c\xd5\x73\x56\x58\xaf\xde\xf1\x48\xa3\xdb\x48\x74\x6a\x6a\x5f\xcc\x70\x93\x82\x3f\xce\x68\x72\x5b\x62\xb8\x98\xe9\xa7\xe2\x3b\xfb\xdb\x5d\xd5\xac\xea\x54\x11\x23\x0a\x9e\xf4\x29\x79\x9f\x47\x01\x34\xc4\xbd\x71\xca\x2f\x8e\x62\xb8\xb7\xa2\xbf\xa3\xa8\x52\x67\x39\x7b\x8f\xab\x04\x11\x46\xf2\xe0\x49\x2d\x61\xf0\xa4\x67\x76\xa4\x77\x3c\x4f\x8a\xb2\x82\x56\xf5\xcd\x5e\xfc\x95\xd4\x82\x3a\xd5\x0b\x36\x1a\xfd\x00\xa4\xd1\x34\xe1\x7c\xff\x35\x32\x8a\x99\xc0\x40\xd9\xb4\xbe\xd9\x4f\x8b\xe8\x2a\x7c\x02\x38\x44\xc0\xcd\x0c\xa6\x98\x42\xb8\x52\x28\x46\x48\x15\x70\xfc\x1e\x41\xa9\x55\x4d\xbc\x9b\xc2\x3b\x00\xbe\x8e\x6a\xa2\x58\xd6\xb0\x36\xe0\xbd\x5e\x40\xbb\xae\x55\x61\xaa\x2a\x38\xad\x10\xd2\xfb\x9a\xdc\xa3\x4f\x65\x91\xf0\xf7\x62\xfb\xed\x6f\x38\xa0\x38\x85\x95\x9c\x8a\x3a\xe6\x33\xd0\x0c\x21\xe1\xb9\x86\x58\xab\xbb\x29\x80\xcd\xc9\x66\xa2\x06\x36\x91\xd0\xf4\xdc\xe7\x64\x35\xfd\xbd\x23\xcd\x04\xe5\x81\xf0\xf2\xc6\x89\xdf\x43\x9e\xb2\xa9\x03\x47\xa3\x91\x8a\xfc\xc2\xef\xb2\x98\xff\x98\x3d\xf0\xdd\x4f\x02\x58\x2f\xe7\x4b\x3f\x9b\xe2\x39\x9c\xee\x1f\x00\x80\xc3\x9e\xba\x12\x66\xb0\xe3\x70\x38\x23\x41\xbb\xe9\xbc\x51\x69\x2e\x20\x4d\xd6\xb9\x0f\xf5\x4f\xbe\xb3\xaf\x97\xb3\x66\x37\xa6\xcd\xb6\xa3\x0d\x5e\x41\x5d\x8d\xba\x80\x37\xd4\x90\x3e\x35\x80\xfe\x82\xc6\x06\xa4\x9b\x3d\x98\x83\x70\xba\x1b\x03\xf2\x56\x0f\xe6\x78\x9c\x6e\xdc\x75\x06\xac\x6e\xba\xce\x50\x57\x87\xcf\x02\xbc\x33\xb4\xe6\x89\x79\x69\x8f\x8d\x93\xd0\xec\xb3\x71\x9c\x5e\x3e\x71\x38\xc9\x3d\xb3\xbe\xef\x83\x9c\x67\xce\x5c\xcf\xe0\xc4\xab\x97\xf6\xd6\x3c\x89\xcd\x2e\x9b\x07\xba\xd5\xaf\x3c\xba\x58\xd8\x3e\xba\xb2\x72\x5c\x3f\x38\xd0\xaf\xac\xd9\x1e\x6a\xdf\xbb\x48\x3c\xe2\xf4\xf2\xb6\x11\xca\xda\x6e\xa8\x96\x51\x9d\x43\x6a\xbf\x44\x7a\xc8\xbc\xdd\xd2\x6c\x34\x6a\xce\x1b\x2f\x68\x19\x31\x5b\x23\x13\x96\x24\x28\x85\xc8\xaa\x9a\xe7\xbc\x54\x41\xae\x1d\x66\xe7\xf9\xe3\xff\x92\xd3\xee\xa0\x95\xd1\xc8\x20\x9e\xfb\xb3\xf0\x04\xf6\x68\xbf\x24\xf4\x1f\x59\x99\xe6\xe9\x46\x3a\xe4\x70\xf0\x61\x27\xf4\xcb\xaf\x6f\xf6\xf5\xa3\x4f\xa8\x5b\xfa\x25\xc4\xc0\x6c\x15\x7f\x55\xb2\x7b\x55\x28\xaf\xf4\xa9\x24\xa0\x3f\xbf\xad\x8b\x1f\x55\x3d\x9f\xbc\xa8\xd2\xd1\x85\x8b\x1f\x59\x96\xf7\x82\xd7\x34\xcd\x76\x3b\xf0\xca\x9b\xd1\x19\xed\x5a\x86\xad\xdb\xdb\x97\x4d\x15\xbf\xd3\x1b\x18\x00\xbc\xac\x3b\x35\xfb\xd0\x65\xf5\x8c\xb0\xa9\x64\x49\x76\x5b\x85\x7e\x0b\x2f\x23\xcd\xba\x74\xdc\x6a\x82\x39\x39\xeb\x21\x5d\xba\xf1\x3a\xee\x9b\xf2\x9b\x01\xac\x5e\xd5\xac\xbe\xad\x74\xda\x85\xbb\x2a\x3c\x71\x25\x9c\x0b\x42\xb2\xe7\xfd\x63\x1e\xab\xc4\x2d\x77\x32\x08\xde\x5d\xd5\x70\x03\x92\x92\xed\x87\xb0\x5e\xd6\xd3\x87\xc0\x79\x79\x66\x2d\x1c\xd4\x7a\x84\x5a\x8f\x7d\xb5\xa4\x94\xe6\xe1\xd2\xb4\x9b\x5c\x9c\x59\x8b\xb8\x54\xdf\x82\x3f\x13\xeb\x0d\xc6\xf4\x78\x78\xed\x54\x57\xab\xa2\x1a\x8c\xad\x77\x72\xdc\x8f\xe6\x5b\xdb\xae\x6f\x3d\x62\xd3\xc7\xf6\xb7\x1e\xbb\xbf\xa5\x1a\xb8\xdf\x6a\x1d\x37\x64\x45\x04\x7a\xb2\x8e\x01\xc8\x2d\x7f\xb8\xe3\xe5\x8e\xed\x65\xe4\x3f\x39\x4c\xe0\x93\xc2\xa7\x63\x3b\x39\x95\x84\x0e\x02\x2a\x70\xf8\x69\xfb\x8a\x02\x37\x8e\xcc\x75\x15\xca\xf7\x2b\x58\xfd\x74\x57\x14\xa5\xdf\xdc\x08\x33\x4a\xf8\x22\x36\x50\x2a\xc1\xf5\xc2\x8c\x65\x5a\x6e\xa2\x50\xcb\x47\x2a\x19\x27\x1b\x2d\x94\x86\xea\x4b\xd3\x72\x34\x6a\x16\x6d\xda\x45\x91\x5a\x3b\xd3\xf3\x53\x19\xe8\x3e\xe8\x46\xff\xde\xd0\x48\xff\x8e\x8e\x84\x36\x7b\xda\xb6\x3b\xaf\xda\x45\x3b\xf7\x7b\xdb\x6a\x17\x3e\x6d\x75\xbf\x5b\x5a\xe9\xdf\x15\xdd\xe9\xdf\xbb\x23\x46\xec\xf3\x70\xb9\xbc\x50\xf5\xb7\x6c\x8f\xdd\x5a\xe1\x8b\x3f\x34\x1d\xe7\xc6\x33\xba\x79\xb6\x46\xf4\x5c\x8d\x63\xd0\x52\xb6\xc9\xf1\x38\xb3\x93\x69\x77\xbb\x36\xcd\x2a\x47\x10\x52\x71\x9f\x91\x91\x74\x11\x96\x2c\x7c\x11\xce\x52\x75\xdb\x68\x4b\xbd\xe9\xc0\x5c\x4a\x18\xd1\x44\x5e\x45\xd8\xdb\x41\x37\xfe\x72\xab\xd8\x28\x4c\x46\x9e\xb9\x2b\x9a\x28\x6c\x81\xb1\x69\x9e\x8e\x8b\xea\x3e\xab\xe3\xad\xdf\x3a\xae\x5a\xde\x40\x9e\x62\x56\x71\xa9\xd5\x09\x9f\x1e\x82\x19\x7d\x0c\x26\xf3\xe3\x22\x2a\x39\xbb\x5e\xa8\x97\x32\xf4\x34\x56\x99\xfe\x41\xd4\x99\xfe\xc1\xa9\x64\x57\x98\x8b\xf7\x33\xe7\xb5\x74\x0d\x6f\x75\xd3\xe8\x45\xa9\xaf\xf4\x50\xe6\x5d\xbd\x60\xb8\x0a\xa8\x33\x81\x5e\xdc\x5a\xf6\x6b\x31\x94\x59\x6b\x36\xad\x0e\xac\xd9\x24\x28\x81\x37\x43\x98\x1d\x8f\x6d\xde\x41\x0a\x65\x96\x72\x2b\x1e\xc2\x7c\xfa\x20\x77\xf8\x31\xcc\xa7\x8f\x6d\x0c\x89\xdb\xa3\xc0\xe3\x4e\xe2\xf0\xbb\x07\x77\xf3\x74\x1f\xf2\x6f\x73\x6b\x03\xfb\x83\x63\xe7\xa5\x98\x89\x35\x82\xd6\x4b\xd5\xf7\xc3\xfb\x4c\x7d\x5b\xd5\xd7\x25\x8f\x00\x3a\xa5\x7b\xc1\x6e\xd9\x1e\xc3\x54\x80\x7e\xb2\x89\xb0\x4b\xa0\x0c\xca\x1e\x2c\x1d\x87\x65\x3f\x7e\x2e\x1b\x98\x18\xbe\x14\xc6\x47\x44\xbe\x56\x51\x09\x5f\x06\xb9\xa1\x52\x8c\xc2\x0b\xfc\x46\xd1\x1e\x2e\xf6\x97\xdd\x6c\x42\x10\x33\x16\x53\x68\x3b\xad\xca\x98\x02\xad\xa9\x4b\xd0\xfb\x5d\x3d\x6d\xa5\x08\x55\xb5\x9e\x42\x65\x9d\xec\x4d\x15\x84\x73\x42\xbd\xea\x4e\xa0\x2a\x24\x7e\xb3\x9b\xcd\x7b\x4c\xed\xac\x70\x33\x96\x57\xc5\x6d\x19\xf3\xf7\xd5\xdd\x06\x08\x63\xfb\x6a\x04\x8a\xf3\xed\xdd\xe6\xcd\x8d\x4c\x58\x2c\xe9\xe8\xfd\x6d\xb5\x85\x08\xf3\xe6\x9b\x98\xe2\x4f\x70\xec\xe4\xd8\x20\xd2\x6c\x6f\xcb\x92\x39\xb6\x76\x5a\x8a\xcd\x9b\xc4\xa0\xa8\xf9\x46\xcc\xd7\x2f\x29\x13\x64\x07\x65\x82\x20\xa0\x17\x67\xf0\xef\x9c\x99\x99\xa2\x95\x83\xf4\xd8\xcc\x52\x5f\x4d\x8f\x49\x4a\x40\xf2\x68\x04\xa5\xdd\x8d\x52\x0c\x08\xeb\xbe\x72\x3b\x51\x48\xd2\xea\xa5\x6a\x15\x9b\x6e\xac\x77\xa2\x1f\x66\x6e\x01\x82\x18\xcf\x2b\x37\x11\xf3\xbd\xb1\xf5\x66\x5a\x8e\x3d\xea\x96\x6c\x5a\x25\x11\x94\x54\x63\x8f\x78\xe6\x6b\x79\xe8\x6d\xab\x9d\xdd\xdd\xb6\xda\x4d\xb7\x4e\x63\x51\x52\x8d\xbd\x7f\x6e\x14\xed\xb0\x08\x3b\xd4\x38\xb8\x41\xdd\xbf\xad\x1f\x77\x3c\xcc\xa9\xf3\x22\xe2\x9b\x2c\xff\x91\xd5\xe8\xa5\x2a\x81\x1c\xf0\x96\x94\xb9\x07\x4e\x75\x56\xc6\x3e\x9b\x3e\x88\x0d\xa4\x35\x9d\xd1\x0b\xc4\x17\x3f\xbe\xa1\xc3\x39\xb1\xb1\x1e\x4f\x36\xcd\xb6\xe2\x06\xf0\x3b\xf6\xdf\x69\x57\x97\x19\xcb\x37\xf8\x5d\x9b\xc1\x29\xd9\xfd\x5b\x31\x38\x67\x5a\x06\x9a\xc6\xf5\xf9\x7c\xfa\xd9\x67\xd0\xe5\x2b\x7a\xe1\x74\x29\x75\x02\x1f\xd0\xe3\xb9\xdf\xc6\x47\xb2\x97\xa9\x52\x2c\x9c\xbf\x12\x18\x0e\x26\x72\x3e\xfd\x97\xcf\xe8\xc5\xf4\xb3\xcf\xce\x5e\xd8\xd2\xa5\x67\xbb\x6b\x51\x77\x3d\xab\x9a\x95\x2f\x9f\xc1\xc5\x0b\x47\xf2\xa9\x9a\xc1\x7c\xfa\x87\x0b\xb1\x78\x67\x62\x1a\xff\x85\x93\x70\x77\x02\x11\x6a\x20\x70\x6b\x17\x36\x23\x78\x17\x20\x3a\x28\xa2\x2b\x73\x34\x4a\xab\xa6\x78\x51\xa2\x49\x5f\x83\xe5\x2c\x2a\x2e\x21\xb9\x3d\x32\xd4\x1c\x21\xfa\xbd\x9c\xd9\x62\x03\xd1\x16\xdf\xe2\x01\xe9\x6d\x0b\xc7\xcd\x3d\x3d\xbb\x2c\xe7\xff\x21\x05\x07\xa7\xbe\x48\x3b\xbe\x86\x4c\x7c\xe3\x8c\xfa\x4d\xae\x58\x8a\x0a\xba\x42\xb7\xf2\x70\xb6\xe0\xaf\xed\x0f\xa3\xfa\x0d\xe9\xc6\x05\x1f\x8f\x89\xfd\x12\xb4\x30\xe8\xa9\x92\xf3\xfb\x81\xf3\x15\xbf\xc5\xb9\x74\x92\x84\x92\xcc\x6d\x0e\xb1\x9d\xc3\xa7\x7f\x88\x38\x0a\xe9\xa8\x21\x86\x28\x15\xc3\xad\x3a\x2b\xbe\xc6\xc4\xd8\x9d\x72\x16\xa5\xef\xec\x16\xb2\x9e\x5f\x2c\xd8\xf4\x61\x1c\x32\x41\xee\x20\x7e\x10\xbf\x1f\xcf\xea\x63\xa3\xcb\x6e\x82\x7a\x1e\x5a\x97\x02\x12\xd4\x4b\x5f\x97\x5c\x76\x52\xd4\x8a\x75\x68\x36\x04\xc1\xb7\x2e\x84\x71\x14\x24\x30\xd5\x5e\xf7\xd3\xe7\x96\x7e\xb1\xb3\xe3\x99\xd5\xf1\x04\x3b\x36\x05\xaf\x67\x76\x9b\x70\x46\xc8\x73\x02\x10\x98\xb5\x25\x00\x11\x53\xc6\x4b\xf4\xb2\x2d\x00\x31\xd3\x75\x45\x26\xe0\x33\x0c\x8d\x60\xaa\x15\x4c\x15\x0b\x5e\xf7\x89\x51\xa4\xf2\xb3\xdd\xdb\xcc\xf4\x36\xc1\xde\xf4\xb3\x9c\x9e\x94\x0d\x89\xd9\x79\x28\x12\x00\xac\xd2\x00\x0a\xa5\xc6\x94\x17\xfe\xd3\xc3\x7b\x08\xe8\xa3\x9a\xd3\x87\xf7\xc0\x27\x04\x96\xb8\xe5\xf1\x7d\x5d\xec\x4d\x8d\xc7\xf7\xc8\x0a\x98\x2a\xdb\xa3\x4d\x27\xa8\x2e\x27\x27\xfa\x1c\x5b\xbd\x89\xce\x27\xa7\x7a\xd7\x95\x35\x4f\x25\xf0\xba\xde\x10\xd3\xab\xd8\xa5\x87\xb0\x9a\xe2\x00\x04\xac\x87\x7d\xd2\x21\x12\x88\x53\xd1\x58\x41\x6c\x0b\x63\x3d\xdd\x18\x6e\x8a\xf6\x00\xb6\x62\x00\x8f\x61\x35\x85\x49\x89\xdb\xa7\xaf\x8b\x7b\xf1\xfd\xc7\xe6\xf7\xb1\xa9\x34\xfc\x3a\xd9\xba\xcd\xe2\xe8\x7d\x7d\x92\xdc\x1a\x00\x80\x33\x4b\x7b\xa5\x04\x3a\x08\x27\xe2\xff\xc0\x5e\x4c\x39\x10\xf5\x0e\x26\xda\xd1\x7e\x2b\xda\x3f\x42\x9d\xc7\xc0\x5e\x0b\xd5\x5e\xbe\x23\x80\x63\xb4\x25\x07\x2a\xac\x5b\xea\x03\x29\x46\x97\x6a\x6e\x50\x16\x10\x29\xcd\x32\xaa\x19\x25\xcb\xf5\x19\xa1\x76\x97\x48\xa7\xbe\xac\xd3\xc3\xe1\x43\x1a\xa2\x01\x2f\x34\x74\x87\x83\x2d\xfb\x06\x24\xd5\x1c\xbf\x63\x44\xcf\xb7\xec\x1d\x92\x6c\x6a\x8f\xa9\x4f\x7b\xa4\x84\xf3\x2d\x08\x92\x76\x0c\xea\x56\x51\xf7\x56\x1e\xf2\xf1\x7c\x91\xf7\xdf\x5c\xb9\xba\xb9\xca\x8e\x9b\x2b\x5f\x2f\x4e\x0f\x44\x4e\x43\x4d\x58\xd4\xb8\x36\x72\x7b\x46\xcb\x0e\x58\x77\x47\xda\xec\x41\xbe\x7d\xae\x13\x47\x6a\xaa\x1b\x63\xa9\xdb\xf6\xd8\xe4\xfc\x40\x39\xf1\x0f\xc9\xfb\x3b\xa9\x06\xdf\xce\x37\xf2\x0f\x11\x0b\x0c\x08\x62\xbf\xc5\xb2\xa2\x0a\xc6\x1d\x79\xa3\x79\x08\xb6\x29\x4e\xa3\x9f\xda\xae\xda\x31\xcb\x63\xbe\xfb\x89\xff\x76\xcb\xab\xfa\xf3\x3c\xbb\xf9\xa6\x64\x37\x1c\xd9\x6c\x90\x3c\xeb\x32\x42\x4f\xd5\x15\xc3\xb4\xaa\x36\x39\xf7\x10\xd9\x55\xea\x50\xbc\x6e\x61\x5c\xdc\xe6\x35\xd4\x9d\x75\xcd\x55\xa9\x90\x2c\x45\x4d\x53\xab\x24\xd8\x89\x5a\x13\x9b\xdd\x80\xd8\x69\x60\xc6\x01\x71\x3e\xd0\x2a\xe4\x80\x02\x1f\x69\x8e\x18\xbb\xfa\xad\xac\xfd\xfa\xac\x1e\x57\x67\x15\x9a\xa2\xbb\xf7\x7d\x97\x16\xbb\xeb\x08\xd9\xf5\x14\x6d\x93\x9f\xfb\xf3\xf3\x67\x2a\x91\xde\x0a\xea\x6b\x62\x50\xe5\xe5\x4c\xc9\x89\xfa\xaa\x03\xf9\xfb\xbe\xdc\x44\xa2\x80\x2f\x7a\xf9\x04\xc5\xfb\xc7\x92\xe3\x8f\x25\x9f\x1f\x4b\xee\xbe\x14\xcc\xf8\x4b\xd8\x85\xb6\xc1\x4a\x2f\x87\xee\xbc\x10\x27\xfa\x5d\xe1\xf3\xe9\x03\xe5\xd3\x47\xd2\xfe\xd4\xbb\x42\xf1\xea\xa4\x9b\x01\xa1\x7d\x0c\x94\x3e\xfd\xbd\x08\xe6\x7f\x0e\x38\xea\x73\x7f\xce\x5f\x9d\xf5\x22\x44\x69\x77\x46\x68\x1c\x56\x2f\xaa\xfa\x57\xb2\xe0\xd3\xbb\x87\x49\x58\x52\x3e\xbd\x7b\x9c\x80\x81\xef\xdd\xc3\x38\x2c\xc5\xdf\xc7\x71\x18\xb7\x66\xdf\xc0\x90\x27\x27\x9f\xe9\xc9\x57\x8d\xc9\x67\x67\x19\xa1\x79\xc8\x15\x81\xac\x65\x54\xf9\x65\x58\x41\x50\x44\x41\x83\x88\xff\x61\x60\xf0\xf3\x91\x1a\xca\x84\xda\x44\x06\xb5\x6e\x42\xc1\xd4\xf5\x0d\xce\x91\xf2\x85\xc3\x99\x46\xb7\xb5\x40\xb7\x97\xf5\xa2\xfe\x6f\xe2\x13\xe9\xd3\x43\xc0\x96\x6c\xba\x2f\xaa\xf7\x27\xf4\x9a\x8f\xba\x52\xbf\x5a\xf3\x48\x08\xad\xc3\x90\x4f\xe6\xc0\xb8\xf7\x68\xde\x7b\x74\xe9\xce\xf4\xe7\xee\xc2\xa1\x11\x5e\xd7\xd2\x75\xdc\x12\x90\xf9\x2a\xe6\xfe\x8c\xf2\x8e\xab\xf5\xd4\x28\x9c\x6f\xba\x94\x94\xf3\x49\x2d\x42\x65\xe0\xf2\xea\x8a\x25\x43\x5d\x40\xb9\x2b\xf7\xd4\x10\x65\x2c\x89\x6b\x9f\xd1\x9a\x56\x34\xa7\x31\x88\xcb\xd9\x30\xac\x09\xf0\xbe\x62\x39\x94\x15\x8e\xb4\x52\x7c\xcf\x73\x4c\xf1\xa6\x04\xa5\x95\x92\x73\xe7\x93\xfd\x99\x9f\x4f\x98\x40\xae\xa7\xac\x7d\x64\x47\x74\x17\xb2\x49\xb1\x48\x42\x36\xde\x51\x0f\xec\x3f\x20\x30\xba\xdf\x1c\x70\x42\xa8\x27\x27\xa3\x6b\x34\x66\x9b\x90\xa3\xce\xa2\x5c\x0a\x6c\xf1\x02\x6b\xa3\xc6\x24\xc4\x1c\xee\xc2\xca\xf0\x69\x77\x61\x0e\xf2\xe0\x61\xc8\x94\x33\xdf\x07\xce\x70\xf1\x5f\x34\xab\x53\xdd\xe0\x04\x9e\xef\x4b\xd6\x43\x91\xc6\x49\xb2\x5b\xd3\x8c\xbf\x8f\x85\x30\xfa\xef\x87\x49\x7b\x95\x6e\x2b\x8e\x67\x1c\x50\xdb\xe3\x89\x1a\x8f\xb4\xb4\x30\x62\x75\x56\x8d\xf3\xb3\x5c\xe0\xed\xf9\xa4\x7c\x66\xf9\xed\x2b\xfc\x43\x80\x21\xbe\x0c\x67\xa3\x11\xa6\x77\x13\xc7\x14\xa4\x03\x6e\x63\x14\x36\x40\xed\x67\x2d\xc6\x86\x3d\x82\x10\xf2\x92\xc6\x97\x3d\x6d\xe5\x59\xd3\xd7\xc2\xb3\x1d\x9d\xc5\x8b\x02\xe6\xd5\x02\x9d\xc2\x8a\xcf\xbb\xd3\x3d\x76\x6c\x49\xd3\xfa\xd4\x7c\x7e\xb2\x83\xee\x67\xcb\x56\xdf\x41\xb3\x64\xd6\x05\x7a\x4e\xdf\x12\x62\x87\xfd\x12\xb3\x67\x57\x4e\x09\xdd\xfa\x7b\x78\xc2\xa3\xfd\x92\x5e\xce\xe2\xc5\xdd\xa5\x7e\x1a\x8d\xee\x9e\x81\x25\x5d\xb1\xe3\xf4\x59\x4b\x7d\x67\x70\xf3\xa4\x53\xbc\x08\x03\x3d\xbd\x0d\x8a\x8c\x15\x43\x7c\x6d\x0f\xf1\xf2\x1f\x19\xa2\xc4\xa1\xcc\x27\x0b\x3b\xc7\x61\xdf\x29\x18\x8d\x98\x95\xbc\xfe\x19\x96\xfc\xf7\x60\x15\x9b\x99\x7f\x6a\xde\x47\xf0\x32\xcb\x37\xcf\xe3\x1b\xa8\xf9\xfe\x79\xac\x63\xea\xf5\xe0\x9e\x7d\xe8\x03\x95\xf3\x15\xab\x39\xc1\x78\x82\x37\xdc\x27\x27\xbb\xab\xb3\x1b\x4e\xce\xe7\xfc\xd5\x62\x7f\xf9\xa2\x4b\x03\x88\x96\x9e\x7b\x17\x84\x9c\xfb\xcb\x8b\xb3\xdf\xd5\x93\x5a\xb1\x70\xa8\xac\xad\x3b\x3f\x31\x27\xc7\xce\x66\xa3\x91\x5f\x3f\x8f\xb7\x7a\xac\xa9\x9b\x54\x88\x7e\x96\x37\x3f\xa1\xcf\xf4\xad\xa8\x99\x7e\x0a\xb2\x09\xd1\xa6\xc0\x5c\x8e\x46\x47\xdd\x29\x15\xea\xa7\xaf\x50\x94\x80\x49\xe7\x6b\x96\x5f\xf8\x09\xdd\xcb\x48\x28\x77\x0f\xe1\x2d\x2a\x36\xe3\xa2\xf2\x19\x41\x72\x5c\x16\x55\x59\x2e\x8a\x5e\x22\x6e\x96\x9c\xc1\xd3\x43\xc0\xa7\x0f\x63\x20\xec\x1f\x03\x3e\x7d\x14\x3f\x1f\x8f\x8b\x1a\x0a\xdb\x72\x4a\xc3\x07\x04\xf5\xf4\x61\xc2\x6d\x39\xa3\x79\x47\x68\x0d\x3d\xb5\xe5\x94\x86\x79\x08\xea\xe9\x63\xab\xbd\x7c\x47\x8e\xbf\x8f\x72\xf8\x20\x59\xdf\x0b\xef\x5e\xc3\x41\x9d\xa2\x2f\xaa\x67\xe9\x8b\x2e\x76\x93\x96\x62\x03\xea\xf3\x9c\x3e\x06\xd5\x79\x7e\xa4\x71\x0f\x42\x6d\xda\x72\xd3\x22\x04\x27\xa1\x10\xbd\xf9\xe6\xe7\xf1\x99\x3f\x99\x23\x10\xec\x8b\x7b\x3f\x3f\x8f\xe9\x05\x19\xcf\xc9\x59\x7c\x56\xd0\x19\xfd\xc3\x8c\xd0\x3b\xb5\xd9\xe5\xf4\xe1\x6c\x27\x77\xbb\x9c\x3e\x9e\xed\x8e\x8b\x17\x40\xcc\xd2\xbf\xb3\x36\xfc\x72\x36\x1a\xdd\x59\x30\xf2\xda\xc0\x08\xec\xe4\x43\x78\x37\x7d\x20\xf4\xce\xda\x63\x6c\xf2\xd8\xd1\x04\xd2\x6b\x4c\x1f\xc3\xbb\xe9\x23\x21\x81\x6a\x4d\x55\xd1\x3f\x80\xf4\x3f\x4c\x84\xab\x91\xbe\x32\x8d\x4f\xb3\x3c\xab\xb6\x60\x38\x6d\x17\x83\x8c\x6b\x3c\xa6\x1d\xa5\x61\x5b\x00\x68\x22\x9b\x75\x75\x2e\x90\x2c\x69\xf6\xe4\x5c\x36\x71\xa8\xb7\xf5\x65\xc0\x71\xfe\x19\x7d\x25\xae\x8f\x67\xef\xa7\x09\x9f\x3e\xd0\xe4\xd9\x7a\x62\x0b\x1f\xe9\x4d\xb8\x3f\xdb\x8f\x93\xb3\x84\xde\x86\x93\xf8\xfc\xe6\x6c\xbe\x88\x2f\xc3\x1b\xeb\x5a\x9e\x29\xa5\x79\x73\x1e\x0a\x37\x70\x30\xb8\x42\x8c\xc5\xc1\xd4\xca\x65\x3f\x6d\xbd\x82\xcb\xef\xbe\x18\x19\xbc\xf8\x48\xb3\x67\x8f\x74\xfd\xec\x91\xb6\x85\x28\xec\x8c\x8d\xeb\x33\x4c\x85\x51\xf5\x91\x6e\x8e\x4f\x8b\x4a\x9b\x77\xa2\x6a\x97\xc0\xb1\x42\x81\xe3\x87\xb4\xe9\x63\x20\x9d\xe1\x80\xe8\x4b\x89\x20\xfb\xe5\x9e\x1f\x2a\x82\x2c\xa5\x08\xb2\x94\x22\xc8\x52\x8a\x20\xf3\xff\x0d\x22\xc8\x53\xdb\x7f\x62\xe3\x7f\x87\xc8\xf2\xe8\xca\xb8\x11\x7a\x95\x47\x8a\x13\x7f\xd3\x43\xb7\x95\x0e\xf0\xd5\x2e\xa9\xcb\xd6\x61\xd8\x49\x6f\xb8\x96\x53\x1e\xdf\xd9\xce\x2a\xf4\x65\xc7\xe8\x70\x78\x11\xa6\x25\x80\xd2\x9a\xdf\xeb\xf0\xb7\x31\x67\x92\x3e\x77\xaa\x77\xa1\x9c\x09\x51\x87\x34\x86\xa4\x4c\xbf\xc0\x71\xc4\xdf\x7f\x35\x52\x13\x51\x01\x1d\x70\x7e\x39\x1c\xdc\xba\x58\xfc\x57\x53\xfc\xd7\xc5\x89\xed\x0e\xd9\xa9\x0d\x0f\x3b\x3c\x7b\x7a\xbb\xea\x74\xf5\xe9\xed\xba\xdb\xf7\xa7\x0b\x6f\x85\xd6\x3a\x1e\xdb\x95\xfa\x57\x1e\xf9\x2a\x77\xe9\x4f\xac\x04\xc4\xc7\x38\xb5\x18\x9d\x15\x9c\x31\xe2\x17\x8f\xa4\x63\x94\x3d\x57\xf6\x4b\x26\x23\xb3\x05\xb8\x31\x5f\x9e\xbd\xe4\x7a\xae\xb7\x53\x87\xdc\xba\xfa\x4e\xb4\x7e\x3c\xd9\x5a\x70\x62\x61\x17\xff\xf6\xb2\x25\x21\xda\x52\xf2\x79\xba\x05\x2d\x0c\xc0\xb9\xbc\xed\xcc\x8c\xdd\x2d\xfb\x24\xf2\x3d\x24\x85\xa8\x33\xb5\xdd\xbf\xbb\xe7\x4a\x82\x79\x1b\x4d\xf5\xf4\xf0\xdf\x36\x84\x17\x36\xbf\x9c\x3b\x1a\xfa\xdf\x35\x04\xc7\x62\x10\x05\xf4\xd2\xf0\xb1\x53\x66\xdf\x4b\xaf\xc1\xce\xf4\x76\x2c\x25\x15\x41\x0f\x3b\x3d\x73\x07\x81\x04\x6e\xd0\x4d\x79\x85\xc3\x59\x27\x95\xda\x2c\x55\xb4\xe8\x9c\x76\xe7\xe5\xee\xeb\x7d\x7e\xa4\xa8\xd5\x3a\x49\x97\x4a\x86\x9f\x1c\xb5\xd7\xdf\x29\xe7\xc0\xb0\x79\xc0\x5b\x46\x84\xb2\x95\x63\x6f\xc7\xc3\x96\xc7\xe4\x59\xdb\x4d\x12\x44\x23\x0d\x54\xce\xcf\xc3\x8b\x96\xef\xab\x0a\x98\xc5\xcf\xfa\x8c\x18\xcf\x4f\x0c\xcc\x84\x11\xa1\x75\x2f\x43\x30\x61\x8b\xd9\x65\xdd\x7f\x2c\x90\xfd\x8f\x2a\xbf\x26\xe4\x14\x90\xd5\xa4\x49\x5d\xd8\xbe\x66\x0d\x95\x9b\xad\x61\xab\xfb\x0d\x1a\x6a\x65\xd0\x50\x75\x18\x34\xd4\x6b\x10\x6c\x3d\x4c\xaa\xe9\x03\x2d\x81\x4a\xae\xa6\x8f\x34\xb6\xa8\xe1\xfc\x2c\x1f\x97\x67\x25\x59\xc4\xaf\x8d\xf0\xd8\x72\xa7\x13\x2c\x1e\x5b\xb2\x53\x4e\x85\x82\xfb\x13\x55\x4e\x78\x14\xf6\x3b\xd8\x71\xd2\x5e\x14\xcb\xcb\xc0\x61\x2e\x94\xdd\x86\x6b\xea\x40\xeb\xf0\xfc\x23\x7f\x35\x9b\xfc\xeb\xe7\x93\x6f\xd6\x4f\xaf\xe8\x67\x47\x72\xbe\xc9\x68\x15\x32\x1d\x02\xa8\xa6\x56\xe0\xbc\x9a\x66\x14\x45\xf5\xbc\xd7\x16\x9f\xb7\x6c\xf1\x79\xcb\x16\x9f\xb7\x6c\xf1\xb5\x64\xa9\xcf\x26\x9f\xb7\x6c\xf2\x79\xdb\x26\x9f\xb7\x6d\xf2\xdd\x8e\x55\x8c\xbb\x23\xa1\x39\x04\x7f\xfc\x62\x57\x44\xfe\xaa\x5a\x53\x19\xe9\x06\x4c\xa4\xcf\xab\xbb\xcd\xf8\xe1\x66\xb7\x88\xb7\xac\xac\x78\x1d\xde\xd6\xe9\xe4\x8f\x82\x20\x29\x55\x44\x86\x9f\x7f\xfa\xf6\x70\x90\xbf\xef\x79\x74\x9d\xd5\x56\x09\x8d\xc3\x52\xee\x05\xc6\xfc\xf8\xf9\xa7\x6f\xfd\x9c\xd0\x02\x3e\x09\xae\x18\x8b\xa2\xe3\xf2\x6f\x85\xa7\xe2\xca\x14\x3b\x2c\x28\x77\x7c\x43\x66\xb4\x9c\x96\xfc\xae\xb8\xb6\xbe\x10\x93\xa6\x7d\xca\x78\x7c\x24\xb4\x98\x56\x65\x1c\xc6\x2d\xac\x04\x99\x9c\x9c\x40\x46\xca\xc6\xe6\x73\x95\xe5\xbe\xdf\x6a\x46\xc5\x13\xf3\x09\xdd\xff\xe5\xed\x57\xc5\x0d\x66\xcb\xa2\xdd\x16\xf2\x61\x33\x8c\x14\xad\x68\xae\xb8\xb0\xea\x2c\x07\xdb\x81\x9c\x16\xe1\xfc\x8f\xb3\x33\x3f\x9e\x5c\x90\xf3\x98\xee\x42\xe9\xdb\x30\x91\x7f\xcf\x8a\xf3\xf9\x1f\x67\x0b\x3e\xad\x18\x7c\x98\x3b\x8c\x11\xc7\xc0\xb1\x3b\x88\x65\x4f\x6b\x51\x20\xd9\xa3\x19\x9d\x19\x2b\xa7\xbb\x70\xb6\x28\x2f\xef\x16\x77\xe3\x31\xe1\x9a\x47\xa2\x33\xb7\x03\x59\x80\x06\x0b\xfe\x8e\x2c\xb8\x34\x0f\x17\x85\xbc\xaa\x8b\x92\xfb\x4d\x3c\xcf\x1f\xf6\x45\x59\x3b\x27\x8f\x3c\x49\x10\x29\xf6\x3c\xf7\x6d\x54\x5d\x17\x5f\xb1\x9a\x89\x5d\x93\x20\xb7\xcf\x37\x1e\xa1\xde\xfb\x68\xc7\xf2\x6b\xaf\xd9\xb7\xd8\xf6\xe6\x99\xd6\x92\x9c\xec\x66\xf3\x9e\x97\x65\x51\x2a\x2b\x25\xcf\x1b\x76\x18\xc4\x6b\x97\x28\x62\x1c\x00\x34\x6a\x10\x80\xf9\xcb\x77\xdf\xfe\xb9\xae\xf7\xd2\x6a\x6a\xc1\x70\xd4\xde\x9f\xbe\x7e\xe7\x75\x58\xf4\x9b\xee\x28\x9b\x16\x79\xc9\x59\xf2\x28\x08\x64\x1e\x6f\x59\xbe\x71\x65\x1b\x9f\x86\x80\x51\x58\xf2\x28\x93\x2b\xfb\x17\xb3\x19\x98\x3b\x4b\x4b\xe7\x96\x11\x16\x77\xb3\xdf\x89\x45\xdf\x17\x79\xc5\x3b\xf0\xe1\x17\x3c\x2d\x4a\x8e\x9a\x7e\x12\xf8\x71\x91\x57\xc5\x8e\x4f\x77\xc5\xc6\xf7\x20\x11\xd8\x60\xff\x97\xb7\x83\x09\x9e\xbb\x41\x5e\xd4\x83\xb4\xb8\xcd\x13\x8f\xd0\xe6\xf2\x0d\x67\x84\x1c\x29\x9b\x56\x10\xed\xd8\xe8\x97\x6a\xeb\xdc\xd6\x2f\x39\xb7\xae\xed\x58\xfd\xcc\xa0\x8f\xe2\x38\x89\x33\x7a\x62\x91\x51\xfa\xd4\x3b\xb7\xef\x8b\x81\xae\xda\x39\xb1\x8e\x93\xe9\x30\xe4\xca\xd7\xae\xdb\x11\x70\xd9\xe9\x2f\xb2\x6c\x60\x1b\xd7\x4c\xdd\xa6\x23\x96\x7e\x8f\x71\xc8\x09\x42\xde\x41\x38\x61\xd9\x69\xca\x67\x4f\x87\x04\x2f\x37\xfa\x23\x41\x63\x85\x54\xdc\x88\x0f\xfe\x28\x09\x5c\x0f\x40\xb9\xe7\xff\x5f\x9e\xf0\xff\xb6\xa9\x75\x11\x86\xe6\x78\xfd\xc3\x50\xae\x7c\x3c\xc3\x16\xf9\xa4\xe0\xdf\xb1\x3d\x6d\xcf\x0e\xde\x0b\xc4\xd4\x37\xa5\x76\x27\xad\x13\xac\xb6\x4b\x4d\x12\x12\x22\x36\x83\x90\x20\x06\x54\x1b\xf4\x82\xaa\x8d\x95\xcb\x5a\xe1\x6f\x9c\xa0\x56\xae\x59\x6b\xbb\xe4\x6d\xf6\x77\xee\x96\x40\xc4\x93\x67\x82\xaf\x9c\x0e\xa1\xd2\x6b\x51\xee\x8a\x68\x4d\x50\x80\x93\xf5\x9b\x13\x06\x2b\x5c\x67\xc6\x46\xab\x82\xa0\xd2\x71\xef\x81\xa7\xdc\xd2\x77\x81\xe4\x14\xea\x9e\x56\xb7\x51\x55\x97\x1d\x4e\x7d\xa6\x8a\xe4\x96\x5e\x91\xce\x6b\xbf\xf1\x31\xc5\x2a\xf5\x5f\x28\x27\x05\xb1\x7d\xb6\xc8\x8b\x56\x7c\xba\x3e\xbe\x6a\x90\xe5\x03\x46\xd8\xaa\x5e\x8f\x46\xe2\x7f\x3b\xed\x63\xbb\x24\x0c\x43\xec\x79\xe9\xf3\x55\xbd\x0e\xc5\x7f\x10\x25\x95\x95\x1b\x08\x96\x59\x41\x20\x53\xce\xe1\x35\x15\xcd\x09\x09\xa0\xaa\xf8\xbd\x30\x29\xa9\x25\x31\xd5\x3c\x61\x1d\x91\x60\xdb\x35\x0d\x3d\xdb\xa0\xdb\x7f\x3a\x59\xe7\xa6\xf8\xfb\xe9\x0a\xc5\x33\xed\xab\x9e\xf7\x36\x79\x24\xeb\x5a\x62\x09\x4e\xe7\xfc\xd5\xf9\x67\x33\x72\x3c\xfa\x44\xcd\xbb\x1b\x81\xf4\xcf\xbe\x8b\x98\x6f\x4c\xfe\xcb\x66\x97\xdd\x4b\xf0\x92\x6a\xc5\x8b\xfa\xaa\x4e\xd6\xb2\x73\x04\x5b\x13\x97\x1c\xc6\x6a\xad\x0b\xd4\x41\x6a\x85\x61\x55\x41\x45\x86\x76\x84\x69\x16\x72\xca\x43\x4f\xb7\x9a\x5c\x55\x1e\xa1\xfc\x70\xf0\x5b\xa5\x8b\x46\x1c\xd7\x46\x56\x70\x81\x99\xdd\x26\x56\x0c\x57\x5a\x85\x76\x83\xea\x8b\x47\x88\xad\xfc\x3d\x60\x79\x54\x9a\xa9\x00\x08\xe2\x28\x2d\xd4\xd3\xe5\x6c\x41\x74\x7c\xe6\x6d\xb6\x4b\x7c\xc8\x6f\x26\xa3\x7a\xe8\xa1\x20\x43\x29\x3b\xf7\x55\xc4\x4e\xb2\xc8\xa7\xb1\xfa\x4c\x98\xd1\x7c\x5a\xd5\x8f\x3b\xe9\xf7\x1a\x7a\xf3\xd9\xec\x9f\x3d\x5d\x28\xe3\x68\x61\xa9\x0c\xfd\xd0\x3f\xd5\x29\x66\x24\xc5\x21\xe5\x64\x81\xe1\x89\xcb\xd1\x08\xf7\xc3\xd8\x28\xef\xff\xf2\x16\x56\x9f\x1c\x3b\x36\x08\x90\x58\x2b\xb8\x14\x46\xc7\xec\xe0\x3a\x32\x9b\xeb\x00\x97\xa2\x53\xbc\x05\x03\x36\xe8\x53\x71\x37\x1b\xf6\x42\xf0\x37\xc0\x5f\x64\x8e\x36\xb4\x0a\xff\xf2\xf6\x87\xef\xa7\x10\x3c\xd8\x67\x3d\xfc\x05\x59\xb4\x67\xe0\x73\x5a\x11\x5a\x8f\x46\xb5\xd2\x02\xf7\xd2\xe1\xee\x64\x06\xf8\xf9\x60\xe0\x8d\xf5\x50\x68\x6f\xdb\x6f\xb2\x1d\xf4\x9c\x66\x1b\x9b\x4b\x11\xc8\x5c\x32\x24\x0b\x7b\x50\x9f\xd8\x50\xf8\x09\x7d\x32\x50\xe9\x05\x4f\x1e\x52\xdf\xe2\x17\x10\xe0\x5e\xf0\xc7\x19\xf5\xe4\x1d\x2b\x4a\x91\x3a\xf3\x82\xba\xbc\xe5\xd4\x33\xb2\x3c\x4f\xc6\x04\xf6\xe0\xc2\xb4\xda\x43\x8c\x5b\x0c\x0d\xec\xc1\xed\x25\xde\x89\x33\xe6\x99\xf0\xc0\x1e\x6a\x09\xc5\x1b\x00\x3f\x2f\x98\xe9\x8e\xbc\x8f\x66\x33\x19\x24\xd8\x44\x04\x78\xf2\x94\xa7\xba\x17\xfc\xe1\xff\xcf\xd7\xd5\xee\x44\x08\x03\xc1\x57\x31\x93\xf8\xc3\xa4\x62\x8b\x40\xb4\x3e\x0c\xe1\x4b\x8e\x28\x68\xb8\xf3\x87\x31\xbc\xbb\xd9\x76\xb7\x14\xf0\xfc\x77\xe9\xd2\xdd\x76\xa6\x70\x3d\xb6\x3b\xb7\x28\x29\x50\xff\x01\xfd\x8c\xb1\x18\xc6\xfe\xa1\x1f\x2e\xa7\xaf\x3a\xa1\x9d\x99\x12\xaf\x46\x6b\x05\xbf\x96\xc1\xf2\xc1\xe1\x3c\xd2\x3a\x62\x9d\xe4\x4a\xc4\x8e\xec\x6b\xf5\x7e\xee\x14\xaa\x69\x18\xe3\xe9\x73\xb3\xab\x5a\x86\x35\xc1\x4d\x39\x0e\x13\x79\x30\x0a\xe7\xef\xa9\xe1\x0b\x29\x8e\x3b\x5b\xb5\x06\x89\x42\x78\x28\xff\x8f\x90\x69\xef\xe1\xba\xff\x68\xd3\x72\xe4\x49\xf2\xd8\xb0\x26\x8f\xa1\x65\x6a\x22\x14\x74\x92\xad\x70\x2d\x0a\xfe\x35\xfe\xde\x1f\x8f\xaa\x20\xcf\x2c\x10\x04\x51\x24\xde\x43\x27\x12\x38\xa1\x41\x0e\xcd\x80\xd5\x89\xc1\x65\x1e\x7f\xcc\x9e\x6b\x44\x60\x0b\x62\x8e\xcb\x40\x60\x4d\x4a\xdc\x11\xef\xf1\x9b\x75\xea\x1f\xd2\xc0\x58\xa5\x89\xe1\xf7\x31\x64\xe6\x54\xee\x71\x42\x3c\x1e\xc9\x18\xd0\xba\xf0\x59\xa4\xab\x97\xb2\x5e\xb1\xe8\x25\x3a\xe3\xe2\xad\x2e\x94\x2b\x1f\xa5\x11\x05\xe8\x33\x9a\xc3\x8e\xa6\x80\xbb\xa1\xe9\x48\x72\xe3\xd0\xcb\x87\xa0\x45\x20\xf9\x02\xd8\x34\x62\xed\x29\x50\xf2\xe8\x86\xc4\x79\x8f\xd8\x0f\x41\xa6\x38\x11\x16\xdd\xf3\xe5\x54\xc3\x66\xae\x93\x50\xbd\xb5\xa5\x0e\xe8\x8d\x14\xad\x20\xe1\x9f\x39\x65\xdb\x8d\x1f\xd4\xef\x34\xb4\x5d\xd9\x54\x73\x1b\xe8\xab\xab\xe6\xad\x9f\xe9\x71\x54\x86\x25\x57\x17\xe6\x39\xcd\xb0\x31\xf2\xed\x8b\x6d\x6b\xf8\x5f\x53\x8b\x5c\xdf\xde\xe4\xf4\x85\x14\xdb\xe7\xee\xb3\xab\x2e\x6e\xdd\xdd\xf3\xe7\x8d\xdd\x83\x86\xc6\x31\xbe\x2c\x77\x2f\xbf\x01\x00\x00\xff\xff\x0d\xcc\x2b\xb4\x02\x39\x02\x00") func assetsLoginDistAllMinJsBytes() ([]byte, error) { return bindataRead( _assetsLoginDistAllMinJs, "assets/login/dist/all.min.js", ) } func assetsLoginDistAllMinJs() (*asset, error) { bytes, err := assetsLoginDistAllMinJsBytes() if err != nil { return nil, err } info := bindataFileInfo{name: "assets/login/dist/all.min.js", size: 145666, mode: os.FileMode(420), modTime: time.Unix(1571033118, 0)} a := &asset{bytes: bytes, info: info} return a, nil } var _assetsLoginDistRespondMinJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x57\x6d\x73\xdb\xb8\xf1\x7f\x7f\x9f\x82\xe2\x3f\x7f\x06\xb0\x20\x50\x72\xf2\xa6\xe4\xc1\xba\xc4\x71\x7a\xd7\x49\xee\xae\x67\x4f\x7b\x53\x49\x99\x01\xc1\xa5\x44\x89\x24\x68\x02\xd4\x83\x45\x7e\xf7\x0e\x48\xea\xc9\x8e\xa7\xed\x1b\x09\x58\x2c\x16\xfb\xf8\xdb\xa5\x7b\xd5\xb3\xfe\x00\x95\xcb\x2c\xa4\x4b\x65\xad\x47\xf4\x3d\xbd\xf6\xac\x34\xce\xdc\x94\x6f\x07\x9b\x38\xd4\x0b\x2b\x85\x30\xe6\xd6\x63\x09\xc5\xce\xca\x65\xb2\x8b\xe2\x24\xb1\xae\xac\x5b\x99\xef\x8a\x78\xbe\xd0\xd6\xf5\x70\xf4\xce\xba\x17\x52\x6b\xeb\x6f\xb0\x48\x7e\xb0\xae\xac\x2f\xb1\x80\x4c\x41\x68\x95\x59\x08\x85\xb5\xd0\x3a\x57\x9e\xeb\xce\x63\xbd\x28\x03\x2a\x64\xea\x2a\xc3\xbf\x84\x45\xe2\x76\x0a\xb8\x41\x22\x03\x37\xe5\x4a\x43\xe1\x7e\xf9\xe5\xf6\xee\xd7\xfb\xbb\xc1\xd7\x5f\x1e\x8c\x38\xeb\xca\xfd\xe1\x87\x5e\x54\x66\x42\xc7\x32\x43\x1c\xef\xed\x52\x81\xa5\x74\x11\x0b\x6d\xfb\x9c\xa6\x5c\x8b\xc5\x57\xa3\x28\x3b\xdf\x54\xd5\xf9\x9d\x35\x2f\xac\x80\x08\xc6\x69\x28\x45\x99\x42\xa6\xef\x12\x30\x7f\x24\x64\x82\x46\x71\xa1\x0e\x84\xdb\x45\x9c\x84\x55\xd5\x11\x9b\x1d\x01\xc6\xa9\x28\x80\x6b\xe8\x98\x90\x1d\xc8\x70\x67\x63\x12\xbd\x3c\x09\xe3\xb5\x8d\xfd\x02\x74\x59\x64\x56\x44\xe3\x90\xd9\xe9\xe3\x40\x83\xd2\x83\x91\x4d\x22\xaa\xf4\x2e\x01\x2a\x94\x7a\x80\xad\x66\x76\x2e\x55\x6c\xb4\xf4\x78\xa0\x64\x52\x6a\xf0\xb5\xcc\xbd\xc1\x68\x38\x84\xd4\x26\xd0\xb1\x07\x5c\xac\xe6\x85\x2c\xb3\x90\xd9\x99\xcc\xc0\x9c\xf0\x3c\x87\x2c\x6c\x34\x44\x11\x26\xe7\xe6\x9e\x5e\xcf\x32\x28\x7e\x7e\xf8\xfa\x85\xbd\x75\xd4\x62\xe7\xff\xd8\x88\x6b\xe3\xca\xec\xb7\x7d\xde\x7f\x6b\xdf\x58\xff\x77\x54\xd0\xda\x5b\x4d\xe4\x3d\xeb\xfd\x75\xbe\xf5\xad\xfa\x47\xb7\xb9\x71\xf3\x96\x08\x1a\x67\x0a\x0a\xfd\x11\x22\x59\x00\x02\x12\x62\x12\xb0\xf7\xd7\x8c\xb1\x88\xca\x28\x52\xa0\xff\x69\xae\x12\x41\x0b\x48\xe5\x1a\x5a\xcd\x00\x93\x7d\x13\x15\x50\x5e\x40\x9a\x87\x3d\x5e\xd7\x35\x3a\x85\x02\xd7\x48\x2f\x62\x75\x69\xc2\x45\x94\x0f\x07\x56\x80\xf0\xbe\x44\xbd\x21\xae\x4d\x44\x05\xdb\xd7\x3e\xa7\x45\x9b\x45\x4c\x10\x41\xcb\x3c\xe4\x1a\xd8\x51\x12\xde\xd7\xbe\x61\x0d\xd9\x64\x46\x2e\xe8\x4d\x4a\xb0\xde\xc8\xd7\xc5\x6e\x1f\xb0\x0c\x36\x16\xa7\x7f\x7e\xfd\xf2\xb3\xd6\xf9\x1f\xf0\x58\x82\xd2\xb5\x30\x8a\x23\x81\x8f\xe7\x1f\x84\x8e\xd7\xf0\xe7\x6f\xc1\x12\x84\x46\xf6\xd7\x58\x14\x52\xc9\x48\x37\x17\x1f\x1e\x7e\xb7\x71\x7d\xf0\xfd\xe9\xa5\x8e\x12\xd4\x35\x32\x19\x73\xb2\x92\x04\xad\x1a\x82\x01\xc2\xbe\x70\x1c\x24\xa8\xcc\x21\x43\xf6\x5f\xef\x1e\x6c\xc2\x49\x6f\x88\x89\xa0\x32\x2b\x80\x87\x3b\xa5\xb9\x06\xb1\xe0\xd9\xfc\xc2\x8e\xf7\x3d\xc6\x8c\xcb\x79\xb8\xbb\x37\x1c\x55\x75\x3d\x1c\x36\x34\x73\xa1\x54\x8e\xf3\x6e\xf8\xfe\x6c\x5f\x55\x01\x12\x9d\xcf\x14\x98\x24\xc4\x35\x79\x2e\xc4\x71\x04\x55\x90\x85\x28\x2b\x93\x04\xe3\xda\x8f\x23\x24\x28\x5f\xf2\x2d\x8b\x88\xa0\x8f\x25\x94\xc0\xc2\x26\xd4\x73\xd8\xb2\x7d\x1b\x57\xf7\xa7\xe6\x7f\xf2\x6d\xba\x9f\xf5\xa7\x7b\x64\x16\xd3\x7a\x76\x35\xdd\x4f\xbe\x4d\xeb\xe9\x7e\x76\x35\xad\x71\xdf\x9d\xc7\x64\x05\xbb\xa8\xe0\x29\x28\xcf\xfd\x09\x8d\xbd\xe9\x00\x8d\x3d\x59\xa5\xf2\xa9\xda\x40\xb0\x8a\x35\x9e\x0e\xf0\xf8\xc8\x74\x14\x38\xf6\xbe\x2f\xd2\xac\xcd\xca\x88\x2e\x8b\x44\x79\x2e\x2a\x8b\x64\x8a\xf0\xe4\xad\x3d\x1b\x1b\x3d\xdc\x29\x7e\x6b\xcf\x26\xdf\xbc\xe6\xbf\xdf\x1d\x4c\x31\x76\xe7\x24\x8a\xb3\xf0\xde\x64\xb9\x3a\x58\x60\x5d\xa1\xf6\x4d\x6c\xac\x98\xde\x4f\xd5\xac\x3f\xc6\x6f\x5c\x22\xb3\x64\xe7\xb9\xc8\xfc\x4d\x55\x1f\x8f\xd1\x84\x0f\x9e\x3e\x0c\xfe\x65\x38\xd5\xd8\x25\x69\x9c\x6d\x3c\x77\x8a\x26\x53\x35\xbb\x4a\xe3\x6c\xda\x02\xe9\x54\x5d\x79\x0d\xa9\x3d\x98\x0c\x07\x7f\x99\xd2\x59\x1f\xa3\x7c\x5b\x41\x8a\x1b\xe2\x14\xbb\x24\xe5\xdb\xb3\xeb\x7c\xfb\xbf\x5d\xaf\x89\xa0\x8d\xfa\x7f\x2f\xa1\x88\x41\xdd\x97\x79\x2e\x0b\x0d\xe1\x05\x30\x3a\x8e\x89\x69\x8f\x5d\x10\x91\x6d\x4c\xb2\x78\x92\xd8\xd8\x71\x5e\x3b\xa1\x5d\x21\x93\xde\x2b\x0f\xb5\xe9\x3c\x27\x0b\x12\x93\xe5\x19\xd8\x92\x15\x5b\xbe\x40\xde\xc4\x94\x64\x6a\x7e\x32\xf3\x23\xd9\xbe\x26\x39\x7b\x37\x24\x8f\x6c\x49\xe7\x70\xe0\x53\x1f\x77\x0f\x7c\xfe\x2b\x4f\x01\xd9\x0b\xe0\xa1\x8d\x27\xc3\x59\x55\xad\x48\xf1\x2a\x5b\xc0\x15\x34\x6c\x44\xb1\xc7\x57\x78\x92\x38\x5b\xd9\x98\xe8\xe7\x90\xc0\x49\xc0\x96\xdf\xc5\x74\x22\xd8\x92\x1a\xdc\x27\x21\x5b\x75\xb8\x1c\xc9\x4c\xdf\xc7\x4f\x40\x80\x89\xa6\x66\x2e\xa9\x91\xc1\x97\x43\xf9\xff\x67\xe4\x37\xf7\x06\x2a\x7e\x02\x6f\x04\xa9\xdf\x02\xf1\xc8\xb4\x01\x51\x55\x48\xb0\xe8\xa5\x62\x5d\x1b\x12\xaf\xb5\x09\x4c\x9e\x6b\xca\xec\xd1\x70\xf8\xff\x36\x79\xae\xeb\x89\x7e\xde\x57\x02\x4c\x22\xc7\x59\x5d\x42\xbf\x20\xab\xb3\xee\x88\x09\x67\xc1\x45\x03\x88\xc6\xab\x8b\x16\x20\xb0\x77\xd9\x13\x82\xef\xa8\x15\x12\x68\xf0\xef\x19\x19\x8c\xf8\x98\xe5\xbc\x50\xf0\x39\x91\x5c\x23\x8e\x6b\x52\x9e\xa2\x76\x84\x50\x5b\x24\x31\x64\xad\x0a\xb6\x09\xd1\x44\x18\xc4\xb7\x6f\xef\xef\x47\xb7\x32\xcd\xb9\xb6\x19\x33\x1e\x6c\xd6\x5f\x65\x08\x8e\x13\x56\x55\x1b\xd2\x89\x98\x55\x55\x48\x22\x93\x83\x92\xa9\x89\xa2\x09\x64\x73\xbd\x18\x8c\x66\xa4\x60\xc8\x80\xff\x27\xae\x01\x9b\x64\x7a\x88\x53\x03\xd7\x71\x84\x02\xc7\x99\x3b\x4e\x7e\x53\x0c\xe6\xb8\x8b\x32\xa7\x22\x01\x5e\x18\x1e\x59\x6a\xb4\xc0\x64\xc1\x38\x55\xed\x2d\x43\x29\x49\x8e\xc9\x5a\xc6\xa1\x35\xf4\xe7\xac\xf0\x23\x59\x20\x63\xc0\xda\x8a\x33\x2b\xc1\x71\x84\x12\xba\xe0\xea\xb7\x4d\xf6\x7b\x21\x73\x28\xf4\x0e\xad\x71\x6b\xe3\x86\x25\x93\xf5\x8c\x6c\xd9\x86\x1a\x9c\x21\x3b\xb3\xe0\xdb\x0d\x79\x62\xa6\xa4\x19\x63\x5b\xf2\xe1\xb0\xdc\x91\x8f\xcc\x86\xd4\xf6\xb7\x8e\x83\xb6\xe7\x0e\xdc\xe2\x2b\xb4\xa5\x71\x16\xc2\xf6\xb7\x08\x7d\xc4\x37\x83\xd1\x38\xae\x2a\x8d\xb0\x37\xc2\x98\xec\x1c\x07\xed\xce\xf9\x77\xf8\x0a\xed\x5e\xe7\xdf\x18\x75\x9b\x11\xd1\x71\xd0\x93\xe3\x7c\xa8\xaa\x1e\x7a\xaa\x2a\xb8\x61\x5b\x6c\xd6\x1f\xaa\x6a\x77\xc3\x00\xe3\xaa\x42\xd1\x64\xd3\x22\xc7\xec\x62\xc3\x26\x33\x4c\x4e\x5b\x9a\x97\x6a\x81\xd2\xc9\x86\x16\x65\x02\x6a\x86\x71\x7d\x70\xd3\xad\x71\x53\x86\xb3\xe7\x3e\xba\xc5\x8e\x93\x4d\x6e\x67\xed\x2f\xcd\x79\x01\x99\xfe\x55\x86\xc0\x18\x7b\x74\x9c\xc7\x8b\xfc\x33\x2c\xd8\xcf\xba\x18\xb3\xe1\x31\x08\x9f\x8c\xf4\xc8\x04\x21\x7a\xfe\xc0\xa7\x2e\x08\x77\x2f\x8b\xb0\x49\x59\x1b\x93\xcf\x2c\x9a\x7c\x9a\xd1\xa5\x8c\x33\x64\x4f\x33\x1b\xfb\x77\x54\xef\x72\x60\xb6\x86\xad\x76\x85\x52\x36\xb9\x6b\x4d\x64\x9f\xc8\xe3\x65\x51\xdd\x11\x49\x33\xd8\xea\xfb\x38\x48\xe2\x6c\x8e\xc9\x5d\x5b\x0a\xf7\x0b\x00\x3d\x3e\xdf\x1c\x11\xe4\xb3\x77\x77\x51\xac\x07\xc5\xcc\xa1\x31\x1d\x7d\xc6\x98\x64\xad\x33\xef\x70\x5d\x93\xf5\xc5\xec\x41\x3a\xb8\x36\xd3\x6d\x01\x79\xc2\x05\xa0\xae\xa1\xd3\x63\xeb\x25\xf6\x01\xf6\x8f\x67\x8d\x01\x66\x90\x01\xc7\x81\xce\x87\x55\x35\xf4\x03\x16\x50\x55\x06\x66\x66\xcb\xe6\x68\x48\x02\x9a\x70\xa5\x7f\xe9\xf2\xc6\x76\x6d\x8c\x9b\x51\x6c\xce\xbe\x33\xaa\xbe\x54\xc1\xf4\x71\x62\xbf\x19\xd9\xfd\xa0\x6f\xbf\xb9\x7e\xf3\xce\xc6\x35\x59\xb0\x5e\xe4\x38\xa1\x1f\x74\xef\x3a\x0e\x0a\xfa\xcc\xc8\x26\x66\x1d\xb1\x11\x3e\x06\x33\x36\x81\xbd\x89\xfd\xb8\xdf\x6f\x0d\x5d\x92\x15\xc9\x88\xf4\x17\x63\xb4\x64\x21\x49\x5b\xcf\xcc\x11\xc7\x18\x7b\x68\xc9\x60\x12\xcf\x9e\xd9\x7a\x1a\x0d\xb0\xe3\xfc\x01\xf3\xbb\x6d\x4e\xdf\x8c\x0e\x57\x0f\x84\x6b\xc7\x99\x9f\x36\xd8\x78\x9d\x2d\xa9\xca\x93\x58\x23\x9b\xd8\x98\x48\x76\x48\xb6\xa3\x76\x39\x1b\xfa\xf2\x26\xf7\xf3\x7e\x1f\xaf\x58\x36\xc9\x67\x24\x69\xa5\x76\xc3\xd4\xea\x20\x00\x35\xad\xec\x99\x62\xa6\x29\x9f\xa9\x74\x5d\x55\xb6\x69\xd1\xa4\x29\x18\x2f\x3d\xc2\x17\x39\x14\xa7\xb7\x3a\x96\xb0\x91\x78\x33\x18\xb5\xc3\xca\xea\x79\x74\xe3\x6c\x83\x1d\xe7\xac\xfe\x8f\x66\xe3\x3e\x3a\x7f\xcf\xc6\xed\xbc\xf2\x42\x02\xdf\xfe\xd7\x12\x6a\x5c\x97\x08\xd7\x64\x73\xde\x86\xe3\x08\x85\x9d\x01\x87\x31\x3d\xa4\x6a\x11\x47\x1a\x61\x3f\x42\x01\x5d\x14\x10\x9d\x3e\x16\x04\xde\xaf\x91\x20\x1d\x39\x38\xe4\xa7\x9c\xb4\x94\x19\xeb\x0d\xc9\x05\x04\x9f\x3d\xb5\x31\x8f\x0f\x8d\x1a\x35\xd9\x9e\xeb\x70\x08\x53\xc0\x86\x7e\xf0\xe3\xa1\x1d\xf8\xc1\x21\x97\x04\x53\x93\xc0\xf4\x17\xd1\x69\xc3\xba\x91\x88\xcc\x9b\x41\x3a\x71\x9c\x16\x17\x94\x29\x59\xd3\x79\x1a\x2a\xd5\xf2\x8b\xdc\x40\x71\xcb\x95\xe9\x21\xd0\x34\x90\x9e\x9c\xc0\xec\xd4\xfc\x9a\x22\x3f\x0e\x13\x6d\xc9\x17\x7c\x73\xdb\x56\xfd\x18\xad\xd1\x2b\x47\x04\x48\x64\xec\x06\x63\x32\xf6\x50\xcf\xfd\x76\x98\x4f\xbd\xd9\xd5\xd4\x9d\xba\xd8\xa5\xe6\x3b\x0f\x01\x76\x9c\x5e\x51\x55\x70\xac\xba\x53\x6e\x9b\x82\xef\x32\xcf\x6d\x32\x8f\x99\x51\x31\x91\x82\x1b\xd7\xd0\x85\x54\x1a\x3b\x0e\xb2\x5d\xd7\x58\x05\x17\x25\x7f\x6d\x4e\xe0\x9c\x3d\x2f\xa4\x96\x42\x26\x7d\xc0\x24\xec\xf2\xdb\x38\xcc\x83\xee\x5b\x30\xaa\x31\xc6\xb5\x89\x83\xbf\x45\xf8\xf4\x05\xb7\x25\xa2\x99\xdc\xd2\x7f\xf0\xa4\x04\xa6\x09\xa7\x3c\x0c\xef\xd6\x90\xe9\x2f\xb1\xd2\x90\x41\x31\x7e\x49\x42\x76\x01\x66\x80\xb2\x49\x40\x7a\x23\xec\x71\xca\xb5\xe6\x62\xd1\x30\x99\xc1\xf6\x6c\x6b\x26\xdb\x23\x37\xae\xbb\x8f\x50\xff\xdf\x01\x00\x00\xff\xff\xed\x16\x16\x7b\x19\x11\x00\x00") func assetsLoginDistRespondMinJsBytes() ([]byte, error) { return bindataRead( _assetsLoginDistRespondMinJs, "assets/login/dist/respond.min.js", ) } func assetsLoginDistRespondMinJs() (*asset, error) { bytes, err := assetsLoginDistRespondMinJsBytes() if err != nil { return nil, err } info := bindataFileInfo{name: "assets/login/dist/respond.min.js", size: 4377, mode: os.FileMode(420), modTime: time.Unix(1570872928, 0)} a := &asset{bytes: bytes, info: info} return a, nil } // Asset loads and returns the asset for the given name. // It returns an error if the asset could not be found or // could not be loaded. func Asset(name string) ([]byte, error) { cannonicalName := strings.ReplaceAll(name, "\\", "/") if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) } return a.bytes, nil } return nil, fmt.Errorf("Asset %s not found", name) } // MustAsset is like Asset but panics when Asset would return an error. // It simplifies safe initialization of global variables. func MustAsset(name string) []byte { a, err := Asset(name) if err != nil { panic("asset: Asset(" + name + "): " + err.Error()) } return a } // AssetInfo loads and returns the asset info for the given name. // It returns an error if the asset could not be found or // could not be loaded. func AssetInfo(name string) (os.FileInfo, error) { cannonicalName := strings.ReplaceAll(name, "\\", "/") if f, ok := _bindata[cannonicalName]; ok { a, err := f() if err != nil { return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) } return a.info, nil } return nil, fmt.Errorf("AssetInfo %s not found", name) } // AssetNames returns the names of the assets. func AssetNames() []string { names := make([]string, 0, len(_bindata)) for name := range _bindata { names = append(names, name) } return names } // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ "assets/login/dist/all.min.css": assetsLoginDistAllMinCss, "assets/login/dist/all.min.js": assetsLoginDistAllMinJs, "assets/login/dist/respond.min.js": assetsLoginDistRespondMinJs, } // AssetDir returns the file names below a certain // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: // data/ // foo.txt // img/ // a.png // b.png // then AssetDir("data") would return []string{"foo.txt", "img"} // AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("foo.txt") and AssetDir("notexist") would return an error // AssetDir("") will return []string{"data"}. func AssetDir(name string) ([]string, error) { node := _bintree if name != "" { cannonicalName := strings.ReplaceAll(name, "\\", "/") pathList := strings.Split(cannonicalName, "/") for _, p := range pathList { node = node.Children[p] if node == nil { return nil, fmt.Errorf("Asset %s not found", name) } } } if node.Func != nil { return nil, fmt.Errorf("Asset %s not found", name) } rv := make([]string, 0, len(node.Children)) for childName := range node.Children { rv = append(rv, childName) } return rv, nil } type bintree struct { Func func() (*asset, error) Children map[string]*bintree } var _bintree = &bintree{nil, map[string]*bintree{ "assets": &bintree{nil, map[string]*bintree{ "login": &bintree{nil, map[string]*bintree{ "dist": &bintree{nil, map[string]*bintree{ "all.min.css": &bintree{assetsLoginDistAllMinCss, map[string]*bintree{}}, "all.min.js": &bintree{assetsLoginDistAllMinJs, map[string]*bintree{}}, "respond.min.js": &bintree{assetsLoginDistRespondMinJs, map[string]*bintree{}}, }}, }}, }}, }} // RestoreAsset restores an asset under the given directory func RestoreAsset(dir, name string) error { data, err := Asset(name) if err != nil { return err } info, err := AssetInfo(name) if err != nil { return err } err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) if err != nil { return err } err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) if err != nil { return err } err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) if err != nil { return err } return nil } // RestoreAssets restores an asset under the given directory recursively func RestoreAssets(dir, name string) error { children, err := AssetDir(name) // File if err != nil { return RestoreAsset(dir, name) } // Dir for _, child := range children { err = RestoreAssets(dir, filepath.Join(name, child)) if err != nil { return err } } return nil } func _filePath(dir, name string) string { cannonicalName := strings.ReplaceAll(name, "\\", "/") return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } ================================================ FILE: template/login/assets_list.go ================================================ package login var AssetsList = []string{ "/login/dist/all.min.css", "/login/dist/all.min.js", "/login/dist/respond.min.js", } ================================================ FILE: template/login/login.go ================================================ package login import ( "bytes" "html/template" "strings" "github.com/GoAdminGroup/go-admin/template/types" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/logger" ) type Login struct { Name string } func GetLoginComponent() *Login { return &Login{ Name: "login", } } var DefaultFuncMap = template.FuncMap{ "lang": language.Get, "langHtml": language.GetFromHtml, "link": func(cdnUrl, prefixUrl, assetsUrl string) string { if cdnUrl == "" { return prefixUrl + assetsUrl } return cdnUrl + assetsUrl }, "isLinkUrl": func(s string) bool { return (len(s) > 7 && s[:7] == "http://") || (len(s) > 8 && s[:8] == "https://") }, "render": func(s, old, repl template.HTML) template.HTML { return template.HTML(strings.ReplaceAll(string(s), string(old), string(repl))) }, "renderJS": func(s template.JS, old, repl template.HTML) template.JS { return template.JS(strings.ReplaceAll(string(s), string(old), string(repl))) }, "divide": func(a, b int) int { return a / b }, } func (l *Login) GetTemplate() (*template.Template, string) { tmpl, err := template.New("login_theme1"). Funcs(DefaultFuncMap). Parse(loginTmpl) if err != nil { logger.Error("Login GetTemplate Error: ", err) } return tmpl, "login_theme1" } func (l *Login) GetAssetList() []string { return AssetsList } func (l *Login) GetAsset(name string) ([]byte, error) { return Asset(name[1:]) } func (l *Login) IsAPage() bool { return true } func (l *Login) GetName() string { return "login" } func (l *Login) GetContent() template.HTML { buffer := new(bytes.Buffer) tmpl, defineName := l.GetTemplate() err := tmpl.ExecuteTemplate(buffer, defineName, l) if err != nil { logger.Error("login ComposeHtml Error:", err) } return template.HTML(buffer.String()) } func (l *Login) GetJS() template.JS { return "" } func (l *Login) GetCSS() template.CSS { return "" } func (l *Login) GetCallbacks() types.Callbacks { return make(types.Callbacks, 0) } ================================================ FILE: template/login/login.tmpl ================================================ {{define "login_theme1"}} {{.Title}}

    {{.Title}}

    © All Rights Reserved. GoAdmin

    {{end}} ================================================ FILE: template/login/template.go ================================================ package login const loginTmpl = `{{define "login_theme1"}} {{.Title}}

    {{.Title}}

    © All Rights Reserved. GoAdmin

    {{end}}` ================================================ FILE: template/template.go ================================================ // Copyright 2019 GoAdmin Core Team. All rights reserved. // Use of this source code is governed by a Apache-2.0 style // license that can be found in the LICENSE file. package template import ( "bytes" "errors" "html/template" "path" "plugin" "strconv" "strings" "sync" "github.com/GoAdminGroup/go-admin/context" c "github.com/GoAdminGroup/go-admin/modules/config" errors2 "github.com/GoAdminGroup/go-admin/modules/errors" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/logger" "github.com/GoAdminGroup/go-admin/modules/menu" "github.com/GoAdminGroup/go-admin/modules/system" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/plugins/admin/models" "github.com/GoAdminGroup/go-admin/template/login" "github.com/GoAdminGroup/go-admin/template/types" "golang.org/x/text/cases" textLang "golang.org/x/text/language" ) // Template is the interface which contains methods of ui components. // It will be used in the plugins for custom the ui. type Template interface { Name() string // Components // layout Col() types.ColAttribute Row() types.RowAttribute // form and table Form() types.FormAttribute Table() types.TableAttribute DataTable() types.DataTableAttribute TreeView() types.TreeViewAttribute Tree() types.TreeAttribute Tabs() types.TabsAttribute Alert() types.AlertAttribute Link() types.LinkAttribute Paginator() types.PaginatorAttribute Popup() types.PopupAttribute Box() types.BoxAttribute Label() types.LabelAttribute Image() types.ImgAttribute Button() types.ButtonAttribute // Builder methods GetTmplList() map[string]string GetAssetList() []string GetAssetImportHTML(exceptComponents ...string) template.HTML GetAsset(string) ([]byte, error) GetTemplate(bool) (*template.Template, string) GetVersion() string GetRequirements() []string GetHeadHTML() template.HTML GetFootJS() template.HTML Get404HTML() template.HTML Get500HTML() template.HTML Get403HTML() template.HTML } type PageType uint8 const ( NormalPage PageType = iota Missing404Page Error500Page NoPermission403Page ) func GetPageTypeFromPageError(err errors2.PageError) PageType { if err == nil { return NormalPage } else if err == errors2.PageError403 { return NoPermission403Page } else if err == errors2.PageError404 { return Missing404Page } else { return Error500Page } } const ( CompCol = "col" CompRow = "row" CompForm = "form" CompTable = "table" CompDataTable = "datatable" CompTree = "tree" CompTreeView = "treeview" CompTabs = "tabs" CompAlert = "alert" CompLink = "link" CompPaginator = "paginator" CompPopup = "popup" CompBox = "box" CompLabel = "label" CompImage = "image" CompButton = "button" ) func HTML(s string) template.HTML { return template.HTML(s) } func CSS(s string) template.CSS { return template.CSS(s) } func JS(s string) template.JS { return template.JS(s) } // The templateMap contains templates registered. var templateMap = make(map[string]Template) // Get the template interface by theme name. If the // name is not found, it panics. func Get(ctx *context.Context, theme string) Template { if ctx != nil { queryTheme := ctx.Theme() if queryTheme != "" { if temp, ok := templateMap[queryTheme]; ok { return temp } } } if temp, ok := templateMap[theme]; ok { return temp } panic("wrong theme name") } // Default get the default template with the theme name set with the global config. // If the name is not found, it panics. func Default(ctx ...*context.Context) Template { if len(ctx) > 0 && ctx[0] != nil { queryTheme := ctx[0].Theme() if queryTheme != "" { if temp, ok := templateMap[queryTheme]; ok { return temp } } } if temp, ok := templateMap[c.GetTheme()]; ok { return temp } panic("wrong theme name") } var ( templateMu sync.Mutex compMu sync.Mutex ) // Add makes a template available by the provided theme name. // If Add is called twice with the same name or if template is nil, // it panics. func Add(name string, temp Template) { templateMu.Lock() defer templateMu.Unlock() if temp == nil { panic("template is nil") } if _, dup := templateMap[name]; dup { panic("add template twice " + name) } templateMap[name] = temp } // CheckRequirements check the theme and GoAdmin interdependence limit. // The first return parameter means that whether GoAdmin version meets the requirement of the theme used or not. // The second return parameter means that whether the version of theme used meets the requirement of GoAdmin or not. func CheckRequirements() (bool, bool) { if !CheckThemeRequirements() { return false, true } // The theme which is not in the default official themes will be ignored. if !utils.InArray(DefaultThemeNames, Default().Name()) { return true, true } return true, VersionCompare(Default().GetVersion(), system.RequireThemeVersion()[Default().Name()]) } func CheckThemeRequirements() bool { return VersionCompare(system.Version(), Default().GetRequirements()) } func VersionCompare(toCompare string, versions []string) bool { for _, v := range versions { if v == toCompare || utils.CompareVersion(v, toCompare) { return true } } return false } func GetPageContentFromPageType(ctx *context.Context, title, desc, msg string, pt PageType) (template.HTML, template.HTML, template.HTML) { if c.GetDebug() { return template.HTML(title), template.HTML(desc), Default(ctx).Alert().SetTitle(errors2.MsgWithIcon).Warning(msg) } if pt == Missing404Page { if c.GetCustom404HTML() != template.HTML("") { return "", "", c.GetCustom404HTML() } else { return "", "", Default(ctx).Get404HTML() } } else if pt == NoPermission403Page { if c.GetCustom404HTML() != template.HTML("") { return "", "", c.GetCustom403HTML() } else { return "", "", Default(ctx).Get403HTML() } } else { if c.GetCustom500HTML() != template.HTML("") { return "", "", c.GetCustom500HTML() } else { return "", "", Default(ctx).Get500HTML() } } } var DefaultThemeNames = []string{"sword", "adminlte"} func Themes() []string { names := make([]string, len(templateMap)) i := 0 for k := range templateMap { names[i] = k i++ } return names } func AddFromPlugin(name string, mod string) { plug, err := plugin.Open(mod) if err != nil { logger.Error("AddFromPlugin err", err) panic(err) } tempPlugin, err := plug.Lookup(cases.Title(textLang.Und).String(name)) if err != nil { logger.Error("AddFromPlugin err", err) panic(err) } var temp Template temp, ok := tempPlugin.(Template) if !ok { logger.Error("AddFromPlugin err: unexpected type from module symbol") panic(errors.New("AddFromPlugin err: unexpected type from module symbol")) } Add(name, temp) } // Component is the interface which stand for a ui component. type Component interface { // GetTemplate return a *template.Template and a given key. GetTemplate() (*template.Template, string) // GetAssetList return the assets url suffix used in the component. // example: // // {{.UrlPrefix}}/assets/login/css/bootstrap.min.css => login/css/bootstrap.min.css // // See: // https://github.com/GoAdminGroup/go-admin/blob/master/template/login/theme1.tmpl#L32 // https://github.com/GoAdminGroup/go-admin/blob/master/template/login/list.go GetAssetList() []string // GetAsset return the asset content according to the corresponding url suffix. // Asset content is recommended to use the tool go-bindata to generate. // // See: http://github.com/jteeuwen/go-bindata GetAsset(string) ([]byte, error) GetContent() template.HTML IsAPage() bool GetName() string GetJS() template.JS GetCSS() template.CSS GetCallbacks() types.Callbacks } var compMap = map[string]Component{ "login": login.GetLoginComponent(), } // GetComp gets the component by registered name. If the // name is not found, it panics. func GetComp(name string) Component { if comp, ok := compMap[name]; ok { return comp } panic("wrong component name") } func GetComponentAsset() []string { assets := make([]string, 0) for _, comp := range compMap { assets = append(assets, comp.GetAssetList()...) } return assets } func GetComponentAssetWithinPage() []string { assets := make([]string, 0) for _, comp := range compMap { if !comp.IsAPage() { assets = append(assets, comp.GetAssetList()...) } } return assets } func GetComponentAssetImportHTML(ctx *context.Context) (res template.HTML) { res = Default(ctx).GetAssetImportHTML(c.GetExcludeThemeComponents()...) assets := GetComponentAssetWithinPage() for i := 0; i < len(assets); i++ { res += getHTMLFromAssetUrl(assets[i]) } return } func getHTMLFromAssetUrl(s string) template.HTML { switch path.Ext(s) { case ".css": return template.HTML(``) case ".js": return template.HTML(``) default: return "" } } func GetAsset(path string) ([]byte, error) { for _, comp := range compMap { res, err := comp.GetAsset(path) if err == nil { return res, nil } } return nil, errors.New(path + " not found") } // AddComp makes a component available by the provided name. // If Add is called twice with the same name or if component is nil, // it panics. func AddComp(comp Component) { compMu.Lock() defer compMu.Unlock() if comp == nil { panic("component is nil") } if _, dup := compMap[comp.GetName()]; dup { panic("add component twice " + comp.GetName()) } compMap[comp.GetName()] = comp } // AddLoginComp add the specified login component. func AddLoginComp(comp Component) { compMu.Lock() defer compMu.Unlock() compMap["login"] = comp } // SetComp makes a component available by the provided name. // If the value corresponding to the key is empty or if component is nil, // it panics. func SetComp(name string, comp Component) { compMu.Lock() defer compMu.Unlock() if comp == nil { panic("component is nil") } if _, dup := compMap[name]; dup { compMap[name] = comp } } type ExecuteParam struct { User models.UserModel Tmpl *template.Template TmplName string IsPjax bool Panel types.Panel Logo template.HTML Config *c.Config Menu *menu.Menu Animation bool Buttons types.Buttons NoCompress bool Iframe bool } func updateNavAndLogoJS(logo template.HTML) template.JS { if logo == template.HTML("") { return "" } return `$(function () { $(".logo-lg").html("` + template.JS(logo) + `"); });` } func updateNavJS(isPjax bool) template.JS { if !isPjax { return "" } return `$(function () { let lis = $(".user-menu .dropdown-menu li"); for (i = 0; i < lis.length - 2; i++) { $(lis[i]).remove(); } $(".user-menu .dropdown-menu").prepend($("#navbar-nav-custom").html()); });` } type ExecuteOptions struct { Animation bool NoCompress bool HideSideBar bool HideHeader bool UpdateMenu bool NavDropDownButton []*types.NavDropDownItemButton } func GetExecuteOptions(options []ExecuteOptions) ExecuteOptions { if len(options) == 0 { return ExecuteOptions{Animation: true} } return options[0] } func Execute(ctx *context.Context, param *ExecuteParam) *bytes.Buffer { buf := new(bytes.Buffer) err := param.Tmpl.ExecuteTemplate(buf, param.TmplName, types.NewPage(ctx, &types.NewPageParam{ User: param.User, Menu: param.Menu, Assets: GetComponentAssetImportHTML(ctx), Buttons: param.Buttons, Iframe: param.Iframe, UpdateMenu: param.IsPjax, Panel: param.Panel. GetContent(append([]bool{param.Config.IsProductionEnvironment() && !param.NoCompress}, param.Animation)...).AddJS(param.Menu.GetUpdateJS(param.IsPjax)). AddJS(updateNavAndLogoJS(param.Logo)).AddJS(updateNavJS(param.IsPjax)), TmplHeadHTML: Default(ctx).GetHeadHTML(), TmplFootJS: Default(ctx).GetFootJS(), Logo: param.Logo, })) if err != nil { logger.Error("template execute error", err) } return buf } func WarningPanel(ctx *context.Context, msg string, pts ...PageType) types.Panel { pt := Error500Page if len(pts) > 0 { pt = pts[0] } pageTitle, description, content := GetPageContentFromPageType(ctx, msg, msg, msg, pt) return types.Panel{ Content: content, Description: description, Title: pageTitle, } } func WarningPanelWithDescAndTitle(ctx *context.Context, msg, desc, title string, pts ...PageType) types.Panel { pt := Error500Page if len(pts) > 0 { pt = pts[0] } pageTitle, description, content := GetPageContentFromPageType(ctx, msg, desc, title, pt) return types.Panel{ Content: content, Description: description, Title: pageTitle, } } var DefaultFuncMap = template.FuncMap{ "lang": language.Get, "langHtml": language.GetFromHtml, "link": func(cdnUrl, prefixUrl, assetsUrl string) string { if cdnUrl == "" { return prefixUrl + assetsUrl } return cdnUrl + assetsUrl }, "isLinkUrl": func(s string) bool { return (len(s) > 7 && s[:7] == "http://") || (len(s) > 8 && s[:8] == "https://") }, "render": func(s, old, repl template.HTML) template.HTML { return template.HTML(strings.ReplaceAll(string(s), string(old), string(repl))) }, "renderJS": func(s template.JS, old, repl template.HTML) template.JS { return template.JS(strings.ReplaceAll(string(s), string(old), string(repl))) }, "divide": func(a, b int) int { return a / b }, "renderRowDataHTML": func(id, content template.HTML, value ...map[string]types.InfoItem) template.HTML { return template.HTML(types.ParseTableDataTmplWithID(id, string(content), value...)) }, "renderRowDataJS": func(id template.HTML, content template.JS, value ...map[string]types.InfoItem) template.JS { return template.JS(types.ParseTableDataTmplWithID(id, string(content), value...)) }, "attr": func(s template.HTML) template.HTMLAttr { return template.HTMLAttr(s) }, "js": func(s interface{}) template.JS { if ss, ok := s.(string); ok { return template.JS(ss) } if ss, ok := s.(template.HTML); ok { return template.JS(ss) } return "" }, "changeValue": func(f types.FormField, index int) types.FormField { if len(f.ValueArr) > 0 { f.Value = template.HTML(f.ValueArr[index]) } if len(f.OptionsArr) > 0 { f.Options = f.OptionsArr[index] } if f.FormType.IsSelect() { f.FieldClass += "_" + strconv.Itoa(index) } return f }, } type BaseComponent struct { Name string HTMLData string CSS template.CSS JS template.JS Callbacks types.Callbacks } func (b *BaseComponent) IsAPage() bool { return false } func (b *BaseComponent) GetName() string { return b.Name } func (b *BaseComponent) GetAssetList() []string { return make([]string, 0) } func (b *BaseComponent) GetAsset(name string) ([]byte, error) { return nil, nil } func (b *BaseComponent) GetJS() template.JS { return b.JS } func (b *BaseComponent) GetCSS() template.CSS { return b.CSS } func (b *BaseComponent) GetCallbacks() types.Callbacks { return b.Callbacks } func (b *BaseComponent) BindActionTo(ctx *context.Context, action types.Action, id string) { action.SetBtnId(id) b.JS += action.Js() b.HTMLData += string(action.ExtContent(ctx)) b.Callbacks = append(b.Callbacks, action.GetCallbacks()) } func (b *BaseComponent) GetContentWithData(obj interface{}) template.HTML { buffer := new(bytes.Buffer) tmpl, defineName := b.GetTemplate() err := tmpl.ExecuteTemplate(buffer, defineName, obj) if err != nil { logger.Error(b.Name+" GetContent error:", err) } return template.HTML(buffer.String()) } func (b *BaseComponent) GetTemplate() (*template.Template, string) { tmpl, err := template.New(b.Name). Funcs(DefaultFuncMap). Parse(b.HTMLData) if err != nil { logger.Error(b.Name+" GetTemplate Error: ", err) } return tmpl, b.Name } ================================================ FILE: template/template_test.go ================================================ package template import ( "testing" "github.com/stretchr/testify/assert" ) func TestVersionCompare(t *testing.T) { assert.Equal(t, true, VersionCompare("v1.2.8", []string{"v1.2.7"})) assert.Equal(t, true, VersionCompare("v1.2.8", []string{"v1.2.8"})) assert.Equal(t, true, VersionCompare("v1.2.8", []string{"v1.2.5", "v1.2.8"})) assert.Equal(t, false, VersionCompare("v1.2.7", []string{"v1.2.8"})) assert.Equal(t, true, VersionCompare("v0.0.30", []string{"v0.0.30"})) assert.Equal(t, true, VersionCompare("v0.0.30", []string{">=v0.0.30"})) assert.Equal(t, true, VersionCompare("v0.0.30", []string{">=v0.0.29"})) assert.Equal(t, false, VersionCompare("v0.0.30", []string{">=v0.1.1"})) assert.Equal(t, true, VersionCompare("v0.0.30", []string{"<=v0.1.1"})) } ================================================ FILE: template/types/action/ajax.go ================================================ package action import ( "encoding/json" "html/template" "strings" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/constant" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/template/types" ) type AjaxAction struct { BaseAction Url string Method string Data AjaxData Alert bool AlertData AlertData SuccessJS template.JS ErrorJS template.JS ParameterJS template.JS Event Event Handlers []context.Handler } type AlertData struct { Title string `json:"title"` Type string `json:"type"` ShowCancelButton bool `json:"showCancelButton"` ConfirmButtonColor string `json:"confirmButtonColor"` ConfirmButtonText string `json:"confirmButtonText"` CloseOnConfirm bool `json:"closeOnConfirm"` CancelButtonText string `json:"cancelButtonText"` } func Ajax(id string, handler types.Handler) *AjaxAction { if id == "" { panic("wrong ajax action parameter, empty id") } return &AjaxAction{ Url: URL(id), Method: "post", Data: NewAjaxData(), SuccessJS: `if (data.code === 0) { swal(data.msg, '', 'success'); } else { swal(data.msg, '', 'error'); }`, ErrorJS: `if (data.responseText !== "") { swal(data.responseJSON.msg, '', 'error'); } else { swal('error', '', 'error'); }`, Handlers: context.Handlers{handler.Wrap()}, Event: EventClick, } } func (ajax *AjaxAction) WithAlert(data ...AlertData) *AjaxAction { ajax.Alert = true if len(data) > 0 { ajax.AlertData = data[0] } else { ajax.AlertData = AlertData{ Title: "", Type: "warning", ShowCancelButton: true, ConfirmButtonColor: "#DD6B55", ConfirmButtonText: language.Get("yes"), CloseOnConfirm: false, CancelButtonText: language.Get("cancel"), } } return ajax } func (ajax *AjaxAction) AddData(data map[string]interface{}) *AjaxAction { ajax.Data = ajax.Data.Add(data) return ajax } func (ajax *AjaxAction) SetData(data map[string]interface{}) *AjaxAction { ajax.Data = data return ajax } func (ajax *AjaxAction) SetUrl(url string) *AjaxAction { ajax.Url = url return ajax } func (ajax *AjaxAction) SetSuccessJS(successJS template.JS) *AjaxAction { ajax.SuccessJS = successJS return ajax } func (ajax *AjaxAction) ChangeHTMLWhenSuccess(identify string, text ...string) *AjaxAction { data := template.JS("data.data") if len(text) > 0 { if len(text[0]) > 5 && text[0][:5] == "data." { data = template.JS(text[0]) } else { data = `"` + template.JS(text[0]) + `"` } } selector := template.JS(identify) if !strings.Contains(identify, "$") { selector = `$("` + template.JS(identify) + `")` } ajax.SuccessJS = ` if (data.code === 0) { if (` + selector + `.is("input")) { ` + selector + `.val(` + data + `); } else if (` + selector + `.is("select")) { ` + selector + `.val(` + data + `); } else { ` + selector + `.html(` + data + `); } } else { swal(data.msg, '', 'error'); }` return ajax } func (ajax *AjaxAction) SetEvent(event Event) *AjaxAction { ajax.Event = event return ajax } func (ajax *AjaxAction) SetErrorJS(errorJS template.JS) *AjaxAction { ajax.ErrorJS = errorJS return ajax } func (ajax *AjaxAction) SetParameterJS(parameterJS template.JS) *AjaxAction { ajax.ParameterJS += parameterJS return ajax } func (ajax *AjaxAction) SetMethod(method string) *AjaxAction { ajax.Method = method return ajax } func (ajax *AjaxAction) GetCallbacks() context.Node { return context.Node{ Path: ajax.Url, Method: ajax.Method, Handlers: ajax.Handlers, Value: map[string]interface{}{constant.ContextNodeNeedAuth: 1}, } } func (ajax *AjaxAction) Js() template.JS { ajaxStatement := `$.ajax({ method: '` + ajax.Method + `', url: "` + ajax.Url + `", data: data, success: function (data) { ` + string(ajax.SuccessJS) + ` }, error: function (data) { ` + string(ajax.ErrorJS) + ` }, });` if ajax.Alert { b, _ := json.Marshal(ajax.AlertData) ajaxStatement = "swal(" + string(b) + `, function () { ` + ajaxStatement + ` });` } return template.JS(`$('`+ajax.BtnId+`').on('`+string(ajax.Event)+`', function (event) { let data = `+ajax.Data.JSON()+`; `) + ajax.ParameterJS + template.JS(` let id = $(this).attr("data-id"); if (id && id !== "") { data["id"] = id; } `+ajaxStatement+` });`) } func (ajax *AjaxAction) BtnAttribute() template.HTML { return template.HTML(`href="javascript:;"`) } ================================================ FILE: template/types/action/base.go ================================================ package action import ( "encoding/json" "html/template" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/utils" "github.com/GoAdminGroup/go-admin/template/types" ) type AjaxData map[string]interface{} func NewAjaxData() AjaxData { return AjaxData{"ids": "{{.Ids}}"} } func (a AjaxData) Add(m map[string]interface{}) AjaxData { for k, v := range m { a[k] = v } return a } func (a AjaxData) JSON() string { b, _ := json.Marshal(a) return utils.ReplaceAll(string(b), `"{%id}"`, "{{.Id}}", `"{%ids}"`, "{{.Ids}}", `"{{.Ids}}"`, "{{.Ids}}", `"{{.Id}}"`, "{{.Id}}") } type BaseAction struct { BtnId string BtnData interface{} JS template.JS } func (base *BaseAction) SetBtnId(btnId string) { if btnId[0] != '.' && btnId[0] != '#' { base.BtnId = "." + btnId } else { base.BtnId = btnId } } func (base *BaseAction) Js() template.JS { return base.JS } func (base *BaseAction) BtnClass() template.HTML { return "" } func (base *BaseAction) BtnAttribute() template.HTML { return "" } func (base *BaseAction) GetCallbacks() context.Node { return context.Node{} } func (base *BaseAction) ExtContent(ctx *context.Context) template.HTML { return template.HTML(``) } func (base *BaseAction) FooterContent(ctx *context.Context) template.HTML { return template.HTML(``) } func (base *BaseAction) SetBtnData(data interface{}) { base.BtnData = data } var _ types.Action = (*AjaxAction)(nil) var _ types.Action = (*PopUpAction)(nil) var _ types.Action = (*JumpAction)(nil) var _ types.Action = (*JumpSelectBoxAction)(nil) func URL(id string) string { return config.Url("/operation/" + utils.WrapURL(id)) } ================================================ FILE: template/types/action/event.go ================================================ package action type Event string const ( EventBlur Event = "blur" EventFocus Event = "focus" EventFocusin Event = "focusin" EventFocusout Event = "focusout" EventLoad Event = "load" EventResize Event = "resize" EventScroll Event = "scroll" EventUnload Event = "unload" EventClick Event = "click" EventDblclick Event = "dblclick" EventMousedown Event = "mousedown" EventMouseup Event = "mouseup" EventMousemove Event = "mousemove" EventMouseover Event = "mouseover" EventMouseout Event = "mouseout" EventMouseenter Event = "mouseenter" EventMouseleave Event = "mouseleave" EventChange Event = "change" EventSelect Event = "select" EventSubmit Event = "submit" EventKeydown Event = "keydown" EventKeypress Event = "keypress" EventKeyup Event = "keyup" EventError Event = "error" EventContextmenu Event = "contextmenu" ) ================================================ FILE: template/types/action/fieldfilter.go ================================================ package action import ( "html/template" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" "github.com/GoAdminGroup/go-admin/template/types" ) type FieldFilterAction struct { BaseAction Field string } func FieldFilter(field string) *FieldFilterAction { return &FieldFilterAction{Field: field} } func (jump *FieldFilterAction) ExtContent(ctx *context.Context) template.HTML { options := jump.BtnData.(types.FieldOptions) cm := `` for _, obejct := range options { cm += `if (e.params.data.text === "` + obejct.Text + `") { $.pjax({url: setURL("` + jump.Field + `", "` + obejct.Value + `"), container: '#pjax-container'}); }` } return template.HTML(``) } ================================================ FILE: template/types/action/file_upload.go ================================================ package action import ( "html/template" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/constant" "github.com/GoAdminGroup/go-admin/template/types" ) type FileUploadAction struct { BaseAction Url string Method string FileName string Handlers []context.Handler } func FileUpload(id string, handler types.Handler) *FileUploadAction { if id == "" { panic("wrong file upload action parameter, empty id") } return &FileUploadAction{ Url: URL(id), Method: "post", FileName: "file", Handlers: context.Handlers{handler.Wrap()}, } } func (file *FileUploadAction) SetUrl(url string) *FileUploadAction { file.Url = url return file } func (file *FileUploadAction) SetMethod(method string) *FileUploadAction { file.Method = method return file } func (file *FileUploadAction) GetCallbacks() context.Node { return context.Node{ Path: file.Url, Method: file.Method, Handlers: file.Handlers, Value: map[string]interface{}{constant.ContextNodeNeedAuth: 1}, } } func (file *FileUploadAction) Js() template.JS { return template.JS(`$('` + file.BtnId + `').on('click', function(){ $('` + file.BtnId + `_input').click(); }); $("` + file.BtnId + `_input").on("change", function () { var files = $('` + file.BtnId + `_input').prop('files'); var data = new FormData(); data.append('` + file.FileName + `', files[0]); NProgress.start(); $.ajax({ url: '` + file.Url + `', type: '` + file.Method + `', data: data, cache: false, processData: false, contentType: false, success: function (data) { NProgress.done(); if (data.code === 0) { swal(data.msg, '', 'success'); $.pjax.reload('#pjax-container'); } else { swal(data.msg, '', 'error'); } }, error: function (data) { NProgress.done(); if (data.responseText !== "") { swal(data.responseJSON.msg, '', 'error'); } else { swal('error', '', 'error'); } }, }); });`) } func (file *FileUploadAction) BtnAttribute() template.HTML { return template.HTML(`href="javascript:;"`) } func (file *FileUploadAction) FooterContent(ctx *context.Context) template.HTML { return template.HTML(``) } ================================================ FILE: template/types/action/jump.go ================================================ package action import ( "html/template" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/utils" ) type JumpAction struct { BaseAction Url string Target string Ext template.HTML NewTabTitle string } func Jump(url string, ext ...template.HTML) *JumpAction { url = utils.ReplaceAll(url, "{%id}", "{{.Id}}", "{%ids}", "{{.Ids}}") if len(ext) > 0 { return &JumpAction{Url: url, Ext: ext[0]} } return &JumpAction{Url: url, NewTabTitle: ""} } func JumpInNewTab(url, title string, ext ...template.HTML) *JumpAction { url = utils.ReplaceAll(url, "{%id}", "{{.Id}}", "{%ids}", "{{.Ids}}") if len(ext) > 0 { return &JumpAction{Url: url, NewTabTitle: title, Ext: ext[0]} } return &JumpAction{Url: url, NewTabTitle: title} } func JumpWithTarget(url, target string, ext ...template.HTML) *JumpAction { url = utils.ReplaceAll(url, "{%id}", "{{.Id}}", "{%ids}", "{{.Ids}}") if len(ext) > 0 { return &JumpAction{Url: url, Target: target, Ext: ext[0]} } return &JumpAction{Url: url, Target: target} } func (jump *JumpAction) GetCallbacks() context.Node { return context.Node{Path: jump.Url, Method: "GET"} } func (jump *JumpAction) BtnAttribute() template.HTML { html := template.HTML(`href="` + jump.Url + `"`) if jump.NewTabTitle != "" { html += template.HTML(` data-title="` + jump.NewTabTitle + `"`) } if jump.Target != "" { html += template.HTML(` target="` + jump.Target + `"`) } return html } func (jump *JumpAction) BtnClass() template.HTML { if jump.NewTabTitle != "" { return "new-tab-link" } return "" } func (jump *JumpAction) ExtContent(ctx *context.Context) template.HTML { return jump.Ext } ================================================ FILE: template/types/action/jump_selectbox.go ================================================ package action import ( "html/template" "github.com/GoAdminGroup/go-admin/context" ) type JumpSelectBoxAction struct { BaseAction Options JumpOptions NewTabTitle string } type JumpOptions []JumpOption type JumpOption struct { Value string Url string } func SelectBoxJump(options JumpOptions) *JumpSelectBoxAction { return &JumpSelectBoxAction{Options: options} } func (jump *JumpSelectBoxAction) ExtContent(ctx *context.Context) template.HTML { cm := `` for _, obejct := range jump.Options { cm += `if (e.params.data.text === "` + obejct.Value + `") { $.pjax({url: "` + obejct.Url + `", container: '#pjax-container'}); }` } return template.HTML(``) } ================================================ FILE: template/types/action/popup.go ================================================ package action import ( "fmt" "html/template" "regexp" "strings" "github.com/GoAdminGroup/go-admin/context" "github.com/GoAdminGroup/go-admin/modules/config" "github.com/GoAdminGroup/go-admin/modules/constant" "github.com/GoAdminGroup/go-admin/modules/language" "github.com/GoAdminGroup/go-admin/modules/utils" template2 "github.com/GoAdminGroup/go-admin/template" "github.com/GoAdminGroup/go-admin/template/icon" "github.com/GoAdminGroup/go-admin/template/types" ) type PopUpAction struct { BaseAction Url string Method string Id string Title string Draggable bool Width string Height string HasIframe bool HideFooter bool BtnTitle template.HTML ParameterJS template.JS Data AjaxData Handlers []context.Handler Event Event } func PopUp(id, title string, handler types.Handler) *PopUpAction { if id == "" { panic("wrong popup action parameter, empty id") } return &PopUpAction{ Url: URL(id), Title: title, Method: "post", BtnTitle: "", Data: NewAjaxData(), Id: "info-popup-model-" + utils.Uuid(10), Handlers: context.Handlers{handler.Wrap()}, Event: EventClick, } } func (pop *PopUpAction) SetData(data map[string]interface{}) *PopUpAction { pop.Data = pop.Data.Add(data) return pop } func (pop *PopUpAction) SetDraggable() *PopUpAction { pop.Draggable = true return pop } func (pop *PopUpAction) SetWidth(width string) *PopUpAction { pop.Width = width return pop } func (pop *PopUpAction) SetHeight(height string) *PopUpAction { pop.Height = height return pop } func (pop *PopUpAction) SetParameterJS(parameterJS template.JS) *PopUpAction { pop.ParameterJS += parameterJS return pop } func (pop *PopUpAction) SetUrl(url string) *PopUpAction { pop.Url = url return pop } type IframeData struct { Width string Height string Src string AddParameterFn func(ctx *context.Context) string } func PopUpWithIframe(id, title string, data IframeData, width, height string) *PopUpAction { if id == "" { panic("wrong popup action parameter, empty id") } if data.Width == "" { data.Width = "100%" } if data.Height == "" { data.Height = "100%" } if strings.Contains(data.Src, "?") { data.Src = data.Src + "&" } else { data.Src = data.Src + "?" } modalID := "info-popup-model-" + utils.Uuid(10) var handler types.Handler = func(ctx *context.Context) (success bool, msg string, res interface{}) { param := "" if data.AddParameterFn != nil { param = data.AddParameterFn(ctx) } return true, "ok", fmt.Sprintf(`