diff --git a/.github/workflows/build_backend.yml b/.github/workflows/build_backend.yml new file mode 100644 index 00000000..0331b4c8 --- /dev/null +++ b/.github/workflows/build_backend.yml @@ -0,0 +1,119 @@ +# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Build CoderBot backend + +on: push + +jobs: + test: + runs-on: ubuntu-latest + container: coderbot/coderbot-ci:3.9-bullseye-slim + steps: + - uses: actions/checkout@v3 # Checking out the repo + - run: pip install -r docker/stub/requirements.txt + - run: | + export PYTHONPATH=./coderbot:./stub:./test + mkdir test-reports + python3 -m unittest test/coderbot_test.py 2>&1 | tee test-reports/test_report.txt + python3 -m unittest test/camera_test.py 2>&1 | tee test-reports/test_report.txt + #python3 -m unittest test/cnn_test.py 2>&1 | tee test-reports/test_report.txt + echo "test complete" + - run: | + export PYTHONPATH=./stub:./coderbot:./test + python3 coderbot/main.py > coderbot.log & + sleep 30 + apt-get install -y python3-venv + mkdir -p schemathesis + python3 -m venv schemathesis + . schemathesis/bin/activate + pip install schemathesis + st run --endpoint 'activities' --hypothesis-max-examples=10 --request-timeout=20 http://localhost:5000/api/v1/openapi.json + #st run --endpoint 'media' --hypothesis-max-examples=10 --request-timeout=20 http://localhost:5000/api/v1/openapi.json + st run --endpoint 'control/speak' --hypothesis-max-examples=10 --request-timeout=20 http://localhost:5000/api/v1/openapi.json + st run --endpoint 'control/stop' --hypothesis-max-examples=10 --request-timeout=20 http://localhost:5000/api/v1/openapi.json + st run --endpoint 'music' --hypothesis-max-examples=10 --request-timeout=20 http://localhost:5000/api/v1/openapi.json + st run --endpoint 'programs' --hypothesis-max-examples=10 --request-timeout=20 http://localhost:5000/api/v1/openapi.json + echo "openapi test complete" + + release-backend: + needs: [test] + runs-on: ubuntu-latest + steps: + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + # list of Docker images to use as base name for tags + images: ghcr.io/coderbotorg/backend + # generate Docker tags based on the following events/attributes + tags: | + # always latest + type=raw,value=latest + # branch event + type=ref,event=branch + # tag event + type=ref,event=tag + # pull request event + type=ref,event=pr + # push event + type=sha,enable=true,prefix=git-,format=short + - uses: actions/checkout@v3 # Checking out the repo + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v3 + with: + push: true + build-args: CODERBOT_VERSION=${{github.ref_name}}-${{github.sha}} + platforms: linux/arm/v7 + tags: ${{ steps.meta.outputs.tags }} + context: . + file: docker/Dockerfile + cache-from: type=registry,ref=ghcr.io/coderbotorg/backend:latest + cache-to: type=inline + + release-stub: + needs: [test] + runs-on: ubuntu-latest + steps: + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + # list of Docker images to use as base name for tags + images: ghcr.io/coderbotorg/backend + # generate Docker tags based on the following events/attributes + tags: | + # always latest + type=raw,value=stub-latest + - uses: actions/checkout@v3 # Checking out the repo + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v3 + with: + push: true + build-args: CODERBOT_VERSION=${{github.ref_name}}-${{github.sha}} + platforms: linux/amd64 + tags: ${{ steps.meta.outputs.tags }} + context: . + file: docker/stub/Dockerfile + cache-from: type=registry,ref=ghcr.io/coderbotorg/backend:stub-latest + cache-to: type=inline diff --git a/.gitignore b/.gitignore index b17f9758..4a3ebb11 100644 --- a/.gitignore +++ b/.gitignore @@ -28,17 +28,26 @@ # Logs and databases # ###################### *.log +*.log.* *.sql *.sqlite # Pictures taken -photos/ +media/*.jpeg +media/*.mp4 +saved_photos + +#cnn models +cnn_models/* + +# Sounds recorded +sounds/*.wav # Logs -logs/ +logs/*.log -# Tutorial -static/blockly-tutorial +# User programs +data/*.json # OS generated files # ###################### @@ -49,3 +58,35 @@ static/blockly-tutorial .Trashes ehthumbs.db Thumbs.db +.vscode + +# Swap files +*.swp + +# Python3 Virtual Environment folders + +bin/ +lib/ +lib64/ +lib64 +share/ +pyvenv.cfg + +# Vue build +dist/ +# Docs +cb_docs/ + +coderbot.cfg + +swagger-ui/ + +# Uploaded updates folder +updatePackages + +# firmware +firmware/ + +# test +cassette.yaml +.hypothesis \ No newline at end of file diff --git a/.x.swp b/.x.swp deleted file mode 100644 index 11dc6682..00000000 Binary files a/.x.swp and /dev/null differ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..31ed3caa --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,336 @@ +That's correct, at least for linking existing material and, overall, providing and overview of the project and the (now many) components. + +As for the "CONTRIBUTING" document, I will prepare something inspired by [this](), according to these [general guidelines](https://mozillascience.github.io/working-open-workshop/contributing/). + +# Contributing to CoderBot + +:+1::robot: Thanks for your interest in the CoderBot project! :robot::+1: + +The following is a set of guidelines for contributing to CoderBot and its modules, which are hosted in the [CoderBot Organization](https://github.com/CoderBotOrg) on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. + +#### Table Of Contents + +[Code of Conduct](#code-of-conduct) + +[What should I know before I get started?](#what-should-i-know-before-i-get-started) + * [CoderBot project description](#coderbot-project-description) + * [CoderBot architecture](#coderbot-architecture) + +[How Can I Contribute?](#how-can-i-contribute) + * [Reporting Bugs](#reporting-bugs) + * [Suggesting Enhancements](#suggesting-enhancements) + * [Your First Code Contribution](#your-first-code-contribution) + * [Pull Requests](#pull-requests) + +[Styleguides](#styleguides) + * [Git Commit Messages](#git-commit-messages) + * [JavaScript Styleguide](#javascript-styleguide) + * [CoffeeScript Styleguide](#coffeescript-styleguide) + * [Specs Styleguide](#specs-styleguide) + * [Documentation Styleguide](#documentation-styleguide) + +[Additional Notes](#additional-notes) + * [Issue and Pull Request Labels](#issue-and-pull-request-labels) + +## Code of Conduct + +This project and everyone participating in it is governed by the [CoderBot Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [info@coderbot.org](info@coderbot.org). + +## What should I know before I get started? + +### CoderBot project description + +CoderBot is an open source project with the objective of providing the hardware and software used in the educational robot with the same name. + +It is composed by several [repositories](https://github.com/CoderBotOrg). When you initially consider contributing to CoderBot, you might be unsure about which of those repositories implements the functionality you want to change or report a bug for. This section should help you with that. + +#### Package Conventions + +### CoderBot architecture + +## How Can I Contribute? + +### Reporting Bugs + +This section guides you through submitting a bug report for CoderBot. Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior :computer: :computer:, and find related reports :mag_right:. + +Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](https://github.com/CoderBotOrg/.github/blob/master/.github/ISSUE_TEMPLATE/bug_report.md), the information it asks for helps us resolve issues faster. + +> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. + +#### Before Submitting A Bug Report + +* TODO + +#### How Do I Submit A (Good) Bug Report? + +Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](#coderbot-and-repos) your bug is related to, create an issue on that repository and provide the following information by filling in [the template](https://github.com/CoderBotOrg/.github/blob/master/.github/ISSUE_TEMPLATE/bug_report.md). + +Explain the problem and include additional details to help maintainers reproduce the problem: + +* **Use a clear and descriptive title** for the issue to identify the problem. +* **Describe the exact steps which reproduce the problem** in as many details as possible. + +Provide more context by answering these questions: + +° TODO + +### Suggesting Enhancements + +This section guides you through submitting an enhancement suggestion for CoderBot, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion :pencil: and find related suggestions :mag_right:. + +Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](https://github.com/CoderBotOrg/.github/blob/master/.github/ISSUE_TEMPLATE/feature_request.md), including the steps that you imagine you would take if the feature you're requesting existed. + +#### Before Submitting An Enhancement Suggestion + +#### How Do I Submit A (Good) Enhancement Suggestion? + +Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](#coderbot-and-repos) your enhancement suggestion is related to, create an issue on that repository and provide the following information: + +* **Use a clear and descriptive title** for the issue to identify the suggestion. +* **Provide a step-by-step description of the suggested enhancement** in as many details as possible. +* **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). +* **Describe the current behavior** and **explain which behavior you expected to see instead** and why. +* **Explain why this enhancement would be useful** to most CoderBot users and isn't something that can or should be implemented as a [community package](#coderbot-and-repos). +* **List some other text editors or applications where this enhancement exists.** + +### Your First Code Contribution + +Unsure where to begin contributing to CoderBot? You can start by looking through these `beginner` and `help-wanted` issues: + +* [Beginner issues][beginner] - issues which should only require a few lines of code, and a test or two. +* [Help wanted issues][help-wanted] - issues which should be a bit more involved than `beginner` issues. + +Both issue lists are sorted by total number of comments. While not perfect, number of comments is a reasonable proxy for impact a given change will have. + +#### Local development + +* TODO + +### Pull Requests + +The process described here has several goals: + +- Maintain CoderBot's quality +- Fix problems that are important to users +- Engage the community in working toward the best possible CoderBot +- Enable a sustainable system for CoderBot's maintainers to review contributions + +Please follow these steps to have your contribution considered by the maintainers: + +1. Follow all instructions in [the template](PULL_REQUEST_TEMPLATE.md) +2. Follow the [styleguides](#styleguides) +3. After you submit your pull request, verify that all [status checks](https://help.github.com/articles/about-status-checks/) are passing
What if the status checks are failing?If a status check is failing, and you believe that the failure is unrelated to your change, please leave a comment on the pull request explaining why you believe the failure is unrelated. A maintainer will re-run the status check for you. If we conclude that the failure was a false positive, then we will open an issue to track that problem with our status check suite.
+ +While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted. + +## Styleguides + +### Git Commit Messages + +* Use the present tense ("Add feature" not "Added feature") +* Use the imperative mood ("Move cursor to..." not "Moves cursor to...") +* Limit the first line to 72 characters or less +* Reference issues and pull requests liberally after the first line +* When only changing documentation, include `[ci skip]` in the commit title + +### JavaScript Styleguide + +All JavaScript code is linted with [Prettier](https://prettier.io/). + +* Prefer the object spread operator (`{...anotherObj}`) to `Object.assign()` +* Inline `export`s with expressions whenever possible + ```js + // Use this: + export default class ClassName { + + } + + // Instead of: + class ClassName { + + } + export default ClassName + ``` +* Place requires in the following order: + * Built in Node Modules (such as `path`) + * Local Modules (using relative paths) +* Place class properties in the following order: + * Class methods and properties (methods starting with `static`) + * Instance methods and properties + +### Documentation Styleguide + +* Use [Markdown](https://daringfireball.net/projects/markdown). +* Reference methods and classes in markdown with the custom `{}` notation: + * Reference classes with `{ClassName}` + * Reference instance methods with `{ClassName::methodName}` + * Reference class methods with `{ClassName.methodName}` + +#### Example + +* TODO + +## Additional Notes + +### Issue and Pull Request Labels + +This section lists the labels we use to help us track and manage issues and pull requests. Most labels are used across all CoderBot repositories. + +[GitHub search](https://help.github.com/articles/searching-issues/) makes it easy to use labels for finding groups of issues or pull requests you're interested in. +The labels are loosely grouped by their purpose, but it's not required that every issue has a label from every group or that an issue can't have more than one label from the same group. + +#### Type of Issue and Issue State + +| Label name | `CoderBotOrg` :mag_right: | `CoderBot`‑org :mag_right: | Description | +| --- | --- | --- | --- | +| `enhancement` | [search][search-coderbot-repo-label-enhancement] | [search][search-coderbot-org-label-enhancement] | Feature requests. | +| `bug` | [search][search-coderbot-repo-label-bug] | [search][search-coderbot-org-label-bug] | Confirmed bugs or reports that are very likely to be bugs. | +| `question` | [search][search-coderbot-repo-label-question] | [search][search-coderbot-org-label-question] | Questions more than bug reports or feature requests (e.g. how do I do X). | +| `feedback` | [search][search-coderbot-repo-label-feedback] | [search][search-coderbot-org-label-feedback] | General feedback more than bug reports or feature requests. | +| `help-wanted` | [search][search-coderbot-repo-label-help-wanted] | [search][search-coderbot-org-label-help-wanted] | The CoderBot core team would appreciate help from the community in resolving these issues. | +| `beginner` | [search][search-coderbot-repo-label-beginner] | [search][search-coderbot-org-label-beginner] | Less complex issues which would be good first issues to work on for users who want to contribute to CoderBot. | +| `more-information-needed` | [search][search-coderbot-repo-label-more-information-needed] | [search][search-coderbot-org-label-more-information-needed] | More information needs to be collected about these problems or feature requests (e.g. steps to reproduce). | +| `needs-reproduction` | [search][search-coderbot-repo-label-needs-reproduction] | [search][search-coderbot-org-label-needs-reproduction] | Likely bugs, but haven't been reliably reproduced. | +| `blocked` | [search][search-coderbot-repo-label-blocked] | [search][search-coderbot-org-label-blocked] | Issues blocked on other issues. | +| `duplicate` | [search][search-coderbot-repo-label-duplicate] | [search][search-coderbot-org-label-duplicate] | Issues which are duplicates of other issues, i.e. they have been reported before. | +| `wontfix` | [search][search-coderbot-repo-label-wontfix] | [search][search-coderbot-org-label-wontfix] | The CoderBot core team has decided not to fix these issues for now, either because they're working as intended or for some other reason. | +| `invalid` | [search][search-coderbot-repo-label-invalid] | [search][search-coderbot-org-label-invalid] | Issues which aren't valid (e.g. user errors). | +| `package-idea` | [search][search-coderbot-repo-label-package-idea] | [search][search-coderbot-org-label-package-idea] | Feature request which might be good candidates for new packages, instead of extending CoderBot or core CoderBot packages. | +| `wrong-repo` | [search][search-coderbot-repo-label-wrong-repo] | [search][search-coderbot-org-label-wrong-repo] | | + +#### Topic Categories + +| Label name | `CoderBotOrg/backend` :mag_right: | `CoderBotOrg`‑org :mag_right: | Description | +| --- | --- | --- | --- | +| `windows` | [search][search-coderbot-repo-label-windows] | [search][search-coderbot-org-label-windows] | Related to CoderBot running on Windows. | +| `linux` | [search][search-coderbot-repo-label-linux] | [search][search-coderbot-org-label-linux] | Related to CoderBot running on Linux. | +| `mac` | [search][search-coderbot-repo-label-mac] | [search][search-coderbot-org-label-mac] | Related to CoderBot running on macOS. | +| `documentation` | [search][search-coderbot-repo-label-documentation] | [search][search-coderbot-org-label-documentation] | Related to any type of documentation (e.g. [API documentation]() and the [flight manual]()). | +| `performance` | [search][search-coderbot-repo-label-performance] | [search][search-coderbot-org-label-performance] | Related to performance. | +| `security` | [search][search-coderbot-repo-label-security] | [search][search-coderbot-org-label-security] | Related to security. | +| `ui` | [search][search-coderbot-repo-label-ui] | [search][search-coderbot-org-label-ui] | Related to visual design. | +| `api` | [search][search-coderbot-repo-label-api] | [search][search-coderbot-org-label-api] | Related to CoderBot's public APIs. | +| `uncaught-exception` | [search][search-coderbot-repo-label-uncaught-exception] | [search][search-coderbot-org-label-uncaught-exception] | Issues about uncaught exceptions. | +| `crash` | [search][search-coderbot-repo-label-crash] | [search][search-coderbot-org-label-crash] | Reports of CoderBot completely crashing. | +| `auto-indent` | [search][search-coderbot-repo-label-auto-indent] | [search][search-coderbot-org-label-auto-indent] | Related to auto-indenting text. | +| `encoding` | [search][search-coderbot-repo-label-encoding] | [search][search-coderbot-org-label-encoding] | Related to character encoding. | +| `network` | [search][search-coderbot-repo-label-network] | [search][search-coderbot-org-label-network] | Related to network problems or working with remote files (e.g. on network drives). | +| `git` | [search][search-coderbot-repo-label-git] | [search][search-coderbot-org-label-git] | Related to Git functionality (e.g. problems with gitignore files or with showing the correct file status). | + +#### `CoderBotOrg/backend` Topic Categories + +| Label name | `CoderBotOrg/backend` :mag_right: | `CoderBotOrg`‑org :mag_right: | Description | +| --- | --- | --- | --- | +| `editor-rendering` | [search][search-coderbot-repo-label-editor-rendering] | [search][search-coderbot-org-label-editor-rendering] | Related to language-independent aspects of rendering text (e.g. scrolling, soft wrap, and font rendering). | +| `build-error` | [search][search-coderbot-repo-label-build-error] | [search][search-coderbot-org-label-build-error] | Related to problems with building CoderBot from source. | +| `error-from-pathwatcher` | [search][search-coderbot-repo-label-error-from-pathwatcher] | [search][search-coderbot-org-label-error-from-pathwatcher] | | +| `error-from-save` | [search][search-coderbot-repo-label-error-from-save] | [search][search-coderbot-org-label-error-from-save] | Related to errors thrown when saving files. | +| `error-from-open` | [search][search-coderbot-repo-label-error-from-open] | [search][search-coderbot-org-label-error-from-open] | Related to errors thrown when opening files. | +| `installer` | [search][search-coderbot-repo-label-installer] | [search][search-coderbot-org-label-installer] | Related to the CoderBot installers for different OSes. | +| `auto-updater` | [search][search-coderbot-repo-label-auto-updater] | [search][search-coderbot-org-label-auto-updater] | Related to the auto-updater for different OSes. | +| `deprecation-help` | [search][search-coderbot-repo-label-deprecation-help] | [search][search-coderbot-org-label-deprecation-help] | Issues for helping package authors remove usage of deprecated APIs in packages. | +| `electron` | [search][search-coderbot-repo-label-electron] | [search][search-coderbot-org-label-electron] | | + +#### Pull Request Labels + +| Label name | `CoderBotOrg/backend` :mag_right: | `CoderBotOrg`‑org :mag_right: | Description +| --- | --- | --- | --- | +| `work-in-progress` | [search][search-coderbot-repo-label-work-in-progress] | [search][search-coderbot-org-label-work-in-progress] | Pull requests which are still being worked on, more changes will follow. | +| `needs-review` | [search][search-coderbot-repo-label-needs-review] | [search][search-coderbot-org-label-needs-review] | Pull requests which need code review, and approval from maintainers or CoderBot core team. | +| `under-review` | [search][search-coderbot-repo-label-under-review] | [search][search-coderbot-org-label-under-review] | Pull requests being reviewed by maintainers or CoderBot core team. | +| `requires-changes` | [search][search-coderbot-repo-label-requires-changes] | [search][search-coderbot-org-label-requires-changes] | Pull requests which need to be updated based on review comments and then reviewed again. | +| `needs-testing` | [search][search-coderbot-repo-label-needs-testing] | [search][search-coderbot-org-label-needs-testing] | Pull requests which need manual testing. | + +[search-coderbot-repo-label-enhancement]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aenhancement +[search-coderbot-org-label-enhancement]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aenhancement +[search-coderbot-repo-label-bug]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Abug +[search-coderbot-org-label-bug]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Abug +[search-coderbot-repo-label-question]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aquestion +[search-coderbot-org-label-question]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aquestion +[search-coderbot-repo-label-feedback]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Afeedback +[search-coderbot-org-label-feedback]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Afeedback +[search-coderbot-repo-label-help-wanted]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Ahelp-wanted +[search-coderbot-org-label-help-wanted]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Ahelp-wanted +[search-coderbot-repo-label-beginner]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Abeginner +[search-coderbot-org-label-beginner]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Abeginner +[search-coderbot-repo-label-more-information-needed]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Amore-information-needed +[search-coderbot-org-label-more-information-needed]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Amore-information-needed +[search-coderbot-repo-label-needs-reproduction]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aneeds-reproduction +[search-coderbot-org-label-needs-reproduction]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aneeds-reproduction +[search-coderbot-repo-label-triage-help-needed]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Atriage-help-needed +[search-coderbot-org-label-triage-help-needed]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Atriage-help-needed +[search-coderbot-repo-label-windows]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Awindows +[search-coderbot-org-label-windows]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Awindows +[search-coderbot-repo-label-linux]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Alinux +[search-coderbot-org-label-linux]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Alinux +[search-coderbot-repo-label-mac]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Amac +[search-coderbot-org-label-mac]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Amac +[search-coderbot-repo-label-documentation]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Adocumentation +[search-coderbot-org-label-documentation]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Adocumentation +[search-coderbot-repo-label-performance]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aperformance +[search-coderbot-org-label-performance]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aperformance +[search-coderbot-repo-label-security]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Asecurity +[search-coderbot-org-label-security]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Asecurity +[search-coderbot-repo-label-ui]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aui +[search-coderbot-org-label-ui]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aui +[search-coderbot-repo-label-api]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aapi +[search-coderbot-org-label-api]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aapi +[search-coderbot-repo-label-crash]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Acrash +[search-coderbot-org-label-crash]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Acrash +[search-coderbot-repo-label-auto-indent]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aauto-indent +[search-coderbot-org-label-auto-indent]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aauto-indent +[search-coderbot-repo-label-encoding]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aencoding +[search-coderbot-org-label-encoding]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aencoding +[search-coderbot-repo-label-network]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Anetwork +[search-coderbot-org-label-network]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Anetwork +[search-coderbot-repo-label-uncaught-exception]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Auncaught-exception +[search-coderbot-org-label-uncaught-exception]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Auncaught-exception +[search-coderbot-repo-label-git]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Agit +[search-coderbot-org-label-git]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Agit +[search-coderbot-repo-label-blocked]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Ablocked +[search-coderbot-org-label-blocked]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Ablocked +[search-coderbot-repo-label-duplicate]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aduplicate +[search-coderbot-org-label-duplicate]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aduplicate +[search-coderbot-repo-label-wontfix]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Awontfix +[search-coderbot-org-label-wontfix]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Awontfix +[search-coderbot-repo-label-invalid]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Ainvalid +[search-coderbot-org-label-invalid]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Ainvalid +[search-coderbot-repo-label-package-idea]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Apackage-idea +[search-coderbot-org-label-package-idea]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Apackage-idea +[search-coderbot-repo-label-wrong-repo]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Awrong-repo +[search-coderbot-org-label-wrong-repo]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Awrong-repo +[search-coderbot-repo-label-editor-rendering]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aeditor-rendering +[search-coderbot-org-label-editor-rendering]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aeditor-rendering +[search-coderbot-repo-label-build-error]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Abuild-error +[search-coderbot-org-label-build-error]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Abuild-error +[search-coderbot-repo-label-error-from-pathwatcher]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aerror-from-pathwatcher +[search-coderbot-org-label-error-from-pathwatcher]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aerror-from-pathwatcher +[search-coderbot-repo-label-error-from-save]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aerror-from-save +[search-coderbot-org-label-error-from-save]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aerror-from-save +[search-coderbot-repo-label-error-from-open]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aerror-from-open +[search-coderbot-org-label-error-from-open]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aerror-from-open +[search-coderbot-repo-label-installer]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Ainstaller +[search-coderbot-org-label-installer]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Ainstaller +[search-coderbot-repo-label-auto-updater]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Aauto-updater +[search-coderbot-org-label-auto-updater]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aauto-updater +[search-coderbot-repo-label-deprecation-help]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3ACoderBotOrg%2Fbackend+label%3Adeprecation-help +[search-coderbot-org-label-deprecation-help]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Adeprecation-help +[search-coderbot-repo-label-electron]: https://github.com/search?q=is%3Aissue+repo%3ACoderBotOrg%2Fbackend+is%3Aopen+label%3Aelectron +[search-coderbot-org-label-electron]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3ACoderBotOrg+label%3Aelectron +[search-coderbot-repo-label-work-in-progress]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3ACoderBotOrg%2Fbackend+label%3Awork-in-progress +[search-coderbot-org-label-work-in-progress]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3ACoderBotOrg+label%3Awork-in-progress +[search-coderbot-repo-label-needs-review]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3ACoderBotOrg%2Fbackend+label%3Aneeds-review +[search-coderbot-org-label-needs-review]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3ACoderBotOrg+label%3Aneeds-review +[search-coderbot-repo-label-under-review]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3ACoderBotOrg%2Fbackend+label%3Aunder-review +[search-coderbot-org-label-under-review]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3ACoderBotOrg+label%3Aunder-review +[search-coderbot-repo-label-requires-changes]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3ACoderBotOrg%2Fbackend+label%3Arequires-changes +[search-coderbot-org-label-requires-changes]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3ACoderBotOrg+label%3Arequires-changes +[search-coderbot-repo-label-needs-testing]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3ACoderBotOrg%2Fbackend+label%3Aneeds-testing +[search-coderbot-org-label-needs-testing]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3ACoderBotOrg+label%3Aneeds-testing + +[beginner]:https://github.com/search?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+label%3Abeginner+label%3Ahelp-wanted+user%3ACoderBotOrg+sort%3Acomments-desc +[help-wanted]:https://github.com/search?q=is%3Aopen+is%3Aissue+label%3Ahelp-wanted+user%3ACoderBotOrg+sort%3Acomments-desc+-label%3Abeginner +[contributing-to-official-coderbot-packages]: todo +[hacking-on-coderbot-core]: todo + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..ade73b06 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,281 @@ +(C) 2014 - 2019 Roberto Previtera, Antonio Vivace, CoderBot contributors. + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + diff --git a/README.md b/README.md index 94ba1704..5d803f11 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,48 @@ -CoderBot -======== +# backend +![Build CoderBot backend](https://github.com/CoderBotOrg/backend/actions/workflows/build_backend.yml/badge.svg) -A RaspberryPI-based bot controller +> CoderBot is a RaspberryPI-based programmable robot for educational purposes. Check the [project website](https://www.coderbot.org) for more information. +> +> For further information about development and technical documentation, see the [Wiki](https://github.com/CoderBotOrg/coderbot/wiki). -The module provide a simple web interface to a raspberry py "robot". +This repository contains the backend, exposing the [CoderBot API](https://github.com/CoderBotOrg/backend/wiki/API-v2). -See the [wiki](https://github.com/CoderBotOrg/coderbot/wiki) for the documentation +### Quickstart +Prerequisites: +```bash +sudo apt install python3 python3-venv +``` + +Be sure you have Python **3.6**. You may need to use `python3.6` and `python3.6-venv` packages on some repositories with python3 already pointing to **3.7** (e.g. debian unstable/sid). + + + +```bash +git clone https://github.com/CoderBotOrg/coderbot.git +cd coderbot +python3 -m venv . +source bin/activate + +# Install the basic requirements +pip3 install -r requirements_stub.txt +# Additional packages if you are running the real thing +pip3 install -r requirements.txt + +# Start the backend in stub mode +PYTHONPATH=stub:test python3 init.py + +# or, run the real thing if you're on a physical RPi +python3 init.py +``` + +Once started, the backend will expose a number of endpoints: + +- Legacy API: [localhost:5000/``](http://localhost:5000/); +- Legacy JQuery web application: [localhost:5000/old](http://localhost:5000/old); +- API v2: [localhost:5000/v2](http://localhost:5000/v2); +- New Vue web application: [localhost:5000/](http://localhost:5000/) (assuming a [vue-app](https://github.com/coderbotorg/vue-app) build is placed in the `dist/` folder); +- Documentation: [localhost:5000/docs](http://localhost:5000/docs) assuming a [docs](https://github.com/coderbotorg/docs) build is placed in the `cb_docs/` folder); +- Swagger UI dynamic documentation of the API v2: [localhost:5000/v2/ui/index.html](http://localhost:5000/v2/ui/index.html) (once you cloned the [swagger-ui](https://github.com/coderbotorg/swagger-ui) repository inside the backend folder). diff --git a/babel.cfg b/babel.cfg deleted file mode 100644 index bc11d2af..00000000 --- a/babel.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[python: **.py] -[jinja2: **/templates/**.html] -[jinja2: **/templates/**.xml] -extensions=jinja2.ext.autoescape,jinja2.ext.with_ diff --git a/bin/start.sh b/bin/start.sh new file mode 100755 index 00000000..f22ba735 --- /dev/null +++ b/bin/start.sh @@ -0,0 +1,2 @@ +#!/bin/bash +python3 coderbot/main.py diff --git a/stop.sh b/bin/stop.sh similarity index 100% rename from stop.sh rename to bin/stop.sh diff --git a/camera.py b/camera.py deleted file mode 100644 index 3dffd619..00000000 --- a/camera.py +++ /dev/null @@ -1,313 +0,0 @@ -import time -import copy -import os -import sys -import math -from PIL import Image as PILImage -from StringIO import StringIO -from threading import Thread, Lock -import logging - -from viz import camera, streamer, image, blob -import config - -CAMERA_REFRESH_INTERVAL=0.1 -MAX_IMAGE_AGE = 0.0 -PHOTO_PATH = "./photos" -PHOTO_PREFIX = "DSC" -VIDEO_PREFIX = "VID" -PHOTO_THUMB_SUFFIX = "_thumb" -PHOTO_THUMB_SIZE = (240,180) -VIDEO_ELAPSE_MAX = 900 - -class Camera(Thread): - - _instance = None - _img_template = image.Image.load("coderdojo-logo.png") - _warp_corners_1 = [(0, -120), (640, -120), (380, 480), (260, 480)] - _warp_corners_2 = [(0, -60), (320, -60), (190, 240), (130, 240)] - _warp_corners_4 = [(0, -30), (160, -30), (95, 120), (65, 120)] - stream_port = 9080 - - @classmethod - def get_instance(cls): - if cls._instance is None: - cls._instance = Camera() - cls._instance.start() - return cls._instance - - def __init__(self): - logging.info("starting camera") - cam_props = {"width":640, "height":480, "exposure_mode": config.Config.get().get("camera_exposure_mode")} - self._camera = camera.Camera(props=cam_props) - self._streamer = streamer.JpegStreamer("0.0.0.0:"+str(self.stream_port), st=0.1) - #self._cam_off_img.save(self._streamer) - self.recording = False - self.video_start_time = time.time() + 8640000 - self._run = True - self._image_time = 0 - self._image_lock = Lock() - - self._photos = [] - - for dirname, dirnames, filenames, in os.walk(PHOTO_PATH): - for filename in filenames: - if (PHOTO_PREFIX in filename or VIDEO_PREFIX in filename) and PHOTO_THUMB_SUFFIX not in filename: - self._photos.append(filename) - - super(Camera, self).__init__() - - def run(self): - try: - self._camera.grab_start() - while self._run: - sleep_time = CAMERA_REFRESH_INTERVAL - (time.time() - self._image_time) - if sleep_time <= 0: - ts = time.time() - #print "run.1" - self._image_lock.acquire() - self._camera.grab_one() - self._image_lock.release() - #print "run.2: " + str(time.time()-ts) - #self.save_image(image.Image(self._camera.get_image_bgr()).open().binarize().to_jpeg()) - self.save_image(self._camera.get_image_jpeg()) - #print "run.3: " + str(time.time()-ts) - else: - time.sleep(sleep_time) - - if self.recording and time.time() - self.video_start_time > VIDEO_ELAPSE_MAX: - self.video_stop() - - self._camera.grab_stop() - except: - logging.error("Unexpected error:" + str(sys.exc_info()[0])) - raise - - def get_image(self, maxage = MAX_IMAGE_AGE): - return image.Image(self._camera.get_image_bgr()) - - def save_image(self, image_jpeg): - self._streamer.set_image(image_jpeg) - self._image_time=time.time() - - def set_text(self, text): - self._camera.set_overlay_text(str(text)) - - def get_next_photo_index(self): - last_photo_index = 0 - for p in self._photos: - try: - index = int(p[len(PHOTO_PREFIX):-len(self._camera.PHOTO_FILE_EXT)]) - if index > last_photo_index: - last_photo_index = index - except: - pass - return last_photo_index + 1 - - def photo_take(self): - photo_index = self.get_next_photo_index() - filename = PHOTO_PREFIX + str(photo_index) + self._camera.PHOTO_FILE_EXT; - filename_thumb = PHOTO_PREFIX + str(photo_index) + PHOTO_THUMB_SUFFIX + self._camera.PHOTO_FILE_EXT; - of = open(PHOTO_PATH + "/" + filename, "w+") - oft = open(PHOTO_PATH + "/" + filename_thumb, "w+") - im_str = self._camera.get_image_jpeg() - of.write(im_str) - # thumb - im_pil = PILImage.open(StringIO(im_str)) - im_pil.resize(PHOTO_THUMB_SIZE).save(oft) - self._photos.append(filename) - - def is_recording(self): - return self.recording - - def video_rec(self, video_name=None): - if self.is_recording(): - return - self.recording = True - - if video_name is None: - video_index = self.get_next_photo_index() - filename = VIDEO_PREFIX + str(video_index) + self._camera.VIDEO_FILE_EXT; - filename_thumb = VIDEO_PREFIX + str(video_index) + PHOTO_THUMB_SUFFIX + self._camera.PHOTO_FILE_EXT; - else: - filename = VIDEO_PREFIX + video_name + self._camera.VIDEO_FILE_EXT; - filename_thumb = VIDEO_PREFIX + video_name + PHOTO_THUMB_SUFFIX + self._camera.PHOTO_FILE_EXT; - try: - os.remove(PHOTO_PATH + "/" + filename) - except: - pass - - oft = open(PHOTO_PATH + "/" + filename_thumb, "w") - im_str = self._camera.get_image_jpeg() - im_pil = PILImage.open(StringIO(im_str)) - im_pil.resize(PHOTO_THUMB_SIZE).save(oft) - self._photos.append(filename) - self._camera.video_rec(PHOTO_PATH + "/" + filename) - self.video_start_time = time.time() - - def video_stop(self): - if self.recording: - self._camera.video_stop() - self.recording = False - - def get_photo_list(self): - return self._photos - - def get_photo_file(self, filename): - return open(PHOTO_PATH + "/" + filename) - - def get_photo_thumb_file(self, filename): - return open(PHOTO_PATH + "/" + filename[:-len(PHOTO_FILE_EXT)] + PHOTO_THUMB_SUFFIX + PHOTO_FILE_EXT) - - def delete_photo(self, filename): - logging.info("delete photo: " + filename) - os.remove(PHOTO_PATH + "/" + filename) - os.remove(PHOTO_PATH + "/" + filename[:filename.rfind(".")] + PHOTO_THUMB_SUFFIX + self._camera.PHOTO_FILE_EXT) - self._photos.remove(filename) - - def exit(self): - self._run = False - self.join() - - def calibrate(self): - img = self._camera.getImage() - self._background = img.hueHistogram()[-1] - - def find_line(self): - self._image_lock.acquire() - img = self.get_image(0).binarize() - slices = [0,0,0] - blobs = [0,0,0] - slices[0] = img.crop(0, 100, 160, 120) - slices[1] = img.crop(0, 80, 160, 100) - slices[2] = img.crop(0, 60, 160, 80) - coords = [-1, -1, -1] - for idx, slice in enumerate(slices): - blobs[idx] = slice.find_blobs(minsize=30, maxsize=160) - if len(blobs[idx]): - coords[idx] = (blobs[idx][0].center[0] * 100) / 160 - logging.info("line coord: " + str(idx) + " " + str(coords[idx])+ " area: " + str(blobs[idx][0].area())) - - self._image_lock.release() - return coords[0] - - def find_signal(self): - #print "signal" - angle = None - ts = time.time() - self._image_lock.acquire() - img = self.get_image(0) - signals = img.find_template(self._img_template) - - logging.info("signal: " + str(time.time() - ts)) - if len(signals): - angle = signals[0].angle - - self._image_lock.release() - - return angle - - def find_face(self): - faceX = faceY = faceS = None - self._image_lock.acquire() - img = self.get_image(0) - ts = time.time() - faces = img.grayscale().find_faces() - print "face.detect: " + str(time.time() - ts) - self._image_lock.release() - print faces - if len(faces): - # Get the largest face, face is a rectangle - x, y, w, h = faces[0] - centerX = x + (w/2) - faceX = ((centerX * 100) / 160) - 50 #center = 0 - centerY = y + (h/2) - faceY = 50 - (centerY * 100) / 120 #center = 0 - size = h - faceS = (size * 100) / 120 - return [faceX, faceY, faceS] - - def path_ahead(self): - #print "path ahead" - ts = time.time() - self._image_lock.acquire() - img = self.get_image(0) - #print "path_ahead.get_image: " + str(time.time() - ts) - #img.crop(0, 100, 160, 120) - - #control_color = control.meanColor() - #color_distance = cropped.dilate().color_distance(control_color) - - #control_hue = control.getNumpy().mean() - #hue_distance = cropped.dilate().hueDistance(control_hue) - - #print "path_ahead.crop: " + str(time.time() - ts) - #control_hue = control_hue - 20 if control_hue > 127 else control_hue + 20 - #binarized = cropped.dilate().binarize(control_hue) - #binarized = cropped.dilate().binarize().invert() - #control_hue = control_hue - 10 - #binarized = color_distance.binarize(control_hue).invert() - #print "path_ahead.binarize: " + str(time.time() - ts) - blobs = img.binarize().find_blobs(minsize=100, maxsize=8000) - #print "path_ahead.blobs: " + str(time.time() - ts) - coordY = 60 - if len(blobs): - obstacle = blob.Blob.sort_distance((80,120), blobs)[0] - #for b in blobs: - # print "blobs.bottom: " + str(b.bottom) + " area: " + str(b.area()) - - logging.info("obstacle:" + str(obstacle.bottom)) - #print "path_ahead.sortdistnace: " + str(time.time() - ts) - #dw_x = 260 + obstacle.coordinates()[0] - (obstacle.width()/2) - #dw_y = 160 + obstacle.coordinates()[1] - (obstacle.height()/2) - #img.drawRectangle(dw_x, dw_y, obstacle.width(), obstacle.height(), color=(255,0,0)) - x, y = img.transform((obstacle.center[0], obstacle.bottom)) - coordY = 60 - ((y * 48) / 100) - logging.info("coordY: " + str(coordY)) - #print obstacle.coordinates()[1]+(obstacle.height()/2) - #ar_layer.centeredRectangle(obstacle.coordinates(), (obstacle.width(), obstacle.height())) - #warped.addDrawingLayer(ar_layer) - #warped.applyLayers() - #self.save_image(warped.warp(self._unwarp_corners), expire=10) - - #img.drawText("path ahead clear for " + str(coordY) + " cm", 0, 0, fontsize=32 ) - #print "path_ahead.drawtext: " + str(time.time() - ts) - #self.save_image(img) - #print "path_ahead.save_image: " + str(time.time() - ts) - self._image_lock.release() - #print "path_ahead: " + str(time.time() - ts) - return coordY - - def find_color(self, s_color): - color = (int(s_color[1:3],16), int(s_color[3:5],16), int(s_color[5:7],16)) - code_data = None - ts = time.time() - self._image_lock.acquire() - img = self.get_image(0) - self._image_lock.release() - bw = img.filter_color(color) - #self.save_image(bw.to_jpeg()) - objects = bw.find_blobs(minsize=20, maxsize=1000) - logging.debug("objects: " + str(objects)) - dist = -1 - angle = 180 - - if objects and len(objects): - obj = objects[-1] - bottom = obj.bottom - logging.info("bottom: " + str(obj.center[0]) + " " +str(obj.bottom)) - coords = bw.transform([(obj.center[0], obj.bottom)]) - logging.info("coordinates: " + str(coords)) - x = coords[0][0] - y = coords[0][1] - dist = math.sqrt(math.pow(12 + (68 * (120 - y) / 100),2) + (math.pow((x-80)*60/160,2))) - angle = math.atan2(x - 80, 120 - y) * 180 / math.pi - logging.info("object found, dist: " + str(dist) + " angle: " + str(angle)) - #self.save_image(img.to_jpeg()) - #print "object: " + str(time.time() - ts) - return [dist, angle] - - def sleep(self, elapse): - logging.debug("sleep: " + elapse) - time.sleep(elapse) - diff --git a/cnn_models/models.json b/cnn_models/models.json new file mode 100644 index 00000000..47b9b270 --- /dev/null +++ b/cnn_models/models.json @@ -0,0 +1,20 @@ +{ + "generic_fast_low": { + "status": 1.0, + "image_height": "224", + "image_width": "224", + "output_layer": "" + }, + "generic_slow_high": { + "status": 1.0, + "image_height": "224", + "image_width": "224", + "output_layer": "" + }, + "generic_object_detect": { + "status": 1.0, + "image_height": "224", + "image_width": "224", + "output_layer": "" + } +} \ No newline at end of file diff --git a/coderbot.cfg b/coderbot.cfg deleted file mode 100644 index 910d219b..00000000 --- a/coderbot.cfg +++ /dev/null @@ -1 +0,0 @@ -{"move_tr_speed": "75", "move_fw_elapse": "1.5", "show_page_program": "true", "load_at_start": "", "move_tr_elapse": "90", "sound_start": "$startup.mp3", "sound_stop": "$shutdown.mp3", "camera_exposure_mode": "auto", "prog_move_motion": "yes", "show_control_move_commands": "true", "prog_level": "adv", "prog_scrollbars": "true", "ctrl_fw_speed": "100", "move_fw_speed": "100", "show_page_control": "true", "sound_shutter": "$shutter.mp3", "show_page_prefs": "true", "prog_maxblocks": "-1", "ctrl_hud_image": "", "button_func": "none", "move_motor_mode": "servo", "ctrl_fw_elapse": "-1", "ctrl_tr_elapse": "-1", "move_power_angle_2": "20", "move_power_angle_3": "20", "ctrl_tr_speed": "80", "move_power_angle_1": "15"} \ No newline at end of file diff --git a/coderbot.py b/coderbot.py deleted file mode 100644 index 439a1c86..00000000 --- a/coderbot.py +++ /dev/null @@ -1,168 +0,0 @@ -import os -import time -import pigpio - -PIN_MOTOR_ENABLE = 22 -PIN_LEFT_FORWARD = 25 -PIN_LEFT_BACKWARD = 24 -PIN_RIGHT_FORWARD = 4 -PIN_RIGHT_BACKWARD = 17 -PIN_PUSHBUTTON = 18 -PIN_SERVO_3 = 9 -PIN_SERVO_4 = 10 - -PWM_FREQUENCY = 100 #Hz -PWM_RANGE = 100 #0-100 - -def coderbot_callback(gpio, level, tick): - return CoderBot.get_instance().callback(gpio, level, tick) - -class CoderBot: - _pin_out = [PIN_MOTOR_ENABLE, PIN_LEFT_FORWARD, PIN_RIGHT_FORWARD, PIN_LEFT_BACKWARD, PIN_RIGHT_BACKWARD, PIN_SERVO_3, PIN_SERVO_4] - - def __init__(self, servo=False): - self.pi = pigpio.pi('localhost') - self.pi.set_mode(PIN_PUSHBUTTON, pigpio.INPUT) - self._cb = dict() - self._cb_last_tick = dict() - self._cb_elapse = dict() - self._servo = servo - if self._servo: - self.motor_control = self._servo_motor - else: - self.motor_control = self._dc_motor - cb1 = self.pi.callback(PIN_PUSHBUTTON, pigpio.EITHER_EDGE, coderbot_callback) - for pin in self._pin_out: - self.pi.set_PWM_frequency(pin, PWM_FREQUENCY) - self.pi.set_PWM_range(pin, PWM_RANGE) - - self.stop() - self._is_moving = False - - the_bot = None - - @classmethod - def get_instance(cls, servo=False): - if not cls.the_bot: - cls.the_bot = CoderBot(servo) - return cls.the_bot - - def move(self, speed=100, elapse=-1): - self.motor_control(speed_left=speed, speed_right=speed, elapse=elapse) - - def turn(self, speed=100, elapse=-1): - self.motor_control(speed_left=speed, speed_right=-speed, elapse=elapse) - - def forward(self, speed=100, elapse=-1): - self.move(speed=speed, elapse=elapse) - - def backward(self, speed=100, elapse=-1): - self.move(speed=-speed, elapse=elapse) - - def left(self, speed=100, elapse=-1): - self.turn(speed=-speed, elapse=elapse) - - def right(self, speed=100, elapse=-1): - self.turn(speed=speed, elapse=elapse) - - def servo3(self, angle): - self._servo_control(PIN_SERVO_3, angle) - - def servo4(self, angle): - self._servo_control(PIN_SERVO_4, angle) - - def _dc_motor(self, speed_left=100, speed_right=100, elapse=-1): - self._is_moving = True - - if speed_left < 0: - speed_left = abs(speed_left) - self.pi.write(PIN_LEFT_FORWARD, 0) - self.pi.set_PWM_dutycycle(PIN_LEFT_BACKWARD, speed_left) - else: - self.pi.write(PIN_LEFT_BACKWARD, 0) - self.pi.set_PWM_dutycycle(PIN_LEFT_FORWARD, speed_left) - - if speed_right < 0: - speed_right = abs(speed_right) - self.pi.write(PIN_RIGHT_FORWARD, 0) - self.pi.set_PWM_dutycycle(PIN_RIGHT_BACKWARD, speed_right) - else: - self.pi.write(PIN_RIGHT_BACKWARD, 0) - self.pi.set_PWM_dutycycle(PIN_RIGHT_FORWARD, speed_right) - - self.pi.write(PIN_MOTOR_ENABLE, 1) - if elapse > 0: - time.sleep(elapse) - self.stop() - - def _servo_motor(self, speed_left=100, speed_right=100, elapse=-1): - self._is_moving = True - speed_left = -speed_left - - self.pi.write(PIN_MOTOR_ENABLE, 1) - self.pi.write(PIN_RIGHT_BACKWARD, 0) - self.pi.write(PIN_LEFT_BACKWARD, 0) - - self._servo_motor_control(PIN_LEFT_FORWARD, speed_left) - self._servo_motor_control(PIN_RIGHT_FORWARD, speed_right) - if elapse > 0: - time.sleep(elapse) - self.stop() - - - def _servo_motor_control(self, pin, speed): - self._is_moving = True - speed = ((speed + 100) * 50 / 200) + 52 - - self.pi.set_PWM_range(pin, 1000) - self.pi.set_PWM_frequency(pin, 50) - self.pi.set_PWM_dutycycle(pin, speed) - - def _servo_control(self, pin, angle): - duty = ((angle + 90) * 100 / 180) + 25 - - self.pi.set_PWM_range(pin, 1000) - self.pi.set_PWM_frequency(pin, 50) - self.pi.set_PWM_dutycycle(pin, duty) - - def stop(self): - for pin in self._pin_out: - self.pi.write(pin, 0) - self._is_moving = False - - def is_moving(self): - return self._is_moving - - def say(self, what): - if what and "$" in what: - os.system ('omxplayer sounds/' + what[1:]) - elif what and len(what): - os.system ('espeak -vit -p 90 -a 200 -s 150 -g 10 "' + what + '" 2>>/dev/null') - - def set_callback(self, gpio, callback, elapse): - self._cb_elapse[gpio] = elapse * 1000 - self._cb[gpio] = callback - self._cb_last_tick[gpio] = 0 - - def callback(self, gpio, level, tick): - cb = self._cb.get(gpio) - if cb: - elapse = self._cb_elapse.get(gpio) - if level == 0: - self._cb_last_tick[gpio] = tick - elif tick - self._cb_last_tick[gpio] > elapse: - self._cb_last_tick[gpio] = tick - print "pushed: ", level, tick - cb() - - def halt(self): - os.system ('sudo halt') - - def restart(self): - os.system ('sudo /etc/init.d/coderbot stop && sudo pkill -9 dbus && sudo /etc/init.d/coderbot start') - - def reboot(self): - os.system ('sudo reboot') - - - diff --git a/coderbot/activity.py b/coderbot/activity.py new file mode 100644 index 00000000..19e3d102 --- /dev/null +++ b/coderbot/activity.py @@ -0,0 +1,51 @@ +from tinydb import TinyDB, Query +from threading import Lock +# Programs and Activities databases +class Activities(): + _instance = None + + @classmethod + def get_instance(cls): + if cls._instance is None: + cls._instance = Activities() + return cls._instance + + def __init__(self): + self.activities = TinyDB("data/activities.json") + self.query = Query() + self.lock = Lock() + + def load(self, name, default): + with self.lock: + if name and default is None: + activities = self.activities.search(self.query.name == name) + if len(activities) > 0: + return activities[0] + elif default is not None: + if len(self.activities.search(self.query.default == True)) > 0: + return self.activities.search(self.query.default == True)[0] + return None + return None + + def save(self, name, activity): + with self.lock: + # if saved activity is "default", reset existing default activity to "non-default" + if activity.get("default", False) is True: + self.activities.update({'default': False}) + if self.activities.search(self.query.name == name) == []: + self.activities.insert(activity) + else: + self.activities.update(activity, self.query.name == activity["name"]) + + def delete(self, name): + with self.lock: + activities = self.activities.search(self.query.name == name) + if len(activities) > 0: + activity = activities[0] + if activity.get("default", False) is True: + self.activities.update({'default': True}, self.query.stock == True) + self.activities.remove(self.query.name == activity["name"]) + + def list(self): + with self.lock: + return self.activities.all() diff --git a/coderbot/api.py b/coderbot/api.py new file mode 100644 index 00000000..70164c49 --- /dev/null +++ b/coderbot/api.py @@ -0,0 +1,398 @@ +""" +API methods implementation +This file contains every method called by the API defined in v2.yml +""" + +import logging +import os +import subprocess +import urllib + +import connexion +import picamera +from flask import Response, request, send_file +from werkzeug.datastructures import Headers + +from config import Config +from activity import Activities +from audio import Audio +from camera import Camera +from cnn.cnn_manager import CNNManager +from runtime_test import run_test +from musicPackages import MusicPackageManager +from program import Program, ProgramEngine + +from balena import Balena +from coderbot import CoderBot + +BUTTON_PIN = 16 + +config = Config.get() +bot = CoderBot.get_instance() +audio_device = Audio.get_instance() +cam = Camera.get_instance() + +def get_serial(): + """ + Extract serial from cpuinfo file + """ + cpuserial = "0000000000000000" + try: + f = open('/proc/cpuinfo', 'r') + for line in f: + if line[0:6] == 'Serial': + cpuserial = line[10:26] + f.close() + except Exception: + cpuserial = "ERROR000000000" + + return cpuserial + +def get_status(): + """ + Expose CoderBot status: + temperature, uptime, and internet connectivity status. + (Cached method) + """ + + temp = "undefined" + try: + temp = os.popen("vcgencmd measure_temp").readline().replace("temp=", "") + except Exception: + pass + + uptime = 0 + try: + uptime = subprocess.check_output(["uptime"]).decode('utf-8').replace('\n', '') + except Exception: + pass + + internet_status = False + try: + urllib.request.urlopen("https://coderbot.org/") + internet_status = True + except Exception: + pass + + return {'internet_status': internet_status, + 'temp': temp, + 'uptime': uptime} + +def get_info(): + """ + Expose informations about the CoderBot system. + (Cached method) + """ + device = {} + serial = get_serial() + + try: + device = Balena.get_instance().device() + logging.info("device: %s", str(device)) + except Exception: + pass + + return { 'release_commit': device.get("commit"), + 'coderbot_version': os.getenv("CODERBOT_VERSION"), + 'update_status': device.get("status"), + 'kernel': device.get("os_version"), + 'serial': serial } + +prog = None +prog_engine = ProgramEngine.get_instance() + +activities = Activities.get_instance() + +## Robot control + +def stop(): + bot.stop() + return 200 + +def move(body): + speed=body.get("speed") + elapse=body.get("elapse") + distance=body.get("distance") + if (speed is None or speed == 0) or (elapse is not None and distance is not None): + return 400 + bot.move(speed=speed, elapse=elapse, distance=distance) + return 200 + +def turn(body): + speed=body.get("speed") + elapse=body.get("elapse") + distance=body.get("distance") + if (speed is None or speed == 0) or (elapse is not None and distance is not None): + return 400 + bot.turn(speed=speed, elapse=elapse, distance=distance) + return 200 + +def takePhoto(): + try: + cam.photo_take() + audio_device.say(config.get("sound_shutter")) + return 200 + except Exception as e: + logging.warning("Error: %s", e) + +def recVideo(): + try: + cam.video_rec() + audio_device.say(config.get("sound_shutter")) + return 200 + except Exception as e: + logging.warning("Error: %s", e) + +def stopVideo(): + try: + cam.video_stop() + audio_device.say(config.get("sound_shutter")) + return 200 + except Exception as e: + logging.warning("Error: %s", e) + +def speak(body): + text = body.get("text", "") + locale = body.get("locale", "") + logging.debug("say: " + text + " in: " + locale) + audio_device.say(text, locale) + return 200 + +def reset(): + Balena.get_instance().purge() + return 200 + +def halt(): + audio_device.say(what=config.get("sound_stop")) + Balena.get_instance().shutdown() + return 200 + +def restart(): + Balena.get_instance().restart() + +def reboot(): + audio_device.say(what=config.get("sound_stop")) + Balena.get_instance().reboot() + return 200 + +def video_stream(a_cam): + while True: + frame = a_cam.get_image_jpeg() + yield ("--BOUNDARYSTRING\r\n" + + "Content-type: image/jpeg\r\n" + + "Content-Length: " + str(len(frame)) + "\r\n\r\n") + yield frame + yield "\r\n" + +def streamVideo(): + try: + h = Headers() + h.add('Age', 0) + h.add('Cache-Control', 'no-cache, private') + h.add('Pragma', 'no-cache') + return Response(video_stream(cam), headers=h, mimetype="multipart/x-mixed-replace; boundary=--BOUNDARYSTRING") + except Exception: + pass + +def listPhotos(): + """ + Expose the list of taken photos + """ + return cam.get_photo_list() + +def getPhoto(name): + mimetype = {'jpg': 'image/jpeg', 'mp4': 'video/mp4'} + try: + media_file = cam.get_photo_file(name) + return send_file(media_file, mimetype=mimetype.get(name[:-3], 'image/jpeg'), max_age=0) + except picamera.exc.PiCameraError as e: + logging.error("Error: %s", str(e)) + return 503 + except FileNotFoundError: + return 404 + +def savePhoto(name, body): + try: + cam.update_photo({"name": name, "tag": body.get("tag")}) + except FileNotFoundError: + return 404 + +def deletePhoto(name): + logging.debug("photo delete") + try: + cam.delete_photo(name) + except FileNotFoundError: + return 404 + +def restoreSettings(): + Config.restore() + return restart() + +def loadSettings(): + return Config.get() + +def saveSettings(body): + Config.write(body) + return 200 + +def updateFromPackage(): + os.system('sudo bash /home/pi/clean-update.sh') + file_to_upload = connexion.request.files['file_to_upload'] + file_to_upload.save(os.path.join('/home/pi/', 'update.tar')) + os.system('sudo reboot') + return 200 + +def listMusicPackages(): + """ + list available music packages + """ + musicPkg = MusicPackageManager.get_instance() + response = musicPkg.listPackages() + return response + +def addMusicPackage(): + """ + Add a musical package an save the list of available packages on disk + also add sounds and directory + zipName = request.args.get("zipname") + """ + try: + file_to_upload = connexion.request.files['file_to_upload'] + logging.info("adding " + file_to_upload.filename) + file_to_upload.save(os.path.join('/tmp/', file_to_upload.filename)) + music_pkg = MusicPackageManager.get_instance() + music_pkg.addPackage(file_to_upload.filename) + return "{}", 200 + except ValueError: + return "{}", 409 + except Exception: + return "{}", 400 + +def deleteMusicPackage(name): + """ + Delete a musical package an save the list of available packages on disk + also delete package sounds and directory + """ + musicPkg = MusicPackageManager.get_instance() + musicPkg.deletePackage(name) + return 200 + +## Programs + +def saveProgram(name, body): + overwrite = body.get("overwrite") + existing_program = prog_engine.load(name) + logging.info("saving - name: %s, body: %s", name, str(existing_program)) + if existing_program is not None and not overwrite: + return "askOverwrite" + elif existing_program is not None and existing_program.is_default() == True: + return "defaultCannotOverwrite", 400 + program = Program(name=body.get("name"), code=body.get("code"), dom_code=body.get("dom_code")) + prog_engine.save(program) + return 200 + +def loadProgram(name): + existing_program = prog_engine.load(name) + if existing_program: + return existing_program.as_dict(), 200 + else: + return 404 + +def deleteProgram(name): + prog_engine.delete(name) + +def listPrograms(): + return prog_engine.prog_list() + +def runProgram(name, body): + """ + Execute the given program + """ + logging.debug("program_exec") + code = body.get('code') + prog = prog_engine.create(name, code) + return prog.execute() + +def stopProgram(name): + """ + Stop the program execution + """ + logging.debug("program_end") + prog = prog_engine.get_current_program() + if prog: + prog.stop() + return "ok" + +def statusProgram(name): + """ + Expose the program status + """ + logging.debug("program_status") + prog = prog_engine.get_current_program() + if prog is None: + prog = Program("") + return {'name': prog.name, "running": prog.is_running(), "log": prog_engine.get_log()} + + +## Activities + +def saveActivity(name, body): + activity = body + activities.save(activity.get("name"), activity) + +def saveAsNewActivity(body): + activity = body + activities.save(activity.get("name"), activity) + +def loadActivity(name=None, default=None): + return activities.load(name, default) + +def deleteActivity(name): + activities.delete(name), 200 + +def listActivities(): + return activities.list() + +def resetDefaultPrograms(): + """ + Delete everything but the default programs + """ + programs.purge() + for filename in os.listdir("data/defaults/programs/"): + if filename.endswith(".json"): + with open("data/defaults/programs/" + filename) as p: + q = p.read() + programs.insert(json.loads(q)) + +## Test +def testCoderbot(body): + return run_test(body.get("tests", [])) + +def listCNNModels(): + cnn = CNNManager.get_instance() + return cnn.get_models() + +def trainCNNModel(body): + cam = Camera.get_instance() + cnn = CNNManager.get_instance() + logging.info("cnn_models_new") + cnn.train_new_model(model_name=body.get("model_name"), + architecture=body.get("architecture"), + image_tags=body.get("image_tags"), + photos_meta=cam.get_photo_list(), + training_steps=body.get("training_steps"), + learning_rate=body.get("learning_rate")) + + return {"name": body.get("model_name"), "status": 0} + +def getCNNModel(name): + cnn = CNNManager.get_instance() + model_status = cnn.get_models().get(name) + + return model_status + +def deleteCNNModel(name): + cnn = CNNManager.get_instance() + model_status = cnn.delete_model(model_name=name) + + return model_status \ No newline at end of file diff --git a/coderbot/audio.py b/coderbot/audio.py new file mode 100644 index 00000000..42a4eeca --- /dev/null +++ b/coderbot/audio.py @@ -0,0 +1,229 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ + +import os +from array import array +import time +import logging +import wave +import audioop +import pyaudio +import alsaaudio + +import queue +# [END import_libraries] + +# Audio recording parameters +RATE = 44100 +CHUNK = int(RATE / 10) # 100ms +FORMAT = pyaudio.paInt16 + +MODELDIR = "/home/pi/coderbot/psmodels/" +SOUNDDIR = "./sounds/" +SOUNDEXT = ".wav" + +SOURCE_OUTPUT = 0 +SOURCE_INPUT = 1 + +class Audio: + + _instance = None + + @classmethod + def get_instance(cls): + if cls._instance is None: + cls._instance = Audio() + return cls._instance + + def __init__(self): + self.pa = pyaudio.PyAudio() + try: + self.stream_in = self.MicrophoneStream(FORMAT, RATE, CHUNK) + except Exception: + logging.info("Audio: input stream not available") + + def exit(self): + pass + + def say(self, what, locale='en'): + if what and "$" in what: + self.play(what[1:] + SOUNDEXT) + elif what and what: + os.system('espeak --stdout -v' + locale + ' -p 90 -a 200 -s 150 -g 10 "' + what + '" 2>>/dev/null | aplay -q') + + def normalize(self, snd_data): + "Average the volume out" + MAXIMUM = 16384 + times = float(MAXIMUM) / max(abs(i) for i in snd_data) + + r = array('h', snd_data) + c = 0 + for i in snd_data: + r[c] = int(i*times) + c += 1 + return r + + def record(self, elapse): + r = bytearray() + t = time.time() + with self.stream_in as stream: + audio_generator = stream.generator() + for content in audio_generator: + r.extend(content) + if time.time() - t >= elapse: + return r + return r + + def record_to_file(self, filename, elapse): + data = self.record(elapse) + #data = pack('<' + ('h'*len(data)), *data) + + wf = wave.open(SOUNDDIR + filename, 'wb') + wf.setnchannels(1) + wf.setsampwidth(self.stream_in.get_sample_size(FORMAT)) + wf.setframerate(RATE) + wf.writeframes(data) + wf.close() + + def play(self, filename): + + f = wave.open(SOUNDDIR + filename, 'rb') + + format = None + + # 8bit is unsigned in wav files + if f.getsampwidth() == 1: + format = alsaaudio.PCM_FORMAT_U8 + # Otherwise we assume signed data, little endian + elif f.getsampwidth() == 2: + format = alsaaudio.PCM_FORMAT_S16_LE + elif f.getsampwidth() == 3: + format = alsaaudio.PCM_FORMAT_S24_3LE + elif f.getsampwidth() == 4: + format = alsaaudio.PCM_FORMAT_S32_LE + else: + raise ValueError('Unsupported format') + + periodsize = f.getframerate() // 8 + + logging.info('%d channels, %d sampling rate, format %d, periodsize %d\n' % (f.getnchannels(), + f.getframerate(), + format, + periodsize)) + + device = alsaaudio.PCM(channels=f.getnchannels(), rate=f.getframerate(), format=format, periodsize=periodsize) + + data = f.readframes(periodsize) + while data: + # Read data from stdin + device.write(data) + data = f.readframes(periodsize) + + def hear(self, level, elapse=1.0): + t = time.time() + with self.stream_in as stream: + audio_generator = stream.generator() + for content in audio_generator: + snd_rms = audioop.rms(content, 2) + if snd_rms > level: + return True + if time.time() - t >= elapse: + return False + return False + + def get_volume(self): + volume = alsaaudio.Mixer('Headphone', cardindex=0).getvolume() + logging.info(volume) # list of per-channel values (floats) + return volume + + def set_volume(self, volume_output, volume_input): + alsaaudio.Mixer('Headphone', cardindex=0).setvolume(volume_output) + alsaaudio.Mixer('Mic', cardindex=1).setvolume(volume_input) + + class MicrophoneStream(object): + """Opens a recording stream as a generator yielding the audio chunks.""" + def __init__(self, fmt, rate, chunk): + self._audio_interface = None + self._format = fmt + self._rate = rate + self._chunk = chunk + + # Create a thread-safe buffer of audio data + self._buff = None + self.closed = True + + def __enter__(self): + self._audio_interface = pyaudio.PyAudio() + self._buff = queue.Queue() + self._audio_stream = self._audio_interface.open( + format=self._format, + # The API currently only supports 1-channel (mono) audio + # https://goo.gl/z757pE + channels=1, rate=self._rate, + input=True, frames_per_buffer=self._chunk, + input_device_index=1, + # Run the audio stream asynchronously to fill the buffer object. + # This is necessary so that the input device's buffer doesn't + # overflow while the calling thread makes network requests, etc. + stream_callback=self._fill_buffer, + ) + self.closed = False + + return self + + def __exit__(self, atype, value, traceback): + self._audio_stream.stop_stream() + self._audio_stream.close() + self._audio_interface.terminate() + self.closed = True + self._buff.put(None) + + def close(self): + pass + + def _fill_buffer(self, in_data, frame_count, time_info, status_flags): + """Continuously collect data from the audio stream, into the buffer.""" + self._buff.put(in_data) + return None, pyaudio.paContinue + + def get_sample_size(self, fmt): + return self._audio_interface.get_sample_size(fmt) + + def generator(self): + while not self.closed: + # Use a blocking get() to ensure there's at least one chunk of + # data, and stop iteration if the chunk is None, indicating the + # end of the audio stream. + chunk = self._buff.get() + if chunk is None: + return + data = [chunk] + + # Now consume whatever other data's still buffered. + while True: + try: + chunk = self._buff.get(block=False) + if chunk is None: + return + data.append(chunk) + except queue.Empty: + break + + yield b''.join(data) +# [END audio_stream] diff --git a/coderbot/balena/__init__.py b/coderbot/balena/__init__.py new file mode 100644 index 00000000..9df7c43f --- /dev/null +++ b/coderbot/balena/__init__.py @@ -0,0 +1,44 @@ +import os +from urllib.request import urlopen, Request +import json +import logging + +class Balena(): + _instance = None + + @classmethod + def get_instance(cls): + if cls._instance is None: + cls._instance = Balena() + return cls._instance + + def __init__(self): + self.supervisor_address = os.environ["BALENA_SUPERVISOR_ADDRESS"] + self.supervisor_key = os.environ["BALENA_SUPERVISOR_API_KEY"] + self.app_id_data = json.dumps({ "appId": os.environ["BALENA_APP_ID"] }).encode("utf-8") + self.headers = { 'Content-Type': 'application/json' } + + def purge(self): + logging.debug("reset bot") + req = Request(f'{self.supervisor_address}/v1/purge?apikey={self.supervisor_key}', data=self.app_id_data, headers=self.headers, method='POST') + return json.load(urlopen(req)) + + def shutdown(self): + logging.debug("shutdown bot") + req = Request(f'{self.supervisor_address}/v1/shutdown?apikey={self.supervisor_key}', headers=self.headers, method='POST') + return json.load(urlopen(req)) + + def restart(self): + logging.debug("restarting bot") + req = Request(f'{self.supervisor_address}/v1/restart?apikey={self.supervisor_key}', data=self.app_id_data, headers=self.headers, method='POST') + return json.load(urlopen(req)) + + def reboot(self): + logging.debug("reboot bot") + req = Request(f'{self.supervisor_address}/v1/reboot?apikey={self.supervisor_key}', headers=self.headers, method='POST') + return json.load(urlopen(req)) + + def device(self): + logging.debug("reboot bot", f'{self.supervisor_address}get?apikey={self.supervisor_key}') + req = Request(f'{self.supervisor_address}/v1/device?apikey={self.supervisor_key}', headers=self.headers, method='GET') + return json.load(urlopen(req)) diff --git a/coderbot/camera.py b/coderbot/camera.py new file mode 100644 index 00000000..8866b9fd --- /dev/null +++ b/coderbot/camera.py @@ -0,0 +1,388 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ + +import time +import os +import math +import json +import logging +import pathlib +from PIL import Image as PILImage +try: + from BytesIO import BytesIO +except ImportError: + from io import BytesIO + +from cv import camera, image, blob + +from cnn.cnn_manager import CNNManager + +import config + +MAX_IMAGE_AGE = 0.0 +PHOTO_PATH = "data/media" +PHOTO_METADATA_FILE = "data/media/metadata.json" +PHOTO_PREFIX = "DSC" +VIDEO_PREFIX = "VID" +PHOTO_THUMB_SUFFIX = "_thumb" +PHOTO_THUMB_SIZE = (240, 180) +VIDEO_ELAPSE_MAX = 900 + +class Camera(object): + + # pylint: disable=too-many-instance-attributes + # pylint: disable=too-many-public-methods + + _instance = None + + @classmethod + def get_instance(cls): + if cls._instance is None: + cls._instance = Camera() + #cls._instance.start() + return cls._instance + + def __init__(self): + logging.info("starting camera") + cam_props = {"width":640, "height":512, + "cv_image_factor": config.Config.get().get("cv_image_factor"), + "exposure_mode": config.Config.get().get("camera_exposure_mode"), + "framerate": config.Config.get().get("camera_framerate"), + "bitrate": config.Config.get().get("camera_jpeg_bitrate"), + "jpeg_quality": int(config.Config.get().get("camera_jpeg_quality"))} + self._camera = camera.Camera(props=cam_props) + self.recording = False + self.video_start_time = time.time() + 8640000 + self._image_time = 0 + self._cv_image_factor = int(config.Config.get().get("cv_image_factor", 4)) + self._image_refresh_timeout = float(config.Config.get().get("camera_refresh_timeout", 0.1)) + self._color_object_size_min = int(config.Config.get().get("camera_color_object_size_min", 80)) / (self._cv_image_factor * self._cv_image_factor) + self._color_object_size_max = int(config.Config.get().get("camera_color_object_size_max", 32000)) / (self._cv_image_factor * self._cv_image_factor) + self._path_object_size_min = int(config.Config.get().get("camera_path_object_size_min", 80)) / (self._cv_image_factor * self._cv_image_factor) + self._path_object_size_max = int(config.Config.get().get("camera_path_object_size_max", 32000)) / (self._cv_image_factor * self._cv_image_factor) + self.load_photo_metadata() + if not self._photos: + self._photos = [] + for filenames in os.walk(PHOTO_PATH): + for filename in filenames[2]: + if (PHOTO_PREFIX in filename or VIDEO_PREFIX in filename) and PHOTO_THUMB_SUFFIX not in filename: + self._photos.append({'name': filename}) + self.save_photo_metadata() + + self._cnn_classifiers = {} + cnn_model = config.Config.get().get("cnn_default_model", "") + if cnn_model != "": + try: + self._cnn_classifiers[cnn_model] = CNNManager.get_instance().load_model(cnn_model) + self._cnn_classifier_default = self._cnn_classifiers[cnn_model] + logging.info("loaded: " + cnn_model + " " + str(self._cnn_classifier_default)) + except Exception: + logging.warning("model not found: %s", cnn_model) + + self._camera.grab_start() + self._image_cv = self.get_image() + + super(Camera, self).__init__() + + def get_image(self): + return image.Image(self._camera.get_image_bgr()) + + def get_image_cv_jpeg(self): + return self._image_cv.to_jpeg() + + def set_image_cv(self, an_image): + self._image_cv = an_image + + def get_image_jpeg(self): + return self._camera.get_image_jpeg() + + def set_text(self, text): + self._camera.set_overlay_text(str(text)) + + def load_photo_metadata(self): + try: + with open(PHOTO_METADATA_FILE, "rt") as f: + self._photos = json.load(f) + f.close() + except Exception: + logging.warning("no metadata file, starting from empty") + pathlib.Path(PHOTO_PATH).mkdir(parents=True, exist_ok=True) + self._photos = [] + self.save_photo_metadata() + + def save_photo_metadata(self): + f = open(PHOTO_METADATA_FILE, "wt") + json.dump(self._photos, f) + f.close() + + def update_photo(self, photo): + for p in self._photos: + if p["name"] == photo["name"]: + p["tag"] = photo["tag"] + self.save_photo_metadata() + + def get_next_photo_index(self): + last_photo_index = 0 + for p in self._photos: + try: + index = int(p["name"][len(PHOTO_PREFIX):-len(self._camera.PHOTO_FILE_EXT)]) + if index > last_photo_index: + last_photo_index = index + except Exception: + pass + return last_photo_index + 1 + + def photo_take(self): + photo_index = self.get_next_photo_index() + filename = PHOTO_PREFIX + str(photo_index) + self._camera.PHOTO_FILE_EXT + filename_thumb = PHOTO_PREFIX + str(photo_index) + PHOTO_THUMB_SUFFIX + self._camera.PHOTO_FILE_EXT + of = open(PHOTO_PATH + "/" + filename, "wb+") + oft = open(PHOTO_PATH + "/" + filename_thumb, "wb+") + im_str = self.get_image_jpeg() + of.write(im_str) + # thumb + im_pil = PILImage.open(BytesIO(im_str)) + im_pil.resize(PHOTO_THUMB_SIZE).save(oft) + self._photos.append({"name":filename}) + self.save_photo_metadata() + of.close() + oft.close() + + def is_recording(self): + return self.recording + + def video_rec(self, video_name=None): + if self.is_recording(): + return + self.recording = True + + if video_name is None: + video_index = self.get_next_photo_index() + filename = VIDEO_PREFIX + str(video_index) + self._camera.VIDEO_FILE_EXT + filename_thumb = VIDEO_PREFIX + str(video_index) + PHOTO_THUMB_SUFFIX + self._camera.PHOTO_FILE_EXT + else: + filename = VIDEO_PREFIX + video_name + self._camera.VIDEO_FILE_EXT + filename_thumb = VIDEO_PREFIX + video_name + PHOTO_THUMB_SUFFIX + self._camera.PHOTO_FILE_EXT + try: + #remove previous file and reference in album + os.remove(PHOTO_PATH + "/" + filename) + self._photos.remove({"name":filename}) + except Exception: + pass + + oft = open(PHOTO_PATH + "/" + filename_thumb, "wb") + im_str = self._camera.get_image_jpeg() + im_pil = PILImage.open(BytesIO(im_str)) + im_pil.resize(PHOTO_THUMB_SIZE).save(oft) + self._photos.append({"name":filename}) + self.save_photo_metadata() + self._camera.video_rec(PHOTO_PATH + "/" + filename) + self.video_start_time = time.time() + oft.close() + + def video_stop(self): + if self.recording: + self._camera.video_stop() + self.recording = False + + def get_photo_list(self): + return self._photos + + def get_photo_file(self, filename): + return open(PHOTO_PATH + "/" + filename, "rb") + + def get_photo_thumb_file(self, filename): + return open(PHOTO_PATH + "/" + filename[:-len(self._camera.PHOTO_FILE_EXT)] + PHOTO_THUMB_SUFFIX + self._camera.PHOTO_FILE_EXT, "rb") + + def delete_photo(self, filename): + logging.info("delete photo: %s", filename) + os.remove(PHOTO_PATH + "/" + filename) + os.remove(PHOTO_PATH + "/" + filename[:filename.rfind(".")] + PHOTO_THUMB_SUFFIX + self._camera.PHOTO_FILE_EXT) + for photo in self._photos: + if photo["name"] == filename: + self._photos.remove(photo) + self.save_photo_metadata() + + def exit(self): + #self.join() + self.video_stop() + self._camera.grab_stop() + + def get_average(self): + avg = self.get_image().get_average() + return avg + + def find_line(self): + img = self.get_image() + avg = img.get_average() + img = img.binarize(int((avg[0]+avg[2])/2)) + img = img.erode().dilate() + if int(img._data.mean()) > 127: + img = img.invert() + slices = [0, 0, 0] + blobs = [0, 0, 0] + slices[0] = img.crop(0, int(self._camera.out_rgb_resolution[1]/1.2), self._camera.out_rgb_resolution[0], self._camera.out_rgb_resolution[1]) + slices[1] = img.crop(0, int(self._camera.out_rgb_resolution[1]/1.5), self._camera.out_rgb_resolution[0], int(self._camera.out_rgb_resolution[1]/1.2)) + slices[2] = img.crop(0, int(self._camera.out_rgb_resolution[1]/2.0), self._camera.out_rgb_resolution[0], int(self._camera.out_rgb_resolution[1]/1.5)) + y_offset = [int(self._camera.out_rgb_resolution[1]/1.2), + int(self._camera.out_rgb_resolution[1]/1.5), + int(self._camera.out_rgb_resolution[1]/2.0)] + coords = [-1, -1, -1] + for idx, slc in enumerate(slices): + blobs[idx] = slc.find_blobs(minsize=2000/(self._cv_image_factor * self._cv_image_factor), maxsize=16000/(self._cv_image_factor * self._cv_image_factor)) + if blobs[idx]: + coords[idx] = (blobs[idx][0].center[0] * 100) / self._camera.out_rgb_resolution[0] + blb = blobs[idx][0] + img.draw_rect(blb.left, y_offset[idx] + blb.top, blb.right, y_offset[idx] + blb.bottom, (0, 255, 0), 5) + self.set_image_cv(img) + return coords + + def find_face(self): + face_x = face_y = face_size = None + img = self.get_image() + faces = img.grayscale().find_faces() + if len(faces): + # Get the largest face, face is a rectangle + x, y, w, h = faces[0] + center_x = x + (w/2) + face_x = ((center_x * 100) / self._camera.out_rgb_resolution[0]) - 50 #center = 0 + center_y = y + (h/2) + face_y = 50 - (center_y * 100) / self._camera.out_rgb_resolution[1] #center = 0 + size = h + face_size = (size * 100) / self._camera.out_rgb_resolution[1] + logging.info("face found, x: " + str(face_x) + " y: " + str(face_y) + " size: " + str(face_size)) + return [face_x, face_y, face_size] + + def path_ahead(self): + image_size = self._camera.out_rgb_resolution + img = self.get_image() + + size_y = img._data.shape[0] + size_x = img._data.shape[1] + threshold = img.crop(0, size_y - int(size_y/12), size_x, size_y)._data.mean() / 2 + + blobs = img.binarize(threshold).dilate().find_blobs(minsize=self._path_object_size_min, maxsize=self._path_object_size_max) + coordY = 60 + if blobs: + obstacle = blob.Blob.sort_distance((image_size[0]/2, image_size[1]), blobs)[0] + + coords = img.transform([(obstacle.center[0], obstacle.bottom)], img.get_transform(img.size()[1])) + x = coords[0][0] + y = coords[0][1] + coordY = 60 - ((y * 48) / (480 / self._cv_image_factor)) + logging.info("x: %s y: %s coordY: %s", str(x), str(y), str(coordY)) + + return coordY + + def find_color(self, s_color): + image_size = self._camera.out_rgb_resolution + color = (int(s_color[1:3], 16), int(s_color[3:5], 16), int(s_color[5:7], 16)) + #ts = time.time() + img = self.get_image() + bw = img.filter_color(color) + objects = bw.find_blobs(minsize=self._color_object_size_min, maxsize=self._color_object_size_max) + logging.debug("objects: %s", str(objects)) + dist = -1 + angle = 180 + fov_offset = 12 #cm + fov_total_y = 68 #cm + fov_total_x = 60 #cm + + if objects: + obj = objects[-1] + logging.info("bottom: " + str(obj.center[0]) + " " + str(obj.bottom)) + coords = bw.transform([(obj.center[0], obj.bottom)], bw.get_transform(bw.size()[1])) + logging.info("coordinates: %s", str(coords)) + x = coords[0][0] + y = coords[0][1] + dist = math.sqrt(math.pow(fov_offset + (fov_total_y * (image_size[1] - y) / (image_size[1]/1.2)), 2) + (math.pow((x-(image_size[0]/2)) * fov_total_x / image_size[0], 2))) + angle = math.atan2(x - (image_size[0]/2), image_size[1] - y) * 180 / math.pi + logging.info("object found, dist: " + str(dist) + " angle: " + str(angle)) + #self.save_image(img.to_jpeg()) + #print "object: " + str(time.time() - ts) + return [dist, angle] + + def find_text(self, lang="en", timeout=0): + t1 = time.time() + text = None + #color = (int(back_color[1:3], 16), int(back_color[3:5], 16), int(back_color[5:7], 16)) + img = self.get_image() + #rec_image = img.find_rect(color=color) + text = img.find_text(lang, timeout) + logging.info("find_text fps: " + str(1.0/(time.time() - t1))) + #if rec_image: + # logging.info("image: %s", str(rec_image)) + # bin_image = rec_image.binarize().invert() + # text = bin_image.find_text(accept) + return text + + def find_qr_code(self): + img = self.get_image() + return img.find_qr_code() + + def find_ar_code(self): + img = self.get_image() + return img.find_ar_code() + + def cnn_classify(self, model_name=None, top_results=3): + classifier = None + if model_name: + classifier = self._cnn_classifiers.get(model_name) + if classifier is None: + classifier = CNNManager.get_instance().load_model(model_name) + self._cnn_classifiers[model_name] = classifier + else: + classifier = self._cnn_classifier_default + + t0 = time.time() + classes = None + try: + img = self.get_image() + classes = classifier.classify_image(img.mat(), top_results=top_results) + except Exception: + logging.warning("classifier not available") + classes = [("None", 1.0)] + raise + logging.info("fps: %f", 1.0/(time.time()-t0)) + return classes + + def find_class(self): + return self.cnn_classify(top_results=1)[0][0] + + def cnn_detect_objects(self, model_name=None, top_results=3): + classifier = None + if model_name: + classifier = self._cnn_classifiers.get(model_name) + if classifier is None: + classifier = CNNManager.get_instance().load_model(model_name) + self._cnn_classifiers[model_name] = classifier + else: + classifier = self._cnn_classifier_default + + t0 = time.time() + classes = None + try: + img = self.get_image() + classes = classifier.detect_objects(img.mat(), top_results=top_results) + except Exception: + logging.warning("classifier not available") + classes = [("None", 100)] + raise + logging.info("fps: %f", 1.0/(time.time()-t0)) + return classes diff --git a/viz/__init__.py b/coderbot/cnn/__init__.py similarity index 100% rename from viz/__init__.py rename to coderbot/cnn/__init__.py diff --git a/coderbot/cnn/cnn_classifier.py b/coderbot/cnn/cnn_classifier.py new file mode 100644 index 00000000..d8e61ce8 --- /dev/null +++ b/coderbot/cnn/cnn_classifier.py @@ -0,0 +1,143 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2017 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ +""" +This module implements the CNNClassifier class, which is the interface for +using an existing and trained CNN model. +""" +import logging + +import numpy as np +try: + from tensorflow.lite.python.interpreter import Interpreter +except: + logging.warning("tensorflow not available (for inference)") +try: + from tflite_runtime.interpreter import Interpreter +except: + logging.warning("tflite not available") + +import cv2 + +logger = logging.getLogger(__name__) + +class CNNClassifier(object): + def __init__(self, model_file, label_file): + logger.info(model_file) + self._interpreter = Interpreter(model_path=model_file, num_threads=4) + self._interpreter.allocate_tensors() + self._labels = self.load_labels(label_file) + self._input_details = self._interpreter.get_input_details() + self._output_details = self._interpreter.get_output_details() + self._input_height=self._input_details[0]['shape'][1] + self._input_width=self._input_details[0]['shape'][2] + self._floating_model = (self._input_details[0]['dtype'] == np.float32) + + def close(self): + pass + + def read_tensor_from_image_file(self, file_name): + image = cv2.imread(file_name) + return self.read_tensor_from_image_mat(image) + + def read_tensor_from_image_mat(self, image_mat): + frame_rgb = cv2.cvtColor(image_mat, cv2.COLOR_BGR2RGB) + frame_resized = cv2.resize(frame_rgb, (self._input_width, self._input_height)) + input_data = np.expand_dims(frame_resized, axis=0) + + # Normalize pixel values if using a floating model (i.e. if model is non-quantized) + if self._floating_model: + input_mean = 127.5 + input_std = 127.5 + input_data = (np.float32(input_data) - input_mean) / input_std + + return input_data + + def load_labels(self, label_file): + labels = [] + with open(label_file, 'r') as f: + labels = [line.strip() for line in f.readlines()] + return labels + + def classify_image(self, + image_file_or_mat, + top_results=3): + input_image = None + if isinstance(image_file_or_mat, str): + input_image = self.read_tensor_from_image_file(file_name=image_file_or_mat) + else: + input_image = self.read_tensor_from_image_mat(image_file_or_mat) + + self._interpreter.set_tensor(self._input_details[0]['index'], input_image) + self._interpreter.invoke() + scores = self._interpreter.get_tensor(self._output_details[0]['index'])[0] + + #print("scores: " + str(scores)) + confidence = 0.4 + base = 1 + # normalize to int8 for quantized models + if len(scores)>0 and (scores[0] == int(scores[0])): + confidence = 128 + base = 256 + pairs = [] + for i in range(0, len(scores)): + if scores[i] > confidence: + object_name = self._labels[i] + pairs.append((object_name, int(100*scores[i]/base))) + + pairs = sorted(pairs, key=lambda x: x[1], reverse=True)[:top_results] + return pairs + + def detect_objects(self, + image_file_or_mat, + top_results=3): + input_image = None + if isinstance(image_file_or_mat, str): + input_image = self.read_tensor_from_image_file(file_name=image_file_or_mat) + else: + input_image = self.read_tensor_from_image_mat(image_file_or_mat) + + self._interpreter.set_tensor(self._input_details[0]['index'], input_image) + self._interpreter.invoke() + + # Retrieve detection results + boxes = self._interpreter.get_tensor(self._output_details[0]['index'])[0] # Bounding box coordinates of detected objects + classes = self._interpreter.get_tensor(self._output_details[1]['index'])[0] # Class index of detected objects + scores = self._interpreter.get_tensor(self._output_details[2]['index'])[0] # Confidence of detected objects + + # Loop over all detections and draw detection box if confidence is above minimum threshold + min_conf_threshold=0.1 + imH=100 + imW=100 + pairs = [] + for i in range(len(scores)): + if ((scores[i] > min_conf_threshold) and (scores[i] <= 1.0)): + + # Get bounding box coordinates and draw box + # Interpreter can return coordinates that are outside of image dimensions, need to force them to be within image using max() and min() + ymin = int(max(1,(boxes[i][0] * imH))) + xmin = int(max(1,(boxes[i][1] * imW))) + ymax = int(min(imH,(boxes[i][2] * imH))) + xmax = int(min(imW,(boxes[i][3] * imW))) + + object_name = self._labels[int(classes[i])+1] + pairs.append((object_name, int(100*scores[i]), (xmin, ymin, xmax, ymax))) + + pairs = sorted(pairs, key=lambda x: x[1], reverse=True)[:top_results] + logger.info(str(pairs)) + return pairs diff --git a/coderbot/cnn/cnn_manager.py b/coderbot/cnn/cnn_manager.py new file mode 100644 index 00000000..5ed012d2 --- /dev/null +++ b/coderbot/cnn/cnn_manager.py @@ -0,0 +1,172 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2017 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ +""" +This module implements the class CNNManager, a singleton which exposes +methods used to create (retrain), list and use existing CNN models. +""" +import os +import shutil +import logging +import json +import threading + +try: + from cnn.cnn_train import CNNTrainer +except: + logging.warning("tensorflow not available (for training)") + +from cnn.cnn_classifier import CNNClassifier + +MODEL_PATH = "./cnn_models" +MODEL_TMP_PATH = "/tmp/images" +MODEL_METADATA = "./cnn_models/models.json" +PHOTO_PATH = "./media" + +logger = logging.getLogger(__name__) + +class CNNManager(object): + instance = None + + @classmethod + def get_instance(cls): + if cls.instance is None: + cls.instance = CNNManager() + return cls.instance + + + def __init__(self): + try: + f = open(MODEL_METADATA, "r") + self._models = json.load(f) + f.close() + except IOError: + self._models = {} + self._save_model_meta() + + self._trainers = {} + + def get_models(self): + return self._models + + def get_model_status(self, model_name): + return self._models[model_name] + + @classmethod + def get_model_info(cls, architecture): + model_info = architecture.split("/")[1].split("_") + return model_info + + @classmethod + def get_model_shape(cls, architecture): + model_info = cls.get_model_info(architecture) + size = int(model_info[3]) + return (size, size) + + def _save_model_meta(self): + f = open(MODEL_METADATA, "w") + json.dump(self._models, f) + f.close() + + def delete_model(self, model_name): + if self._models.get(model_name): + try: + os.remove(MODEL_PATH + "/" + model_name + ".tflite") + os.remove(MODEL_PATH + "/" + model_name + ".txt") + except Exception: + logging.warning("model files not found: %s", model_name) + del self._models[model_name] + self._save_model_meta() + + def train_new_model(self, + model_name, + architecture, + image_tags, + photos_meta, + training_steps, + learning_rate): + try: + CNNManager + logging.info("starting") + trainer = self.TrainThread(self, model_name, architecture, image_tags, photos_meta, training_steps, learning_rate) + trainer.start() + self._trainers[model_name] = trainer + except NameError: + logging.warning("tensorflow not available (for training)") + + def save_model_status(self, model_name, architecture, status): + model_info = self.get_model_info(architecture) + self._models[model_name] = {"status": status, "image_height": model_info[3], "image_width": model_info[3], "output_layer": "final_result"} + self._save_model_meta() + + def wait_train_jobs(self): + for t in self._trainers: + t.join() + + def load_model(self, model_name): + model_info = self._models.get(model_name) + if model_info: + return CNNClassifier(model_file=MODEL_PATH + "/" + model_name + ".tflite", + label_file=MODEL_PATH + "/" + model_name + ".txt") + return None + + class TrainThread(threading.Thread): + + def __init__(self, manager, model_name, architecture, image_tags, photos_metadata, training_steps, learning_rate): + super(CNNManager.TrainThread, self).__init__() + self.manager = manager + self.model_name = model_name + self.architecture = architecture + self.image_tags = image_tags + self.photos_metadata = photos_metadata + self.learning_rate = learning_rate + self.training_steps = training_steps + self.trainer = None + + def update_train_status(self, model_name, status): + model = self.manager._models.get(model_name) + model["status"] = status + + def run(self): + self.trainer = CNNTrainer(self.manager, self.architecture, CNNManager.get_model_shape(self.architecture)) + self.manager.save_model_status(self.model_name, self.architecture, 0) + image_dir = self.prepare_images() + logging.info("retrain") + self.trainer.retrain(image_dir, MODEL_PATH + "/" + self.model_name, self.training_steps, self.learning_rate, flip_left_right=False, random_crop=0, random_scale=0) + self.manager.save_model_status(self.model_name, self.architecture, 1) + self.clear_filesystem() + logging.info("finish") + + def prepare_images(self): + logging.info("prepare_images") + photo_abs_path = os.path.abspath(PHOTO_PATH) + model_image_path = MODEL_TMP_PATH + "/" + self.model_name + os.makedirs(model_image_path) + for t in self.image_tags: + tag_path = model_image_path + "/" + t + os.makedirs(tag_path) + for p in self.photos_metadata: + if p.get("tag", "---") == t: + os.symlink(photo_abs_path + "/" + p["name"], tag_path + "/" + p["name"]) + + return model_image_path + + def clear_filesystem(self): + shutil.rmtree(MODEL_TMP_PATH + "/" + self.model_name) + #shutil.rmtree(MODEL_TMP_PATH + "/bottleneck") + #shutil.rmtree(MODEL_TMP_PATH + "/retrain_logs") diff --git a/coderbot/cnn/cnn_train.py b/coderbot/cnn/cnn_train.py new file mode 100644 index 00000000..e3105686 --- /dev/null +++ b/coderbot/cnn/cnn_train.py @@ -0,0 +1,142 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2017 Roberto Previtera +# The code contained in this file is mostly derived from TensorFlow +# "retrain.py" exmple from main tensorflow repository. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ +"""Simple transfer learning with Inception v3 or Mobilenet models. + +With support for TensorBoard. + +This example shows how to take a Inception v3 or Mobilenet model trained on +ImageNet images, and train a new top layer that can recognize other classes of +images. + +The top layer receives as input a 2048-dimensional vector (1001-dimensional for +Mobilenet) for each image. We train a softmax layer on top of this +representation. Assuming the softmax layer contains N labels, this corresponds +to learning N + 2048*N (or 1001*N) model parameters corresponding to the +learned biases and weights. + +Here's an example, which assumes you have a folder containing class-named +subfolders, each full of images for each label. The example folder flower_photos +should have a structure like this: + +~/flower_photos/daisy/photo1.jpg +~/flower_photos/daisy/photo2.jpg +... +~/flower_photos/rose/anotherphoto77.jpg +... +~/flower_photos/sunflower/somepicture.jpg +""" + +import time +import tempfile +import numpy as np +import tensorflow as tf +import tensorflow_hub as hub +from tensorflow_hub.tools.make_image_classifier import make_image_classifier_lib as lib + +class CNNTrainer(object): + # pylint: disable=too-many-instance-attributes + # pylint: disable=too-many-locals + # pylint: disable=too-many-arguments + # pylint: disable=too-many-boolean-expressions + + def __init__(self, manager, architecture, shape): + self.manager = manager + self.architecture = architecture + self.shape = shape + + def retrain(self, + image_dir, + output_graph, + training_steps, + learning_rate, + desired_training_accuracy=100.0, + desired_validation_accuracy=100.0, + flip_left_right=True, + random_crop=30, + random_scale=30, + random_brightness=30): + + _check_keras_dependencies() + hparams = _get_hparams(train_epochs=training_steps, + learning_rate=learning_rate) + + image_size=self.shape[0] + tfhub_module="https://tfhub.dev/google/"+self.architecture + model, labels, train_result = lib.make_image_classifier( + tfhub_module, image_dir, hparams, image_size) + print("Done with training.") + + labels_output_file=output_graph+".txt" + with tf.io.gfile.GFile(labels_output_file, "w") as f: + f.write("\n".join(labels + ("",))) + print("Labels written to", labels_output_file) + + saved_model_dir = tempfile.mkdtemp() + tf.saved_model.save(model, saved_model_dir) + print("SavedModel model exported to", saved_model_dir) + + tflite_output_file = output_graph+".tflite" + converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) + converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_LATENCY] + lite_model_content = converter.convert() + with tf.io.gfile.GFile(tflite_output_file, "wb") as f: + f.write(lite_model_content) + print("TFLite model exported to", tflite_output_file) + + +def _get_hparams(train_epochs=1, learning_rate=0.005): + "Creates dict of hyperparameters from flags.""" + return lib.HParams( + train_epochs=train_epochs, + do_fine_tuning=False, + batch_size=2, + learning_rate=learning_rate, + momentum=0.9) + +def _check_keras_dependencies(): + """Checks dependencies of tf.keras.preprocessing.image are present. + This function may come to depend on flag values that determine the kind + of preprocessing being done. + Raises: + ImportError: If dependencies are missing. + """ + try: + tf.keras.preprocessing.image.load_img(six.BytesIO()) + except ImportError: + print("\n*** Unsatisfied dependencies of keras_preprocessing.image. ***\n" + "To install them, use your system's equivalent of\n" + "pip install tensorflow_hub[make_image_classifier]\n") + raise + except Exception as e: # pylint: disable=broad-except + # Loading from dummy content as above is expected to fail in other ways. + pass + + +def _assert_accuracy(train_result, assert_accuracy_at_least): + # Fun fact: With TF1 behavior, the key was called "val_acc". + val_accuracy = train_result.history["val_accuracy"][-1] + accuracy_message = "found {:f}, expected at least {:f}".format( + val_accuracy, assert_accuracy_at_least) + if val_accuracy >= assert_accuracy_at_least: + print("ACCURACY PASSED:", accuracy_message) + else: + raise AssertionError("ACCURACY FAILED:", accuracy_message) + diff --git a/coderbot/coderbot.py b/coderbot/coderbot.py new file mode 100644 index 00000000..89c0de1c --- /dev/null +++ b/coderbot/coderbot.py @@ -0,0 +1,277 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ + +import os +import sys +import time +from math import copysign +import logging +import pigpio +import sonar +from hw import mpu +from rotary_encoder.wheelsaxel import WheelsAxel + +# GPIO +class GPIO_CODERBOT_V_4(): + # motors + PIN_MOTOR_ENABLE = 22 + PIN_LEFT_FORWARD = 25 + PIN_LEFT_BACKWARD = 24 + PIN_RIGHT_FORWARD = 4 + PIN_RIGHT_BACKWARD = 17 + + PIN_PUSHBUTTON = 11 + # servo + PIN_SERVO_1 = 9 + PIN_SERVO_2 = 10 + # sonar + PIN_SONAR_1_TRIGGER = 18 + PIN_SONAR_1_ECHO = 7 + PIN_SONAR_2_TRIGGER = 18 + PIN_SONAR_2_ECHO = 8 + PIN_SONAR_3_TRIGGER = 18 + PIN_SONAR_3_ECHO = 23 + PIN_SONAR_4_TRIGGER = 18 + PIN_SONAR_4_ECHO = 13 + + # encoder + PIN_ENCODER_LEFT_A = 14 + PIN_ENCODER_LEFT_B = 6 + PIN_ENCODER_RIGHT_A = 15 + PIN_ENCODER_RIGHT_B = 12 + + HAS_ENCODER = False + +class GPIO_CODERBOT_V_5(): + # motors + PIN_MOTOR_ENABLE = None #22 + PIN_LEFT_FORWARD = 17 #25 + PIN_LEFT_BACKWARD = 18 # 24 + PIN_RIGHT_FORWARD = 22 # 4 + PIN_RIGHT_BACKWARD = 23 #17 + + PIN_PUSHBUTTON = 16 #11 + # servo + PIN_SERVO_1 = 19 #9 + PIN_SERVO_2 = 26 #10 + # sonar + PIN_SONAR_1_TRIGGER = 5 #18 + PIN_SONAR_1_ECHO = 27 #7 + PIN_SONAR_2_TRIGGER = 5 #18 + PIN_SONAR_2_ECHO = 6 #8 + PIN_SONAR_3_TRIGGER = 5 #18 + PIN_SONAR_3_ECHO = 12 #23 + PIN_SONAR_4_TRIGGER = 5 #18 + PIN_SONAR_4_ECHO = 13 #23 + + # encoder + PIN_ENCODER_LEFT_A = 14 + PIN_ENCODER_LEFT_B = 15 #6 + PIN_ENCODER_RIGHT_A = 24 #15 + PIN_ENCODER_RIGHT_B = 25 #12 + + HAS_ENCODER = True + +# PWM +PWM_FREQUENCY = 100 #Hz +PWM_RANGE = 100 #0-100 + +HW_VERSIONS = { + "4": GPIO_CODERBOT_V_4(), + "5": GPIO_CODERBOT_V_5() +} + +class CoderBot(object): + + # pylint: disable=too-many-instance-attributes + + def __init__(self, motor_trim_factor=1.0, motor_min_power=0, motor_max_power=100, hw_version="5", pid_params=(0.8, 0.1, 0.01, 200, 0.01)): + try: + self._mpu = mpu.AccelGyroMag() + logging.info("MPU available") + except: + logging.info("MPU not available") + + self.GPIOS = HW_VERSIONS.get(hw_version, GPIO_CODERBOT_V_5()) + self._pin_out = [self.GPIOS.PIN_LEFT_FORWARD, self.GPIOS.PIN_RIGHT_FORWARD, self.GPIOS.PIN_LEFT_BACKWARD, self.GPIOS.PIN_RIGHT_BACKWARD, self.GPIOS.PIN_SERVO_1, self.GPIOS.PIN_SERVO_2] + self.pi = pigpio.pi('localhost') + self.pi.set_mode(self.GPIOS.PIN_PUSHBUTTON, pigpio.INPUT) + self._cb = dict() + self._cb_last_tick = dict() + self._cb_elapse = dict() + self._encoder = self.GPIOS.HAS_ENCODER + self._motor_trim_factor = motor_trim_factor + self._motor_min_power = motor_min_power + self._motor_max_power = motor_max_power + self._twin_motors_enc = WheelsAxel( + self.pi, + enable_pin=self.GPIOS.PIN_MOTOR_ENABLE, + left_forward_pin=self.GPIOS.PIN_LEFT_FORWARD, + left_backward_pin=self.GPIOS.PIN_LEFT_BACKWARD, + left_encoder_feedback_pin_A=self.GPIOS.PIN_ENCODER_LEFT_A, + left_encoder_feedback_pin_B=self.GPIOS.PIN_ENCODER_LEFT_B, + right_forward_pin=self.GPIOS.PIN_RIGHT_FORWARD, + right_backward_pin=self.GPIOS.PIN_RIGHT_BACKWARD, + right_encoder_feedback_pin_A=self.GPIOS.PIN_ENCODER_RIGHT_A, + right_encoder_feedback_pin_B=self.GPIOS.PIN_ENCODER_RIGHT_B, + pid_params=pid_params) + self.motor_control = self._dc_enc_motor + + self._cb1 = self.pi.callback(self.GPIOS.PIN_PUSHBUTTON, pigpio.EITHER_EDGE, self._cb_button) + + for pin in self._pin_out: + self.pi.set_PWM_frequency(pin, PWM_FREQUENCY) + self.pi.set_PWM_range(pin, PWM_RANGE) + + self.sonar = [sonar.Sonar(self.pi, self.GPIOS.PIN_SONAR_1_TRIGGER, self.GPIOS.PIN_SONAR_1_ECHO), + sonar.Sonar(self.pi, self.GPIOS.PIN_SONAR_2_TRIGGER, self.GPIOS.PIN_SONAR_2_ECHO), + sonar.Sonar(self.pi, self.GPIOS.PIN_SONAR_3_TRIGGER, self.GPIOS.PIN_SONAR_3_ECHO), + sonar.Sonar(self.pi, self.GPIOS.PIN_SONAR_4_TRIGGER, self.GPIOS.PIN_SONAR_4_ECHO)] + self._servos = [self.GPIOS.PIN_SERVO_1, self.GPIOS.PIN_SERVO_2] + + self.stop() + + the_bot = None + + def exit(self): + self._cb1.cancel() + if self._encoder: + self._twin_motors_enc.cancel_callback() + for s in self.sonar: + s.cancel() + + @classmethod + def get_instance(cls, motor_trim_factor=1.0, motor_max_power=100, motor_min_power=0, hw_version="5", pid_params=(0.8, 0.1, 0.01, 200, 0.01), from_defaults=True): + if not cls.the_bot: + if from_defaults: + raise ValueError("incorrect CoderBot initialisation") + cls.the_bot = CoderBot(motor_trim_factor=motor_trim_factor, motor_max_power= motor_max_power, motor_min_power=motor_min_power, hw_version=hw_version, pid_params=pid_params) + return cls.the_bot + + def get_motor_power(self, speed): + return int(copysign(min(max(((self._motor_max_power - self._motor_min_power) * abs(speed) / 100) + self._motor_min_power, self._motor_min_power), self._motor_max_power), speed)) + + def move(self, speed=100, elapse=None, distance=None): + speed_left = speed * self._motor_trim_factor + speed_right = speed / self._motor_trim_factor + self.motor_control(speed_left=speed_left, speed_right=speed_right, time_elapse=elapse, target_distance=distance) + + def turn(self, speed=100, elapse=None, distance=None): + speed_left = speed * self._motor_trim_factor + speed_right = -speed / self._motor_trim_factor + self.motor_control(speed_left=speed_left, speed_right=speed_right, time_elapse=elapse, target_distance=distance) + + def turn_angle(self, speed=100, angle=0): + z = self._mpu.get_gyro()[2] + self.turn(speed, elapse=0) + while abs(z - self._mpu.get_gyro()[2]) < angle: + time.sleep(0.05) + logging.info(self._mpu.get_gyro()[2]) + self.stop() + + def forward(self, speed=100, elapse=None, distance=None): + self.move(speed=speed, elapse=elapse, distance=distance) + + def backward(self, speed=100, elapse=None, distance=None): + self.move(speed=-speed, elapse=elapse, distance=distance) + + def left(self, speed=100, elapse=-1): + self.turn(speed=-speed, elapse=elapse) + + def right(self, speed=100, elapse=-1): + self.turn(speed=speed, elapse=elapse) + + def servo(self, servo, angle): + self._servo_control(self._servos[servo], angle) + + def get_sonar_distance(self, sonar_id=0): + return self.sonar[sonar_id].get_distance() + + def get_mpu_accel(self, axis=None): + acc = self._mpu.get_acc() + if axis is None: + return acc + else: + return int(acc[axis]*100.0)/100.0 + + def get_mpu_gyro(self, axis=None): + gyro = self._mpu.get_gyro() + if axis is None: + return gyro + else: + return int(gyro[axis]*100.0)/200.0 + + def get_mpu_heading(self): + hdg = self._mpu.get_hdg() + return int(hdg) + + def get_mpu_temp(self): + temp = self._mpu.get_temp() + return int(temp*100.0)/100.0 + + def _servo_control(self, pin, angle): + duty = ((angle + 90) * 100 / 180) + 25 + + self.pi.set_PWM_range(pin, 1000) + self.pi.set_PWM_frequency(pin, 50) + self.pi.set_PWM_dutycycle(pin, duty) + + def _dc_enc_motor(self, speed_left=100, speed_right=100, time_elapse=None, target_distance=None): + self._twin_motors_enc.control(power_left=self.get_motor_power(speed_left), + power_right=self.get_motor_power(speed_right), + time_elapse=time_elapse, + target_distance=target_distance) + + def stop(self): + self._twin_motors_enc.stop() + + def is_moving(self): + return self._twin_motors_enc._is_moving + + # Distance travelled getter + def distance(self): + return self._twin_motors_enc.distance() + + # CoderBot velocity getter + def speed(self): + return self._twin_motors_enc.speed() + + # CoderBot direction getter + def direction(self): + return self._twin_motors_enc.speed() + + def set_callback(self, gpio, callback, elapse): + self._cb_elapse[gpio] = elapse * 1000 + self._cb[gpio] = callback + self._cb_last_tick[gpio] = 0 + + def sleep(self, elapse): + logging.debug("sleep: %s", str(elapse)) + time.sleep(elapse) + + def _cb_button(self, gpio, level, tick): + cb = self._cb.get(gpio) + if cb: + elapse = self._cb_elapse.get(gpio) + if level == 0: + self._cb_last_tick[gpio] = tick + elif tick - self._cb_last_tick[gpio] > elapse: + self._cb_last_tick[gpio] = tick + logging.info("pushed: %d, %d", level, tick) + cb() \ No newline at end of file diff --git a/coderbot/config.py b/coderbot/config.py new file mode 100644 index 00000000..071dd7da --- /dev/null +++ b/coderbot/config.py @@ -0,0 +1,54 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ + +import os +import json + +CONFIG_FILE = "data/config.json" +CONFIG_DEFAULT_FILE = "defaults/config.json" + +class Config(object): + + _config = {} + + @classmethod + def get(cls): + return cls._config + + @classmethod + def read(cls): + if not os.path.exists(CONFIG_FILE): + cls.restore() + with open(CONFIG_FILE, 'r') as f: + cls._config = json.load(f) + f.close() + return cls._config + + @classmethod + def write(cls, config): + cls._config = config + f = open(CONFIG_FILE, 'w') + json.dump(cls._config, f) + return cls._config + + @classmethod + def restore(cls): + with open(CONFIG_DEFAULT_FILE) as f: + cls.write(json.loads(f.read())) + diff --git a/coderbot/cv/__init__.py b/coderbot/cv/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/coderbot/cv/blob.py b/coderbot/cv/blob.py new file mode 100644 index 00000000..c45a2d40 --- /dev/null +++ b/coderbot/cv/blob.py @@ -0,0 +1,58 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ + +import cv2 + +class Blob(): + + def __init__(self, contour): + self._contour = contour + + @property + def bottom(self): + return self._contour[self._contour[:, :, 1].argmax()][0][1] + + @property + def top(self): + return self._contour[self._contour[:, :, 1].argmin()][0][1] + + @property + def left(self): + return self._contour[self._contour[:, :, 0].argmin()][0][0] + + @property + def right(self): + return self._contour[self._contour[:, :, 0].argmax()][0][0] + + @property + def center(self): + return ((self.right + self.left) / 2, (self.top + self.bottom) / 2) + + def area(self): + return cv2.contourArea(self._contour) + + def minAreaRect(self): + return cv2.minAreaRect(self._contour) + + def contour(self): + return self._contour + + @classmethod + def sort_distance(cls, point, blobs): + return sorted(blobs, key=lambda blob: (point[0] - blob.bottom)) diff --git a/coderbot/cv/camera.py b/coderbot/cv/camera.py new file mode 100644 index 00000000..f2b1b68f --- /dev/null +++ b/coderbot/cv/camera.py @@ -0,0 +1,129 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2017 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ +""" +The Camera module implements the Camera class, which is the abstraction +from the lower lever PiCamera (RPI specific) +""" +import io +import os +import logging +from threading import Condition +import numpy as np +import picamera + +class Camera(object): + + FFMPEG_CMD = 'ffmpeg' + PHOTO_FILE_EXT = ".jpg" + VIDEO_FILE_EXT = ".mp4" + VIDEO_FILE_EXT_H264 = '.h264' + + class StreamingOutputMJPEG(object): + def __init__(self): + self.frame = None + self.buffer = io.BytesIO() + self.condition = Condition() + + def write(self, buf): + if buf.startswith(b'\xff\xd8'): + # New frame, copy the existing buffer's content and notify all + # clients it's available + self.buffer.truncate() + with self.condition: + self.frame = self.buffer.getvalue() + self.condition.notify_all() + self.buffer.seek(0) + return self.buffer.write(buf) + + class StreamingOutputBGR(object): + def __init__(self, resolution): + self.frame = None + self.condition = Condition() + self.resolution = resolution + self.count = 0 + + def write(self, buf): + with self.condition: + frame = np.frombuffer(buf, dtype=np.uint8) + self.frame = frame.reshape(self.resolution[1], self.resolution[0], 4) + self.frame = np.delete(self.frame, 3, 2) + self.condition.notify_all() + return len(buf) + + def __init__(self, props): + logging.info("camera init") + self.camera = picamera.PiCamera() + self.camera.resolution = (props.get('width', 640), props.get('height', 512)) + self.out_rgb_resolution = (int(self.camera.resolution[0] / int(props.get('cv_image_factor', 4))), int(self.camera.resolution[1] / int(props.get('cv_image_factor', 4)))) + self.camera.framerate = float(props.get('framerate', 20)) + self.camera.exposure_mode = props.get('exposure_mode', "auto") + self.output_mjpeg = self.StreamingOutputMJPEG() + self.output_bgr = self.StreamingOutputBGR(self.out_rgb_resolution) + self.h264_encoder = None + self.recording = None + self.video_filename = None + self._jpeg_quality = props.get('jpeg_quality', 20) + self._jpeg_bitrate = props.get('jpeg_bitrate', 5000000) + + def video_rec(self, filename): + self.video_filename = filename[:filename.rfind(".")] + self.camera.start_recording(self.video_filename + self.VIDEO_FILE_EXT_H264, format="h264", quality=23, splitter_port=2) + + def video_stop(self): + logging.debug("video_stop") + self.camera.stop_recording(2) + + # pack in mp4 container + params = " -loglevel quiet -stats -framerate " + str(self.camera.framerate) + \ + " -i " + self.video_filename + self.VIDEO_FILE_EXT_H264 + \ + " -c copy " + self.video_filename + self.VIDEO_FILE_EXT + + os.system(self.FFMPEG_CMD + params) + # remove h264 file + os.remove(self.video_filename + self.VIDEO_FILE_EXT_H264) + + def grab_start(self): + logging.debug("grab_start") + self.camera.start_recording(self.output_mjpeg, format="mjpeg", splitter_port=0, bitrate=self._jpeg_bitrate) + self.camera.start_recording(self.output_bgr, format="bgra", splitter_port=1, resize=self.out_rgb_resolution) + + def grab_stop(self): + logging.debug("grab_stop") + + self.camera.stop_recording(0) + self.camera.stop_recording(1) + + def get_image_jpeg(self): + with self.output_mjpeg.condition: + self.output_mjpeg.condition.wait() + return self.output_mjpeg.frame + + def get_image_bgr(self): + with self.output_bgr.condition: + self.output_bgr.condition.wait() + return self.output_bgr.frame + + def set_overlay_text(self, text): + try: + self.camera.annotate_text = text + except picamera.PiCameraValueError: + logging.info("PiCameraValueError") + + def close(self): + self.camera.close() diff --git a/coderbot/cv/image.py b/coderbot/cv/image.py new file mode 100644 index 00000000..3c602379 --- /dev/null +++ b/coderbot/cv/image.py @@ -0,0 +1,281 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ + +import logging +import colorsys +import numpy as np +import cv2 +import cv2.aruco +import cv.blob as blob +import pytesseract + +MIN_MATCH_COUNT = 10 + +try: + from pyzbar.pyzbar import decode +except: + logging.info("zbar not availabe") + +class Image(): + r_from = np.float32([[0, 0], [640, 0], [640, 480], [0, 480]]) + r_dest = np.float32([[0, -120], [640, -120], [380, 480], [260, 480]]) + + _aruco_dict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_ARUCO_ORIGINAL) + _aruco_parameters = cv2.aruco.DetectorParameters_create() + + _face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') + + def __init__(self, array): + self._data = array + img_size_y = self._data.shape[0] + kernel_size = int(img_size_y / 40) + self._kernel = np.ones((kernel_size, kernel_size), np.uint8) + + def size(self): + return self._data.shape + + def mat(self): + return self._data + + @classmethod + def load(cls, filename): + return Image(cv2.imread(filename)) + + def resize(self, width, heigth): + return Image(cv2.resize(self._data, (width, heigth))) + + def crop(self, x1, y1, x2, y2): + return Image(self._data[y1:y2, x1:x2]) + + def warp(self, r_from, r_dest): + tx = cv2.getPerspectiveTransform(r_from, r_dest) + dest = cv2.warpPerspective(self._data, tx, (640, 480)) + return Image(dest) + + @classmethod + def transform(cls, vector, tx): + v = np.array(vector, dtype='float32') + v = np.array([v]) + dest = cv2.perspectiveTransform(v, tx) + return dest[0] + + @classmethod + def get_transform(cls, image_size_x): + k = 640 / image_size_x + rfrom = cls.r_from / k + rdest = cls.r_dest / k + tx = cv2.getPerspectiveTransform(rfrom, rdest) + return tx + + def find_faces(self): + faces = self._face_cascade.detectMultiScale(self._data) + return faces + + def filter_color(self, color): + h, s, v = colorsys.rgb_to_hsv(color[0]/255.0, color[1]/255.0, color[2]/255.0) + image_hsv = cv2.cvtColor(self._data, cv2.COLOR_BGR2HSV) + h = h * 180 + s = s * 255 + v = v * 255 + logging.debug("color_hsv: " + str(h) + " " + str(s) + " " + str(v)) + #lower_color = np.array([h-10 if h>=10 else 0.0, 0, 0]) + #upper_color = np.array([h+10 if h<=170 else 179.0, 255, 255]) + lower_color = np.array([h-5, 50, 50]) + upper_color = np.array([h+5, 255, 255]) + logging.debug("lower: " + str(lower_color) + " upper: " + str(upper_color)) + mask = cv2.inRange(image_hsv, lower_color, upper_color) + return Image(mask) + + def dilate(self): + data = cv2.dilate(self._data, self._kernel) + return Image(data) + + def erode(self): + data = cv2.erode(self._data, self._kernel) + return Image(data) + + def open(self): + data = cv2.morphologyEx(self._data, cv2.MORPH_OPEN, self._kernel) + return Image(data) + + def close(self): + data = cv2.morphologyEx(self._data, cv2.MORPH_CLOSE, self._kernel) + return Image(data) + + def grayscale(self): + data = cv2.cvtColor(self._data, cv2.COLOR_BGR2GRAY) + return Image(data) + + def blackwhite(self): + data = cv2.threshold(self._data, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) + return Image(data) + + def invert(self): + data = cv2.bitwise_not(self._data) + return Image(data) + + def binarize(self, threshold=-1): + data = cv2.cvtColor(self._data, cv2.COLOR_BGR2GRAY) + if threshold < 0: + data = cv2.adaptiveThreshold(data, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, max((self._kernel.shape[0]/2*2)+1, 3), 3) + else: + ret, data = cv2.threshold(data, threshold, 255, cv2.THRESH_BINARY_INV) + return Image(data) + + def get_average(self): + data = cv2.cvtColor(self._data, cv2.COLOR_BGR2HSV) + logging.info("shape: " + str(data.shape)) + h = np.average(data[:, :, 0]) + s = np.average(data[:, :, 1]) + v = np.average(data[:, :, 2]) + return [h, s, v] + + def find_blobs(self, minsize=0, maxsize=10000000): + blobs = [] + image = contours = hyerarchy = None + contours, hyerarchy = cv2.findContours(self._data, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) + + for c in contours: + area = cv2.contourArea(c) + if area > minsize and area < maxsize: + if len(blobs) and area > blobs[0].area(): + blobs.insert(0, blob.Blob(c)) + else: + blobs.append(blob.Blob(c)) + + return blobs + + def find_template(self, img_template): + # Initiate SIFT detector + sift = cv2.SIFT() + + # find the keypoints and descriptors with SIFT + kp1, des1 = sift.detectAndCompute(img_template._data, None) + kp2, des2 = sift.detectAndCompute(self._data, None) + + FLANN_INDEX_KDTREE = 0 + index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) + search_params = dict(checks=50) + + flann = cv2.FlannBasedMatcher(index_params, search_params) + + matches = flann.knnMatch(des1, des2, k=2) + + # store all the good matches as per Lowe's ratio test. + good = [] + templates = [] + for m, n in matches: + if m.distance < 0.7 * n.distance: + good.append(m) + + if len(good) > MIN_MATCH_COUNT: + src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2) + dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2) + + M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) + matchesMask = mask.ravel().tolist() + + h, w = img_template.shape + pts = np.float32([[0, 0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2) + dst = cv2.perspectiveTransform(pts, M) + logging.info("found template: %s", dst) + templates[0] = dst + + else: + logging.info("Not enough matches are found - %d/%d", len(good), MIN_MATCH_COUNT) + matchesMask = None + + return templates + + def find_rect(self, color): + rect_image = None + filtered_image = self.filter_color(color) + blobs = filtered_image.find_blobs(minsize=1000) + image_size = self.size() + logging.info("blobs: " + str(blobs)) + if len(blobs): + blob = blobs[0] + b_area = blob.area() + for b in blobs: + if b.area() > b_area: + blob = b + b_area = blob.area() + rect = blob.minAreaRect() + center = rect[0] + size = rect[1] + angle = rect[2] + if size[0] < size[1]: + angle = angle + 90 + size = (size[1], size[0]) + + rot_matrix = cv2.getRotationMatrix2D(center, angle, 1) + logging.info("center: " + str(center) + " size: " + str(size) + " angle: " + str(angle)) + rect_image = Image(cv2.warpAffine(self._data, rot_matrix, (image_size[1], image_size[0]))) + border = 5 + rect_image = rect_image.crop(int(max(0, border+center[0]-(size[0])/2)), + int(max(0, border+center[1]-(size[1]+5)/2)), + int(min(image_size[1], -border+center[0]+(size[0])/2)), + int(min(image_size[0], -border+center[1]+(size[1]-5)/2))) + return rect_image + + def find_text(self, lang, timeout): + text = '?' + try: + text = pytesseract.image_to_string(self._data, lang, timeout) + except RuntimeError as e: + pass + return text + + def find_qr_code(self): + text_found = None + img_size = self._data.shape + gray = cv2.cvtColor(self._data, cv2.COLOR_BGR2GRAY) + image_code = decode(gray) + for symbol in image_code: + text_found = symbol.data.decode("utf-8") + break + return text_found + + def find_ar_code(self): + gray = cv2.cvtColor(self._data, cv2.COLOR_BGR2GRAY) + corners, ids, rejectedImgPoints = cv2.aruco.detectMarkers(gray, self._aruco_dict, parameters=self._aruco_parameters) + codes = [] + positions = [] + if ids is not None: + for i in range(0, len(ids)): + if ids[i][0] != 1023: + codes.append(ids[i][0]) + rect = corners[i][0] + positions.append([(rect[0][0]+rect[1][0]+rect[2][0]+rect[3][0])/4, + (rect[0][1]+rect[1][1]+rect[2][1]+rect[3][1])/4]) + return {"codes": codes, "positions": positions} + + def draw_blob(self, blob): + cv2.drawContours(self._data, blob.contour(), -1, (0, 255, 0)) + + def draw_rect(self, x1, y1, x2, y2, color, thickness): + cv2.rectangle(self._data, (x1, y1), (x2, y2), color, thickness) + + def to_jpeg(self): + ret, jpeg_array = cv2.imencode('.jpeg', self._data) + return np.array(jpeg_array).tostring() + + def to_rgb(self): + rgb_img = cv2.cvtColor(self._data, cv2.COLOR_BGR2RGB) + return rgb_img diff --git a/coderbot/event.py b/coderbot/event.py new file mode 100644 index 00000000..2ca0bedd --- /dev/null +++ b/coderbot/event.py @@ -0,0 +1,48 @@ +import threading +from event_channel.threaded_event_channel import ThreadedEventChannel + +class EventManager(object): + _instance = None + @classmethod + def get_instance(cls, node_name=None): + if cls._instance is None and node_name is not None: + cls._instance = EventManager(node_name) + return cls._instance + + def __init__(self, node_name): + self._channel = ThreadedEventChannel(blocking=False) + self._publisher_threads = None + self._subscribers = [] + self._node_name = node_name + self._event_generators = [] + + def publish(self, topic, msg): + self._publisher_threads = self._channel.publish(topic, msg) + + def register_event_listener(self, topic, callback): + self._channel.subscribe(topic, callback) + self._subscribers.append((topic, callback)) + + def register_event_generator(self, generator_func): + generator = threading.Thread(target=generator_func) + self._event_generators.append(generator) + generator.start() + + def unregister_listeners(self): + for l in self._subscribers: + self._channel.unsubscribe(l[0], l[1]) + self._subscribers = [] + + def unregister_publishers(self): + if self._publisher_threads: + for t in self._publisher_threads: + t.join() + + def start_event_generators(self): + for g in self._event_generators: + g.start() + + def wait_event_generators(self): + for g in self._event_generators: + g.join() + self._event_generators = [] diff --git a/coderbot/hw/__init__.py b/coderbot/hw/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/coderbot/hw/atmega328p.py b/coderbot/hw/atmega328p.py new file mode 100644 index 00000000..76c3965b --- /dev/null +++ b/coderbot/hw/atmega328p.py @@ -0,0 +1,84 @@ +# RPi PINOUTS +# MOSI -> GPIO10 +# MISO -> GPIO9 +# SCK -> GPIO11 +# CE1 -> GPIO7 +# CE1 -> GPIO8 + +# get the GPIO Library and SPI Library +import spidev +import time + +BAUDRATE_MAX = 250000 +BAUDRATE = 10000 + +START = 0xff +CMD_RESET = 0x00 +CMD_SET_DATA = 0x01 +CMD_GET_DATA = 0x02 +CMD_SET_MODE = 0x03 +CMD_SET_LED = 0x04 + +ADDR_AI_FIRST = 0x00 +ADDR_AI_LAST = 0x01 +ADDR_DI_FIRST = 0x02 +ADDR_DI_LAST = 0x05 +ADDR_DO_FIRST = 0x00 +ADDR_DO_LAST = 0x0a + +class ATMega328(): + + _instance = None + + @classmethod + def get_instance(cls): + if cls._instance is None: + cls._instance = ATMega328() + return cls._instance + + def __init__(self): + # Initialze the SPI + self.spi = spidev.SpiDev() + self.spi.open(0,0) + self.spi.max_speed_hz = BAUDRATE_MAX + + def close(self): + self.spi.close() + + def digitalWrite(self, addr, value): + resp = self.spi.xfer([START, CMD_SET_DATA, addr, value, 0], BAUDRATE) + + def digitalRead(self, addr): + resp = self.spi.xfer([START, CMD_GET_DATA, addr, 0, 0], BAUDRATE) + return resp[3] + + def analogRead(self, addr): + resp = self.spi.xfer([START, CMD_GET_DATA, addr, 0, 0], BAUDRATE) + return resp[3] + + def setLed(self, begin_led, end_led, red, green, blue): + resp = self.spi.xfer([START, CMD_SET_LED, + min(max(begin_led, 0), 60), + min(max(end_led, 0), 60), + min(max(red, 0), 254), + min(max(green, 0), 254), + min(max(blue, 0), 254)], BAUDRATE) + return resp[3] + + def set_led(self, begin_led, end_led, red, green, blue): + begin = begin_led - 1 + end = end_led - 1 + red = int(red * 255 / 100) + green = int(green * 255 / 100) + blue = int(blue * 255 / 100) + return self.setLed(begin, end, red, green, blue) + + def get_input(self, addr): + if addr >= ADDR_AI_FIRST and addr <= ADDR_AI_LAST: + return self.analogRead(addr) + elif addr >= ADDR_DI_FIRST and addr <= ADDR_DI_LAST: + return self.digitalRead(addr) + + def set_output(self, addr, value): + if addr >= ADDR_DO_FIRST and addr <= ADDR_DO_LAST: + self.digitalWrite(addr, value) diff --git a/coderbot/hw/lsm9ds1.py b/coderbot/hw/lsm9ds1.py new file mode 100644 index 00000000..101b7daf --- /dev/null +++ b/coderbot/hw/lsm9ds1.py @@ -0,0 +1,431 @@ +import os +import time +import math +import json +import spidev +import threading + +from smbus2 import SMBus + +MAX_INVALID_MAG = 99.0 + +# Hardware Constants +# +# from LSM9DS1_Datasheet.pdf +class Register: + """Register constants""" + WHO_AM_I = 0x0F + CTRL_REG1_G = 0x10 + CTRL_REG2_G = 0x11 + CTRL_REG3_G = 0x12 + OUT_TEMP_L = 0x15 + STATUS_REG = 0x17 + OUT_X_G = 0x18 + CTRL_REG4 = 0x1E + CTRL_REG5_XL = 0x1F + CTRL_REG6_XL = 0x20 + CTRL_REG7_XL = 0x21 + CTRL_REG8 = 0x22 + CTRL_REG9 = 0x23 + CTRL_REG10 = 0x24 + OUT_X_XL = 0x28 + REFERENCE_G = 0x0B + INT1_CTRL = 0x0C + INT2_CTRL = 0x0D + WHO_AM_I_M = 0x0F + CTRL_REG1_M = 0x20 + CTRL_REG2_M = 0x21 + CTRL_REG3_M = 0x22 + CTRL_REG4_M = 0x23 + CTRL_REG5_M = 0x24 + STATUS_REG_M = 0x27 + OUT_X_L_M = 0x28 + + +class MagCalibration: + def __init__(self, xmin=MAX_INVALID_MAG, xmax=-MAX_INVALID_MAG, ymin=MAX_INVALID_MAG, ymax=-MAX_INVALID_MAG, + heading_offset=0.0): + self.xmax = xmax + self.xmin = xmin + self.ymax = ymax + self.ymin = ymin + self.heading_offset = heading_offset + + def to_json(self): + obj = self.to_dict() + return json.dumps(obj) + + def to_dict(self): + obj = {"xmin": self.xmin, "xmax": self.xmax, "ymin": self.ymin, "ymax": self.ymax, + "heading_offset": self.heading_offset} + return obj + + @staticmethod + def from_dict(obj): + return MagCalibration(xmin=obj['xmin'], xmax=obj['xmax'], ymin=obj['ymin'], ymax=obj['ymax'], + heading_offset=obj['heading_offset']) + + +# +# Status Classes +# +class AGStatus: + def __init__(self, status): + self.status = status + + @property + def accelerometer_interrupt(self): + return (self.status & 0x40) != 0 + + @property + def gyroscope_interrupt(self): + return (self.status & 0x20) != 0 + + @property + def inactivity_interrupt(self): + return (self.status & 0x10) != 0 + + @property + def boot_status(self): + return (self.status & 0x08) != 0 + + @property + def temperature_data_available(self): + return (self.status & 0x04) != 0 + + @property + def gyroscope_data_available(self): + return (self.status & 0x02) != 0 + + @property + def accelerometer_data_available(self): + return (self.status & 0x01) != 0 + + +class MagnetometerStatus: + def __init__(self, status): + self.status = status + + @property + def overrun(self): + """data overrun on all axes""" + return (self.status & 0x80) != 0 + + @property + def z_overrun(self): + """Z axis data overrun""" + return (self.status & 0x40) != 0 + + @property + def y_overrun(self): + """Y axis data overrun""" + return (self.status & 0x20) != 0 + + @property + def x_overrun(self): + """X axis data overrun""" + return (self.status & 0x10) != 0 + + @property + def data_available(self): + """There's new data available for all axes.""" + return (self.status & 0x08) != 0 + + @property + def z_axis_data_available(self): + return (self.status & 0x04) != 0 + + @property + def y_axis_data_available(self): + return (self.status & 0x02) != 0 + + @property + def x_axis_data_available(self): + return (self.status & 0x01) != 0 + +class I2CTransport(): + I2C_AG_ADDRESS = 0x6B + I2C_MAG_ADDRESS = 0x1E + + def __init__(self, port, i2c_address, data_ready_pin=None): + super().__init__() + self.port = port + self.i2c_device = i2c_address + self.data_ready_interrupt = None + + def write_byte(self, address, value): + with SMBus(self.port) as bus: + bus.write_byte_data(self.i2c_device, address, value) + + def read_byte(self, address): + with SMBus(self.port) as bus: + bus.write_byte(self.i2c_device, address) + return bus.read_byte(self.i2c_device) + + def read_bytes(self, address, length): + with SMBus(self.port) as bus: + bus.write_byte(self.i2c_device, address) + result = bus.read_i2c_block_data(self.i2c_device, address, length) + return result + +# +# Main Interface: lsm9ds1 +# +def make_i2c(i2cbus_no): + return lsm9ds1( + I2CTransport(i2cbus_no, I2CTransport.I2C_AG_ADDRESS), + I2CTransport(i2cbus_no, I2CTransport.I2C_MAG_ADDRESS)) + + +class lsm9ds1: + AG_ID = 0b01101000 + MAG_ID = 0b00111101 + + # from LSM9DS1_Datasheet.pdf + ACC_SENSOR_SCALE = 0.061 / 1000.0 + GAUSS_SENSOR_SCALE = 0.14 / 1000.0 + DPS_SENSOR_SCALE = 8.75 / 1000.0 + TEMP_SENSOR_SCALE = 59.5 / 1000.0 + TEMPC_0 = 25 + YMAG_IND = 1 + XMAG_IND = 0 + + def __init__(self, ag_protocol, magnetometer_protocol, high_priority=False): + self.ag = ag_protocol + self.mag = magnetometer_protocol + self.mag_calibration = None + # Needs to be a high priority process or it'll drop samples + # when other processes are under heavy load. + if high_priority: + priority = os.sched_get_priority_max(os.SCHED_FIFO) + param = os.sched_param(priority) + os.sched_setscheduler(0, os.SCHED_FIFO, param) + + def set_mag_calibration(self, mag_calibration): + self.mag_calibration = mag_calibration + + def configure(self, mag_calibration=None): + """Resets the device and configures it. Optionally pass in the mag calibration info""" + + self.set_mag_calibration(mag_calibration) + + ################################################### + # - Bit 0 - SW_RESET - software reset for accelerometer and gyro - default 0 + # - Bit 2 - IF_ADD_INC - automatic register increment for multibyte access - default 1 + # - Bit 6 - BDU - Block data update . Ensures high and low bytes come from + # the same sample. Not necessary if waiting for data ready - default 0 + self.ag.write_byte(Register.CTRL_REG8, 0x05) + # 0x08 - reboot magnetometer, +/- 4 Gauss full scale - fixes occasional magnetometer hang + # 0x04 - soft reset magnetometer, +/- 4 Gauss full scale + self.mag.write_byte(Register.CTRL_REG2_M, 0x08) + time.sleep(0.01) # Wait for reset + ################################################### + # Confirm that we're connected to the device + if self.ag.read_byte(Register.WHO_AM_I) != lsm9ds1.AG_ID: + raise RuntimeError('Could not find LSM9DS1 Acceleromter/Gyro. Check wiring and port numbers.') + if self.mag.read_byte(Register.WHO_AM_I_M) != lsm9ds1.MAG_ID: + raise RuntimeError('Could not find LSM9DS1 Magnetometer. Check wiring and port numbers.') + ################################################### + # Set up output data rate for Accelerometer and Gyro if using both + # Use CTRL_REG2_G and CTRL_REG3_G to control the optional additional filters + # 0x6A - 500 dps, 119 Hz ODR, 38Hz cut off (31 Hz Cut off if HP filter is enabled) + # 0x8A - 500 dps, 238 Hz ODR, 76Hz cut off (63 Hz Cut off if HP filter is enabled) + # 0xAA - 500 dps, 476 Hz ODR, 100Hz cut off (57 Hz Cut off if HP filter is enabled) + # 0x00 - disabled + self.ag.write_byte(Register.CTRL_REG1_G, 0x8A) + # 0x03 - Enable LPF2 - Frequency set by REG1 (2nd Low Pass Filter) + # self.ag.write_byte(Register.CTRL_REG2_G, 0x03) + # 0x45 - Enable High Pass Filter at (0.2 Hz @ 119 ODR) or (0.5 Hz @ 238 ODR) + # self.ag.write_byte(Register.CTRL_REG3_G, 0x45) + ################################################### + # Set up Accelerometer + # 0xC0 - Set to +- 2G, 119 Hz ODR, 50 Hz BW (Frequency is ignored if Gryo is enabled) + # 0x87 - Set to +- 2G, 238 Hz ODR, 50 Hz BW (Frequency is ignored if Gryo is enabled) + self.ag.write_byte(Register.CTRL_REG6_XL, 0x87) + # 0x01 INT1_A/G pin set by accelerometer data ready + self.ag.write_byte(Register.INT1_CTRL, 0x01) + ################################################### + # Set up magnetometer + # MSB enables temperature compensation + # 0x98 - 40 Hz ODR, Enable Temp Comp + # 0x9C - 80 Hz ODR, Enable Temp Comp + # 0x18 - 40 Hz ODR, Disable Temp Comp + # 0x1C - 80 Hz ODR, Enable Temp Comp + # 0xE2 - 155 Hz ODR, Enable Temp Comp, x and y ultra high performance + # 0xC2 - 300 Hz ODR, Enable Temp Comp, x and y high performance + # 0xA2 - 560 Hz ODR, Enable Temp Comp, x and y medium performance + # 0x82 - 1000 Hz ODR, Enable Temp Comp, x and y low performance + self.mag.write_byte(Register.CTRL_REG1_M, 0xC2) + # 0x00 - Magnetometer continuous operation - I2C enabled + # 0x80 - Magnetometer continuous operation - I2C disabled + self.mag.write_byte(Register.CTRL_REG3_M, 0x00) + # 0x08 - z axi high performance mode - doesn't seem to do anything + self.mag.write_byte(Register.CTRL_REG4_M, 0x08) + # Enable BDU (block data update) to ensure high and low bytes come from the same sample + self.mag.write_byte(Register.CTRL_REG5_M, 0x40) + + def close(self): + """Closes the I2C/SPI connection. This must be called on shutdown.""" + self.ag.close() + self.mag.close() + + # + # Simplified scaled interface + # + def mag_heading(self): + """Returns the heading in 360°""" + values = self.mag_values() + y = values[lsm9ds1.YMAG_IND] + x = values[lsm9ds1.XMAG_IND] + if self.mag_calibration is not None: + mc = self.mag_calibration + # scale these samples between -1:1 + if mc.xmax != mc.xmin: + x = ((x - mc.xmin) / (mc.xmax - mc.xmin)) * 2 - 1 + if mc.ymax != mc.ymin: + y = ((y - mc.ymin) / (mc.ymax - mc.ymin)) * 2 - 1 + heading = math.atan2(y, x) + heading = (heading / (2 * math.pi)) * 360.0 + if self.mag_calibration is not None: + heading = (heading + self.mag_calibration.heading_offset) % 360.0 + return heading + + def read_values(self): + """Returns scaled values of temp, accel, gyro""" + temp, acc, gyro = self.read_ag_data() + tempc = lsm9ds1.TEMPC_0 + temp * lsm9ds1.TEMP_SENSOR_SCALE + tempf = (tempc * 9/5) + 32 + acc = [c * lsm9ds1.ACC_SENSOR_SCALE for c in acc] + gyro = [g * lsm9ds1.DPS_SENSOR_SCALE for g in gyro] + return tempc, acc, gyro + + # + # Raw interface + # + def ag_data_ready(self, timeout_millis): + return self.ag.data_ready(timeout_millis) + + def read_ag_status(self): + """Returns the status byte for the accelerometer and gyroscope.""" + data = self.ag.read_byte(Register.STATUS_REG) + return AGStatus(data) + + def read_ag_data(self): + """Returns the current temperature, acceleration and angular velocity + values in one go. This is faster than fetching them independently. + These values can be invalid unless they're read when the data is ready.""" + data = self.ag.read_bytes(Register.OUT_TEMP_L, 14) + temp = lsm9ds1.to_int16(data[0:2]) + gyro = lsm9ds1.to_vector_left_to_right_hand_rule(data[2:8]) + acc = lsm9ds1.to_vector_left_to_right_hand_rule(data[8:14]) + return temp, acc, gyro + + def read_temperature(self): + """Reads the temperature. See also read_ag_data()""" + data = self.ag.read_bytes(Register.OUT_TEMP_L, 2) + return lsm9ds1.to_int16(data) + + def read_acceleration(self): + """Reads the accelerations. See also read_ag_data()""" + data = self.ag.read_bytes(Register.OUT_X_XL, 6) + return lsm9ds1.to_vector_left_to_right_hand_rule(data) + + def read_gyroscope(self): + """Reads the angular velocities. See also read_ag_data()""" + data = self.ag.read_bytes(Register.OUT_X_G, 6) + return lsm9ds1.to_vector_left_to_right_hand_rule(data) + + def magnetometer_data_ready(self, timout_millis: int) -> bool: + return self.mag.data_ready(timout_millis) + + def read_magnetometer_status(self): + """Returns the status byte for the magnetometer""" + data = self.mag.read_byte(Register.STATUS_REG_M) + return MagnetometerStatus(data) + + def mag_values(self): + mag = self.read_magnetometer() + mag = [m * lsm9ds1.GAUSS_SENSOR_SCALE for m in mag] + return mag + + def read_magnetometer(self): + """Reads the magnetometer field strengths""" + data = self.mag.read_bytes(Register.OUT_X_L_M, 6) + return lsm9ds1.to_vector(data) + + @staticmethod + def to_vector(data): + return [lsm9ds1.to_int16(data[0:2]), lsm9ds1.to_int16(data[2:4]), lsm9ds1.to_int16(data[4:6])] + + @staticmethod + def to_vector_left_to_right_hand_rule(data): + """Like to_vector except it converts from the left to the right hand rule + by negating the x-axis.""" + return [-lsm9ds1.to_int16(data[0:2]), lsm9ds1.to_int16(data[2:4]), lsm9ds1.to_int16(data[4:6])] + + @staticmethod + def to_int16(data): + """ + Converts little endian bytes into a signed 16-bit integer + :param data: 16bit int in little endian, two's complement form + :return: an integer + """ + return int.from_bytes(data, byteorder='little', signed=True) + + +# +# Run me as an application to get calibration info: +# python -m lsm9ds1.lsm9ds1 +# +def poll_mag_calibration(imu, mc, evt, verbose=True): + """ + Will poll the x, y mag gauss values in order to establish min, max + """ + samples = 0 + while not evt.is_set(): + m = imu.mag_values() + samples += 1 + x = m[lsm9ds1.XMAG_IND] + y = m[lsm9ds1.YMAG_IND] + if x < mc.xmin: + mc.xmin = x + if x > mc.xmax: + mc.xmax = x + if y < mc.ymin: + mc.ymin = y + if y > mc.ymax: + mc.ymax = y + + if verbose: + print("%d samples." % samples) + + +def run_interactive_calibration(i2cbus_no): + mc = MagCalibration() + evt = threading.Event() + imu = make_i2c(i2cbus_no) + calibration__thread = threading.Thread(target=poll_mag_calibration, args=[imu, mc, evt]) + calibration__thread.start() + + input("Rotate device for 2 revolutions at approximately 10 seconds per revolution press enter when done >") + evt.set() + calibration__thread.join() + + while True: + current = input("What direction am I currently facing (in 360°) >") + try: + current = float(current) + break + except Exception: + print("I need a floating point number for the heading") + + imu.set_mag_calibration(mc) + observed = imu.mag_heading() + + mc.heading_offset = current - observed + return mc + + +if __name__ == '__main__': + mc = run_interactive_calibration(1) + print(mc.to_json()) diff --git a/coderbot/hw/mpu.py b/coderbot/hw/mpu.py new file mode 100644 index 00000000..702dab45 --- /dev/null +++ b/coderbot/hw/mpu.py @@ -0,0 +1,59 @@ +from . import lsm9ds1 +import time + +class AccelGyroMag: + X_IND = 0 + Y_IND = 1 + Z_IND = 2 + + PITCH_IND = 0 + ROLL_IND = 1 + YAW_IND = 2 + + """This example shows how to poll the sensor for new data. + It queries the sensor to discover when the accelerometer/gyro + has new data and then reads all the sensors.""" + def __init__(self): + self.driver = lsm9ds1.make_i2c(1) + mc = lsm9ds1.MagCalibration(xmin=0.03234, xmax=0.25718, + ymin=0.036120000000000006, ymax=0.19138000000000002, + heading_offset=-130.29698965718163) + self.driver.configure(mc) + + + GYRO_THRESHOLD = 1.5 + + def read_ag(self): + temp, acc, gyro = self.driver.read_values() + print("Temp: %.1f °f" % temp) + print("Gyro Roll: %.4f, Pitch: %.4f, Yaw: %.4f" % (gyro[AccelGyroMag.ROLL_IND], + gyro[AccelGyroMag.PITCH_IND], + gyro[AccelGyroMag.YAW_IND])) + print("X: %.4f, Y: %.4f, Z: %.4f" % (acc[AccelGyroMag.X_IND], + acc[AccelGyroMag.Y_IND], + acc[AccelGyroMag.Z_IND])) + + def read_magnetometer(self): + hdg = self.driver.mag_heading() + print("Heading: " + str(hdg)) + + + def get_gyro(self): + temp, acc, gyro = self.driver.read_values() + return (gyro[AccelGyroMag.ROLL_IND], + gyro[AccelGyroMag.PITCH_IND], + gyro[AccelGyroMag.YAW_IND]) + + def get_acc(self): + temp, acc, gyro = self.driver.read_values() + return (acc[AccelGyroMag.X_IND], + acc[AccelGyroMag.Y_IND], + acc[AccelGyroMag.Z_IND]) + + def get_hdg(self): + hdg = self.driver.mag_heading() + return hdg + + def get_temp(self): + temp, acc, gyro = self.driver.read_values() + return temp diff --git a/coderbot/hw/mpu2.py b/coderbot/hw/mpu2.py new file mode 100644 index 00000000..d7a3278d --- /dev/null +++ b/coderbot/hw/mpu2.py @@ -0,0 +1,56 @@ +import time + +from hw import lsm9ds1 + +class SimpleExample: + X_IND = 0 + Y_IND = 1 + Z_IND = 2 + + PITCH_IND = 0 + ROLL_IND = 1 + YAW_IND = 2 + + """This example shows how to poll the sensor for new data. + It queries the sensor to discover when the accelerometer/gyro + has new data and then reads all the sensors.""" + def __init__(self): + self.driver = lsm9ds1.make_i2c(1) + mc = lsm9ds1.MagCalibration(xmin=0.03234, xmax=0.25718, + ymin=0.036120000000000006, ymax=0.19138000000000002, + heading_offset=-130.29698965718163) + self.driver.configure(mc) + + def main(self): + try: + count = 0 + while True: + ag_data_ready = self.driver.read_ag_status().accelerometer_data_available + if ag_data_ready: + self.read_ag() + print("") + #self.read_magnetometer() + count += 1 + time.sleep(0.05) + finally: + self.driver.close() + + def read_ag(self): + temp, acc, gyro = self.driver.read_values() + #print("Temp: %.1f °f" % temp, end='') + #print("Gyro Roll: %.4f, Pitch: %.4f, Yaw: %.4f" % (gyro[SimpleExample.ROLL_IND], + # gyro[SimpleExample.PITCH_IND], + # gyro[SimpleExample.YAW_IND]), end='') + print("X: %.4f, Y: %.4f, Z: %.4f" % (acc[SimpleExample.X_IND], + acc[SimpleExample.Y_IND], + acc[SimpleExample.Z_IND]), end='') + + def read_magnetometer(self): + hdg = self.driver.mag_heading() + print("headind: %f ", hdg, end='') + mag = self.driver.read_magnetometer() + print('Mag {}'.format(mag)) + + +if __name__ == '__main__': + SimpleExample().main() diff --git a/coderbot/main.py b/coderbot/main.py new file mode 100644 index 00000000..36383240 --- /dev/null +++ b/coderbot/main.py @@ -0,0 +1,117 @@ +""" +This module provides the http web server exposing the +CoderBot REST API and static resources +""" +import os +import logging +import logging.handlers +import picamera +import connexion + +from connexion.options import SwaggerUIOptions +from connexion.middleware import MiddlewarePosition +from starlette.middleware.cors import CORSMiddleware + +from camera import Camera +from motion import Motion +from audio import Audio +from program import ProgramEngine +from config import Config +from cnn.cnn_manager import CNNManager +from event import EventManager +from coderbot import CoderBot + +# Logging configuration +logger = logging.getLogger() +logger.setLevel(os.environ.get("LOGLEVEL", "INFO")) + +## (Connexion) Flask app configuration + +# Serve a custom version of the swagger ui (Jinja2 templates) based on the default one +# from the folder 'swagger-ui'. Clone the 'swagger-ui' repository inside the backend folder +swagger_ui_options = SwaggerUIOptions(swagger_ui=True) +app = connexion.App(__name__, swagger_ui_options=swagger_ui_options) +app.add_middleware( + CORSMiddleware, + position=MiddlewarePosition.BEFORE_EXCEPTION, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) +app.prog_engine = ProgramEngine.get_instance() + +## New API and web application + +# API v1 is defined in v1.yml and its methods are in api.py +app.add_api('v1.yml') + +def button_pushed(): + if app.bot_config.get('button_func') == "startstop": + prog = app.prog_engine.get_current_prog() + if prog and prog.is_running(): + prog.end() + elif prog and not prog.is_running(): + prog.execute() + +def remove_doreset_file(): + try: + os.remove("/home/pi/doreset") + except OSError: + pass + +# Finally, get the server running +def run_server(): + bot = None + cam = None + try: + try: + app.bot_config = Config.read() + bot = CoderBot.get_instance(motor_trim_factor=float(app.bot_config.get('move_motor_trim', 1.0)), + motor_max_power=int(app.bot_config.get('motor_max_power', 100)), + motor_min_power=int(app.bot_config.get('motor_min_power', 0)), + hw_version=app.bot_config.get('hardware_version'), + pid_params=(float(app.bot_config.get('pid_kp', 1.0)), + float(app.bot_config.get('pid_kd', 0.1)), + float(app.bot_config.get('pid_ki', 0.01)), + float(app.bot_config.get('pid_max_speed', 200)), + float(app.bot_config.get('pid_sample_time', 0.01))), + from_defaults=False) + + try: + audio_device = Audio.get_instance() + audio_device.set_volume(int(app.bot_config.get('audio_volume_level')), 100) + audio_device.say(app.bot_config.get("sound_start")) + except Exception: + logging.warning("Audio not present") + + try: + logging.info("starting camera") + cam = Camera.get_instance() + Motion.get_instance() + except picamera.exc.PiCameraError: + logging.warning("Camera not present") + + CNNManager.get_instance() + EventManager.get_instance("coderbot") + + if app.bot_config.get('load_at_start') and app.bot_config.get('load_at_start'): + prog = app.prog_engine.load(app.bot_config.get('load_at_start')) + prog.execute() + except ValueError as e: + app.bot_config = {} + logging.error(e) + + bot.set_callback(bot.GPIOS.PIN_PUSHBUTTON, button_pushed, 100) + + remove_doreset_file() + + app.run(host="0.0.0.0", port=5000) + finally: + if cam: + cam.exit() + if bot: + bot.exit() + +if __name__ == "__main__": + run_server() \ No newline at end of file diff --git a/motion.py b/coderbot/motion.py similarity index 61% rename from motion.py rename to coderbot/motion.py index bf41ae9c..95d66563 100644 --- a/motion.py +++ b/coderbot/motion.py @@ -1,38 +1,55 @@ -import cv2 -import math -import numpy as np +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ + +from time import time import logging -from time import clock, time, sleep -from viz import image, streamer +import numpy as np +import cv2 +from cv import image from coderbot import CoderBot from camera import Camera -from program import get_prog_eng from config import Config -lk_params = dict( winSize = (15, 15), - maxLevel = 2, - criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) +lk_params = dict(winSize=(15, 15), + maxLevel=2, + criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) -feature_params = dict( maxCorners = 500, - qualityLevel = 0.3, - minDistance = 7, - blockSize = 7 ) +feature_params = dict(maxCorners=500, + qualityLevel=0.3, + minDistance=7, + blockSize=7) PI_CAM_FOV_H_DEG = 53.0 PI_CAM_FOV_V_CM = 100.0 -IMAGE_WIDTH = 160.0 -IMAGE_HEIGHT = 120.0 class Motion: + # pylint: disable=too-many-instance-attributes + def __init__(self): self.bot = CoderBot.get_instance() self.cam = Camera.get_instance() self.track_len = 2 self.detect_interval = 5 self.tracks = [] - self.frame_idx = 0 + self.frame_idx = 0 self.ts = time() self.frame_gray = None self.prev_gray = None @@ -43,8 +60,13 @@ def __init__(self): self.delta_angle = 0.0 self.target_angle = 0.0 cfg = Config.get() - self.power_angles = [[15, (int(cfg.get("move_power_angle_1")), -1)], [4, (int(cfg.get("move_power_angle_2")), 0.05)], [1, (int(cfg.get("move_power_angle_3")), 0.02)], [0, (0, 0)]] - + self.power_angles = [[15, (int(cfg.get("move_power_angle_1")), -1)], + [4, (int(cfg.get("move_power_angle_2")), 0.05)], + [1, (int(cfg.get("move_power_angle_3")), 0.02)], + [0, (0, 0)]] + self.image_width = 640 / int(cfg.get("cv_image_factor")) + self.image_heigth = 480 / int(cfg.get("cv_image_factor")) + self.transform = image.Image.get_transform(self.image_width) _motion = None @classmethod @@ -54,20 +76,20 @@ def get_instance(cls): return cls._motion def move(self, dist): - self.delta_dist = 0.0 + self.delta_dist = 0.0 self.delta_angle = 0.0 - self.target_dist = dist + self.target_dist = dist self.target_angle = 0.0 self.delta_power = 0.0 self.loop_move() def turn(self, angle): - self.delta_dist = 0.0 + self.delta_dist = 0.0 self.delta_angle = 0.0 self.target_dist = 0.0 self.target_angle = angle self.loop_turn() - + def stop(self): self.running = False @@ -80,10 +102,10 @@ def loop_move(self): if len(self.tracks) < 2 or self.frame_idx % self.detect_interval == 0: self.find_keypoints(self.frame_gray, self.tracks) - if len(self.tracks) > 0 and self.prev_gray is not None: - self.track_keypoints(self.prev_gray, self.frame_gray, self.tracks) + if self.tracks and self.prev_gray is not None: + self.track_keypoints(self.prev_gray, self.frame_gray, self.tracks) - if len(self.tracks) > 0: + if self.tracks: delta_angle, delta_dist = self.calc_motion() self.running = self.running and self.bot_move(self.target_dist, delta_dist, delta_angle) @@ -100,10 +122,10 @@ def loop_turn(self): if len(self.tracks) < 2 or self.frame_idx % self.detect_interval == 0: self.find_keypoints(self.frame_gray, self.tracks) - if len(self.tracks) > 0 and self.prev_gray is not None: + if self.tracks and self.prev_gray is not None: self.track_keypoints(self.prev_gray, self.frame_gray, self.tracks) - if len(self.tracks) > 0: + if self.tracks: delta_angle, delta_dist = self.calc_motion() self.running = self.running and self.bot_turn(self.target_angle, delta_angle) @@ -113,21 +135,21 @@ def loop_turn(self): self.bot.stop() def find_keypoints(self, image_gray, tracks): - #print "find_keypoints" + #print "find_keypoints" ts = time() mask = np.zeros_like(image_gray._data) - mask[:] = 255 - #for x, y in [np.int32(tr[-1]) for tr in tracks]: - # cv2.circle(mask, (x, y), 5, 0, -1) - p = cv2.goodFeaturesToTrack(image_gray._data, mask = mask, **feature_params) - if p is not None: - for x, y in np.float32(p).reshape(-1, 2): - tracks.append([(x, y)]) + mask[:] = 255 + #for x, y in [np.int32(tr[-1]) for tr in tracks]: + # cv2.circle(mask, (x, y), 5, 0, -1) + p = cv2.goodFeaturesToTrack(image_gray._data, mask=mask, **feature_params) + if p is not None: + for x, y in np.float32(p).reshape(-1, 2): + tracks.append([(x, y)]) #print "fk: ", str(time() - ts) def track_keypoints(self, prev_image, cur_image, tracks): - #print "track_keypoints" - ts = time() + #print "track_keypoints" + #ts = time() img0, img1 = prev_image._data, cur_image._data p0 = np.float32([tr[-1] for tr in tracks]).reshape(-1, 1, 2) p1, st, err = cv2.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params) @@ -139,7 +161,7 @@ def track_keypoints(self, prev_image, cur_image, tracks): new_tracks = [] for tr, (x, y), good_flag in zip(tracks, p1.reshape(-1, 2), good): if not good_flag: - continue + continue tr.append((x, y)) if len(tr) > self.track_len: del tr[0] @@ -148,12 +170,12 @@ def track_keypoints(self, prev_image, cur_image, tracks): #print "initial tp: ", len(self.tracks), " current tp: ", len(new_tracks) #print len(new_tracks), len(tracks) tracks[:] = new_tracks[:] - if len(tracks) == 0: - logging.warn("lost ALL tp!") + if tracks is False: + logging.warning("lost ALL tp!") self.bot.stop() #exit(0) #cv2.polylines(self.vis, [np.int32(tr) for tr in self.tracks], False, (0, 255, 0)) - + def calc_motion(self): vectors = self.tracks @@ -167,52 +189,53 @@ def calc_motion(self): vectors_t.append(vect[-2]) vectors_t.append(vect[-1]) avg_delta_x += (vect[-1][0] - vect[-2][0]) - + vectors_t = vectors_t[:min(len(vectors_t), 20)] #max 10 keypoints #avg_delta_x_t = 0.0 - if len(vectors_t) > 0: - vectors_t = image.Image.transform(vectors_t) + if vectors_t: + vectors_t = image.Image.transform(vectors_t, self.transform) for v in vectors_t.reshape(-1, 2, 2): avg_delta_y += (v[1][1] - v[0][1]) #avg_delta_x_t += v[1][0] - v[0][0] #avg_delta_x_t = avg_delta_x_t / (vectors_t.shape[0] / 2) #for v in vectors_t.reshape(-1, 2, 2): #if abs(v[1][0] - v[0][0] - avg_delta_x_t) > 2: - #print "this is an obstacle: ", str(v[1]), " delta_x: ", v[1][0] - v[0][0] - - if count > 0: + #print "this is an obstacle: ", str(v[1]), " delta_x: ", v[1][0] - v[0][0] + + if count > 0: avg_delta_x = (avg_delta_x / count) avg_delta_y = (avg_delta_y / (vectors_t.shape[0] / 2)) - - self.delta_angle -= (avg_delta_x * PI_CAM_FOV_H_DEG ) / IMAGE_WIDTH - self.delta_dist += (avg_delta_y * PI_CAM_FOV_V_CM) / IMAGE_HEIGHT + + self.delta_angle -= (avg_delta_x * PI_CAM_FOV_H_DEG) / self.image_width + self.delta_dist += (avg_delta_y * PI_CAM_FOV_V_CM) / self.image_heigth #print "count: ", count, "delta_a: ", self.delta_angle, " avg_delta_x: ", avg_delta_x, " delta_y: ", self.delta_dist, " avg_delta_y: ", avg_delta_y #cv2.line(self.vis, (int(80+deltaAngle),20), (80,20), (0, 0, 255)) - #cv2.putText(self.vis, "delta: " + str(int((self.deltaAngle*53.0)/160.0)) + " avg_delta: " + str(int(((avg_delta_x*53.0)/160.0))), (0,20), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 255)) + #cv2.putText(self.vis, "delta: " + str(int((self.deltaAngle*53.0)/160.0)) + " avg_delta: " + str(int(((avg_delta_x*53.0)/160.0))), + #(0,20), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 255)) + return self.delta_angle, self.delta_dist def bot_turn(self, target_angle, delta_angle): run = True sign = (target_angle - delta_angle) / abs(target_angle - delta_angle) - logging.info( "abs delta: " + str(abs(target_angle - delta_angle)) + " sign delta: " + str(sign) ) + logging.info("abs delta: %s sign delta: %s", str(abs(target_angle - delta_angle)), str(sign)) for p_a in self.power_angles: - if abs(target_angle - delta_angle) > p_a[0] and self.running: - #print "pow: ", p_a[1][0], " duration: ", p_a[1][1] - self.bot.motor_control(sign * p_a[1][0], -1 * sign * p_a[1][0], p_a[1][1]) - run = p_a[1][0] > 0 #stopped - break - + if abs(target_angle - delta_angle) > p_a[0] and self.running: + #print "pow: ", p_a[1][0], " duration: ", p_a[1][1] + self.bot.motor_control(sign * p_a[1][0], -1 * sign * p_a[1][0], p_a[1][1]) + run = p_a[1][0] > 0 #stopped + break + return run - + def bot_move(self, target_dist, delta_dist, delta_angle): base_power = 100 * (target_dist/abs(target_dist)) self.delta_power += (delta_angle * 0.01) - logging.info("base power: " + str(base_power) + " delta power: " + str(self.delta_power) + " delta_dist: " + str(delta_dist) + " target_dist: " + str(target_dist)) + logging.info("base power: %s delta power: %s delta_dist: %s target_dist: %s", str(base_power), str(self.delta_power), str(delta_dist), str(target_dist)) if abs(delta_dist) < abs(target_dist): - self.bot.motor_control(min(max(base_power-self.delta_power,-100),100), min(max(base_power+self.delta_power,-100),100), -1) + self.bot.motor_control(min(max(base_power - self.delta_power, -100), 100), min(max(base_power + self.delta_power, -100), 100), -1) else: self.bot.stop() return abs(delta_dist) < abs(target_dist) - diff --git a/coderbot/music.py b/coderbot/music.py new file mode 100644 index 00000000..0544b468 --- /dev/null +++ b/coderbot/music.py @@ -0,0 +1,152 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# MUSICAL EXTENTION for CoderBot +# This extention is develop by: +# Michele Carbonera - miki_992@hotmail.it - m.carbonera@campus.unimib.it - michele.carbonera@unimib.it +# Antonino Tramontana - a.tramontana1@campus.unimib.it +# Copyright (C) 2020 +############################################################################ + +import os +import sox +import time + +class Music: + _instance = None + managerPackage = None + + noteDict = { + 'C2': -7.0, 'D2' : -5.0, 'E2' : -3.0, 'F2' : -2.0, 'F#2' : -1.0, 'G2' : 0.0, + 'A2' : 2.0, 'Bb2' : 3.0, 'B2' : 4.0, 'C3' : 5.0, 'D3' : 7.0, 'E3' : 9.0, + 'F3' : 10.0, 'G3' : 12.0 + } + + + @classmethod + def get_instance(cls,managerPackage): + if cls._instance is None: + cls._instance = Music(managerPackage) + return cls._instance + + def __init__(self,managerPackage): + + #os.putenv('AUDIODRIVER', 'alsa') + #os.putenv('AUDIODEV', 'hw:1,0') + self.managerPackage = managerPackage + print("We have create a class: MUSICAL") + + def test(self): + tfm = sox.Transformer() + tfm.preview('cat.wav') + tfm.build('cat.wav', 'outMusicDemo.wav') + + #play a pause + # @param duration: duration of the pause in seconds + def play_pause(self, duration): + duration = float(duration) + time.sleep(duration) + + #play a given note for a given instrument + # @param instrument: name of the instrument to be used + # @param note: name of the note in the following format "A2" + # @para alteration: if it is a diesis or a bemolle + # @param time: duration of the note in seconds + def play_note(self, note, instrument='piano', alteration='none', duration=1.0): + print(note) + tfm = sox.Transformer() + + duration = float(duration) + + alt = 0.0 + if alteration == 'bmolle': + alt = -1.0 + elif alteration == 'diesis': + alt = 1.0 + + if note in self.noteDict : + shift = self.noteDict[note]+ alt + else: + print('note not exist') + return + + tfm.pitch(shift, quick=False) + tfm.trim(0.0, end_time=0.5*duration) + if self.managerPackage.isPackageAvailable(instrument): + tfm.preview('./sounds/notes/' + instrument + '/audio.wav') + else: + print("no instrument:"+str(instrument)+" present in this coderbot!") + + def play_animal(self, instrument, note='G2', alteration='none', duration=1.0): + tfm = sox.Transformer() + + duration = float(duration) + + alt = 0.0 + if alteration == 'bmolle': + alt = -1.0 + elif alteration == 'diesis': + alt = 1.0 + + if note == 'C2': + shift = -7.0 + alt + elif note == 'D2': + shift = -5.0 + alt + elif note == 'E2': + shift = -3.0 + alt + elif note == 'F2': + shift = -2.0 + alt + elif note == 'F#2': + shift = -1.0 + alt + elif note == 'G2': + shift = 0.0 + alt + elif note == 'A2': + shift = 2.0 + alt + elif note == 'Bb2': + shift = 3.0 + alt + elif note == 'B2': + shift = 4.0 + alt + elif note == 'C3': + shift = 5.0 + alt + elif note == 'D3': + shift = 7.0 + alt + elif note == 'E3': + shift = 9.0 + alt + elif note == 'F3': + shift = 10.0 + alt + elif note == 'G3': + shift = 12.0 + alt + + if note in self.noteDict : + shift = self.noteDict[note]+ alt + else: + print('note not exist') + return + + if self.managerPackage.isPackageAvailable(instrument): + tfm.preview('./sounds/notes/' + instrument + '/audio.wav') + else: + print("no animal verse:"+str(instrument)+" present in this coderbot!") + return + tfm.pitch(shift, quick=False) + tfm.trim(0.0, end_time=0.5*duration) + #tfm.stretch(time, window=20) + tfm.preview('./sounds/notes/' + instrument + '/audio.wav') diff --git a/coderbot/musicPackages.py b/coderbot/musicPackages.py new file mode 100644 index 00000000..e671b7e7 --- /dev/null +++ b/coderbot/musicPackages.py @@ -0,0 +1,218 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# MUSICAL EXTENTION for CoderBot +# This extention is develop by: +# Michele Carbonera - miki_992@hotmail.it - m.carbonera@campus.unimib.it - michele.carbonera@unimib.it +# Antonino Tramontana - a.tramontana1@campus.unimib.it +# Copyright (C) 2020 +############################################################################ + +import json +import os +import logging +import copy + +class MusicPackage: + + def __init__(self, nameID, category, name_IT, name_EN, version, date): + self.nameID = nameID + self.category = category + self.name_IT = name_IT + self.name_EN = name_EN + self.version = version + self.date = date + self.interfaces = list() + + def getNameID(self): + return self.nameID + + def getCategory(self): + return self.category + + def getNameIT(self): + return self.name_IT + + def getNameEN(self): + return self.name_EN + + def getVersion(self): + return self.version + + def getDate(self): + return self.date + + def getInterfaces(self): + return self.interfaces + + def addInterface(self, musicPackageInterface): + self.interfaces.append(musicPackageInterface) + +class MusicPackageInterface: + + def __init__(self,interfaceName,available,icon): + self.interfaceName = interfaceName + self.available = available + self.icon = icon + + def getInterfaceName(self): + return self.interfaceName + + def getAvailable(self): + return self.available + + def getIcon(self): + return self.icon + +class MusicPackageManager: + _instance = None + + @classmethod + def get_instance(cls): + if cls._instance is None: + cls._instance = MusicPackageManager() + return cls._instance + + def __init__(self): + self.packages = dict() + with open('./sounds/notes/music_package.json') as json_file: + data = json.load(json_file) + for p in data['packages']: + + package = data['packages'][p] + mp = MusicPackage(p,package['category'],package['name_IT'],package['name_EN'],package['version'],package['date']) + for i in package['interface']: + interfaceItem = package['interface'][i] + mpi = MusicPackageInterface(i,interfaceItem['available'],interfaceItem['icon']) + mp.addInterface(mpi) + + if p not in self.packages: + self.packages[p] = mp + + def listPackages(self): + packages_serializable = dict() + for name, package in self.packages.items(): + package_copy = copy.deepcopy(package) + packages_serializable[name] = package_copy.__dict__ + packages_serializable[name]['interfaces'] = [] + for i in package.interfaces: + packages_serializable[name]['interfaces'].append(i.__dict__) + return packages_serializable + + def updatePackages(self): + newdict = { 'packages': {} } + for element in self.packages: + nameID = self.packages[element].getNameID() + newdict['packages'][nameID] = { } + newdict['packages'][nameID]['category']= self.packages[element].getCategory() + newdict['packages'][nameID]['name_IT']= self.packages[element].getNameIT() + newdict['packages'][nameID]['name_EN']= self.packages[element].getNameEN() + newdict['packages'][nameID]['version']= self.packages[element].getVersion() + newdict['packages'][nameID]['date']= self.packages[element].getDate() + newdict['packages'][nameID]['interface']= {'base':{}, 'intermediate':{}, 'advanced': {}} + newdict['packages'][nameID]['interface']['base']['available'] = self.packages[element].getInterfaces()[0].getAvailable() + newdict['packages'][nameID]['interface']['base']['icon'] = self.packages[element].getInterfaces()[0].getIcon() + newdict['packages'][nameID]['interface']['intermediate']['available'] = self.packages[element].getInterfaces()[1].getAvailable() + newdict['packages'][nameID]['interface']['intermediate']['icon'] = self.packages[element].getInterfaces()[1].getIcon() + newdict['packages'][nameID]['interface']['advanced']['available'] = self.packages[element].getInterfaces()[2].getAvailable() + newdict['packages'][nameID]['interface']['advanced']['icon'] = self.packages[element].getInterfaces()[2].getIcon() + + #json_packages = json.dumps(newdict) + with open('sounds/notes/music_package.json', 'w', encoding='utf-8') as json_file: + json.dump(newdict, json_file, ensure_ascii=False, indent=4) + + + def deletePackage(self, packageName): + logging.info("packageName: " + packageName) + if packageName in self.packages: + del self.packages[packageName] + self.updatePackages() + else: + logging.error("errore, il pacchetto " + packageName + " non è stato trovato") + return 2 + + if os.path.exists('./sounds/notes/' + packageName): + os.system('rm -rf ./sounds/notes/' + packageName) + return 1 + + + def verifyVersion(self, packageName, version): + logging.info("verifica pacchetto") + #newversionList = version.split('.') + if packageName not in self.packages: + return True + + newVersionList = [int(x) for x in version.split('.')] + #for i in ragen(0,len(newversionList) -1): + #newversionList[i] = int(newLversionList[i]) + + oldVersion = self.packages[packageName].getVersion() + oldVersionList = [int(x) for x in oldVersion.split('.')] + + for i in range(0,len(newVersionList) -1): + if(newVersionList[i] > oldVersionList[i] ): + return True + elif(newVersionList[i] < oldVersionList[i] ): + return False + + return False + + def addPackage(self, filename): + pkgnames = filename.split('_') + version = pkgnames[1].replace('.zip', '') + logging.info("Music Package version: " + version) + pkgname = pkgnames[0] + pkgpath = './sounds/notes/' + pkgname + if not self.verifyVersion(pkgname, version): + if (version == self.packages[pkgname].getVersion()): + logging.error("errore, il pacchetto " + pkgname + " ha versione identica a quello attualmente installato") + raise ValueError() + else: + logging.info("errore, il pacchetto " + pkgname + " ha versione precendente a quello attualmente installato") + raise ValueError() + else: + os.system('unzip -o ' + '/tmp/' + filename + " -d /tmp") + os.system('mkdir ' + pkgpath) + os.system('mv /tmp/' + pkgname + "/" + 'audio.wav ' + pkgpath + '/') + + with open('/tmp/' + pkgname + '/' + pkgname + '.json') as json_file: + logging.info("adding " + pkgname + " package") + data = json.load(json_file) + for p in data['packages']: + package = data['packages'][p] + mp = MusicPackage(p,package['category'],package['name_IT'],package['name_EN'],package['version'],package['date']) + for i in package['interface']: + interfaceItem = package['interface'][i] + mpi = MusicPackageInterface(i,interfaceItem['available'],interfaceItem['icon']) + mp.addInterface(mpi) + + self.packages[p] = mp + + self.updatePackages() + + os.system('rm -rf /tmp/' + pkgname) + + + def isPackageAvailable(self,namePackage): + if namePackage in self.packages: + return True + else: + return False diff --git a/coderbot/program.py b/coderbot/program.py new file mode 100644 index 00000000..bc66fc3e --- /dev/null +++ b/coderbot/program.py @@ -0,0 +1,250 @@ +############################################################################ +# CoderBot, a didactical programmable robot. +# Copyright (C) 2014, 2015 Roberto Previtera +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +############################################################################ + +import os +import threading +import json +import shutil +import logging + +import math +from tinydb import TinyDB, Query +from threading import Lock + +import coderbot +import camera +import motion +import config +import audio +import event +import music +import musicPackages +from hw.atmega328p import ATMega328 + +PROGRAM_PATH = "./data/" +PROGRAM_PREFIX = "program_" +PROGRAM_SUFFIX = ".json" +PROGRAMS_DB = "data/programs.json" +PROGRAMS_PATH_DEFAULTS = "defaults/programs/" + +musicPackageManager = musicPackages.MusicPackageManager.get_instance() + +def get_cam(): + return camera.Camera.get_instance() + +def get_bot(): + return coderbot.CoderBot.get_instance() + +def get_motion(): + return motion.Motion.get_instance() + +def get_audio(): + return audio.Audio.get_instance() + +def get_prog_eng(): + return ProgramEngine.get_instance() + +def get_event(): + return event.EventManager.get_instance() + +def get_music(): + return music.Music.get_instance(musicPackageManager) + +def get_atmega(): + return ATMega328.get_instance() + +class ProgramEngine: + + # pylint: disable=exec-used + + _instance = None + + def __init__(self): + self._program = None + self._log = "" + self._programs = TinyDB(PROGRAMS_DB) + # initialise DB from default programs + query = Query() + self.lock = Lock() + for dirname, dirnames, filenames, in os.walk(PROGRAMS_PATH_DEFAULTS): + dirnames + for filename in filenames: + if PROGRAM_PREFIX in filename: + program_name = filename[len(PROGRAM_PREFIX):-len(PROGRAM_SUFFIX)] + if self._programs.search(query.name == program_name) == []: + logging.info("adding program %s in path %s as default %r", program_name, dirname, ("default" in dirname)) + with open(os.path.join(dirname, filename), "r") as f: + program_dict = json.load(f) + program_dict["default"] = "default" in dirname + program = Program.from_dict(program_dict) + self.save(program) + + @classmethod + def get_instance(cls): + if not cls._instance: + cls._instance = ProgramEngine() + return cls._instance + + def prog_list(self): + return self._programs.all() + + def save(self, program): + with self.lock: + query = Query() + self._program = program + program_db_entry = self._program.as_dict() + if self._programs.search(query.name == program.name) != []: + self._programs.update(program_db_entry, query.name == program.name) + else: + self._programs.insert(program_db_entry) + + def load(self, name): + with self.lock: + query = Query() + program_db_entries = self._programs.search(query.name == name) + if len(program_db_entries) > 0: + prog_db_entry = program_db_entries[0] + logging.debug(prog_db_entry) + self._program = Program.from_dict(prog_db_entry) + return self._program + return None + + def delete(self, name): + with self.lock: + query = Query() + program_db_entries = self._programs.search(query.name == name) + self._programs.remove(query.name == name) + + def create(self, name, code): + self._program = Program(name, code) + return self._program + + def is_running(self, name): + return self._program.is_running() and self._program.name == name + + def check_end(self): + return self._program.check_end() + + def log(self, text): + self._log += text + "\n" + + def get_log(self): + return self._log + + def set_log(self, log): + self._log = "" + + def get_current_program(self): + return self._program + +class Program: + _running = False + + @property + def dom_code(self): + return self._dom_code + + def __init__(self, name, code=None, dom_code=None, default=False): + self._thread = None + self.name = name + self._dom_code = dom_code + self._code = code + self._default = default + + def execute(self, options={}): + if self._running: + raise RuntimeError('already running') + + ProgramEngine.get_instance().set_log("") + self._running = True + try: + self._thread = threading.Thread(target=self.run, args=(options,)) + self._thread.start() + except RuntimeError as re: + logging.error("RuntimeError: %s", str(re)) + except Exception as e: + logging.error("Exception: %s", str(e)) + + return "ok" + + def stop(self): + if self._running: + self._running = False + self._thread.join() + + def check_end(self): + if self._running is False: + raise RuntimeError('stop requested') + return None + + def is_running(self): + return self._running + + def is_default(self): + return self._default + + def run(self, *args): + options = args[0] + try: + program = self + try: + if options.get("autoRecVideo") == True: + get_cam().video_rec(program.name.replace(" ", "_")) + logging.debug("starting video") + except Exception as e: + logging.error("Camera not available: " + str(e)) + + self._log = "" #clear log + imports = "import json\n" + code = imports + self._code + env = globals() + logging.debug("** start code **\n"+str(code)+ "\n** end code **") + exec(code, env, env) + except RuntimeError as re: + logging.info("quit: %s", str(re)) + get_prog_eng().log(str(re)) + except Exception as e: + logging.info("quit: %s", str(e)) + get_prog_eng().log(str(e)) + finally: + try: + get_event().wait_event_generators() + get_event().unregister_listeners() + get_event().unregister_publishers() + except Exception as e: + logging.error("error polishing event system: %s", str(e)) + try: + get_bot().stop() + get_cam().video_stop() #if video is running, stop it + get_cam().set_text("") #clear overlay text (if any) + get_motion().stop() + except Exception: + logging.error("Camera not available") + self._running = False + + + def as_dict(self): + return {'name': self.name, + 'dom_code': self._dom_code, + 'code': self._code, + 'default': self._default} + + @classmethod + def from_dict(cls, amap): + return Program(name=amap['name'], dom_code=amap['dom_code'], code=amap['code'], default=amap.get('default', False)) diff --git a/coderbot/rotary_encoder/motorencoder.py b/coderbot/rotary_encoder/motorencoder.py new file mode 100644 index 00000000..2b2ad82a --- /dev/null +++ b/coderbot/rotary_encoder/motorencoder.py @@ -0,0 +1,183 @@ +import pigpio +import threading +from time import sleep, time + +from rotary_encoder.rotarydecoder import RotaryDecoder + + +class MotorEncoder: + """ Class that handles rotary decoder motors modelisation + + The support class RotaryDecoder decodes mechanical rotary encoder + pulses. See the file for more. + + Every movement method must acquire lock in order not to have + concurrency problems on GPIO READ/WRITE """ + + # default constructor + def __init__(self, pi, enable_pin, forward_pin, backward_pin, feedback_pin_A, feedback_pin_B): + # setting pin variables + self._pi = pi + self._enable_pin = enable_pin + self._forward_pin = forward_pin + self._backward_pin = backward_pin + self._feedback_pin_A = feedback_pin_A + self._feedback_pin_B = feedback_pin_B + + # setting movement variables + self._direction = 0 + self._distance_per_tick = 0.06 #(mm) + self._ticks = 0 + self._power = 0 + self._encoder_speed = 0 + self._is_moving = False + + # quadrature encoder variables + self._start_timer = 0 + self._current_timer = 0 + self._ticks_threshold = 100 + self._ticks_counter = 0 + + # other + self._encoder_lock = threading.RLock() + self._rotary_decoder = RotaryDecoder(pi, feedback_pin_A, feedback_pin_B, self.rotary_callback) + + # GETTERS + # ticks + def ticks(self): + return self._ticks + + # distance + def distance(self): + #return self._distance + return self._ticks * self._distance_per_tick + + # direction + def direction(self): + return self._direction + + # speed + def speed(self): + return self._encoder_speed + + # is_moving + def is_moving(self): + return self._is_moving + + # MOVEMENT + """ The stop function acquires the lock to operate on motor + then writes a 0 on movement pins to stop the motor + and releases the lock afterwards + Motor speed on range 0 - 100 already set on PWM_set_range(100) + if a time_elapse parameter value is provided, motion is locked + for a certain amount of time """ + + def control(self, power=100.0, time_elapse=0): + # resetting distance and ticks before new movement + self._distance = 0 # resetting distance travelled + self._ticks = 0 # resetting ticks + + self._direction = 1 if power > 0 else -1 # setting direction according to speed + self._power = abs(power) # setting current power + + if self._enable_pin is not None: + self._pi.write(self._enable_pin, True) # enabling motors + + # going forward + if (self._direction == 1): + self._pi.write(self._backward_pin, 0) + self._pi.set_PWM_dutycycle(self._forward_pin, self._power) + # going bacakward + else: + self._pi.write(self._forward_pin, 0) + self._pi.set_PWM_dutycycle(self._backward_pin, self._power) + + self._is_moving = True + + # movement time elapse + if (time_elapse > 0): + sleep(time_elapse) + self.stop() + + """ The stop function acquires the lock to operate on motor + then writes a 0 on movement pins to stop the motor + and releases the lock afterwards """ + + def stop(self): + # stopping motor + self._pi.write(self._backward_pin, 0) + self._pi.write(self._forward_pin, 0) + + # resetting wheel state + self.reset_state() + + # stop auxiliary function, resets wheel state + def reset_state(self): + # returning state variables to consistent state + # after stopping, values of distance and ticks remains until + # next movement + self._ticks = 0 # resetting ticks + self._power = 0 # resetting PWM power + self._encoder_speed = 0 # resetting encoder speed + self._direction = 0 # resetting direction + self._start_timer = 0 + self._current_timer = 0 + self._ticks_counter = 0 + self._is_moving = False # resetting moving flag + + # adjust power for velocity control loop + def adjust_power(self, power): + self._power = power # setting current power + + # adjusting power forward + if (self._direction == 1): + self._pi.set_PWM_dutycycle(self._forward_pin, abs(power)) + # adjusting power bacakward + else: + self._pi.set_PWM_dutycycle(self._backward_pin, abs(power)) + + # CALLBACK + """ The callback function rotary_callback is called on EITHER_EDGE by the + rotary_decoder with a parameter value of 1 (1 new tick) + - Gearbox ratio: 120:1 (1 wheel revolution = 120 motor revolution) + - Encoder ratio: 16:1 encoder ticks for 1 motor revolution + - 1 wheel revolution = 120 * 16 = 1920 ticks + - R = 32.5mm + - 1 wheel revolution = 2πR = 2 * π * 32.5mm = 204.2mm + - 3840 ticks = 204.2mm + - 1 tick = 0.053mm + - 1 tick : 0.053mm = x : 1000mm -> x = 18867 ticks approximately + So 0.053 is the ticks->distance(mm) conversion coefficient + The callback function calculates current velocity by taking groups of + ticks_threshold ticks""" + # callback function + def rotary_callback(self, tick): + self._encoder_lock.acquire() + + # taking groups of n ticks each + if (self._ticks_counter == 0): + self._start_timer = tick # clock started + elif (abs(self._ticks_counter) == self._ticks_threshold): + self._current_timer = tick + elapse = (self._current_timer - self._start_timer) / 1000000.0 # calculating time elapse + # calculating current speed + self._encoder_speed = self._ticks_threshold * self._distance_per_tick / elapse # (mm/s) + + self._ticks += 1 # updating ticks + + if(abs(self._ticks_counter) < self._ticks_threshold): + self._ticks_counter += 1 + else: + self._start_timer = tick # clock started + self._ticks_counter = 0 + + # updating ticks counter using module + # 0, 1, 2, ... 8, 9, 10, 0, 1, 2, ... + # not ideal, module on ticks counter not precise, may miss an interrupt + #self._ticks_counter += 1 % (self._ticks_threshold + 1) + + self._encoder_lock.release() # releasing lock + + # callback cancelling + def cancel_callback(self): + self._rotary_decoder.cancel() diff --git a/coderbot/rotary_encoder/rotarydecoder.py b/coderbot/rotary_encoder/rotarydecoder.py new file mode 100644 index 00000000..99fd8766 --- /dev/null +++ b/coderbot/rotary_encoder/rotarydecoder.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python + +import pigpio +import threading + +class RotaryDecoder: + + """ Class to decode mechanical rotary encoder pulses """ + + def __init__(self, pi, feedback_pin_A, feedback_pin_B, callback): + + self._pi = pi + self._feedback_pin_A = feedback_pin_A # encoder feedback pin A + self._feedback_pin_B = feedback_pin_B # encoder feedback pin B + self._callback = callback # callback function on event + self._direction = 0 # direction, forward = 1, backward = -1, steady = 0 + + self._levelA = 0 # value of encoder feedback pin A + self._levelB = 0 # value of encoder feedback pin B + + self._lock = threading.RLock() + + # setting up GPIO + self._pi.set_mode(feedback_pin_A, pigpio.INPUT) + self._pi.set_mode(feedback_pin_B, pigpio.INPUT) + self._pi.set_pull_up_down(feedback_pin_A, pigpio.PUD_UP) + self._pi.set_pull_up_down(feedback_pin_B, pigpio.PUD_UP) + + # callback function on EITHER_EDGE for each pin + self._callback_triggerA = self._pi.callback(feedback_pin_A, pigpio.EITHER_EDGE, self._pulseA) + self._callback_triggerB = self._pi.callback(feedback_pin_B, pigpio.EITHER_EDGE, self._pulseA) + + self._lastGpio = None + + """ pulse is the callback function on EITHER_EDGE + We have two feedback input from pin A and B (two train waves) + it returns a 1 if the square waves have A leading B because we're moving forward + It returns a -1 if the square waves have B leading A because we're moving backwards + In either case, A is staggered from B by (+-)pi/2 radiants + Note: level = 0 falling edge + 1 raising edge + 2 from watchdog + + +---------+ +---------+ 0 + | | | | + B | | | | + | | | | + +---------+ +---------+ +----- 1 # B leading A + +---------+ +---------+ 0 # forward + | | | | + A | | | | + | | | | + ----+ +---------+ +----------+ 1 + + + +---------+ +---------+ 0 + | | | | + A | | | | + | | | | + ----+ +---------+ +----------+ 1 # A leading B + +---------+ +---------+ 0 # backward + | | | | + B | | | | + | | | | + +---------+ +---------+ +----- 1 + """ + def _pulse(self, gpio, level, tick): + self._lock.acquire() + # interrupt comes from pin A + if (gpio == self._feedback_pin_A): + self._levelA = level # set level of squared wave (0, 1) on A + # interrupt comes from pin B + else: + self._levelB = level # set level of squared wave (0, 1) on B + + if (gpio != self._lastGpio): # debounce + self._lastGpio = gpio + + # forward (A leading B) + if (gpio == self._feedback_pin_A and + ((level == 1 and self._levelB == 0) or + (level == 0 and self._levelB == 1))): + self._direction = 1 # forward + # backward (B leading A) + elif (gpio == self._feedback_pin_B and + ((level == 1 and self._levelA == 0) or + (level == 0 and self._levelA == 1))): + self._direction = -1 # forward + + direction = self._direction + self._lock.release() + self._callback(direction) + + def _pulseA(self, gpio, level, tick): + self._callback(tick) + + def cancel(self): + + """ + Cancel the rotary encoder decoder callbacks. + """ + self._callback_triggerA.cancel() + self._callback_triggerB.cancel() + + diff --git a/coderbot/rotary_encoder/wheelsaxel.py b/coderbot/rotary_encoder/wheelsaxel.py new file mode 100644 index 00000000..abfef001 --- /dev/null +++ b/coderbot/rotary_encoder/wheelsaxel.py @@ -0,0 +1,319 @@ +import pigpio +import threading +from time import sleep, time +import logging + +from rotary_encoder.motorencoder import MotorEncoder + +class WheelsAxel: + """ Class that handles both motor encoders, left and right + + This class works like a wheels axle, coordinating left and right + wheels at the same time + + It also tries to handle the inconsistent tension on wheels + that makes one wheel go slower than the other """ + + def __init__(self, pi, enable_pin, + left_forward_pin, left_backward_pin, left_encoder_feedback_pin_A, left_encoder_feedback_pin_B, + right_forward_pin, right_backward_pin, right_encoder_feedback_pin_A, right_encoder_feedback_pin_B, + pid_params): + + # state variables + self._is_moving = False + + # left motor + self._left_motor = MotorEncoder(pi, + enable_pin, + left_forward_pin, + left_backward_pin, + left_encoder_feedback_pin_A, + left_encoder_feedback_pin_B) + # right motor + self._right_motor = MotorEncoder(pi, + enable_pin, + right_backward_pin, + right_forward_pin, + right_encoder_feedback_pin_A, + right_encoder_feedback_pin_B) + + self.pid_kp = pid_params[0] + self.pid_kd = pid_params[1] + self.pid_ki = pid_params[2] + self.pid_max_speed = pid_params[3] + self.pid_sample_time = pid_params[4] + + # other + #self._wheelsAxle_lock = threading.RLock() # race condition lock + + # STATE GETTERS + """ Distance and speed are calculated by a mean of the feedback + from the two motors """ + + def is_moving(self): + return self._left_motor.is_moving() or self._right_motor.is_moving() + + # distance + def distance(self): + l_dist = self._left_motor.distance() + r_dist = self._right_motor.distance() + return (l_dist + r_dist) * 0.5 + + #speed + def speed(self): + l_speed = self._left_motor.speed() + r_speed = self._right_motor.speed() + return (l_speed + r_speed) * 0.5 + + #direction + def direction(self): + l_dir = self._left_motor.direction() + r_dir = self._right_motor.direction() + if(l_dir == r_dir): + return l_dir + else: + return 0 + + # MOVEMENT + """ Movement wrapper method + if time is specified and distance is not, control_time is called + if distance is specified and time is not, control_distance is called + if both distance and time are specified, control_velocity is called """ + def control(self, power_left=100, power_right=100, time_elapse=None, target_distance=None): + if(time_elapse is not None and target_distance is None): # time + self.control_time(power_left, power_right, time_elapse) + elif(time_elapse is None and target_distance is not None): # distance + self.control_distance(power_left, power_right, target_distance) + else: # velocity + self.control_velocity(time_elapse, target_distance) + + """ Motor time control allows the motors + to run for a certain amount of time """ + def control_time(self, power_left=100, power_right=100, time_elapse=-1): + if time_elapse > 0: + return self.control_time_encoder(power_left, power_right, time_elapse) + + # applying tension to motors + self._left_motor.control(power_left, -1) + self._right_motor.control(power_right, -1) + self._is_moving = True + + # moving for desired time + # fixed for direct control that uses time_elapse -1 and stops manually + if(time_elapse > 0): + sleep(time_elapse) + self.stop() + + """ Motor time control allows the motors + to run for a certain amount of time """ + def control_time_encoder(self, power_left=100, power_right=100, time_elapse=-1): + #self._wheelsAxle_lock.acquire() # wheelsAxle lock acquire + self._is_moving = True + + # get desired direction from power, then normalize on power > 0 + left_direction = power_left/abs(power_left) + right_direction = power_right/abs(power_right) + power_left = abs(power_left) + power_right = abs(power_right) + + self._left_motor.reset_state() + self._right_motor.reset_state() + + # applying tension to motors + self._left_motor.control(power_left * left_direction) + self._right_motor.control(power_right * right_direction) + + #PID parameters + # assuming that power_right is equal to power_left and that coderbot + # moves at 11.5mm/s at full PWM duty cycle + + target_speed_left = (self.pid_max_speed / 100) * power_left #velocity [mm/s] + target_speed_right = (self.pid_max_speed / 100) * power_right # velocity [mm/s] + + left_derivative_error = 0 + right_derivative_error = 0 + left_integral_error = 0 + right_integral_error = 0 + left_prev_error = 0 + right_prev_error = 0 + time_init = time() + + # moving for certaing amount of distance + logging.info("moving? " + str(self._is_moving) + " distance: " + str(self.distance()) + " target: " + str(time_elapse)) + while(time() - time_init < time_elapse and self._is_moving == True): + # PI controller + logging.debug("speed.left: " + str(self._left_motor.speed()) + " speed.right: " + str(self._right_motor.speed())) + if(abs(self._left_motor.speed()) > 10 and abs(self._right_motor.speed()) > 10): + # relative error + left_error = float(target_speed_left - self._left_motor.speed()) / target_speed_left + right_error = float(target_speed_right - self._right_motor.speed()) / target_speed_right + + left_correction = (left_error * self.pid_kp) + (left_derivative_error * self.pid_kd) + (left_integral_error * self.pid_ki) + right_correction = (right_error * self.pid_kp) + (right_derivative_error * self.pid_kd) + (right_integral_error * self.pid_ki) + + corrected_power_left = power_left + (left_correction * power_left) + corrected_power_right = power_right + (right_correction * power_right) + + #print("LEFT correction: %f" % (left_error * KP + left_derivative_error * KD + left_integral_error * KI)) + #print("RIGHT correction: %f" % (right_error * KP + right_derivative_error * KD + right_integral_error * KI)) + + # conrispondent new power + power_left_norm = max(min(corrected_power_left, power_left), 0) + power_right_norm = max(min(corrected_power_right, power_right), 0) + + logging.debug("ls:" + str(int(self._left_motor.speed())) + " rs: " + str(int(self._right_motor.speed())) + + " le:" + str(left_error) + " re: " + str(right_error) + + " ld:" + str(left_derivative_error) + " rd: " + str(right_derivative_error) + + " li:" + str(left_integral_error) + " ri: " + str(right_integral_error) + + " lc: " + str(int(left_correction)) + " rc: " + str(int(right_correction)) + + " lp: " + str(int(power_left_norm)) + " rp: " + str(int(power_right_norm))) + + # adjusting power on each motors + self._left_motor.adjust_power(power_left_norm * left_direction ) + self._right_motor.adjust_power(power_right_norm * right_direction) + + left_derivative_error = (left_error - left_prev_error) / self.pid_sample_time + right_derivative_error = (right_error - right_prev_error) / self.pid_sample_time + left_integral_error += (left_error * self.pid_sample_time) + right_integral_error += (right_error * self.pid_sample_time) + + left_prev_error = left_error + right_prev_error = right_error + + # checking each SAMPLETIME seconds + sleep(self.pid_sample_time) + + logging.info("control_distance.stop, target elapse: " + str(time_elapse) + + " actual distance: " + str(self.distance()) + + " l ticks: " + str(self._left_motor.ticks()) + + " r ticks: " + str(self._right_motor.ticks())) + # robot arrived + self.stop() + + """ Motor distance control allows the motors + to run for a certain amount of distance (mm) """ + def control_distance(self, power_left=100, power_right=100, target_distance=0): + #self._wheelsAxle_lock.acquire() # wheelsAxle lock acquire + self._is_moving = True + + # get desired direction from power, then normalize on power > 0 + left_direction = power_left/abs(power_left) + right_direction = power_right/abs(power_right) + power_left = abs(power_left) + power_right = abs(power_right) + + self._left_motor.reset_state() + self._right_motor.reset_state() + + # applying tension to motors + self._left_motor.control(power_left * left_direction) + self._right_motor.control(power_right * right_direction) + + #PID parameters + # assuming that power_right is equal to power_left and that coderbot + # moves at 11.5mm/s at full PWM duty cycle + + target_speed_left = (self.pid_max_speed / 100) * power_left #velocity [mm/s] + target_speed_right = (self.pid_max_speed / 100) * power_right # velocity [mm/s] + + # SOFT RESPONSE + # KP = 0.04 #proportional coefficient + # KD = 0.02 # derivative coefficient + # KI = 0.005 # integral coefficient + + # MEDIUM RESPONSE + # KP = 0.9 # proportional coefficient + # KD = 0.1 # derivative coefficient + # KI = 0.05 # integral coefficient + + # STRONG RESPONSE + # KP = 0.9 # proportional coefficient + # KD = 0.05 # derivative coefficient + # KI = 0.03 # integral coefficient + + left_derivative_error = 0 + right_derivative_error = 0 + left_integral_error = 0 + right_integral_error = 0 + left_prev_error = 0 + right_prev_error = 0 + # moving for certaing amount of distance + logging.info("moving? " + str(self._is_moving) + " distance: " + str(self.distance()) + " target: " + str(target_distance)) + while(abs(self.distance()) < abs(target_distance) and self._is_moving == True): + # PI controller + logging.debug("speed.left: " + str(self._left_motor.speed()) + " speed.right: " + str(self._right_motor.speed())) + if(abs(self._left_motor.speed()) > 10 and abs(self._right_motor.speed()) > 10): + # relative error + left_error = float(target_speed_left - self._left_motor.speed()) / target_speed_left + right_error = float(target_speed_right - self._right_motor.speed()) / target_speed_right + + left_correction = (left_error * self.pid_kp) + (left_derivative_error * self.pid_kd) + (left_integral_error * self.pid_ki) + right_correction = (right_error * self.pid_kp) + (right_derivative_error * self.pid_kd) + (right_integral_error * self.pid_ki) + + corrected_power_left = power_left + (left_correction * power_left) + corrected_power_right = power_right + (right_correction * power_right) + + #print("LEFT correction: %f" % (left_error * KP + left_derivative_error * KD + left_integral_error * KI)) + #print("RIGHT correction: %f" % (right_error * KP + right_derivative_error * KD + right_integral_error * KI)) + + # conrispondent new power + power_left_norm = max(min(corrected_power_left, power_left), 0) + power_right_norm = max(min(corrected_power_right, power_right), 0) + + logging.debug("ls:" + str(int(self._left_motor.speed())) + " rs: " + str(int(self._right_motor.speed())) + + " le:" + str(left_error) + " re: " + str(right_error) + + " ld:" + str(left_derivative_error) + " rd: " + str(right_derivative_error) + + " li:" + str(left_integral_error) + " ri: " + str(right_integral_error) + + " lc: " + str(int(left_correction)) + " rc: " + str(int(right_correction)) + + " lp: " + str(int(power_left_norm)) + " rp: " + str(int(power_right_norm))) + + # adjusting power on each motors + self._left_motor.adjust_power(power_left_norm * left_direction ) + self._right_motor.adjust_power(power_right_norm * right_direction) + + left_derivative_error = (left_error - left_prev_error) / self.pid_sample_time + right_derivative_error = (right_error - right_prev_error) / self.pid_sample_time + left_integral_error += (left_error * self.pid_sample_time) + right_integral_error += (right_error * self.pid_sample_time) + + left_prev_error = left_error + right_prev_error = right_error + + # checking each SAMPLETIME seconds + sleep(self.pid_sample_time) + + logging.info("control_distance.stop, target dist: " + str(target_distance) + + " actual distance: " + str(self.distance()) + + " l ticks: " + str(self._left_motor.ticks()) + + " r ticks: " + str(self._right_motor.ticks())) + # robot arrived + self.stop() + + """ Motor speed control to travel given distance + in given time adjusting power on motors + NOT very intuitive, idea has been postponed""" + def control_velocity(self, time_elapse=0, target_distance=0): + pass + + """ The stop function calls the two stop functions of the two + correspondent motors. + Locks are automatically obtained """ + def stop(self): + # stopping left and right motors + self._left_motor.stop() + self._right_motor.stop() + + # trying to fix distance different than zero after + # wheels has stopped by re-resetting state after 0.5s + + #self._left_motor.reset_state() + #self._right_motor.reset_state() + + # updating state + logging.info("stopping") + self._is_moving = False + + # CALLBACK + def cancel_callback(self): + self._right_motor.cancel_callback() + self._left_motor.cancel_callback() diff --git a/coderbot/runtime_test.py b/coderbot/runtime_test.py new file mode 100644 index 00000000..4a6260a5 --- /dev/null +++ b/coderbot/runtime_test.py @@ -0,0 +1,142 @@ +""" + This file defines base tests for CoderBot + in order to test its functionality + + The function run_test(varargin) lanuches tests + according to required test from the front-end. + e.g. varagrin = ["motor_test", "sonar_test"] + __test_encoder() and __test_sonar() will be launched. + + If something goes wrong a -1 is returned for the correspondent failed test. + If a test passes for correspondent component, a 1 is returned. + If no test was executed on that component, 0 is preserved. +""" +import logging +from coderbot import CoderBot + +# Single components tests + +# encoder motors +def __test_encoder(): + try: + c = CoderBot.get_instance() + # moving both wheels at speed 100 clockwise + logging.info("moving both wheels at speed 100 clockwise") + assert(c.speed() == 0) + c.move(speed=100, elapse=2) + assert(c.distance() != 0) + assert (c.speed() == 0) + + # moving both wheels at speed 40 clockwise + logging.info("moving both wheels at speed 40 clockwise") + assert(c.speed() == 0) + c.move(speed=40, elapse=2) + assert(c.distance() != 0) + assert (c.speed() == 0) + + # moving both wheels at speed 100 counter-clockwise + logging.info("moving both wheels at speed 100 counter-clockwise") + assert(c.speed() == 0) + c.move(speed=-100, elapse=2) + assert(c.distance() != 0) + assert (c.speed() == 0) + + # moving both wheels at speed 40 counter-clockwise + logging.info("moving both wheels at speed 40 counter-clockwise") + assert(c.speed() == 0) + c.move(speed=-40, elapse=2) + assert(c.distance() != 0) + assert (c.speed() == 0) + + # moving forward + logging.info("moving forward") + assert(c.speed() == 0) + c.forward(speed=100, elapse=2) + assert(c.distance() != 0) + assert (c.speed() == 0) + + # moving backwards + logging.info("moving backwards") + assert(c.speed() == 0) + c.backward(speed=100, elapse=2) + assert(c.distance() != 0) + assert (c.speed() == 0) + + # moving forward for 1 meter + logging.info("moving forward for 1 meter") + assert(c.speed() == 0) + c.forward(speed=100, distance=1000) + assert(c.distance() != 0) + assert (c.speed() == 0) + + # moving backwards for 1 meter + logging.info("moving backwards for 1 meter") + assert(c.speed() == 0) + c.backward(speed=100, distance=1000) + assert(c.distance() != 0) + assert (c.speed() == 0) + + # turning left + logging.info("turning left") + assert(c.speed() == 0) + c.left(speed=100, elapse=2) + assert(c.distance() != 0) + assert (c.speed() == 0) + + # turning right + logging.info("turning right") + assert(c.speed() == 0) + c.right(speed=100, elapse=2) + assert(c.distance() != 0) + assert (c.speed() == 0) + + return 1 + except: + return -1 + +# sonar +def __testSonar(): + return 1 + +# speaker +def __test_speaker(): + return 1 + +# OCR +def __test_OCR(): + return 1 + +# add more tests here + +""" Main test function + it launches tests to test single components individually. + A dictionary is returned monitoring the state of the + tests for each component. + Varargin is a list of strings that indicates which test + to run. """ +def run_test(varargin): + # state for each executed test + # 0 = component not tested + # 1 = test passed + # -1 = test failed + tests_state = { + "motors": 0, + "sonar": 0, + "speaker": 0, + "OCR": 0 + # add more tests state here + } + + # running chosen tests + for test in varargin: + if(test == 'motors'): + tests_state[test] = __test_encoder() + elif(test == 'sonar'): + tests_state[test] = __testSonar() + elif (test == 'speaker'): + tests_state[test] = __test_speaker() + elif(test == 'ocr'): + tests_state[test] = __test_OCR() + #add more test cases here + + return tests_state diff --git a/coderbot/sonar.py b/coderbot/sonar.py new file mode 100644 index 00000000..e54f7a19 --- /dev/null +++ b/coderbot/sonar.py @@ -0,0 +1,94 @@ +import time +import pigpio +import logging + +class Sonar: + """ + This class encapsulates a type of acoustic ranger. In particular + the type of ranger with separate trigger and echo pins. + + A pulse on the trigger initiates the sonar ping and shortly + afterwards a sonar pulse is transmitted and the echo pin + goes high. The echo pins stays high until a sonar echo is + received (or the response times-out). The time between + the high and low edges indicates the sonar round trip time. + """ + + MICROSECONDS = 1000000.0 + SOUND_SPEED = 34030.0 + ECHO_TIMEOUT = 0.1 + + def __init__(self, pi, trigger, echo): + """ + The class is instantiated with the Pi to use and the + gpios connected to the trigger and echo pins. + """ + self.pi = pi + self._trig = trigger + self._echo = echo + + self._ping = False + self._high = None + self._time = None + + self._triggered = False + + self._trig_mode = pi.get_mode(self._trig) + self._echo_mode = pi.get_mode(self._echo) + + pi.set_mode(self._trig, pigpio.OUTPUT) + pi.set_mode(self._echo, pigpio.INPUT) + + self._cb = pi.callback(self._trig, pigpio.EITHER_EDGE, self._cbf) + self._cb = pi.callback(self._echo, pigpio.EITHER_EDGE, self._cbf) + + self._inited = True + + def _cbf(self, gpio, level, tick): + if gpio == self._trig and self._triggered == False: + if level == 0: # trigger sent + self._triggered = True + self._high = None + else: + if self._triggered: + if level == 1: + self._high = tick + else: + if self._high is not None: + self._time = tick - self._high + self._high = None + self._ping = True + self._triggered = False + def read(self): + """ + Triggers a reading. The returned reading is the number + of microseconds for the sonar round-trip. + + round trip cms = round trip time / 1000000.0 * 34030 + """ + if self._inited: + self._ping = False + self.pi.gpio_trigger(self._trig) + start = time.time() + while not self._ping: + if (time.time()-start) > self.ECHO_TIMEOUT: + return 20000 + time.sleep(0.001) + return self._time + else: + return None + + def get_distance(self): + time.sleep(0.05) + return round(self.read() / self.MICROSECONDS * self.SOUND_SPEED / 2, 1) # seconds / microseconds * sound speed / 2 (half trip) + + def cancel(self): + """ + Cancels the sonars and returns the gpios to their + original mode. + """ + if self._inited: + self._inited = False + self._cb.cancel() + self.pi.set_mode(self._trig, self._trig_mode) + self.pi.set_mode(self._echo, self._echo_mode) diff --git a/coderbot/v1.yml b/coderbot/v1.yml new file mode 100644 index 00000000..37142724 --- /dev/null +++ b/coderbot/v1.yml @@ -0,0 +1,765 @@ +openapi: "3.0.0" +info: + version: "1.0" + title: OpenAPI 3.0 definition of Coderbot API v3 + +servers: + - url: http://coderbot.local/api/v1 + +# Paths supported by the server application +paths: + /settings: + get: + operationId: "api.loadSettings" + summary: "Load settings" + responses: + 200: + description: "ok" + tags: + - CoderBot configuration + put: + operationId: "api.saveSettings" + summary: "Save settings" + requestBody: + description: Save Settings + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Settings' + responses: + 200: + description: "ok" + tags: + - CoderBot configuration + /settings/restore: + post: + operationId: "api.restoreSettings" + summary: "Restore settings to default" + responses: + 200: + description: "ok" + tags: + - CoderBot configuration + /media: + get: + operationId: "api.listPhotos" + summary: "Get the list of all photos" + tags: + - Photos management + responses: + 200: + description: "ok" + post: + operationId: "api.takePhoto" + summary: "take a new photo" + tags: + - Photos management + responses: + 200: + description: "ok" + /media/{name}: + get: + operationId: "api.getPhoto" + summary: "Get photo by name" + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 16 + pattern: '^(DSC|VID)+[0-9]+(_thumb)?\.?(jpg|mp4)?$' + tags: + - Photos management + responses: + 200: + description: Image in JPEG format + content: + image/jpeg: + schema: + type: string + format: binary + put: + operationId: "api.savePhoto" + summary: "Save photo by name" + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 16 + pattern: '^(DSC|VID)+[0-9]+(_thumb)?\.?(jpg|mp4)?$' + requestBody: + description: Save Photo metadata + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Photo' + tags: + - Photos management + responses: + 200: + description: "ok" + delete: + operationId: "api.deletePhoto" + summary: "Delete photo by name" + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 16 + pattern: '^(DSC|VID)+[0-9]+(_thumb)?\.?(jpg|mp4)?$' + tags: + - Photos management + responses: + 200: + description: "ok" + /video/stream: + get: + operationId: "api.streamVideo" + summary: "Stream video" + tags: + - Video management + responses: + 200: + description: "ok" + /video/rec: + post: + operationId: "api.recVideo" + summary: "Rec video" + tags: + - Video management + responses: + 200: + description: "ok" + /video/stop: + post: + operationId: "api.stopVideo" + summary: "Stop rec video" + tags: + - Video management + responses: + 200: + description: "ok" + + /programs: + get: + operationId: "api.listPrograms" + summary: "Get the list of all the saved programs" + tags: + - Program management + responses: + 200: + description: "ok" + + /programs/{name}: + get: + operationId: "api.loadProgram" + summary: "Get the program with the specified name" + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + + tags: + - Program management + responses: + 200: + description: "ok" + delete: + operationId: "api.deleteProgram" + summary: "Delete a program" + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + responses: + 200: + description: "ok" + tags: + - Program management + put: + operationId: "api.saveProgram" + summary: "Save an existing program" + tags: + - Program management + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + requestBody: + description: Program object + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Program' + responses: + 200: + description: "ok" + 400: + description: "Failed to save the program" + + /programs/{name}/run: + post: + operationId: "api.runProgram" + summary: "Execute the given program" + tags: + - Program management + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + requestBody: + description: Program object + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Program' + responses: + 200: + description: "ok" + + /programs/{name}/status: + get: + operationId: "api.statusProgram" + summary: "Get the status of the given program" + tags: + - Program management + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + responses: + 200: + description: "ok" + + /programs/{name}/stop: + patch: + operationId: "api.stopProgram" + summary: "Stop the given program" + tags: + - Program management + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + responses: + 200: + description: "ok" + + /activities: + get: + operationId: "api.listActivities" + summary: "Get the list of all the saved activities" + tags: + - Activity management + responses: + 200: + description: "ok" + post: + operationId: "api.saveAsNewActivity" + summary: "Save a new activity" + tags: + - Activity management + requestBody: + description: Create new Activity + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Activity' + responses: + 200: + description: "ok" + 400: + description: "Failed to save the activity" + /activities/{name}: + get: + operationId: "api.loadActivity" + summary: "Get the activity with the specified name" + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + - name: default + in: query + schema: + type: string + required: false + tags: + - Activity management + responses: + 200: + description: "ok" + put: + operationId: "api.saveActivity" + summary: "Save the activity with the specified name" + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + requestBody: + description: Update Activity + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Activity' + tags: + - Activity management + responses: + 200: + description: "ok" + delete: + operationId: "api.deleteActivity" + summary: "Delete an activity" + tags: + - Activity management + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + responses: + 200: + description: "ok" + + /music/packages: + get: + operationId: "api.listMusicPackages" + summary: "List Music Packages" + responses: + 200: + description: "ok" + tags: + - Music extensions + post: + operationId: "api.addMusicPackage" + summary: "Add Music Package" + requestBody: + description: Add a Music Package + required: true + content: + application/x-www-form-urlencoded: + schema: + type: object + tags: + - System operations + responses: + 200: + description: "ok" + 400: + description: "upload failed" + /music/packages/{name}: + delete: + operationId: "api.deleteMusicPackage" + summary: "Delete Music Package" + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + tags: + - Music extensions + responses: + 200: + description: "ok" + 400: + description: "not found" + + /system/status: + get: + operationId: "api.get_status" + summary: "Bot general informations, execution status and reset log file" + tags: + - System operations + responses: + 200: + description: "Bot status" + + /system/test: + post: + summary: Tests CoderBot components. + operationId: "api.testCoderbot" + tags: + - System operations + requestBody: + description: Performs onboard tests + required: true + content: + application/json: + schema: + type: object + properties: + tests: + type: array + items: + type: string + responses: + 200: + description: Test ended. + 400: + description: Invalid input. + + /system/info: + get: + operationId: "api.get_info" + summary: "Bot general informations and execution status" + tags: + - System operations + responses: + 200: + description: "Bot status" + + /control/stop: + post: + operationId: "api.stop" + summary: Stops the bot motors + tags: + - Direct control + responses: + 200: + description: "Successfully stopped the motors" + + /control/move: + post: + summary: Moves the bot forward or backward. + operationId: "api.move" + tags: + - Direct control + requestBody: + description: Movement speed and duration or distance + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/MoveParamsElapse' + - $ref: '#/components/schemas/MoveParamsDistance' + responses: + 200: + description: Sent command to the bot GPIO. + /control/turn: + post: + summary: Make a turn with the motors + operationId: "api.turn" + tags: + - Direct control + requestBody: + description: Movement Speed and duration or distance + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/TurnParamsElapse' + - $ref: '#/components/schemas/TurnParamsDistance' + responses: + 200: + description: Sent command to the bot GPIO. + /control/speak: + post: + operationId: "api.speak" + summary: Pronounce a phrase + tags: + - Direct control + requestBody: + description: Movement Speed and duration + required: true + content: + application/json: + schema: + type: object + properties: + text: + type: string + minLength: 1 + maxLength: 256 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + description: text to be "spoken" + locale: + type: string + minLength: 1 + maxLength: 2 + pattern: '^[a-zA-Z]+$' + description: locale of text to be "spoken" + required: + - text + - locale + responses: + 200: + description: "phrase received" + /system/halt: + post: + operationId: "api.halt" + summary: Halt system (system shutdown) + tags: + - System operations + responses: + 200: + description: "accepted" + /system/reset: + post: + operationId: "api.reset" + summary: Reset all local configuration to factory state + tags: + - System operations + responses: + 200: + description: "" + /system/restart: + post: + operationId: "api.restart" + summary: Restart backend + tags: + - System operations + responses: + 200: + description: "accepted" + /system/reboot: + post: + operationId: "api.reboot" + summary: Reboot all device + tags: + - System operations + responses: + 200: + description: "accepted" + + /cnnmodels: + get: + operationId: "api.listCNNModels" + summary: "list of CNN Models" + tags: + - CNN Models + responses: + 200: + description: "CNN Models as JSON Object" + post: + operationId: "api.trainCNNModel" + summary: "train new CNN Model" + requestBody: + description: CNN Model parameters + required: true + content: + application/json: + schema: + type: object + tags: + - CNN Models + responses: + 200: + description: "CNN Models as JSON Object" + /cnnmodels/{name}: + get: + operationId: "api.getCNNModel" + summary: "get CNN Model" + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + tags: + - CNN Models + responses: + 200: + description: "CNN Model as JSON Object" + delete: + operationId: "api.deleteCNNModel" + summary: "delete CNN Model" + parameters: + - name: name + in: path + required: true + schema: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + tags: + - CNN Models + responses: + 200: + description: "CNN Model deleted" + +components: + schemas: + MoveParamsElapse: + type: object + properties: + speed: + type: number + minimum: -100.0 + maximum: 100.0 + description: 0 to 100 represent a forward movement (100 being the maximum speed), while 0 to -100 is a backward movement (-100 being the maximu speed) + elapse: + type: number + minimum: -1.0 + maximum: 10.0 + description: Duration of the movement. 0 doesn't move the coderbot. + required: + - speed + - elapse + MoveParamsDistance: + type: object + properties: + speed: + type: number + minimum: -100.0 + maximum: 100.0 + description: 0 to 100 represent a forward movement (100 being the maximum speed), while 0 to -100 is a backward movement (-100 being the maximu speed) + distance: + type: number + minimum: 0.0 + maximum: 1000.0 + description: Target distqnce in mm. + required: + - speed + - distance + TurnParamsElapse: + type: object + properties: + speed: + type: number + minimum: -100.0 + maximum: 100.0 + description: 0 to 100 represent a forward movement (100 being the maximum speed), while 0 to -100 is a backward movement (-100 being the maximu speed) + elapse: + type: number + minimum: -1.0 + maximum: 1.0 + description: Duration of the movement. 0 doesn't move the coderbot. + required: + - speed + - elapse + TurnParamsDistance: + type: object + properties: + speed: + type: number + minimum: -100.0 + maximum: 100.0 + description: 0 to 100 represent a forward movement (100 being the maximum speed), while 0 to -100 is a backward movement (-100 being the maximu speed) + distance: + type: number + minimum: 0.0 + maximum: 100000.0 + description: Target distqnce in mm. + required: + - speed + - distance + Settings: + type: object + Photo: + type: object + properties: + name: + type: string + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + tag: + type: string + Program: + type: object + properties: + name: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + code: + type: string + minLength: 1 + dom_code: + type: string + default: + type: boolean + overwrite: + type: boolean + required: + - name + - code + + Activity: + type: object + properties: + name: + type: string + minLength: 1 + maxLength: 128 + pattern: '^[a-zA-ZA-zÀ-ú0-9-_ ]+$' + description: + type: string + minLength: 0 + maxLength: 256 + default: + type: boolean + stock: + type: boolean + required: + - name + - description + - default + - stock + \ No newline at end of file diff --git a/coderdojo-logo.png b/coderdojo-logo.png deleted file mode 100644 index 93a07e8d..00000000 Binary files a/coderdojo-logo.png and /dev/null differ diff --git a/config.py b/config.py deleted file mode 100644 index b996336f..00000000 --- a/config.py +++ /dev/null @@ -1,25 +0,0 @@ -import json - -CONFIG_FILE = "coderbot.cfg" - -class Config: - - _config = {} - - @classmethod - def get(cls): - return cls._config - - @classmethod - def read(cls): - f = open(CONFIG_FILE, 'r') - cls._config = json.load(f) - return cls._config - - @classmethod - def write(cls, config): - cls._config = config - f = open(CONFIG_FILE, 'w') - json.dump(cls._config, f) - return cls._config - diff --git a/data/.gitkeep b/data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/data/media/.gitkeep b/data/media/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/data/media/metadata.json b/data/media/metadata.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/data/media/metadata.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/data/program_.data b/data/program_.data deleted file mode 100644 index 4c951874..00000000 --- a/data/program_.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "", "code": "", "name": ""} \ No newline at end of file diff --git a/data/program_00-ufoprova1.data b/data/program_00-ufoprova1.data deleted file mode 100644 index 1c6d87ad..00000000 --- a/data/program_00-ufoprova1.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "", "code": "get_bot().left(speed=75, elapse=1)\nget_bot().left(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\n", "name": "00-ufoprova1"} \ No newline at end of file diff --git a/data/program_a b.data b/data/program_a b.data deleted file mode 100644 index 23e19989..00000000 --- a/data/program_a b.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "", "code": "get_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\n", "name": "a b"} \ No newline at end of file diff --git a/data/program_basic.data b/data/program_basic.data deleted file mode 100644 index ad99d71b..00000000 --- a/data/program_basic.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "", "code": "bot.forward(speed=100, elapse=1)\nbot.left(speed=80, elapse=0.8)\nbot.forward(speed=100, elapse=1)\nbot.left(speed=80, elapse=0.8)\nbot.forward(speed=100, elapse=1)\nbot.left(speed=80, elapse=0.8)\nbot.forward(speed=100, elapse=1)\nbot.left(speed=80, elapse=0.8)\n", "name": "basic"} \ No newline at end of file diff --git a/data/program_camera.data b/data/program_camera.data deleted file mode 100644 index 15db9e04..00000000 --- a/data/program_camera.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUEGTE16FORWARD800.10.3WHILELT16RIGHT700.10.3WHILELT16LEFT700.10.3", "code": "while True:\n program.check_end()\n if cam.path_ahead() >= 16:\n bot.forward(speed=80, elapse=0.1)\n cam.sleep(0.3)\n else:\n while cam.path_ahead() < 16:\n program.check_end()\n bot.right(speed=70, elapse=0.1)\n cam.sleep(0.3)\n while cam.path_ahead() < 16:\n program.check_end()\n bot.left(speed=70, elapse=0.1)\n cam.sleep(0.3)\n", "name": "camera"} \ No newline at end of file diff --git a/data/program_color_keeper.data b/data/program_color_keeper.data deleted file mode 100644 index 6851b078..00000000 --- a/data/program_color_keeper.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUEdistanzaDIST#cc0000angoloANGLE#cc0000GTdistanza25avantiFORWARD1000.2ANDGTdistanza0LTEdistanza15indietroBACKWARD800.2fermoLTangolo-20sinistraLEFT800.2GTdistanza20destraRIGHT800.2fermo", "code": "distanza = None\nangolo = None\n\n\nwhile True:\n get_prog_eng().check_end()\n distanza = get_cam().find_color('#cc0000')[0]\n angolo = get_cam().find_color('#cc0000')[1]\n if distanza > 25:\n get_cam().set_text('avanti')\n get_bot().forward(speed=100, elapse=0.2)\n elif distanza > 0 and distanza <= 15:\n get_cam().set_text('indietro')\n get_bot().backward(speed=80, elapse=0.2)\n else:\n get_cam().set_text('fermo')\n if angolo < -20:\n get_cam().set_text('sinistra')\n get_bot().left(speed=80, elapse=0.2)\n elif distanza > 20:\n get_cam().set_text('destra')\n get_bot().right(speed=80, elapse=0.2)\n else:\n get_cam().set_text('fermo')\n", "name": "color_keeper"} \ No newline at end of file diff --git a/data/program_egg_catcher.data b/data/program_egg_catcher.data deleted file mode 100644 index 61416c01..00000000 --- a/data/program_egg_catcher.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUElooking for eggsegg_dist_angleBOTH#ff0000egg_distROUNDGETFIRSTegg_dist_angleegg_angleROUNDGETLASTegg_dist_angleGTEegg_dist0egg found at egg_dist cm, egg_angle angleegg_angleegg_dist30", "code": "import math\n\negg_dist_angle = None\negg_dist = None\negg_angle = None\n\n\nwhile True:\n get_prog_eng().check_end()\n get_cam().set_text('looking for eggs')\n egg_dist_angle = get_cam().find_color('#ff0000')\n egg_dist = round(egg_dist_angle[0])\n egg_angle = round(egg_dist_angle[-1])\n if egg_dist >= 0:\n get_cam().set_text(''.join([str(temp_value) for temp_value in ['egg found at ', egg_dist, ' cm, ', egg_angle, ' angle']]))\n get_motion().turn(angle=egg_angle)\n get_motion().move(dist=egg_dist)\n else:\n get_motion().turn(angle=30)\n", "name": "egg_catcher"} \ No newline at end of file diff --git a/data/program_egg_catcher_2.data b/data/program_egg_catcher_2.data deleted file mode 100644 index 9cb72b08..00000000 --- a/data/program_egg_catcher_2.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUElooking for eggsegg_dist_angleBOTH#ff0000egg_distROUNDGETFIRSTegg_dist_angleegg_angleROUNDGETLASTegg_dist_angleGTEegg_dist0egg found at: egg_distcm, egg_angle degreeANDORGTEegg_angle3LTEegg_angle-3GTegg_dist20GTEegg_angle15RIGHT800.2GTEegg_angle3RIGHT800.05LTEegg_angle-15LEFT800.2LTEegg_angle-3LEFT800.05FORWARD1000.4FORWARD1002RIGHT800.4RIGHT00.2", "code": "import math\n\negg_dist_angle = None\negg_dist = None\negg_angle = None\n\n\nwhile True:\n get_prog_eng().check_end()\n get_cam().set_text('looking for eggs')\n egg_dist_angle = get_cam().find_color('#ff0000')\n egg_dist = round(egg_dist_angle[0])\n egg_angle = round(egg_dist_angle[-1])\n if egg_dist >= 0:\n get_cam().set_text(''.join([str(temp_value) for temp_value in ['egg found at: ', egg_dist, 'cm, ', egg_angle, ' degree']]))\n if (egg_angle >= 3 or egg_angle <= -3) and egg_dist > 20:\n if egg_angle >= 15:\n get_bot().right(speed=80, elapse=0.2)\n elif egg_angle >= 3:\n get_bot().right(speed=80, elapse=0.05)\n elif egg_angle <= -15:\n get_bot().left(speed=80, elapse=0.2)\n elif egg_angle <= -3:\n get_bot().left(speed=80, elapse=0.05)\n else:\n get_bot().forward(speed=100, elapse=0.4)\n else:\n get_bot().forward(speed=100, elapse=2)\n else:\n get_bot().right(speed=80, elapse=0.4)\n get_bot().right(speed=0, elapse=0.2)\n", "name": "egg_catcher_2"} \ No newline at end of file diff --git a/data/program_face.data b/data/program_face.data deleted file mode 100644 index a7db5176..00000000 --- a/data/program_face.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUEfaccia_xfaccia_xGTEfaccia_x0LTfaccia_x45LEFT80DIVIDEMINUS50faccia_x100.1GTfaccia_x55RIGHT80DIVIDEMINUSfaccia_x50100.1", "code": "faccia_x = None\n\n\nwhile True:\n get_prog_eng().check_end()\n faccia_x = get_cam().find_face()\n get_cam().set_text(faccia_x)\n if faccia_x >= 0:\n if faccia_x < 45:\n get_bot().left(speed=80, elapse=(50 - faccia_x) / 100.1)\n elif faccia_x > 55:\n get_bot().right(speed=80, elapse=(faccia_x - 50) / 100.1)\n", "name": "face"} \ No newline at end of file diff --git a/data/program_face_finder.data b/data/program_face_finder.data deleted file mode 100644 index 7f29f8fd..00000000 --- a/data/program_face_finder.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUEface_x_y_sizeALLface_xGETFROM_STARTface_x_y_size1face_x$i-see-you.mp3face_yGETFROM_STARTface_x_y_size2face_sizeGETFROM_STARTface_x_y_size3face at face_xx, face_yy, face_size sizeGTface_x10RIGHT400.2LTface_x-10RIGHT400.2looking for face$still-there.mp3RIGHT400.2", "code": "face_x_y_size = None\nface_x = None\nface_y = None\nface_size = None\n\n\nwhile True:\n get_prog_eng().check_end()\n face_x_y_size = get_cam().find_face()\n face_x = face_x_y_size[0]\n if face_x:\n get_bot().say('$i-see-you.mp3')\n face_y = face_x_y_size[1]\n face_size = face_x_y_size[2]\n get_cam().set_text(''.join([str(temp_value) for temp_value in ['face at ', face_x, 'x, ', face_y, 'y, ', face_size, ' size']]))\n if face_x > 10:\n get_bot().right(speed=40, elapse=0.2)\n elif face_x < -10:\n get_bot().right(speed=40, elapse=0.2)\n else:\n get_cam().set_text('looking for face')\n get_bot().say('$still-there.mp3')\n get_bot().right(speed=40, elapse=0.2)\n", "name": "face_finder"} \ No newline at end of file diff --git a/data/program_face_finder_2.data b/data/program_face_finder_2.data deleted file mode 100644 index 12dae269..00000000 --- a/data/program_face_finder_2.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUEface_x_y_sizeALLface_xGETFROM_STARTface_x_y_size1face_xface_yGETFROM_STARTface_x_y_size2face_sizeGETFROM_STARTface_x_y_size3face at face_xx, face_yy, face_size sizeGTface_x10RIGHT400.2LTface_x-10RIGHT400.2looking for face", "code": "face_x_y_size = None\nface_x = None\nface_y = None\nface_size = None\n\n\nwhile True:\n get_prog_eng().check_end()\n face_x_y_size = get_cam().find_face()\n face_x = face_x_y_size[0]\n if face_x:\n face_y = face_x_y_size[1]\n face_size = face_x_y_size[2]\n get_cam().set_text(''.join([str(temp_value) for temp_value in ['face at ', face_x, 'x, ', face_y, 'y, ', face_size, ' size']]))\n if face_x > 10:\n get_bot().right(speed=40, elapse=0.2)\n elif face_x < -10:\n get_bot().right(speed=40, elapse=0.2)\n else:\n get_cam().set_text('looking for face')\n", "name": "face_finder_2"} \ No newline at end of file diff --git a/data/program_find_color.data b/data/program_find_color.data deleted file mode 100644 index cca777cf..00000000 --- a/data/program_find_color.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "colore_oggetto#990000colore_deposito#ffcc00colore_oggettocolore_oggettocolore_depositocolore_depositocerca_oggettoWHILELTDISTcolore0giro0WHILEANDLTDISTcolore0LTgiro1LEFT750.4giroADDgiro0.05oggetto trovatoprendi_oggettoWHILEGTDISTcolore25WHILELTANGLEcolore-5LEFT800.1WHILEGTANGLEcolore5RIGHT800.1FORWARD100DIVIDEDISTcolore20FORWARD1001.5oggetto agganciatocerca_depositoWHILELTDISTcolore0giro0WHILEANDLTDISTcolore0LTgiro1LEFT750.4giroADDgiro0.06FORWARD1002deposito avvistatoraggiungi_depositoWHILEGTDISTcolore0WHILELTANGLEcolore-5LEFT800.1WHILEGTANGLEcolore5RIGHT800.1FORWARD1002missione compiuta", "code": "colore_oggetto = None\ncolore = None\ncolore_deposito = None\ngiro = None\n\ndef cerca_oggetto(colore):\n global giro\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[0] < 0:\n get_prog_eng().check_end()\n giro = 0\n while get_cam().find_color(colore)[0] < 0 and giro < 1:\n get_prog_eng().check_end()\n get_bot().left(speed=75, elapse=0.4)\n giro = giro + 0.05\n get_bot().say('oggetto trovato')\n\ndef prendi_oggetto(colore):\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[0] > 25:\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[1] < -5:\n get_prog_eng().check_end()\n get_bot().left(speed=80, elapse=0.1)\n while get_cam().find_color(colore)[1] > 5:\n get_prog_eng().check_end()\n get_bot().right(speed=80, elapse=0.1)\n get_bot().forward(speed=100, elapse=get_cam().find_color(colore)[0] / 20)\n get_bot().forward(speed=100, elapse=1.5)\n get_bot().say('oggetto agganciato')\n\ndef cerca_deposito(colore):\n global giro\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[0] < 0:\n get_prog_eng().check_end()\n giro = 0\n while get_cam().find_color(colore)[0] < 0 and giro < 1:\n get_prog_eng().check_end()\n get_bot().left(speed=75, elapse=0.4)\n giro = giro + 0.06\n get_bot().forward(speed=100, elapse=2)\n get_bot().say('deposito avvistato')\n\ndef raggiungi_deposito(colore):\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[0] > 0:\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[1] < -5:\n get_prog_eng().check_end()\n get_bot().left(speed=80, elapse=0.1)\n while get_cam().find_color(colore)[1] > 5:\n get_prog_eng().check_end()\n get_bot().right(speed=80, elapse=0.1)\n get_bot().forward(speed=100, elapse=2)\n get_bot().say('missione compiuta')\n\n\ncolore_oggetto = '#990000'\ncolore_deposito = '#ffcc00'\ncerca_oggetto(colore_oggetto)\nprendi_oggetto(colore_oggetto)\ncerca_deposito(colore_deposito)\nraggiungi_deposito(colore_deposito)\n", "name": "find_color"} \ No newline at end of file diff --git a/data/program_find_color_servo.data b/data/program_find_color_servo.data deleted file mode 100644 index 936a22ee..00000000 --- a/data/program_find_color_servo.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "colore_oggetto#990000colore_deposito#ffcc00colore_oggettocolore_oggettocolore_depositocolore_depositocerca_oggettoWHILELTDISTcolore0giro0WHILEANDLTDISTcolore0LTgiro1LEFT750.4giroADDgiro0.05oggetto trovatocerca_depositoWHILELTDISTcolore0giro0WHILEANDLTDISTcolore0LTgiro1LEFT750.4giroADDgiro0.06FORWARD1002deposito avvistatoprendi_oggettoWHILEGTDISTcolore250WHILELTANGLEcolore-5LEFT200.10WHILEGTANGLEcolore5RIGHT200.1FORWARD100DIVIDEDISTcolore15FORWARD1001.5oggetto agganciatoraggiungi_depositoWHILEGTDISTcolore0WHILELTANGLEcolore-5LEFT800.1WHILEGTANGLEcolore5RIGHT800.1FORWARD1002missione compiuta", "code": "colore_oggetto = None\ncolore = None\ncolore_deposito = None\ngiro = None\n\ndef cerca_oggetto(colore):\n global giro\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[0] < 0:\n get_prog_eng().check_end()\n giro = 0\n while get_cam().find_color(colore)[0] < 0 and giro < 1:\n get_prog_eng().check_end()\n get_bot().left(speed=75, elapse=0.4)\n giro = giro + 0.05\n get_bot().say('oggetto trovato')\n\ndef cerca_deposito(colore):\n global giro\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[0] < 0:\n get_prog_eng().check_end()\n giro = 0\n while get_cam().find_color(colore)[0] < 0 and giro < 1:\n get_prog_eng().check_end()\n get_bot().left(speed=75, elapse=0.4)\n giro = giro + 0.06\n get_bot().forward(speed=100, elapse=2)\n get_bot().say('deposito avvistato')\n\ndef prendi_oggetto(colore):\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[0] > 25:\n get_prog_eng().check_end()\n get_cam().sleep(0)\n while get_cam().find_color(colore)[1] < -5:\n get_prog_eng().check_end()\n get_bot().left(speed=20, elapse=0.1)\n get_cam().sleep(0)\n while get_cam().find_color(colore)[1] > 5:\n get_prog_eng().check_end()\n get_bot().right(speed=20, elapse=0.1)\n get_bot().forward(speed=100, elapse=get_cam().find_color(colore)[0] / 15)\n get_bot().forward(speed=100, elapse=1.5)\n get_bot().say('oggetto agganciato')\n\ndef raggiungi_deposito(colore):\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[0] > 0:\n get_prog_eng().check_end()\n while get_cam().find_color(colore)[1] < -5:\n get_prog_eng().check_end()\n get_bot().left(speed=80, elapse=0.1)\n while get_cam().find_color(colore)[1] > 5:\n get_prog_eng().check_end()\n get_bot().right(speed=80, elapse=0.1)\n get_bot().forward(speed=100, elapse=2)\n get_bot().say('missione compiuta')\n\n\ncolore_oggetto = '#990000'\ncolore_deposito = '#ffcc00'\ncerca_oggetto(colore_oggetto)\nprendi_oggetto(colore_oggetto)\ncerca_deposito(colore_deposito)\nraggiungi_deposito(colore_deposito)\n", "name": "find_color_servo"} \ No newline at end of file diff --git a/data/program_i6alieni-prova1.data b/data/program_i6alieni-prova1.data deleted file mode 100644 index 6143c37a..00000000 --- a/data/program_i6alieni-prova1.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "", "code": "get_bot().right(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().left(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\n", "name": "i6alieni-prova1"} \ No newline at end of file diff --git a/data/program_line_follower.data b/data/program_line_follower.data deleted file mode 100644 index f6da3386..00000000 --- a/data/program_line_follower.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUEline_positionline_positionLTline_position0BACKWARD500.1LTline_position40LEFT600.1GTline_position60RIGHT600.1FORWARD700.2", "code": "line_position = None\n\n\nwhile True:\n get_prog_eng().check_end()\n line_position = get_cam().find_line()\n get_cam().set_text(line_position)\n if line_position < 0:\n get_bot().backward(speed=50, elapse=0.1)\n elif line_position < 40:\n get_bot().left(speed=60, elapse=0.1)\n elif line_position > 60:\n get_bot().right(speed=60, elapse=0.1)\n else:\n get_bot().forward(speed=70, elapse=0.2)\n", "name": "line_follower"} \ No newline at end of file diff --git a/data/program_maze.data b/data/program_maze.data deleted file mode 100644 index 88f6620f..00000000 --- a/data/program_maze.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUEGT20GT20GT20GT20", "code": "while True:\n program.check_end()\n bot.right(speed=75, elapse=1)\n if cam.path_ahead() > 20:\n bot.forward(speed=100, elapse=1.5)\n else:\n bot.left(speed=75, elapse=1)\n if cam.path_ahead() > 20:\n bot.forward(speed=100, elapse=1.5)\n else:\n bot.left(speed=75, elapse=1)\n if cam.path_ahead() > 20:\n bot.forward(speed=100, elapse=1.5)\n else:\n bot.left(speed=75, elapse=1)\n if cam.path_ahead() > 20:\n bot.forward(speed=100, elapse=1.5)\n", "name": "maze"} \ No newline at end of file diff --git a/data/program_move_pen.data b/data/program_move_pen.data deleted file mode 100644 index 9f72416a..00000000 --- a/data/program_move_pen.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "20FORWARD1000.3LEFT1004", "code": "for count in range(20):\n program.check_end()\n bot.forward(speed=100, elapse=0.3)\n bot.left(speed=100, elapse=4)\n", "name": "move_pen"} \ No newline at end of file diff --git a/data/program_move_square.data b/data/program_move_square.data deleted file mode 100644 index 0f3fd85a..00000000 --- a/data/program_move_square.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "ora mi muovo in un quadrato4LEFT500.4FORWARD1001", "code": "bot.say('ora mi muovo in un quadrato')\nfor count in range(4):\n program.check_end()\n bot.left(speed=50, elapse=0.4)\n bot.forward(speed=100, elapse=1)\n", "name": "move_square"} \ No newline at end of file diff --git a/data/program_path_ahead.data b/data/program_path_ahead.data deleted file mode 100644 index 2ee8b9ee..00000000 --- a/data/program_path_ahead.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "100", "code": "for count in range(100):\n get_prog_eng().check_end()\n print(get_cam().path_ahead())\n", "name": "path_ahead"} \ No newline at end of file diff --git a/data/program_pathfinder.data b/data/program_pathfinder.data deleted file mode 100644 index c2fc6956..00000000 --- a/data/program_pathfinder.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUE0.3path_aheadGTpath_ahead30FORWARD600.2RIGHT500.10.3LTADDpath_ahead0LEFT500.2", "code": "path_ahead = None\n\n\nwhile True:\n program.check_end()\n cam.sleep(0.3)\n path_ahead = cam.path_ahead()\n if path_ahead > 30:\n bot.forward(speed=60, elapse=0.2)\n else:\n bot.right(speed=50, elapse=0.1)\n cam.sleep(0.3)\n if cam.path_ahead() < path_ahead + 0:\n bot.left(speed=50, elapse=0.2)\n", "name": "pathfinder"} \ No newline at end of file diff --git a/data/program_prova.data b/data/program_prova.data deleted file mode 100644 index 66503df0..00000000 --- a/data/program_prova.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "WHILETRUEspazioGTEspazio30FORWARD800.2UNTILORGTspazio_2spazioLTspazio_230spaziospazio_2RIGHT800.2spazio_2UNTILORGTspazio_2spazioLTspazio_230spaziospazio_2LEFT800.2spazio_2", "code": "spazio = None\nspazio_2 = None\n\n\nwhile True:\n program.check_end()\n spazio = cam.path_ahead()\n if spazio >= 30:\n bot.forward(speed=80, elapse=0.2)\n else:\n while not (spazio_2 > spazio or spazio_2 < 30):\n program.check_end()\n spazio = spazio_2\n bot.right(speed=80, elapse=0.2)\n spazio_2 = cam.path_ahead()\n while not (spazio_2 > spazio or spazio_2 < 30):\n program.check_end()\n spazio = spazio_2\n bot.left(speed=80, elapse=0.2)\n spazio_2 = cam.path_ahead()\n", "name": "prova"} \ No newline at end of file diff --git a/data/program_scienziatistellari1.data b/data/program_scienziatistellari1.data deleted file mode 100644 index 014099ca..00000000 --- a/data/program_scienziatistellari1.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "", "code": "get_bot().backward(speed=100, elapse=1.5)\nget_bot().right(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().left(speed=75, elapse=1)\n", "name": "scienziatistellari1"} \ No newline at end of file diff --git a/data/program_servo test.data b/data/program_servo test.data deleted file mode 100644 index b256a5b2..00000000 --- a/data/program_servo test.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "10301", "code": "get_bot().motor_control(speed_left=10, speed_right=30, elapse=1)\n", "name": "servo test"} \ No newline at end of file diff --git a/data/program_spiral.data b/data/program_spiral.data deleted file mode 100644 index b04c05c1..00000000 --- a/data/program_spiral.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "elemento010elementoADDelemento0.1LEFT1000.2FORWARD100elemento", "code": "elemento = None\n\n\nelemento = 0\nfor count in range(10):\n program.check_end()\n elemento = elemento + 0.1\n bot.left(speed=100, elapse=0.2)\n bot.forward(speed=100, elapse=elemento)\n", "name": "spiral"} \ No newline at end of file diff --git a/data/program_squadra_1.data b/data/program_squadra_1.data deleted file mode 100644 index f0872d0f..00000000 --- a/data/program_squadra_1.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "10", "code": "for count in range(10):\n get_prog_eng().check_end()\n get_bot().forward(speed=100, elapse=1.5)\n get_bot().forward(speed=100, elapse=1.5)\n", "name": "squadra_1"} \ No newline at end of file diff --git a/data/program_squadra_2.data b/data/program_squadra_2.data deleted file mode 100644 index 09c40145..00000000 --- a/data/program_squadra_2.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "", "code": "get_bot().forward(speed=100, elapse=1.5)\nget_bot().backward(speed=100, elapse=1.5)\n", "name": "squadra_2"} \ No newline at end of file diff --git a/data/program_squadra_3.data b/data/program_squadra_3.data deleted file mode 100644 index a57c478d..00000000 --- a/data/program_squadra_3.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "", "code": "get_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().left(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_cam().photo_take()\nget_bot().right(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_cam().photo_take()\nget_bot().right(speed=75, elapse=1)\nget_cam().photo_take()\nget_bot().right(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().left(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_cam().photo_take()\n", "name": "squadra_3"} \ No newline at end of file diff --git a/data/program_squadra_4.data b/data/program_squadra_4.data deleted file mode 100644 index eba20d15..00000000 --- a/data/program_squadra_4.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "", "code": "get_bot().left(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().right(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().right(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().left(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().left(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().right(speed=75, elapse=1)\n", "name": "squadra_4"} \ No newline at end of file diff --git a/data/program_test_motion_flow.data b/data/program_test_motion_flow.data deleted file mode 100644 index f2a20b7d..00000000 --- a/data/program_test_motion_flow.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "70", "code": "get_motion().move(dist=70)\n", "name": "test_motion_flow"} \ No newline at end of file diff --git a/data/program_thespaceguys-prova1.data b/data/program_thespaceguys-prova1.data deleted file mode 100644 index 84e298f3..00000000 --- a/data/program_thespaceguys-prova1.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "", "code": "get_bot().forward(speed=100, elapse=1.5)\nget_bot().forward(speed=100, elapse=1.5)\nget_bot().right(speed=75, elapse=1)\nget_bot().right(speed=75, elapse=1)\nget_bot().forward(speed=100, elapse=1.5)\n", "name": "thespaceguys-prova1"} \ No newline at end of file diff --git a/data/program_wcap_labirinto_1.data b/data/program_wcap_labirinto_1.data deleted file mode 100644 index 9402439e..00000000 --- a/data/program_wcap_labirinto_1.data +++ /dev/null @@ -1 +0,0 @@ -{"dom_code": "Si parteSono arrivato", "code": "bot.say('Si parte')\nbot.forward(speed=100, elapse=0.25)\nbot.forward(speed=100, elapse=0.25)\nbot.forward(speed=100, elapse=0.25)\nbot.forward(speed=100, elapse=0.25)\nbot.right(speed=70, elapse=0.1)\nbot.right(speed=70, elapse=0.1)\nbot.forward(speed=100, elapse=0.25)\nbot.forward(speed=100, elapse=0.25)\nbot.forward(speed=100, elapse=0.25)\nbot.right(speed=70, elapse=0.1)\nbot.right(speed=70, elapse=0.1)\nbot.forward(speed=100, elapse=0.25)\nbot.forward(speed=100, elapse=0.25)\nbot.forward(speed=100, elapse=0.25)\nbot.forward(speed=100, elapse=0.25)\nbot.forward(speed=100, elapse=0.25)\nbot.say('Sono arrivato')\n", "name": "wcap_labirinto_1"} \ No newline at end of file diff --git a/defaults/config.json b/defaults/config.json new file mode 100644 index 00000000..c206cc0a --- /dev/null +++ b/defaults/config.json @@ -0,0 +1,54 @@ +{ + "move_power_angle_3":"60", + "cnn_default_model":"generic_fast_low", + "prog_maxblocks":"-1", + "camera_jpeg_quality":"5", + "show_page_control":"true", + "camera_framerate":"30", + "prog_scrollbars":"true", + "move_fw_speed":"100", + "motor_min_power":"0", + "motor_max_power":"100", + "prog_level":"adv", + "move_motor_trim":"1", + "cv_image_factor":"2", + "move_power_angle_1":"45", + "camera_path_object_size_min":"4000", + "button_func":"none", + "camera_color_object_size_min":"4000", + "camera_jpeg_bitrate":"1000000", + "move_fw_elapse":"1", + "show_control_move_commands":"true", + "camera_color_object_size_max":"160000", + "show_page_prefs":"true", + "camera_exposure_mode":"auto", + "ctrl_tr_elapse":"-1", + "show_page_program":"true", + "move_tr_elapse":"0.5", + "camera_path_object_size_max":"160000", + "sound_shutter":"$shutter", + "ctrl_fw_elapse":"-1", + "sound_stop":"$shutdown", + "ctrl_tr_speed":"80", + "ctrl_fw_speed":"100", + "move_tr_speed":"85", + "move_power_angle_2":"60", + "ctrl_hud_image":"", + "load_at_start":"", + "sound_start":"$startup", + "hardware_version":"5", + "audio_volume_level":"100", + "wifi_mode":"ap", + "wifi_ssid":"coderbot", + "wifi_psk":"coderbot", + "packages_installed":"", + "admin_password":"", + "pid_kp":"8.0", + "pid_kd":"0.0", + "pid_ki":"0.0", + "pid_max_speed":"200", + "pid_sample_time":"0.05", + "movement_use_mpu": "false", + "movement_use_motion": "false", + "movement_use_encoder": "true" +} diff --git a/defaults/manifest.json b/defaults/manifest.json new file mode 100644 index 00000000..1273d397 --- /dev/null +++ b/defaults/manifest.json @@ -0,0 +1,4 @@ +{ + "coderbot_version": "undefined", + "coderbot_commit": "12345678" +} \ No newline at end of file diff --git a/defaults/programs/program_demo_ar_tags.json b/defaults/programs/program_demo_ar_tags.json new file mode 100644 index 00000000..329f45d9 --- /dev/null +++ b/defaults/programs/program_demo_ar_tags.json @@ -0,0 +1 @@ +{"dom_code": "tag_mapcodelistacodespositionsWHILETRUEtag_mapcodescodestag_mappositionspositionstag_mapGTcodes0GTGETLASTGETFIRSTpositions150codeGETFIRSTcodescodesEQcode1FORWARD1001LEFT1001EQcode2FORWARD1003EQcode3FORWARD1001RIGHT1001EQcode42RIGHT1000.5LEFT1000.5itSono arrivato!EQcode5itAttenzione!", "code": "tag_map = None\ncode = None\nlista = None\ncodes = None\npositions = None\n\n\nwhile True:\n get_prog_eng().check_end()\n tag_map = get_cam().find_ar_code()\n codes = tag_map.get('codes')\n positions = tag_map.get('positions')\n if len(codes) > 0:\n if positions[0][-1] > 150:\n code = codes[0]\n get_cam().set_text(codes)\n if code == 1:\n get_bot().forward(speed=100, elapse=1)\n get_bot().left(speed=100, elapse=1)\n elif code == 2:\n get_bot().forward(speed=100, elapse=3)\n elif code == 3:\n get_bot().forward(speed=100, elapse=1)\n get_bot().right(speed=100, elapse=1)\n elif code == 4:\n for count in range(2):\n get_prog_eng().check_end()\n get_bot().right(speed=100, elapse=0.5)\n get_bot().left(speed=100, elapse=0.5)\n get_audio().say('Sono arrivato!', locale=\"it\")\n elif code == 5:\n get_audio().say('Attenzione!', locale=\"it\")\n get_cam().set_text('')\n", "name": "ar_bot"} \ No newline at end of file diff --git a/defaults/programs/program_demo_cat_follower.json b/defaults/programs/program_demo_cat_follower.json new file mode 100644 index 00000000..2c744cc5 --- /dev/null +++ b/defaults/programs/program_demo_cat_follower.json @@ -0,0 +1 @@ +{"name": "cat_follower", "dom_code": "objectclasspositionpos_xWHILETRUEobjectGETFIRSTgeneric_object_detectclassGETFIRSTobjectEQclasscatpositionGETFROM_STARTobject3pos_xDIVIDEADDGETFROM_STARTposition1GETFROM_STARTposition32classLTpos_x40LEFT600.1GTpos_x60RIGHT600.1FORWARD1000.2object", "code": "object2 = None\nclass2 = None\nposition = None\npos_x = None\n\n\nwhile True:\n get_prog_eng().check_end()\n object2 = get_cam().cnn_detect_objects(\"generic_object_detect\")[0]\n class2 = object2[0]\n if class2 == 'cat':\n position = object2[2]\n pos_x = (position[0] + position[2]) / 2\n get_cam().set_text(class2)\n if pos_x < 40:\n get_bot().left(speed=60, elapse=0.1)\n elif pos_x > 60:\n get_bot().right(speed=60, elapse=0.1)\n else:\n get_bot().forward(speed=100, elapse=0.2)\n else:\n get_cam().set_text(object2)\n"} \ No newline at end of file diff --git a/defaults/programs/program_demo_color_seeker.json b/defaults/programs/program_demo_color_seeker.json new file mode 100644 index 00000000..75c14d28 --- /dev/null +++ b/defaults/programs/program_demo_color_seeker.json @@ -0,0 +1 @@ +{"dom_code": "WHILETRUEdistDIST#96b73cangleANGLE#96b73cDistance: dist angle: angleGTdist32FORWARD1000.1ANDLTdist28GTEdist0BACKWARD1000.1GTangle5RIGHT300.1LTangle-5LEFT300.1", "code": "dist = None\nangle = None\n\n\nwhile True:\n get_prog_eng().check_end()\n dist = get_cam().find_color('#96b73c')[0]\n angle = get_cam().find_color('#96b73c')[1]\n get_cam().set_text(''.join([str(temp_value) for temp_value in ['Distance: ', dist, ' angle: ', angle]]))\n if dist > 32:\n get_bot().forward(speed=100, elapse=0.1)\n elif dist < 28 and dist >= 0:\n get_bot().backward(speed=100, elapse=0.1)\n if angle > 5:\n get_bot().right(speed=30, elapse=0.1)\n elif angle < -5:\n get_bot().left(speed=30, elapse=0.1)\n", "name": "colour_seeker"} \ No newline at end of file diff --git a/defaults/programs/program_demo_io_ext.json b/defaults/programs/program_demo_io_ext.json new file mode 100644 index 00000000..3265bfcb --- /dev/null +++ b/defaults/programs/program_demo_io_ext.json @@ -0,0 +1 @@ +{"name": "test_io_ext", "dom_code": "Analog_Input_1WHILETRUEAnalog_Input_10Analog Input 1: Analog_Input_1GTAnalog_Input_11000TRUE0FALSE", "code": "Analog_Input_1 = None\n\n\nwhile True:\n get_prog_eng().check_end()\n Analog_Input_1 = get_atmega().get_input(0)\n get_cam().set_text('Analog Input 1: ' + str(Analog_Input_1))\n if Analog_Input_1 > 100:\n get_atmega().set_output(0, True)\n else:\n get_atmega().set_output(0, False)\n"} \ No newline at end of file diff --git a/defaults/programs/program_demo_line_follower.json b/defaults/programs/program_demo_line_follower.json new file mode 100644 index 00000000..da7ba861 --- /dev/null +++ b/defaults/programs/program_demo_line_follower.json @@ -0,0 +1 @@ +{"dom_code": "line_x_1listaline_x_listline_x_2ar_codear_code_listWHILETRUEline_x_listline_x_1GETFIRSTline_x_listar_code_listcodesar_code_listar_codeGETFIRSTar_code_listar_code0ar_codeEQar_code18080-110001000EQar_code26060-120001550EQar_code66060-115502000GTEline_x_10GTline_x_16040-40-1MINUSline_x_150MINUSline_x_150LTline_x_140-4040-1MINUS50line_x_1MINUS50line_x_15050-1150150", "code": "line_x_1 = None\nlista = None\nline_x_list = None\nline_x_2 = None\nar_code = None\nar_code_list = None\n\n\nwhile True:\n get_prog_eng().check_end()\n line_x_list = get_cam().find_line()\n line_x_1 = line_x_list[0]\n ar_code_list = get_cam().find_ar_code().get('codes')\n if not not len(ar_code_list):\n ar_code = ar_code_list[0]\n else:\n ar_code = 0\n get_cam().set_text(ar_code)\n if ar_code == 1:\n get_bot().motor_control(speed_left=80, speed_right=80, elapse=-1, steps_left=1000, steps_right=1000)\n elif ar_code == 2:\n get_bot().motor_control(speed_left=60, speed_right=60, elapse=-1, steps_left=2000, steps_right=1550)\n elif ar_code == 6:\n get_bot().motor_control(speed_left=60, speed_right=60, elapse=-1, steps_left=1550, steps_right=2000)\n else:\n if line_x_1 >= 0:\n if line_x_1 > 60:\n get_bot().motor_control(speed_left=40, speed_right=-40, elapse=-1, steps_left=line_x_1 - 50, steps_right=line_x_1 - 50)\n elif line_x_1 < 40:\n get_bot().motor_control(speed_left=-40, speed_right=40, elapse=-1, steps_left=50 - line_x_1, steps_right=50 - line_x_1)\n else:\n get_bot().motor_control(speed_left=50, speed_right=50, elapse=-1, steps_left=150, steps_right=150)\n", "name": "line_follower"} \ No newline at end of file diff --git a/defaults/programs/program_demo_obstacle_avoidance.json b/defaults/programs/program_demo_obstacle_avoidance.json new file mode 100644 index 00000000..ab3e4a8e --- /dev/null +++ b/defaults/programs/program_demo_obstacle_avoidance.json @@ -0,0 +1 @@ +{"name": "demo_obstacle_avoidance", "code": "while True:\n get_prog_eng().check_end()\n if get_bot().get_sonar_distance(0) < 15:\n get_bot().right(speed=100, elapse=0.5)\n else:\n get_bot().forward(speed=100, elapse=1)\n", "dom_code": "WHILETRUELT015RIGHT1000.5FORWARD1001"} \ No newline at end of file diff --git a/defaults/programs/program_demo_roboetologist.json b/defaults/programs/program_demo_roboetologist.json new file mode 100644 index 00000000..b53ba7e2 --- /dev/null +++ b/defaults/programs/program_demo_roboetologist.json @@ -0,0 +1 @@ +{"name":"roboetologia","dom_code":"attesavelocita_maxvar_marciaIndietrovar_giravoltevar_ritiratavelocitastancoScodinzolaDescrivi questa funzione...3RIGHT50MULTIPLY100velocita1100velocita_max0.30.2attesaLEFT50MULTIPLY100velocita1100velocita_max0.50.2attesaRIGHT50MULTIPLY100velocita1100velocita_max0.30.2attesaEvita_OstacoliDescrivi questa funzione...15LT020BACKWARD50MULTIPLY100velocita1100velocita_max0.50.2attesaRIGHT50MULTIPLY100velocita1100velocita_max0.50.2attesaLT120LEFT50MULTIPLY100velocita1100velocita_max0.50.2attesaLT220RIGHT50MULTIPLY100velocita1100velocita_max0.50.2attesaFORWARD50MULTIPLY100velocita1100velocita_max0.50.2attesaattesa0.2velocita_max80var_marciaIndietro0var_giravolte0var_ritirata0stanco0velocita1WHILETRUEstanco1var_marciaIndietro1var_giravolte1var_ritirata1EQstanco5stanco0velocita1GTstanco3velocita0.5EQvar_ritirata4var_ritirata0EQvar_giravolte8var_giravolte05EQvar_marciaIndietro6var_marciaIndietro0GiravolteDescrivi questa funzione...RIGHT50MULTIPLY100velocita1100velocita_max20.2attesaPatugliamentoDescrivi questa funzione...3RIGHT50MULTIPLY100velocita1100velocita_max10.5Ritirata_e_fugaDescrivi questa funzione...BACKWARD50MULTIPLY100velocita1100velocita_max10.2attesaLEFT50MULTIPLY100velocita1100velocita_max30.2attesaFORWARD50MULTIPLY100velocita1100velocita_max10.2attesaMarciaIndietro_e_ScartoDescrivi questa funzione...BACKWARD50MULTIPLY100velocita1100velocita_max10.2attesaRIGHT50MULTIPLY100velocita1100velocita_max10.2attesa","code":"from numbers import Number\n\nattesa = None\nvelocita_max = None\nvar_marciaIndietro = None\nvar_giravolte = None\nvar_ritirata = None\nvelocita = None\nstanco = None\n\n# Descrivi questa funzione...\ndef Scodinzola():\n global attesa, velocita_max, var_marciaIndietro, var_giravolte, var_ritirata, velocita, stanco\n get_prog_eng().check_end()\n for count in range(3):\n get_prog_eng().check_end()\n get_bot().right(speed=min(max(100 * velocita, 1), velocita_max), elapse=0.3)\n get_bot().sleep(attesa)\n get_bot().left(speed=min(max(100 * velocita, 1), velocita_max), elapse=0.5)\n get_bot().sleep(attesa)\n get_bot().right(speed=min(max(100 * velocita, 1), velocita_max), elapse=0.3)\n get_bot().sleep(attesa)\n\n# Descrivi questa funzione...\ndef Evita_Ostacoli():\n global attesa, velocita_max, var_marciaIndietro, var_giravolte, var_ritirata, velocita, stanco\n get_prog_eng().check_end()\n for count2 in range(15):\n get_prog_eng().check_end()\n if get_bot().get_sonar_distance(0) < 20:\n get_bot().backward(speed=min(max(100 * velocita, 1), velocita_max), elapse=0.5)\n get_bot().sleep(attesa)\n get_bot().right(speed=min(max(100 * velocita, 1), velocita_max), elapse=0.5)\n get_bot().sleep(attesa)\n elif get_bot().get_sonar_distance(1) < 20:\n get_bot().left(speed=min(max(100 * velocita, 1), velocita_max), elapse=0.5)\n get_bot().sleep(attesa)\n elif get_bot().get_sonar_distance(2) < 20:\n get_bot().right(speed=min(max(100 * velocita, 1), velocita_max), elapse=0.5)\n get_bot().sleep(attesa)\n else:\n get_bot().forward(speed=min(max(100 * velocita, 1), velocita_max), elapse=0.5)\n get_bot().sleep(attesa)\n\n# Descrivi questa funzione...\ndef Giravolte():\n global attesa, velocita_max, var_marciaIndietro, var_giravolte, var_ritirata, velocita, stanco\n get_prog_eng().check_end()\n get_bot().right(speed=min(max(100 * velocita, 1), velocita_max), elapse=2)\n get_bot().sleep(attesa)\n\n# Descrivi questa funzione...\ndef Patugliamento():\n global attesa, velocita_max, var_marciaIndietro, var_giravolte, var_ritirata, velocita, stanco\n get_prog_eng().check_end()\n for count3 in range(3):\n get_prog_eng().check_end()\n get_bot().right(speed=min(max(100 * velocita, 1), velocita_max), elapse=1)\n get_bot().sleep(0.5)\n\n# Descrivi questa funzione...\ndef Ritirata_e_fuga():\n global attesa, velocita_max, var_marciaIndietro, var_giravolte, var_ritirata, velocita, stanco\n get_prog_eng().check_end()\n get_bot().backward(speed=min(max(100 * velocita, 1), velocita_max), elapse=1)\n get_bot().sleep(attesa)\n get_bot().left(speed=min(max(100 * velocita, 1), velocita_max), elapse=3)\n get_bot().sleep(attesa)\n get_bot().forward(speed=min(max(100 * velocita, 1), velocita_max), elapse=1)\n get_bot().sleep(attesa)\n\n# Descrivi questa funzione...\ndef MarciaIndietro_e_Scarto():\n global attesa, velocita_max, var_marciaIndietro, var_giravolte, var_ritirata, velocita, stanco\n get_prog_eng().check_end()\n get_bot().backward(speed=min(max(100 * velocita, 1), velocita_max), elapse=1)\n get_bot().sleep(attesa)\n get_bot().right(speed=min(max(100 * velocita, 1), velocita_max), elapse=1)\n get_bot().sleep(attesa)\n\n\nattesa = 0.2\nvelocita_max = 80\nvar_marciaIndietro = 0\nvar_giravolte = 0\nvar_ritirata = 0\nstanco = 0\nvelocita = 1\nwhile True:\n get_prog_eng().check_end()\n stanco = (stanco if isinstance(stanco, Number) else 0) + 1\n var_marciaIndietro = (var_marciaIndietro if isinstance(var_marciaIndietro, Number) else 0) + 1\n var_giravolte = (var_giravolte if isinstance(var_giravolte, Number) else 0) + 1\n var_ritirata = (var_ritirata if isinstance(var_ritirata, Number) else 0) + 1\n if stanco == 5:\n stanco = 0\n velocita = 1\n elif stanco > 3:\n velocita = 0.5\n Scodinzola()\n Evita_Ostacoli()\n Patugliamento()\n if var_ritirata == 4:\n var_ritirata = 0\n Ritirata_e_fuga()\n if var_giravolte == 8:\n var_giravolte = 0\n Giravolte()\n get_bot().sleep(5)\n if var_marciaIndietro == 6:\n var_marciaIndietro = 0\n MarciaIndietro_e_Scarto()\n","default":""} \ No newline at end of file diff --git a/defaults/programs/program_demo_sound_clap_control.json b/defaults/programs/program_demo_sound_clap_control.json new file mode 100644 index 00000000..29f377f3 --- /dev/null +++ b/defaults/programs/program_demo_sound_clap_control.json @@ -0,0 +1 @@ +{"dom_code": "WHILETRUEnoise10000.2noiseEQnoiseFALSEFORWARD100-1RIGHT1000.5", "code": "noise = None\n\n\nwhile True:\n get_prog_eng().check_end()\n noise = get_audio().hear(level=1000, elapse=0.2)\n get_cam().set_text(noise)\n if noise == False:\n get_bot().forward(speed=100, elapse=-1)\n else:\n get_bot().right(speed=100, elapse=0.5)\nget_bot().stop()\n", "name": "clap_control"} \ No newline at end of file diff --git a/defaults/programs/program_test_cnn_classifier.json b/defaults/programs/program_test_cnn_classifier.json new file mode 100644 index 00000000..e79a8329 --- /dev/null +++ b/defaults/programs/program_test_cnn_classifier.json @@ -0,0 +1 @@ +{"name": "test_cnn_classifier", "dom_code": "WHILETRUEgeneric_fast_low", "code": "while True:\n get_prog_eng().check_end()\n get_cam().set_text(get_cam().cnn_classify(\"generic_fast_low\"))\n"} \ No newline at end of file diff --git a/defaults/programs/program_test_cnn_object_detect.json b/defaults/programs/program_test_cnn_object_detect.json new file mode 100644 index 00000000..9723235d --- /dev/null +++ b/defaults/programs/program_test_cnn_object_detect.json @@ -0,0 +1 @@ +{"name": "test_cnn_object_detect", "dom_code": "WHILETRUEgeneric_object_detect", "code": "while True:\n get_prog_eng().check_end()\n get_cam().set_text(get_cam().cnn_detect_objects(\"generic_object_detect\"))\n"} \ No newline at end of file diff --git a/defaults/programs/program_test_find_code.json b/defaults/programs/program_test_find_code.json new file mode 100644 index 00000000..0f16e779 --- /dev/null +++ b/defaults/programs/program_test_find_code.json @@ -0,0 +1 @@ +{"dom_code": "WHILETRUE", "code": "while True:\n get_prog_eng().check_end()\n get_cam().set_text(get_cam().find_qr_code())\n", "name": "find_code_test"} \ No newline at end of file diff --git a/defaults/programs/program_test_find_color.json b/defaults/programs/program_test_find_color.json new file mode 100644 index 00000000..68bc4586 --- /dev/null +++ b/defaults/programs/program_test_find_color.json @@ -0,0 +1 @@ +{"dom_code": "WHILETRUEdistDIST#96b73cangleANGLE#96b73cDistance: dist angle: angle", "code": "dist = None\nangle = None\n\n\nwhile True:\n get_prog_eng().check_end()\n dist = get_cam().find_color('#96b73c')[0]\n angle = get_cam().find_color('#96b73c')[1]\n get_cam().set_text(''.join([str(temp_value) for temp_value in ['Distance: ', dist, ' angle: ', angle]]))\n", "name": "find_color"} \ No newline at end of file diff --git a/defaults/programs/program_test_find_face.json b/defaults/programs/program_test_find_face.json new file mode 100644 index 00000000..ace65032 --- /dev/null +++ b/defaults/programs/program_test_find_face.json @@ -0,0 +1 @@ +{"dom_code": "faceface_xface_sizeWHILETRUEfaceALLface_xGETFROM_STARTface1face_sizeGETFROM_STARTface2face: face_xface_xLTface_x-10LEFT800.1GTface_x10RIGHT800.1", "code": "face = None\nface_x = None\nface_size = None\n\n\nwhile True:\n get_prog_eng().check_end()\n face = get_cam().find_face()\n face_x = face[0]\n face_size = face[1]\n get_cam().set_text(str('face: ') + str(face_x))\n if face_x:\n if face_x < -10:\n get_bot().left(speed=80, elapse=0.1)\n elif face_x > 10:\n get_bot().right(speed=80, elapse=0.1)\n else:\n get_bot().stop()\n", "name": "face_find"} \ No newline at end of file diff --git a/defaults/programs/program_test_find_path_ahead.json b/defaults/programs/program_test_find_path_ahead.json new file mode 100644 index 00000000..c494a2d2 --- /dev/null +++ b/defaults/programs/program_test_find_path_ahead.json @@ -0,0 +1 @@ +{"dom_code": "spazio_liberoWHILETRUEspazio_liberospazio_liberoANDGTspazio_libero30NEQspazio_libero60FORWARD1000.2RIGHT1000.2", "code": "spazio_libero = None\n\n\nwhile True:\n get_prog_eng().check_end()\n spazio_libero = get_cam().path_ahead()\n get_cam().set_text(spazio_libero)\n if spazio_libero > 30 and spazio_libero != 60:\n get_bot().forward(speed=100, elapse=0.2)\n else:\n get_bot().right(speed=100, elapse=0.2)\n", "name": "path_ahead"} \ No newline at end of file diff --git a/defaults/programs/program_test_img_average.json b/defaults/programs/program_test_img_average.json new file mode 100644 index 00000000..90bacb94 --- /dev/null +++ b/defaults/programs/program_test_img_average.json @@ -0,0 +1 @@ +{"dom_code": "WHILETRUEV", "code": "while True:\n get_prog_eng().check_end()\n get_cam().set_text(get_cam().get_average()[2])\n", "name": "img_average_test"} \ No newline at end of file diff --git a/defaults/programs/program_test_input.json b/defaults/programs/program_test_input.json new file mode 100644 index 00000000..781dc25a --- /dev/null +++ b/defaults/programs/program_test_input.json @@ -0,0 +1 @@ +{"name": "test_input", "dom_code": "WHILETRUEanalog 1: 0 analog 2: 1 digital 1: 2", "code": "while True:\n get_prog_eng().check_end()\n get_cam().set_text(''.join([str(x) for x in ['analog 1: ', get_atmega().get_input(0), ' analog 2: ', get_atmega().get_input(1), ' digital 1: ', get_atmega().get_input(2)]]))\n"} \ No newline at end of file diff --git a/defaults/programs/program_test_led.json b/defaults/programs/program_test_led.json new file mode 100644 index 00000000..7246e80d --- /dev/null +++ b/defaults/programs/program_test_led.json @@ -0,0 +1 @@ +{"name": "test_led", "dom_code": "ledsicleds6031leds000i1leds11MINUSi1000ADDi5leds000c11005iADDi5MULTIPLYc0MULTIPLYc0MULTIPLYc31leds000", "code": "leds = None\ni = None\nc = None\n\ndef upRange(start, stop, step):\n while start <= stop:\n yield start\n start += abs(step)\n\ndef downRange(start, stop, step):\n while start >= stop:\n yield start\n start -= abs(step)\n\n\nleds = 60\nfor count in range(3):\n get_prog_eng().check_end()\n get_atmega().set_led(1, leds, 0, 0, 0)\n for i in (1 <= float(leds)) and upRange(1, float(leds), 1) or downRange(1, float(leds), 1):\n get_prog_eng().check_end()\n get_atmega().set_led(1, i - 1, 0, 0, 0)\n get_atmega().set_led(i + 5, leds, 0, 0, 0)\n for c in range(1, 101, 5):\n get_prog_eng().check_end()\n get_atmega().set_led(i, i + 5, c * 0, c * 0, c * 3)\n get_atmega().set_led(1, leds, 0, 0, 0)\n"} \ No newline at end of file diff --git a/defaults/programs/program_test_music.json b/defaults/programs/program_test_music.json new file mode 100644 index 00000000..a3d0f3fd --- /dev/null +++ b/defaults/programs/program_test_music.json @@ -0,0 +1 @@ +{"name": "test_music", "dom_code": "C2nonedog1D2nonecat1E2nonepig1F2noneelephant1G2nonesnake1A2noneduck1B2nonecat1", "code": "get_music().play_note(note=\"C2\", alteration=\"none\" ,instrument=\"dog\" ,duration=1)\nget_music().play_note(note=\"D2\", alteration=\"none\" ,instrument=\"cat\" ,duration=1)\nget_music().play_note(note=\"E2\", alteration=\"none\" ,instrument=\"pig\" ,duration=1)\nget_music().play_note(note=\"F2\", alteration=\"none\" ,instrument=\"elephant\" ,duration=1)\nget_music().play_note(note=\"G2\", alteration=\"none\" ,instrument=\"snake\" ,duration=1)\nget_music().play_note(note=\"A2\", alteration=\"none\" ,instrument=\"duck\" ,duration=1)\nget_music().play_note(note=\"B2\", alteration=\"none\" ,instrument=\"cat\" ,duration=1)\n"} \ No newline at end of file diff --git a/defaults/programs/program_test_output.json b/defaults/programs/program_test_output.json new file mode 100644 index 00000000..dbd31e04 --- /dev/null +++ b/defaults/programs/program_test_output.json @@ -0,0 +1 @@ +{"name": "test_output", "dom_code": "WHILETRUE0TRUE0.11TRUE0.12TRUE0.10FALSE0.11FALSE0.12FALSE0.1", "code": "while True:\n get_prog_eng().check_end()\n get_atmega().set_output(0, True)\n get_bot().sleep(0.1)\n get_atmega().set_output(1, True)\n get_bot().sleep(0.1)\n get_atmega().set_output(2, True)\n get_bot().sleep(0.1)\n get_atmega().set_output(0, False)\n get_bot().sleep(0.1)\n get_atmega().set_output(1, False)\n get_bot().sleep(0.1)\n get_atmega().set_output(2, False)\n get_bot().sleep(0.1)\n"} \ No newline at end of file diff --git a/defaults/programs/program_test_sonars.json b/defaults/programs/program_test_sonars.json new file mode 100644 index 00000000..6664424a --- /dev/null +++ b/defaults/programs/program_test_sonars.json @@ -0,0 +1 @@ +{"name": "test_sonars", "dom_code": "WHILETRUEFront: 0 Right: 1 Left: 2", "code": "while True:\n get_prog_eng().check_end()\n get_cam().set_text(''.join([str(x) for x in ['Front: ', get_bot().get_sonar_distance(0), ' Right: ', get_bot().get_sonar_distance(1), ' Left: ', get_bot().get_sonar_distance(2)]]))\n"} \ No newline at end of file diff --git a/defaults/programs/program_test_sound_hear.json b/defaults/programs/program_test_sound_hear.json new file mode 100644 index 00000000..31ff1247 --- /dev/null +++ b/defaults/programs/program_test_sound_hear.json @@ -0,0 +1 @@ +{"dom_code": "WHILETRUE1001.0", "code": "while True:\n get_prog_eng().check_end()\n get_cam().set_text(get_audio().hear(level=100, elapse=1))\n", "name": "hear_test"} \ No newline at end of file diff --git a/defaults/programs/program_test_sound_rec.json b/defaults/programs/program_test_sound_rec.json new file mode 100644 index 00000000..de267400 --- /dev/null +++ b/defaults/programs/program_test_sound_rec.json @@ -0,0 +1 @@ +{"dom_code": "test01.wav5", "code": "get_audio().record_to_file(filename='test01.wav', elapse=5)\n", "name": "sound_rec_test"} \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..40a5fafa --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,71 @@ +FROM coderbot/rpi-debian:bullseye-20240227 + +ENV QEMU_CPU=max +ENV DEBIAN_FRONTEND=noninteractive + +RUN install_packages \ + libraspberrypi0 \ + procps \ + sudo \ + wget \ + unzip \ + xz-utils \ + ffmpeg \ + portaudio19-dev \ + python3 \ + python3-pip \ + libopenjp2-7-dev \ + libtiff5 \ + libatlas-base-dev \ + libhdf5-dev \ + alsa-utils \ + espeak +RUN install_packages \ + libharfbuzz-bin \ + libwebp6 \ + libjasper1 \ + libilmbase25 \ + libgstreamer1.0-0 \ + libavcodec-extra58 \ + libavformat58 +RUN install_packages \ + libopencv-dev \ + zbar-tools \ + libzbar0 \ + sox \ + libsox-fmt-all \ + libopenblas-dev +RUN install_packages \ + avrdude \ + tesseract-ocr \ + tesseract-ocr-eng \ + tesseract-ocr-ita \ + tesseract-ocr-fra \ + tesseract-ocr-spa \ + tesseract-ocr-deu + +ENV READTHEDOCS=True +ADD requirements.txt /tmp/. +RUN pip install --no-cache-dir -r /tmp/requirements.txt + +RUN mkdir -p /coderbot && \ +mkdir -p /coderbot/data && \ +mkdir -p /coderbot/logs && \ +mkdir -p /coderbot/cnn_modules && \ +mkdir -p /coderbot/coderbot && \ +mkdir -p /coderbot/defaults && \ +mkdir -p /coderbot/sounds + +ADD coderbot /coderbot/coderbot/. +ADD defaults /coderbot/defaults/. +ADD sounds /coderbot/sounds/. + +ADD docker/scripts/*.sh /tmp/. +RUN /tmp/install_generic_cnn_models.sh +RUN /tmp/install_lib_firmware.sh +ADD docker/start.sh /coderbot/. + +ARG CODERBOT_VERSION +ENV CODERBOT_VERSION=${CODERBOT_VERSION} + +ENTRYPOINT /coderbot/start.sh diff --git a/docker/scripts/install_generic_cnn_models.sh b/docker/scripts/install_generic_cnn_models.sh new file mode 100755 index 00000000..8b0bfe0e --- /dev/null +++ b/docker/scripts/install_generic_cnn_models.sh @@ -0,0 +1,8 @@ +#!/bin/bash +CUR_DIR=$(pwd) +cd /coderbot +wget -nc https://github.com/CoderBotOrg/net-models/raw/master/archive/cnn_models.tar.xz +tar xJf cnn_models.tar.xz +rm cnn_models.tar.xz +echo '{"generic_fast_low":{"status":1.0, "image_height": "128", "image_width":"128", "output_layer": "MobilenetV2/Predictions/Reshape_1"}, "generic_slow_high":{"status":1.0, "image_height":"224", "image_width": "224", "output_layer": "MobilenetV2/Predictions/Reshape_1"}}' > models.json +cd $CUR_DIR \ No newline at end of file diff --git a/docker/scripts/install_lib_firmware.sh b/docker/scripts/install_lib_firmware.sh new file mode 100755 index 00000000..50650608 --- /dev/null +++ b/docker/scripts/install_lib_firmware.sh @@ -0,0 +1,13 @@ +#!/bin/bash +CUR_DIR=$(pwd) +cd /usr/lib/arm-linux-gnueabihf +ln -s libbcm_host.so.0 libbcm_host.so +ln -s libmmal.so.0 libmmal.so +ln -s libmmal_core.so.0 libmmal_core.so +ln -s libmmal_util.so.0 libmmal_util.so +ln -s libmmal_vc_client.so.0 libmmal_vc_client.so +ln -s libbcm_host.so.0 libbcm_host.so +ln -s libvcsm.so.0 libvcsm.so +ln -s libvchiq_arm.so.0 libvchiq_arm.so +ln -s libvcos.so.0 libvcos.so +cd $CUR_DIR \ No newline at end of file diff --git a/docker/start.sh b/docker/start.sh new file mode 100755 index 00000000..dda61b36 --- /dev/null +++ b/docker/start.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# disable ethernet, usb +[ "$CODERBOT_disable_eth_usb" = "true" ] && echo '1-1' | tee /sys/bus/usb/drivers/usb/unbind +# disable HDMI output +/usr/bin/tvservice -o +# enable i2c driver +modprobe i2c-dev +# set home +cd /coderbot +# start coderbot +python3 coderbot/main.py diff --git a/docker/stub/Dockerfile b/docker/stub/Dockerfile new file mode 100644 index 00000000..66281565 --- /dev/null +++ b/docker/stub/Dockerfile @@ -0,0 +1,66 @@ +FROM debian:bullseye-slim + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update -y && apt-get install -y \ + procps \ + sudo \ + wget \ + unzip \ + xz-utils \ + ffmpeg \ + portaudio19-dev \ + python3 \ + python3-pip \ + libopenjp2-7-dev \ + libtiff5 \ + libatlas-base-dev \ + libhdf5-dev \ + alsa-utils \ + espeak \ + libharfbuzz-bin \ + libwebp6 \ + libilmbase25 \ + libgstreamer1.0-0 \ + libavcodec-extra58 \ + libavformat58 \ + libopencv-dev \ + zbar-tools \ + libzbar0 \ + sox \ + libsox-fmt-all \ + libopenblas-dev \ + avrdude \ + tesseract-ocr \ + tesseract-ocr-eng \ + tesseract-ocr-ita \ + tesseract-ocr-fra \ + tesseract-ocr-spa \ + tesseract-ocr-deu + +ADD docker/stub/requirements.txt /tmp/. +RUN pip install --no-cache-dir -r /tmp/requirements.txt + +RUN mkdir -p /coderbot && \ +mkdir -p /coderbot/data && \ +mkdir -p /coderbot/logs && \ +mkdir -p /coderbot/updatePackages && \ +mkdir -p /coderbot/cnn_modules && \ +mkdir -p /coderbot/coderbot && \ +mkdir -p /coderbot/defaults && \ +mkdir -p /coderbot/sounds + +ADD coderbot /coderbot/coderbot/. +ADD stub /coderbot/stub/. +ADD test /coderbot/test/. +ADD defaults /coderbot/defaults/. +ADD sounds /coderbot/sounds/. + +ADD docker/scripts/*.sh /tmp/. +RUN /tmp/install_generic_cnn_models.sh +ADD docker/stub/start.sh /coderbot/. + +ARG CODERBOT_VERSION +ENV CODERBOT_VERSION=${CODERBOT_VERSION} + +ENTRYPOINT /coderbot/start.sh diff --git a/docker/stub/requirements.txt b/docker/stub/requirements.txt new file mode 100644 index 00000000..d937b268 --- /dev/null +++ b/docker/stub/requirements.txt @@ -0,0 +1,23 @@ +# API framework +connexion[uvicorn,flask,swagger-ui]==3.0.5 +tinydb==4.8.0 + +# Misc utils +setuptools==69.2.0 +event-channel==0.4.3 + +# IO extensions +spidev==3.6 + +# Audio +sox==1.4.1 + +# Computer Vision +grpcio==1.62.1 +numpy==1.26.4 +Pillow==10.2.0 +protobuf==4.25.2 +opencv-contrib-python==4.5.5.62 +tflite-runtime==2.11.0 +pytesseract==0.3.10 +pyzbar==0.1.9 diff --git a/docker/stub/start.sh b/docker/stub/start.sh new file mode 100755 index 00000000..f28cc766 --- /dev/null +++ b/docker/stub/start.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +export PYTHONPATH=./stub:./test:./coderbot +cd /coderbot +python3 coderbot/main.py & python3 stub/wifi/main.py \ No newline at end of file diff --git a/init.py b/init.py deleted file mode 100755 index cc459059..00000000 --- a/init.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/python - -import coderbot -import main - -if __name__=="__main__": - main.run_server() diff --git a/main.py b/main.py deleted file mode 100644 index 8858e5b4..00000000 --- a/main.py +++ /dev/null @@ -1,227 +0,0 @@ -import os -import json -import logging -import logging.handlers - -from coderbot import CoderBot, PIN_PUSHBUTTON -from camera import Camera -from motion import Motion -from program import ProgramEngine, Program -from config import Config - -from flask import Flask, render_template, request, send_file, redirect -from flask.ext.babel import Babel -#from flask_sockets import Sockets - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# add a rotating handler -handler = logging.handlers.RotatingFileHandler('logs/coderbot.log', maxBytes=1000000, backupCount=5) -logger.addHandler(handler) - -bot = None -cam = None -motion = None - -app = Flask(__name__,static_url_path="") -#app.config.from_pyfile('coderbot.cfg') -babel = Babel(app) -app.debug = True -#sockets = Sockets(app) - -app.prog_engine = ProgramEngine.get_instance() -app.prog = None - -@babel.localeselector -def get_locale(): - # otherwise try to guess the language from the user accept - # header the browser transmits. - loc = request.accept_languages.best_match(['it', 'en']) - if loc is None: - loc = 'it' - return loc - -@app.route("/") -def handle_home(): - return render_template('main.html', host=request.host[:request.host.find(':')], stream_port=cam.stream_port, locale = get_locale(), config=app.bot_config, program_level=app.bot_config.get("prog_level", "std")) - -@app.route("/config", methods=["POST"]) -def handle_config(): - Config.write(request.form) - app.bot_config = Config.get() - return "ok"; - -@app.route("/wifi", methods=["POST"]) -def handle_wifi(): - mode = request.form.get("wifi_mode") - ssid = request.form.get("wifi_ssid") - psk = request.form.get("wifi_psk") - logging.info( "mode ", mode, " ssid: ", ssid, " psk: ", psk) - client_params = " \"" + ssid + "\" \"" + psk + "\"" if ssid != "" and psk != "" else "" - logging.info(client_params) - os.system("sudo python wifi.py updatecfg " + mode + client_params) - if mode == "ap": - return "http://coder.bot:8080/"; - else: - return "http://coderbotsrv.appspot.com/" - -@app.route("/bot", methods=["GET"]) -def handle_bot(): - cmd = request.args.get('cmd') - param1 = request.args.get('param1') - param2 = request.args.get('param2') - - if cmd == "move": - bot.move(speed=int(param1), elapse=float(param2)) - elif cmd == "turn": - bot.turn(speed=int(param1), elapse=float(param2)) - elif cmd == "move_motion": - motion.move(dist=float(param2)) - elif cmd == "turn_motion": - motion.turn(angle=float(param2)) - elif cmd == "stop": - bot.stop() - motion.stop() - elif cmd == "take_photo": - cam.photo_take() - bot.say(app.bot_config.get("sound_shutter")) - elif cmd == "video_rec": - cam.video_rec() - bot.say(app.bot_config.get("sound_shutter")) - elif cmd == "video_stop": - cam.video_stop() - bot.say(app.bot_config.get("sound_shutter")) - - elif cmd == "say": - logging.info("say: " + str(param1)) - bot.say(param1) - - elif cmd == "halt": - logging.info("shutting down") - bot.say(app.bot_config.get("sound_stop")) - bot.halt() - elif cmd == "restart": - logging.info("restarting bot") - bot.restart() - elif cmd == "reboot": - logging.info("rebooting") - bot.reboot() - - return "ok" - -@app.route("/bot/status", methods=["GET"]) -def handle_bot_status(): - logging.info( "bot_status" ) - return json.dumps({'status': 'ok'}) - -@app.route("/photos", methods=["GET"]) -def handle_photos(): - logging.info("photos") - return json.dumps(cam.get_photo_list()) - -@app.route("/photos/", methods=["GET"]) -def handle_photo(filename): - logging.info("photo") - mimetype = {'jpeg': 'image/jpeg', 'h264': 'video/mp4'} - video = None - try: - video = cam.get_photo_file(filename) - except: - pass - - return send_file(video, mimetype.get(filename[:-3],'image'), cache_timeout=0) - -@app.route("/photos/", methods=["POST"]) -def handle_photo_cmd(filename): - logging.debug("photo delete") - cam.delete_photo(filename) - return "ok" - -@app.route("/photos//thumb", methods=["GET"]) -def handle_photo_thumb(filename): - logging.debug("photo_thumb") - return send_file(cam.get_photo_thumb_file(filename)) - -@app.route("/program/list", methods=["GET"]) -def handle_program_list(): - logging.debug("program_list") - return json.dumps(app.prog_engine.list()) - -@app.route("/program/load", methods=["GET"]) -def handle_program_load(): - logging.debug("program_load") - name = request.args.get('name') - app.prog = app.prog_engine.load(name) - return app.prog.dom_code - -@app.route("/program/save", methods=["POST"]) -def handle_program_save(): - logging.debug("program_save") - name = request.form.get('name') - dom_code = request.form.get('dom_code') - code = request.form.get('code') - prog = Program(name, dom_code = dom_code, code = code) - app.prog_engine.save(prog) - return "ok" - -@app.route("/program/delete", methods=["POST"]) -def handle_program_delete(): - logging.debug("program_delete") - name = request.form.get('name') - app.prog_engine.delete(name) - return "ok" - -@app.route("/program/exec", methods=["POST"]) -def handle_program_exec(): - logging.debug("program_exec") - name = request.form.get('name') - code = request.form.get('code') - app.prog = app.prog_engine.create(name, code) - return json.dumps(app.prog.execute()) - -@app.route("/program/end", methods=["POST"]) -def handle_program_end(): - logging.debug("program_end") - if app.prog: - app.prog.end() - app.prog = None - return "ok" - -@app.route("/program/status", methods=["GET"]) -def handle_program_status(): - logging.debug("program_status") - prog = Program("") - if app.prog: - prog = app.prog - return json.dumps({'name': prog.name, "running": prog.is_running()}) - -@app.route("/tutorial") -def handle_tutorial(): - return redirect("/blockly-tutorial/apps/index.html", code=302) - -def button_pushed(): - if app.bot_config.get('button_func') == "startstop": - if app.prog and app.prog.is_running(): - app.prog.end() - elif app.prog and not app.prog.is_running(): - app.prog.execute() - -def run_server(): - global bot - global cam - global motion - try: - app.bot_config = Config.read() - bot = CoderBot.get_instance(servo=(app.bot_config.get("move_motor_mode")=="servo")) - cam = Camera.get_instance() - motion = Motion.get_instance() - except ValueError as e: - app.bot_config = {} - logging.error(e) - if app.bot_config.get('load_at_start') and len(app.bot_config.get('load_at_start')): - app.prog = app.prog_engine.load(app.bot_config.get('load_at_start')) - - bot.set_callback(PIN_PUSHBUTTON, button_pushed, 100) - bot.say(app.bot_config.get("sound_start")) - app.run(host="0.0.0.0", port=8080, debug=True, use_reloader=False, threaded=True) diff --git a/messages.pot b/messages.pot deleted file mode 100644 index 1234ecd0..00000000 --- a/messages.pot +++ /dev/null @@ -1,439 +0,0 @@ -# Translations template for PROJECT. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the PROJECT project. -# FIRST AUTHOR , 2015. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PROJECT VERSION\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-04-04 00:32+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 1.3\n" - -#: templates/blocks_adv.xml:2 templates/blocks_std.xml:13 -msgid "Logic" -msgstr "" - -#: templates/blocks_adv.xml:11 -msgid "Loops" -msgstr "" - -#: templates/blocks_adv.xml:40 templates/blocks_std.xml:24 -msgid "Math" -msgstr "" - -#: templates/blocks_adv.xml:83 templates/blocks_std.xml:29 -msgid "Text" -msgstr "" - -#: templates/blocks_adv.xml:96 templates/blocks_adv.xml:103 -#: templates/blocks_adv.xml:110 -msgid "text" -msgstr "" - -#: templates/blocks_adv.xml:123 -msgid "Lists" -msgstr "" - -#: templates/blocks_adv.xml:138 templates/blocks_adv.xml:145 -#: templates/blocks_adv.xml:152 templates/blocks_adv.xml:159 -msgid "list" -msgstr "" - -#: templates/blocks_adv.xml:164 -msgid "Colour" -msgstr "" - -#: templates/blocks_adv.xml:170 templates/blocks_std.xml:19 -msgid "Variables" -msgstr "" - -#: templates/blocks_adv.xml:171 -msgid "Functions" -msgstr "" - -#: templates/blocks_adv.xml:172 templates/blocks_std.xml:35 -#: templates/config.html:15 -msgid "Movement" -msgstr "" - -#: templates/blocks_adv.xml:229 -msgid "Camera" -msgstr "" - -#: templates/blocks_adv.xml:234 templates/blocks_std.xml:61 -#: templates/config.html:14 -msgid "Sensor" -msgstr "" - -#: templates/blocks_adv.xml:246 templates/blocks_std.xml:73 -msgid "Sound" -msgstr "" - -#: templates/blocks_std.xml:2 templates/config.html:11 templates/control.html:8 -#: templates/program.html:8 -msgid "Control" -msgstr "" - -#: templates/config.html:3 templates/control.html:63 -msgid "Back" -msgstr "" - -#: templates/config.html:12 -msgid "Programming" -msgstr "" - -#: templates/config.html:13 -msgid "Sounds" -msgstr "" - -#: templates/config.html:16 -msgid "Start" -msgstr "" - -#: templates/config.html:17 -msgid "Button" -msgstr "" - -#: templates/config.html:18 templates/config.html:127 -msgid "User Interface" -msgstr "" - -#: templates/config.html:19 -msgid "WiFi" -msgstr "" - -#: templates/config.html:24 templates/config.html:63 -msgid "Movement assisted by vision" -msgstr "" - -#: templates/config.html:27 -msgid "Step timing | distance / angle" -msgstr "" - -#: templates/config.html:28 templates/config.html:66 -msgid "Forward speed" -msgstr "" - -#: templates/config.html:30 templates/config.html:68 -msgid "Forward elapse / distance" -msgstr "" - -#: templates/config.html:32 templates/config.html:70 -msgid "Turn speed" -msgstr "" - -#: templates/config.html:34 templates/config.html:72 -msgid "Turn elapse / angle" -msgstr "" - -#: templates/config.html:37 -msgid "Show control counter" -msgstr "" - -#: templates/config.html:40 -msgid "HUD image name" -msgstr "" - -#: templates/config.html:45 -msgid "Editor level" -msgstr "" - -#: templates/config.html:47 -msgid "Move" -msgstr "" - -#: templates/config.html:49 -msgid "Basic" -msgstr "" - -#: templates/config.html:51 -msgid "Standard" -msgstr "" - -#: templates/config.html:53 -msgid "Advanced" -msgstr "" - -#: templates/config.html:56 -msgid "Program editor details" -msgstr "" - -#: templates/config.html:57 -msgid "Shows Editor scrollbars" -msgstr "" - -#: templates/config.html:59 -msgid "Save program before every run" -msgstr "" - -#: templates/config.html:75 -msgid "Other program parameters" -msgstr "" - -#: templates/config.html:76 -msgid "Auto record video on program run" -msgstr "" - -#: templates/config.html:79 -msgid "Max number of blocks allowed" -msgstr "" - -#: templates/config.html:83 -msgid "Start sound" -msgstr "" - -#: templates/config.html:85 -msgid "Stop sound" -msgstr "" - -#: templates/config.html:87 -msgid "Shutter sound" -msgstr "" - -#: templates/config.html:91 -msgid "Camera parameters" -msgstr "" - -#: templates/config.html:92 -msgid "Exposure mode" -msgstr "" - -#: templates/config.html:103 -msgid "Motor control mode" -msgstr "" - -#: templates/config.html:105 -msgid "Power (target angle -15)" -msgstr "" - -#: templates/config.html:107 -msgid "Power (target angle -4)" -msgstr "" - -#: templates/config.html:109 -msgid "Power (target angle -1)" -msgstr "" - -#: templates/config.html:113 -msgid "Load at start" -msgstr "" - -#: templates/config.html:118 -msgid "Button function" -msgstr "" - -#: templates/config.html:119 -msgid "None" -msgstr "" - -#: templates/config.html:121 -msgid "Start/Stop current program" -msgstr "" - -#: templates/config.html:128 -msgid "Show Control page" -msgstr "" - -#: templates/config.html:130 -msgid "Show Control movement commands" -msgstr "" - -#: templates/config.html:132 -msgid "Show Program page" -msgstr "" - -#: templates/config.html:134 -msgid "Show Preferences button" -msgstr "" - -#: templates/config.html:139 -msgid "WiFi Client access mode" -msgstr "" - -#: templates/config.html:142 templates/config.html:164 -msgid "Cancel" -msgstr "" - -#: templates/config.html:143 templates/program.html:18 -#: templates/program.html:26 -msgid "Save" -msgstr "" - -#: templates/config.html:151 -msgid "WiFi Client mode access data" -msgstr "" - -#: templates/config.html:153 -msgid "WiFi mode" -msgstr "" - -#: templates/config.html:155 -msgid "Access Point" -msgstr "" - -#: templates/config.html:157 -msgid "Client" -msgstr "" - -#: templates/config.html:159 -msgid "WiFi name" -msgstr "" - -#: templates/config.html:161 -msgid "WiFi password" -msgstr "" - -#: templates/config.html:165 -msgid "Apply Wifi config" -msgstr "" - -#: templates/config.html:172 -msgid "WiFi AP mode access" -msgstr "" - -#: templates/config.html:184 -msgid "WiFi Client mode access" -msgstr "" - -#: templates/config_params.html:20 -msgid "Say what:" -msgstr "" - -#: templates/config_params.html:21 -msgid "Saved" -msgstr "" - -#: templates/config_params.html:22 -msgid "Program saved" -msgstr "" - -#: templates/config_params.html:23 -msgid "Program name already in use, overwrite?" -msgstr "" - -#: templates/config_params.html:24 -msgid "Delete" -msgstr "" - -#: templates/config_params.html:25 -msgid "Delete photo" -msgstr "" - -#: templates/config_params.html:26 -msgid "Reset move counter?" -msgstr "" - -#: templates/config_params.html:27 templates/program.html:40 -msgid "is running" -msgstr "" - -#: templates/config_params.html:28 -msgid "stopped" -msgstr "" - -#: templates/config_params.html:29 templates/control.html:51 -#: templates/program.html:32 -msgid "Stop" -msgstr "" - -#: templates/config_params.html:30 -msgid "Close" -msgstr "" - -#: templates/control.html:5 templates/program.html:5 -msgid "Preferences" -msgstr "" - -#: templates/control.html:9 templates/program.html:9 -msgid "Program" -msgstr "" - -#: templates/control.html:19 -msgid "Halt" -msgstr "" - -#: templates/control.html:24 -msgid "Forward" -msgstr "" - -#: templates/control.html:27 -msgid "Left" -msgstr "" - -#: templates/control.html:28 -msgid "Right" -msgstr "" - -#: templates/control.html:31 -msgid "Backward" -msgstr "" - -#: templates/control.html:40 -msgid "Say" -msgstr "" - -#: templates/control.html:45 -msgid "Photo" -msgstr "" - -#: templates/control.html:50 -msgid "Rec" -msgstr "" - -#: templates/control.html:54 -msgid "Photos" -msgstr "" - -#: templates/program.html:16 templates/program.html:24 -msgid "New" -msgstr "" - -#: templates/program.html:17 templates/program.html:25 -msgid "Load" -msgstr "" - -#: templates/program.html:19 templates/program.html:31 -msgid "Run" -msgstr "" - -#: templates/program.html:20 -msgid "Show last" -msgstr "" - -#: templates/program.html:27 -msgid "Save as" -msgstr "" - -#: templates/program.html:30 -msgid "Show" -msgstr "" - -#: templates/program.html:51 -msgid "New Program" -msgstr "" - -#: templates/program.html:52 templates/program.html:53 -#: templates/program.html:60 templates/program.html:61 -msgid "Program name" -msgstr "" - -#: templates/program.html:54 templates/program.html:62 -msgid "Create" -msgstr "" - -#: templates/program.html:59 -msgid "Save Program As" -msgstr "" - -#: templates/program.html:67 -msgid "Load Program" -msgstr "" - diff --git a/program.py b/program.py deleted file mode 100644 index 80d507de..00000000 --- a/program.py +++ /dev/null @@ -1,143 +0,0 @@ -import os -import sys -import threading -import json -import logging - -import coderbot -import camera -import motion -import config - -PROGRAM_PATH = "./data/" -PROGRAM_PREFIX = "program_" -PROGRAM_SUFFIX = ".data" - -def get_cam(): - return camera.Camera.get_instance() - -def get_bot(): - return coderbot.CoderBot.get_instance() - -def get_motion(): - return motion.Motion.get_instance() - -def get_prog_eng(): - return ProgramEngine.get_instance() - -class ProgramEngine: - - _instance = None - - def __init__(self): - self._program = None - self._repository = {} - for dirname, dirnames, filenames, in os.walk("./data"): - for filename in filenames: - if PROGRAM_PREFIX in filename: - program_name = filename[len(PROGRAM_PREFIX):-len(PROGRAM_SUFFIX)] - self._repository[program_name] = filename - - @classmethod - def get_instance(cls): - if not cls._instance: - cls._instance = ProgramEngine() - return cls._instance - - def list(self): - return self._repository.keys() - - def save(self, program): - self._program = self._repository[program.name] = program - f = open(PROGRAM_PATH + PROGRAM_PREFIX + program.name + PROGRAM_SUFFIX, 'w') - json.dump(program.as_json(), f) - f.close() - - def load(self, name): - #return self._repository[name] - f = open(PROGRAM_PATH + PROGRAM_PREFIX + name + PROGRAM_SUFFIX, 'r') - self._program = Program.from_json(json.load(f)) - return self._program - - def delete(self, name): - del self._repository[name] - os.remove(PROGRAM_PATH + PROGRAM_PREFIX + name + PROGRAM_SUFFIX) - return "ok" - - def create(self, name, code): - self._program = Program(name, code) - return self._program - - def is_running(self, name): - return self._repository[name].is_running() - - def check_end(self): - return self._program.check_end() - -class Program: - _running = False - - @property - def dom_code(self): - return self._dom_code - - def __init__(self, name, code=None, dom_code=None): - #super(Program, self).__init__() - self._thread = None - self.name = name - self._dom_code = dom_code - self._code = code - - def execute(self): - if self._running: - raise RuntimeError('already running') - - self._running = True - - try: - self._thread = threading.Thread(target=self.run) - self._thread.start() - except RuntimeError as re: - logging.error("RuntimeError:" + str(re)) - return "ok" - - def end(self): - if self._running: - self._running = False - self._thread.join() - - def check_end(self): - if self._running == False: - raise RuntimeError('end requested') - return None - - def is_running(self): - return self._running - - def run(self): - try: - #print "run.1" - bot = coderbot.CoderBot.get_instance() - cam = camera.Camera.get_instance() - program = self - if config.Config.get().get("prog_video_rec") == "true": - get_cam().video_rec(program.name) - logging.debug("starting video") - exec(self._code) - #print "run.2" - except RuntimeError as re: - logging.info("quit: " + str(re)) - finally: - get_cam().video_stop() #if video is running, stop it - get_motion().stop() - self._running = False - - def as_json(self): - return {'name': self.name, - 'dom_code': self._dom_code, - 'code': self._code} - - @classmethod - def from_json(cls, map): - return Program(name=map['name'], dom_code=map['dom_code'], code=map['code']) - diff --git a/pylintrc b/pylintrc new file mode 100644 index 00000000..6b6d5a4b --- /dev/null +++ b/pylintrc @@ -0,0 +1,371 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Pickle collected data for later comparisons. +persistent=yes + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Use multiple processes to speed up Pylint. +jobs=1 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" + +disable= + attribute-defined-outside-init, + duplicate-code, + fixme, + invalid-name, + missing-docstring, + protected-access, + too-few-public-methods, + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=yes + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_$|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=180 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=2000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[BASIC] + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,input + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for function names +function-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for variable names +variable-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for attribute names +attr-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for argument names +argument-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for method names +method-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=__.*__ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# List of decorators that define properties, such as abc.abstractproperty. +property-classes=abc.abstractproperty + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis +ignored-modules= + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject, optparse.Values, thread._local, _thread._local + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members=REQUEST,acl_users,aq_parent + +# List of decorators that create context managers from functions, such as +# contextlib.contextmanager. +contextmanager-decorators=contextlib.contextmanager + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=10 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=25 + +# Maximum number of return / yield for function / method body +max-returns=11 + +# Maximum number of branch for function / method body +max-branches=26 + +# Maximum number of statements in function / method body +max-statements=100 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=11 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=25 + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..d2085ec9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,28 @@ +# API framework +connexion[uvicorn,flask,swagger-ui]==3.0.5 +tinydb==4.8.0 + +# Misc utils +setuptools==69.2.0 +event-channel==0.4.3 + +# IO extensions +pigpio==1.78 +smbus2==0.4.3 +spidev==3.6 + +# Audio +sox==1.4.1 +PyAudio==0.2.14 +pyalsaaudio==0.10.0 + +# Computer Vision +grpcio==1.62.1 +numpy==1.26.4 +Pillow==10.2.0 +protobuf==4.25.2 +opencv-contrib-python==4.5.5.62 +tflite-runtime==2.11.0 +pytesseract==0.3.10 +picamera==1.13 +pyzbar==0.1.9 diff --git a/scripts/coderbot b/scripts/coderbot deleted file mode 100755 index 2d0f3d1a..00000000 --- a/scripts/coderbot +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides: myservice -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: CoderBot service -# Description: Provide CoderBot Service web application -### END INIT INFO - -# Change the next 3 lines to suit where you install your script and what you want to call it -DIR=/home/pi/coderbot -DAEMON=$DIR/init.py -DAEMON_NAME=coderbot - -# This next line determines what user the script runs as. -# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python. -DAEMON_USER=pi - -# The process ID of the script when it runs is stored here: -PIDFILE=/var/run/$DAEMON_NAME.pid - -. /lib/lsb/init-functions - -do_start () { - log_daemon_msg "Starting system $DAEMON_NAME daemon" - start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chdir $DIR --chuid $DAEMON_USER --exec /usr/bin/python -- ./init.py - log_end_msg $? -} -do_stop () { - log_daemon_msg "Stopping system $DAEMON_NAME daemon" - start-stop-daemon --stop --pidfile $PIDFILE --retry 10 - log_end_msg $? -} - -case "$1" in - - start|stop) - do_${1} - ;; - - restart|reload|force-reload) - do_stop - do_start - ;; - - status) - status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $? - ;; - *) - echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}" - exit 1 - ;; - -esac -exit 0 diff --git a/scripts/coderbot_wifi.conf b/scripts/coderbot_wifi.conf deleted file mode 100644 index d59c3b93..00000000 --- a/scripts/coderbot_wifi.conf +++ /dev/null @@ -1 +0,0 @@ -{"wifi_mode": "ap"} \ No newline at end of file diff --git a/scripts/etc/dnsmasq.conf b/scripts/etc/dnsmasq.conf deleted file mode 100644 index 497d16be..00000000 --- a/scripts/etc/dnsmasq.conf +++ /dev/null @@ -1,3 +0,0 @@ -interface=wlan0 # To get dnsmasq to listen only on wlan0. -dhcp-range=10.0.0.2,10.0.0.5,255.255.255.0,12h # This sets the available range from 10.0.0.2 to 10.0.0.5 -dhcp-authoritative diff --git a/scripts/etc/hostapd/hostapd.RT5370 b/scripts/etc/hostapd/hostapd.RT5370 deleted file mode 100644 index 922e53bf..00000000 --- a/scripts/etc/hostapd/hostapd.RT5370 +++ /dev/null @@ -1,16 +0,0 @@ -interface=wlan0 -driver=nl80211 -#driver=rtl871xdrv -ctrl_interface=/var/run/hostapd -ctrl_interface_group=0 -ssid=coderbot -hw_mode=g -channel=8 -wpa=2 -wpa_passphrase=coderbot -wpa_key_mgmt=WPA-PSK -wpa_pairwise=CCMP -rsn_pairwise=CCMP -beacon_int=100 -auth_algs=3 -wmm_enabled=1 diff --git a/scripts/etc/hostapd/hostapd.RTL8188 b/scripts/etc/hostapd/hostapd.RTL8188 deleted file mode 100644 index a1fcb119..00000000 --- a/scripts/etc/hostapd/hostapd.RTL8188 +++ /dev/null @@ -1,16 +0,0 @@ -interface=wlan0 -#driver=nl80211 -driver=rtl871xdrv -ctrl_interface=/var/run/hostapd -ctrl_interface_group=0 -ssid=coderbot -hw_mode=g -channel=8 -wpa=2 -wpa_passphrase=coderbot -wpa_key_mgmt=WPA-PSK -wpa_pairwise=CCMP -rsn_pairwise=CCMP -beacon_int=100 -auth_algs=3 -wmm_enabled=1 diff --git a/scripts/etc/hostapd/hostapd.conf b/scripts/etc/hostapd/hostapd.conf deleted file mode 100644 index a1fcb119..00000000 --- a/scripts/etc/hostapd/hostapd.conf +++ /dev/null @@ -1,16 +0,0 @@ -interface=wlan0 -#driver=nl80211 -driver=rtl871xdrv -ctrl_interface=/var/run/hostapd -ctrl_interface_group=0 -ssid=coderbot -hw_mode=g -channel=8 -wpa=2 -wpa_passphrase=coderbot -wpa_key_mgmt=WPA-PSK -wpa_pairwise=CCMP -rsn_pairwise=CCMP -beacon_int=100 -auth_algs=3 -wmm_enabled=1 diff --git a/scripts/hostapd b/scripts/hostapd deleted file mode 100755 index b19a99f7..00000000 --- a/scripts/hostapd +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides: hostapd -# Required-Start: $remote_fs -# Required-Stop: $remote_fs -# Should-Start: $network -# Should-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Advanced IEEE 802.11 management daemon -# Description: Userspace IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP -# Authenticator -### END INIT INFO - -PATH=/sbin:/bin:/usr/sbin:/usr/bin -DAEMON_SBIN_1=/usr/sbin/hostapd.RT5370 -DAEMON_SBIN_2=/usr/sbin/hostapd.RTL8188 -DAEMON_DEFS_1=/etc/hostapd/hostapd.RT5370 -DAEMON_DEFS_2=/etc/hostapd/hostapd.RTL8188 -DAEMON_CONF= -NAME=hostapd -DESC="advanced IEEE 802.11 management" -PIDFILE=/var/run/hostapd.pid - -[ -x "$DAEMON_SBIN_1" ] || exit 0 -[ -s "$DAEMON_DEFS_1" ] && . /etc/default/hostapd -[ -n "$DAEMON_CONF" ] || exit 0 - -DAEMON_OPTS="-B -P $PIDFILE $DAEMON_OPTS $DAEMON_CONF" - -. /lib/lsb/init-functions - -case "$1" in - start) - log_daemon_msg "Starting $DESC" "$NAME" - echo "starting 1" - start-stop-daemon --start --oknodo --quiet --exec "$DAEMON_SBIN_1" --pidfile "$PIDFILE" -- $DAEMON_DEFS_1 >/dev/null - echo "starting 2" - start-stop-daemon --start --oknodo --quiet --exec "$DAEMON_SBIN_2" --pidfile "$PIDFILE" -- $DAEMON_DEFS_2 >/dev/null - echo "$?" - log_end_msg "$?" - ;; - stop) - log_daemon_msg "Stopping $DESC" "$NAME" - start-stop-daemon --stop --oknodo --quiet --exec "$DAEMON_SBIN_1" --pidfile "$PIDFILE" - start-stop-daemon --stop --oknodo --quiet --exec "$DAEMON_SBIN_2" --pidfile "$PIDFILE" - log_end_msg "$?" - ;; - reload) - log_daemon_msg "Reloading $DESC" "$NAME" - start-stop-daemon --stop --signal HUP --exec "$DAEMON_SBIN_1" --pidfile "$PIDFILE" - start-stop-daemon --stop --signal HUP --exec "$DAEMON_SBIN_2" --pidfile "$PIDFILE" - log_end_msg "$?" - ;; - restart|force-reload) - $0 stop - sleep 8 - $0 start - ;; - status) - status_of_proc "$DAEMON_SBIN_1" "$NAME" - exit $? - ;; - *) - N=/etc/init.d/$NAME - echo "Usage: $N {start|stop|restart|force-reload|reload|status}" >&2 - exit 1 - ;; -esac - -exit 0 diff --git a/scripts/interfaces_ap b/scripts/interfaces_ap deleted file mode 100644 index e6970d05..00000000 --- a/scripts/interfaces_ap +++ /dev/null @@ -1,12 +0,0 @@ -auto lo -iface lo inet loopback -iface eth0 inet dhcp -#allow-hotplug wlan0 -#iface wlan0 inet manual -#wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf -#iface default inet dhcp -iface wlan0 inet static -address 10.0.0.1 -netmask 255.255.255.0 -wireless-power off - diff --git a/scripts/interfaces_cli b/scripts/interfaces_cli deleted file mode 100644 index 74e4884f..00000000 --- a/scripts/interfaces_cli +++ /dev/null @@ -1,9 +0,0 @@ -auto lo -iface lo inet loopback -iface eth0 inet dhcp -allow-hotplug wlan0 -iface wlan0 inet manual -wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf -iface wlan0 inet dhcp -iface default inet dhcp -wireless-power off diff --git a/scripts/pigpiod b/scripts/pigpiod deleted file mode 100755 index 408a9cc9..00000000 --- a/scripts/pigpiod +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides: pigpiod -# Required-Start: udev -# Required-Stop: -# Default-Start: S -# Default-Stop: -# X-Interactive: -# Description: PI GPIO Server -# Short-Description: Provides access to GPIO to non-root users -### END INIT INFO - -PATH='/sbin:/bin:/usr/bin' - -NAME=pigpiod -PIGPIOD=/usr/local/bin/pigpiod -FIND_PID="ps -eo pid,args | grep /usr/local/bin/pigpiod | awk '{print $1}'" - -RET=0 - -. /lib/lsb/init-functions - -kill_pid () { - PID=$(eval $FIND_PID) - if [ ! -z $PID ]; then - kill $PID - PID=$(eval $FIND_PID) - if [ ! -z $PID ]; then - sleep 3 - kill -9 $PID - fi - fi -} - -case "$1" in - start|reload|restart|force-reload) - kill_pid - log_daemon_msg "Starting PIGPIO Daemon" "pigpiod" - echo - $PIGPIOD - RET=$? - ;; - stop) - kill_pid - RET=$? - ;; - status) - ;; - *) - log_failure_msg "Usage: /etc/init.d/$NAME {start|stop|restart}" - RET=1 - ;; -esac - -exit $RET - -: diff --git a/scripts/wifi b/scripts/wifi deleted file mode 100755 index 81729d82..00000000 --- a/scripts/wifi +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides: wifi -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: WiFi service -# Description: Provide WiFi -### END INIT INFO - -# Change the next 3 lines to suit where you install your script and what you want to call it -DIR=/home/pi/coderbot -DAEMON=$DIR/wifi.py -DAEMON_NAME=wifi - -# This next line determines what user the script runs as. -# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python. -DAEMON_USER=root - -# The process ID of the script when it runs is stored here: -PIDFILE=/var/run/$DAEMON_NAME.pid - -. /lib/lsb/init-functions - -do_start () { - log_daemon_msg "Starting system $DAEMON_NAME daemon" - start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chdir $DIR --chuid $DAEMON_USER --startas $DAEMON - log_end_msg $? -} -do_stop () { - log_daemon_msg "Stopping system $DAEMON_NAME daemon" - start-stop-daemon --stop --pidfile $PIDFILE --retry 10 - log_end_msg $? -} - -case "$1" in - - start|stop) - do_${1} - ;; - - restart|reload|force-reload) - do_stop - do_start - ;; - - status) - status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $? - ;; - *) - echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}" - exit 1 - ;; - -esac -exit 0 diff --git a/sounds/buzz.mp3 b/sounds/buzz.mp3 deleted file mode 100644 index e28d0f69..00000000 Binary files a/sounds/buzz.mp3 and /dev/null differ diff --git a/sounds/buzz.wav b/sounds/buzz.wav new file mode 100644 index 00000000..dae05b95 Binary files /dev/null and b/sounds/buzz.wav differ diff --git a/sounds/i-see-you.mp3 b/sounds/i-see-you.mp3 deleted file mode 100644 index 9965ad52..00000000 Binary files a/sounds/i-see-you.mp3 and /dev/null differ diff --git a/sounds/i-see-you.wav b/sounds/i-see-you.wav new file mode 100644 index 00000000..a3ab3021 Binary files /dev/null and b/sounds/i-see-you.wav differ diff --git a/sounds/notes/cat/audio.wav b/sounds/notes/cat/audio.wav new file mode 100644 index 00000000..eb20db75 Binary files /dev/null and b/sounds/notes/cat/audio.wav differ diff --git a/sounds/notes/dinosaur.wav b/sounds/notes/dinosaur.wav new file mode 100644 index 00000000..4fe28f48 Binary files /dev/null and b/sounds/notes/dinosaur.wav differ diff --git a/sounds/notes/dog/audio.wav b/sounds/notes/dog/audio.wav new file mode 100644 index 00000000..fa3e4e67 Binary files /dev/null and b/sounds/notes/dog/audio.wav differ diff --git a/sounds/notes/duck/audio.wav b/sounds/notes/duck/audio.wav new file mode 100644 index 00000000..ee416bc0 Binary files /dev/null and b/sounds/notes/duck/audio.wav differ diff --git a/sounds/notes/elephant/audio.wav b/sounds/notes/elephant/audio.wav new file mode 100644 index 00000000..7d313846 Binary files /dev/null and b/sounds/notes/elephant/audio.wav differ diff --git a/sounds/notes/flute/audio.wav b/sounds/notes/flute/audio.wav new file mode 100644 index 00000000..1e14fa57 Binary files /dev/null and b/sounds/notes/flute/audio.wav differ diff --git a/sounds/notes/guitar/audio.wav b/sounds/notes/guitar/audio.wav new file mode 100644 index 00000000..673b5127 Binary files /dev/null and b/sounds/notes/guitar/audio.wav differ diff --git a/sounds/notes/music_package.json b/sounds/notes/music_package.json new file mode 100644 index 00000000..d876c5c3 --- /dev/null +++ b/sounds/notes/music_package.json @@ -0,0 +1,193 @@ +{ + "packages": { + "piano": { + "category": "instrument", + "name_IT": "pianoforte", + "name_EN": "piano", + "version": "0.1", + "date": "2020-04-08", + "interface": { + "base": { + "available": "TRUE", + "icon": "piano.png" + }, + "intermediate": { + "available": "TRUE", + "icon": "piano.png" + }, + "advanced": { + "available": "TRUE", + "icon": "piano.png" + } + } + }, + "guitar": { + "category": "instrument", + "name_IT": "chitarra", + "name_EN": "guitar", + "version": "0.1", + "date": "2020-04-08", + "interface": { + "base": { + "available": "TRUE", + "icon": "guitar.png" + }, + "intermediate": { + "available": "TRUE", + "icon": "guitar.png" + }, + "advanced": { + "available": "TRUE", + "icon": "guitar.png" + } + } + }, + "flute": { + "category": "instrument", + "name_IT": "flauto", + "name_EN": "flute", + "version": "0.1", + "date": "2020-04-08", + "interface": { + "base": { + "available": "TRUE", + "icon": "flute.png" + }, + "intermediate": { + "available": "TRUE", + "icon": "flute.png" + }, + "advanced": { + "available": "TRUE", + "icon": "flute.png" + } + } + }, + "cat": { + "category": "animal", + "name_IT": "gatto", + "name_EN": "cat", + "version": "0.1", + "date": "2020-04-08", + "interface": { + "base": { + "available": "TRUE", + "icon": "cat.png" + }, + "intermediate": { + "available": "TRUE", + "icon": "cat.png" + }, + "advanced": { + "available": "TRUE", + "icon": "cat.png" + } + } + }, + "dog": { + "category": "animal", + "name_IT": "cane", + "name_EN": "dog", + "version": "0.1", + "date": "2020-04-08", + "interface": { + "base": { + "available": "TRUE", + "icon": "dog.png" + }, + "intermediate": { + "available": "TRUE", + "icon": "dog.png" + }, + "advanced": { + "available": "TRUE", + "icon": "dog.png" + } + } + }, + "pig": { + "category": "animal", + "name_IT": "maiale", + "name_EN": "pig", + "version": "0.1", + "date": "2020-06-01", + "interface": { + "base": { + "available": "TRUE", + "icon": "pig.png" + }, + "intermediate": { + "available": "TRUE", + "icon": "pig.png" + }, + "advanced": { + "available": "TRUE", + "icon": "pig.png" + } + } + }, + "elephant": { + "category": "animal", + "name_IT": "elefante", + "name_EN": "elephant", + "version": "0.1", + "date": "2020-06-01", + "interface": { + "base": { + "available": "TRUE", + "icon": "elephant.png" + }, + "intermediate": { + "available": "TRUE", + "icon": "elephant.png" + }, + "advanced": { + "available": "TRUE", + "icon": "elephant.png" + } + } + }, + "snake": { + "category": "animal", + "name_IT": "serpente", + "name_EN": "snake", + "version": "0.1", + "date": "2020-06-01", + "interface": { + "base": { + "available": "TRUE", + "icon": "snake.png" + }, + "intermediate": { + "available": "TRUE", + "icon": "snake.png" + }, + "advanced": { + "available": "TRUE", + "icon": "snake.png" + } + } + }, + "duck": { + "category": "animal", + "name_IT": "anatra", + "name_EN": "duck", + "version": "0.1", + "date": "2020-06-01", + "interface": { + "base": { + "available": "TRUE", + "icon": "duck.png" + }, + "intermediate": { + "available": "TRUE", + "icon": "duck.png" + }, + "advanced": { + "available": "TRUE", + "icon": "duck.png" + } + } + } + } +} diff --git a/sounds/notes/piano/audio.wav b/sounds/notes/piano/audio.wav new file mode 100644 index 00000000..5eaabb67 Binary files /dev/null and b/sounds/notes/piano/audio.wav differ diff --git a/sounds/notes/pig/audio.wav b/sounds/notes/pig/audio.wav new file mode 100644 index 00000000..63ddcf4c Binary files /dev/null and b/sounds/notes/pig/audio.wav differ diff --git a/sounds/notes/snake/audio.wav b/sounds/notes/snake/audio.wav new file mode 100644 index 00000000..39775e14 Binary files /dev/null and b/sounds/notes/snake/audio.wav differ diff --git a/sounds/phaser.mp3 b/sounds/phaser.mp3 deleted file mode 100644 index 632a307b..00000000 Binary files a/sounds/phaser.mp3 and /dev/null differ diff --git a/sounds/phaser.wav b/sounds/phaser.wav new file mode 100644 index 00000000..bc3a59ff Binary files /dev/null and b/sounds/phaser.wav differ diff --git a/sounds/scanner.mp3 b/sounds/scanner.mp3 deleted file mode 100644 index 534647f3..00000000 Binary files a/sounds/scanner.mp3 and /dev/null differ diff --git a/sounds/scanner.wav b/sounds/scanner.wav new file mode 100644 index 00000000..9212f29a Binary files /dev/null and b/sounds/scanner.wav differ diff --git a/sounds/shutdown.mp3 b/sounds/shutdown.mp3 deleted file mode 100644 index 0039e395..00000000 Binary files a/sounds/shutdown.mp3 and /dev/null differ diff --git a/sounds/shutdown.wav b/sounds/shutdown.wav new file mode 100644 index 00000000..73627427 Binary files /dev/null and b/sounds/shutdown.wav differ diff --git a/sounds/shutter.mp3 b/sounds/shutter.mp3 deleted file mode 100644 index b376d7c3..00000000 Binary files a/sounds/shutter.mp3 and /dev/null differ diff --git a/sounds/shutter.wav b/sounds/shutter.wav new file mode 100644 index 00000000..96bc89c6 Binary files /dev/null and b/sounds/shutter.wav differ diff --git a/sounds/startup.mp3 b/sounds/startup.mp3 deleted file mode 100644 index a33852fe..00000000 Binary files a/sounds/startup.mp3 and /dev/null differ diff --git a/sounds/startup.wav b/sounds/startup.wav new file mode 100644 index 00000000..707ace6b Binary files /dev/null and b/sounds/startup.wav differ diff --git a/sounds/still-there.mp3 b/sounds/still-there.mp3 deleted file mode 100644 index 9bd92881..00000000 Binary files a/sounds/still-there.mp3 and /dev/null differ diff --git a/sounds/still-there.wav b/sounds/still-there.wav new file mode 100644 index 00000000..35c2f01b Binary files /dev/null and b/sounds/still-there.wav differ diff --git a/sounds/there-you-are.mp3 b/sounds/there-you-are.mp3 deleted file mode 100644 index 92165bc8..00000000 Binary files a/sounds/there-you-are.mp3 and /dev/null differ diff --git a/sounds/there-you-are.wav b/sounds/there-you-are.wav new file mode 100644 index 00000000..bf18c808 Binary files /dev/null and b/sounds/there-you-are.wav differ diff --git a/static/.DS_Store b/static/.DS_Store deleted file mode 100644 index eb3d484a..00000000 Binary files a/static/.DS_Store and /dev/null differ diff --git a/static/css/.DS_Store b/static/css/.DS_Store deleted file mode 100644 index 5008ddfc..00000000 Binary files a/static/css/.DS_Store and /dev/null differ diff --git a/static/css/coderbot.css b/static/css/coderbot.css deleted file mode 100644 index 18b0f44f..00000000 --- a/static/css/coderbot.css +++ /dev/null @@ -1,201 +0,0 @@ -.ui-btn-traslucent { -background:rgba(246,246,246,0.5) !important; -border-radius: 14em; -} -.ui-center { -text-align: center; -} - -/* A bit custom styling */ -#page-photos .ui-listview li .ui-btn p { - color: #c0c0c0; -} -#page-photos .ui-listview li .ui-btn .ui-li-aside { - color: #eee; -} - -.ui-icon-cb-new:after { - background-image: url("https://github.com/css/images/icons-svg/cb-new.svg"); - background-size: 14px 14px; -} -/* Fallback */ -.ui-nosvg .ui-icon-cb-new:after { - background-image: url("https://github.com/css/images/icons-png/cb-new.png"); -} -.ui-icon-cb-load:after { - background-image: url("https://github.com/css/images/icons-svg/cb-load.svg"); - background-size: 16px 16px; -} -/* Fallback */ -.ui-nosvg .ui-icon-cb-load:after { - background-image: url("https://github.com/css/images/icons-png/cb-load.png"); -} -.ui-icon-cb-save:after { - background-image: url("https://github.com/css/images/icons-svg/cb-save.svg"); - background-size: 16px 16px; -} -/* Fallback */ -.ui-nosvg .ui-icon-cb-save:after { - background-image: url("https://github.com/css/images/icons-png/cb-save.png"); -} -.ui-icon-cb-copy:after { - background-image: url("https://github.com/css/images/icons-svg/cb-copy.svg"); - background-size: 14px 14px; -} -/* Fallback */ -.ui-nosvg .ui-icon-cb-copy:after { - background-image: url("https://github.com/css/images/icons-png/cb-copy.png"); -} -.ui-icon-cb-code:after { - background-image: url("https://github.com/css/images/icons-svg/cb-code.svg"); - background-size: 14px 14px; -} -/* Fallback */ -.ui-nosvg .ui-icon-cb-code:after { - background-image: url("https://github.com/css/images/icons-png/cb-code.png"); -} -.ui-icon-cb-run:after { - background-image: url("https://github.com/css/images/icons-svg/cb-run.svg"); - background-size: 14px 14px; -} -/* Fallback */ -.ui-nosvg .ui-icon-cb-run:after { - background-image: url("https://github.com/css/images/icons-png/cb-run.png"); -} -.ui-icon-cb-stop:after { - background-image: url("https://github.com/css/images/icons-svg/cb-stop.svg"); - background-size: 14px 14px; -} -/* Fallback */ -.ui-nosvg .ui-icon-cb-stop:after { - background-image: url("https://github.com/css/images/icons-png/cb-stop.png"); -} - -/* First breakpoint is 48em (768px). 3 column layout. Tiles 250x250 pixels incl. margin at the breakpoint. */ -@media ( min-width: 48em ) { - #page-photos .ui-content { - padding: .5625em; /* 9px */ - } - #page-photos .ui-listview li { - float: left; - width: 30.9333%; /* 33.3333% incl. 2 x 1.2% margin */ - height: 173px; /* 232p */ - margin: .5625em 1.2%; - } - #page-photos .ui-listview li > .ui-btn { - -webkit-box-sizing: border-box; /* include padding and border in height so we can set it to 100% */ - -moz-box-sizing: border-box; - box-sizing: border-box; - height: 100%; - } - #page-photos .ui-listview li.ui-li-has-thumb .ui-li-thumb { - height: auto; /* To keep aspect ratio. */ - max-width: 100%; - max-height: none; - } - /* Make all list items and anchors inherit the border-radius from the UL. */ - #page-photos .ui-listview li, - #page-photos .ui-listview li .ui-btn, - #page-photos .ui-listview .ui-li-thumb { - -webkit-border-radius: inherit; - border-radius: inherit; - } - /* Hide the icon */ - #page-photos .ui-listview .ui-btn-icon-right:after { - display: none; - } - /* Make text wrap. */ - #page-photos .ui-listview h2, - #page-photos .ui-listview p { - white-space: normal; - overflow: visible; - position: absolute; - left: 0; - right: 0; - } - /* Text position */ - #page-photos .ui-listview h2 { - font-size: 1.25em; - margin: 0; - padding: .125em 1em; - bottom: 50%; - } - #page-photos .ui-listview p { - font-size: 1em; - margin: 0; - padding: 0 1.25em; - min-height: 50%; - bottom: 0; - } - /* Semi transparent background and different position if there is a thumb. The button has overflow hidden so we don't need to set border-radius. */ - .ui-listview .ui-li-has-thumb h2, - .ui-listview .ui-li-has-thumb p { - background: #111; - background: rgba(0,0,0,.8); - } - .ui-listview .ui-li-has-thumb h2 { - bottom: 35%; - } - .ui-listview .ui-li-has-thumb p { - min-height: 35%; - } - /* ui-li-aside has class .ui-li-desc as well so we have to override some things. */ - #page-photos .ui-listview .ui-li-aside { - padding: .125em .625em; - width: auto; - min-height: 0; - top: 0; - left: auto; - bottom: auto; - /* Custom styling. */ - background: #990099; - background: rgba(153,0,153,.85); - -webkit-border-top-right-radius: inherit; - border-top-right-radius: inherit; - -webkit-border-bottom-left-radius: inherit; - border-bottom-left-radius: inherit; - -webkit-border-bottom-right-radius: 0; - border-bottom-right-radius: 0; - } - /* If you want to add shadow, don't kill the focus style. */ - #page-photos .ui-listview li { - -moz-box-shadow: 0px 0px 9px #111; - -webkit-box-shadow: 0px 0px 9px #111; - box-shadow: 0px 0px 9px #111; - } - /* Images mask the hover bg color so we give desktop users feedback by applying the focus style on hover as well. */ - #page-photos .ui-listview li > .ui-btn:hover { - -moz-box-shadow: 0px 0px 12px #33ccff; - -webkit-box-shadow: 0px 0px 12px #33ccff; - box-shadow: 0px 0px 12px #33ccff; - } - /* Animate focus and hover style, and resizing. */ - #page-photos .ui-listview li, - #page-photos .ui-listview .ui-btn { - -webkit-transition: all 500ms ease; - -moz-transition: all 500ms ease; - -o-transition: all 500ms ease; - -ms-transition: all 500ms ease; - transition: all 500ms ease; - } -} -/* Second breakpoint is 63.75em (1020px). 4 column layout. Tiles will be 250x250 pixels incl. margin again at the breakpoint. */ -@media ( min-width: 63.75em ) { - #page-photos .ui-content { - padding: .625em; /* 10px */ - } - /* Set a max-width for the last breakpoint to prevent too much stretching on large screens. - By setting the max-width equal to the breakpoint width minus padding we keep square tiles. */ - #page-photos .ui-listview { - max-width: 62.5em; /* 1000px */ - margin: 0 auto; - } - /* Because of the 1000px max-width the width will always be 230px (and margin left/right 10px), - but we stick to percentage values for demo purposes. */ - #page-photos .ui-listview li { - width: 23%; - #height: 230px; - margin: .625em 1%; - } -} -/* For this demo we used images with a size of 310x310 pixels. Just before the second breakpoint the images reach their max width: 1019px - 2 x 9px padding = 1001px x 30.9333% = ~310px */ diff --git a/static/css/images/ajax-loader.gif b/static/css/images/ajax-loader.gif deleted file mode 100755 index 57f5624e..00000000 Binary files a/static/css/images/ajax-loader.gif and /dev/null differ diff --git a/static/css/images/icons-png/action-black.png b/static/css/images/icons-png/action-black.png deleted file mode 100755 index d10dc792..00000000 Binary files a/static/css/images/icons-png/action-black.png and /dev/null differ diff --git a/static/css/images/icons-png/action-white.png b/static/css/images/icons-png/action-white.png deleted file mode 100755 index 1daddabf..00000000 Binary files a/static/css/images/icons-png/action-white.png and /dev/null differ diff --git a/static/css/images/icons-png/alert-black.png b/static/css/images/icons-png/alert-black.png deleted file mode 100755 index 784cd062..00000000 Binary files a/static/css/images/icons-png/alert-black.png and /dev/null differ diff --git a/static/css/images/icons-png/alert-white.png b/static/css/images/icons-png/alert-white.png deleted file mode 100755 index 5c00e0aa..00000000 Binary files a/static/css/images/icons-png/alert-white.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-d-black.png b/static/css/images/icons-png/arrow-d-black.png deleted file mode 100755 index 358f0e82..00000000 Binary files a/static/css/images/icons-png/arrow-d-black.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-d-l-black.png b/static/css/images/icons-png/arrow-d-l-black.png deleted file mode 100755 index c7f6c9da..00000000 Binary files a/static/css/images/icons-png/arrow-d-l-black.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-d-l-white.png b/static/css/images/icons-png/arrow-d-l-white.png deleted file mode 100755 index d103c06a..00000000 Binary files a/static/css/images/icons-png/arrow-d-l-white.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-d-r-black.png b/static/css/images/icons-png/arrow-d-r-black.png deleted file mode 100755 index 648d7686..00000000 Binary files a/static/css/images/icons-png/arrow-d-r-black.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-d-r-white.png b/static/css/images/icons-png/arrow-d-r-white.png deleted file mode 100755 index 713d3c81..00000000 Binary files a/static/css/images/icons-png/arrow-d-r-white.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-d-white.png b/static/css/images/icons-png/arrow-d-white.png deleted file mode 100755 index 460cf4a5..00000000 Binary files a/static/css/images/icons-png/arrow-d-white.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-l-black.png b/static/css/images/icons-png/arrow-l-black.png deleted file mode 100755 index 8083f945..00000000 Binary files a/static/css/images/icons-png/arrow-l-black.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-l-white.png b/static/css/images/icons-png/arrow-l-white.png deleted file mode 100755 index 09d1ca5b..00000000 Binary files a/static/css/images/icons-png/arrow-l-white.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-r-black.png b/static/css/images/icons-png/arrow-r-black.png deleted file mode 100755 index 2adc5f18..00000000 Binary files a/static/css/images/icons-png/arrow-r-black.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-r-white.png b/static/css/images/icons-png/arrow-r-white.png deleted file mode 100755 index 9a4ff07c..00000000 Binary files a/static/css/images/icons-png/arrow-r-white.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-u-black.png b/static/css/images/icons-png/arrow-u-black.png deleted file mode 100755 index de107e15..00000000 Binary files a/static/css/images/icons-png/arrow-u-black.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-u-l-black.png b/static/css/images/icons-png/arrow-u-l-black.png deleted file mode 100755 index 707a7c4e..00000000 Binary files a/static/css/images/icons-png/arrow-u-l-black.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-u-l-white.png b/static/css/images/icons-png/arrow-u-l-white.png deleted file mode 100755 index 157e10b3..00000000 Binary files a/static/css/images/icons-png/arrow-u-l-white.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-u-r-black.png b/static/css/images/icons-png/arrow-u-r-black.png deleted file mode 100755 index f5f4a420..00000000 Binary files a/static/css/images/icons-png/arrow-u-r-black.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-u-r-white.png b/static/css/images/icons-png/arrow-u-r-white.png deleted file mode 100755 index 9026da63..00000000 Binary files a/static/css/images/icons-png/arrow-u-r-white.png and /dev/null differ diff --git a/static/css/images/icons-png/arrow-u-white.png b/static/css/images/icons-png/arrow-u-white.png deleted file mode 100755 index a55ca59e..00000000 Binary files a/static/css/images/icons-png/arrow-u-white.png and /dev/null differ diff --git a/static/css/images/icons-png/audio-black.png b/static/css/images/icons-png/audio-black.png deleted file mode 100755 index 05cc4fd8..00000000 Binary files a/static/css/images/icons-png/audio-black.png and /dev/null differ diff --git a/static/css/images/icons-png/audio-white.png b/static/css/images/icons-png/audio-white.png deleted file mode 100755 index 279102b4..00000000 Binary files a/static/css/images/icons-png/audio-white.png and /dev/null differ diff --git a/static/css/images/icons-png/back-black.png b/static/css/images/icons-png/back-black.png deleted file mode 100755 index e3ee4ea6..00000000 Binary files a/static/css/images/icons-png/back-black.png and /dev/null differ diff --git a/static/css/images/icons-png/back-white.png b/static/css/images/icons-png/back-white.png deleted file mode 100755 index 4c4e76bd..00000000 Binary files a/static/css/images/icons-png/back-white.png and /dev/null differ diff --git a/static/css/images/icons-png/bars-black.png b/static/css/images/icons-png/bars-black.png deleted file mode 100755 index 5a261326..00000000 Binary files a/static/css/images/icons-png/bars-black.png and /dev/null differ diff --git a/static/css/images/icons-png/bars-white.png b/static/css/images/icons-png/bars-white.png deleted file mode 100755 index 9c8ceeca..00000000 Binary files a/static/css/images/icons-png/bars-white.png and /dev/null differ diff --git a/static/css/images/icons-png/bullets-black.png b/static/css/images/icons-png/bullets-black.png deleted file mode 100755 index a1d29253..00000000 Binary files a/static/css/images/icons-png/bullets-black.png and /dev/null differ diff --git a/static/css/images/icons-png/bullets-white.png b/static/css/images/icons-png/bullets-white.png deleted file mode 100755 index 754b30d9..00000000 Binary files a/static/css/images/icons-png/bullets-white.png and /dev/null differ diff --git a/static/css/images/icons-png/calendar-black.png b/static/css/images/icons-png/calendar-black.png deleted file mode 100755 index 579487a8..00000000 Binary files a/static/css/images/icons-png/calendar-black.png and /dev/null differ diff --git a/static/css/images/icons-png/calendar-white.png b/static/css/images/icons-png/calendar-white.png deleted file mode 100755 index b03f2eb3..00000000 Binary files a/static/css/images/icons-png/calendar-white.png and /dev/null differ diff --git a/static/css/images/icons-png/camera-black.png b/static/css/images/icons-png/camera-black.png deleted file mode 100755 index d4e69213..00000000 Binary files a/static/css/images/icons-png/camera-black.png and /dev/null differ diff --git a/static/css/images/icons-png/camera-white.png b/static/css/images/icons-png/camera-white.png deleted file mode 100755 index 3758bab8..00000000 Binary files a/static/css/images/icons-png/camera-white.png and /dev/null differ diff --git a/static/css/images/icons-png/carat-d-black.png b/static/css/images/icons-png/carat-d-black.png deleted file mode 100755 index 86972cca..00000000 Binary files a/static/css/images/icons-png/carat-d-black.png and /dev/null differ diff --git a/static/css/images/icons-png/carat-d-white.png b/static/css/images/icons-png/carat-d-white.png deleted file mode 100755 index 12c0e67b..00000000 Binary files a/static/css/images/icons-png/carat-d-white.png and /dev/null differ diff --git a/static/css/images/icons-png/carat-l-black.png b/static/css/images/icons-png/carat-l-black.png deleted file mode 100755 index 1a19660b..00000000 Binary files a/static/css/images/icons-png/carat-l-black.png and /dev/null differ diff --git a/static/css/images/icons-png/carat-l-white.png b/static/css/images/icons-png/carat-l-white.png deleted file mode 100755 index 7c549270..00000000 Binary files a/static/css/images/icons-png/carat-l-white.png and /dev/null differ diff --git a/static/css/images/icons-png/carat-r-black.png b/static/css/images/icons-png/carat-r-black.png deleted file mode 100755 index 1b47d50a..00000000 Binary files a/static/css/images/icons-png/carat-r-black.png and /dev/null differ diff --git a/static/css/images/icons-png/carat-r-white.png b/static/css/images/icons-png/carat-r-white.png deleted file mode 100755 index fae9babc..00000000 Binary files a/static/css/images/icons-png/carat-r-white.png and /dev/null differ diff --git a/static/css/images/icons-png/carat-u-black.png b/static/css/images/icons-png/carat-u-black.png deleted file mode 100755 index c7b85cf4..00000000 Binary files a/static/css/images/icons-png/carat-u-black.png and /dev/null differ diff --git a/static/css/images/icons-png/carat-u-white.png b/static/css/images/icons-png/carat-u-white.png deleted file mode 100755 index 9035505d..00000000 Binary files a/static/css/images/icons-png/carat-u-white.png and /dev/null differ diff --git a/static/css/images/icons-png/cb-code.png b/static/css/images/icons-png/cb-code.png deleted file mode 100755 index d9ea48cb..00000000 Binary files a/static/css/images/icons-png/cb-code.png and /dev/null differ diff --git a/static/css/images/icons-png/cb-copy.png b/static/css/images/icons-png/cb-copy.png deleted file mode 100755 index 73009613..00000000 Binary files a/static/css/images/icons-png/cb-copy.png and /dev/null differ diff --git a/static/css/images/icons-png/cb-load.png b/static/css/images/icons-png/cb-load.png deleted file mode 100755 index 044ad81c..00000000 Binary files a/static/css/images/icons-png/cb-load.png and /dev/null differ diff --git a/static/css/images/icons-png/cb-new.png b/static/css/images/icons-png/cb-new.png deleted file mode 100755 index a94656d9..00000000 Binary files a/static/css/images/icons-png/cb-new.png and /dev/null differ diff --git a/static/css/images/icons-png/cb-record.png b/static/css/images/icons-png/cb-record.png deleted file mode 100755 index 3643eb16..00000000 Binary files a/static/css/images/icons-png/cb-record.png and /dev/null differ diff --git a/static/css/images/icons-png/cb-run.png b/static/css/images/icons-png/cb-run.png deleted file mode 100755 index 49cddf0c..00000000 Binary files a/static/css/images/icons-png/cb-run.png and /dev/null differ diff --git a/static/css/images/icons-png/cb-save.png b/static/css/images/icons-png/cb-save.png deleted file mode 100755 index d02eaf21..00000000 Binary files a/static/css/images/icons-png/cb-save.png and /dev/null differ diff --git a/static/css/images/icons-png/cb-stop.png b/static/css/images/icons-png/cb-stop.png deleted file mode 100755 index 1f253846..00000000 Binary files a/static/css/images/icons-png/cb-stop.png and /dev/null differ diff --git a/static/css/images/icons-png/check-black.png b/static/css/images/icons-png/check-black.png deleted file mode 100755 index 816c8307..00000000 Binary files a/static/css/images/icons-png/check-black.png and /dev/null differ diff --git a/static/css/images/icons-png/check-white.png b/static/css/images/icons-png/check-white.png deleted file mode 100755 index 3abbe9ea..00000000 Binary files a/static/css/images/icons-png/check-white.png and /dev/null differ diff --git a/static/css/images/icons-png/clock-black.png b/static/css/images/icons-png/clock-black.png deleted file mode 100755 index 411a7388..00000000 Binary files a/static/css/images/icons-png/clock-black.png and /dev/null differ diff --git a/static/css/images/icons-png/clock-white.png b/static/css/images/icons-png/clock-white.png deleted file mode 100755 index fe8bdef8..00000000 Binary files a/static/css/images/icons-png/clock-white.png and /dev/null differ diff --git a/static/css/images/icons-png/cloud-black.png b/static/css/images/icons-png/cloud-black.png deleted file mode 100755 index 84a07a9f..00000000 Binary files a/static/css/images/icons-png/cloud-black.png and /dev/null differ diff --git a/static/css/images/icons-png/cloud-white.png b/static/css/images/icons-png/cloud-white.png deleted file mode 100755 index 47214248..00000000 Binary files a/static/css/images/icons-png/cloud-white.png and /dev/null differ diff --git a/static/css/images/icons-png/comment-black.png b/static/css/images/icons-png/comment-black.png deleted file mode 100755 index 430f6d44..00000000 Binary files a/static/css/images/icons-png/comment-black.png and /dev/null differ diff --git a/static/css/images/icons-png/comment-white.png b/static/css/images/icons-png/comment-white.png deleted file mode 100755 index f5276994..00000000 Binary files a/static/css/images/icons-png/comment-white.png and /dev/null differ diff --git a/static/css/images/icons-png/delete-black.png b/static/css/images/icons-png/delete-black.png deleted file mode 100755 index 71f34925..00000000 Binary files a/static/css/images/icons-png/delete-black.png and /dev/null differ diff --git a/static/css/images/icons-png/delete-white.png b/static/css/images/icons-png/delete-white.png deleted file mode 100755 index 42d9164b..00000000 Binary files a/static/css/images/icons-png/delete-white.png and /dev/null differ diff --git a/static/css/images/icons-png/edit-black.png b/static/css/images/icons-png/edit-black.png deleted file mode 100755 index fcbb3dae..00000000 Binary files a/static/css/images/icons-png/edit-black.png and /dev/null differ diff --git a/static/css/images/icons-png/edit-white.png b/static/css/images/icons-png/edit-white.png deleted file mode 100755 index bbb6a524..00000000 Binary files a/static/css/images/icons-png/edit-white.png and /dev/null differ diff --git a/static/css/images/icons-png/eye-black.png b/static/css/images/icons-png/eye-black.png deleted file mode 100755 index 8ffe2cc2..00000000 Binary files a/static/css/images/icons-png/eye-black.png and /dev/null differ diff --git a/static/css/images/icons-png/eye-white.png b/static/css/images/icons-png/eye-white.png deleted file mode 100755 index d2a65baf..00000000 Binary files a/static/css/images/icons-png/eye-white.png and /dev/null differ diff --git a/static/css/images/icons-png/forbidden-black.png b/static/css/images/icons-png/forbidden-black.png deleted file mode 100755 index 1f7d0d23..00000000 Binary files a/static/css/images/icons-png/forbidden-black.png and /dev/null differ diff --git a/static/css/images/icons-png/forbidden-white.png b/static/css/images/icons-png/forbidden-white.png deleted file mode 100755 index f23d7355..00000000 Binary files a/static/css/images/icons-png/forbidden-white.png and /dev/null differ diff --git a/static/css/images/icons-png/forward-black.png b/static/css/images/icons-png/forward-black.png deleted file mode 100755 index ace9799f..00000000 Binary files a/static/css/images/icons-png/forward-black.png and /dev/null differ diff --git a/static/css/images/icons-png/forward-white.png b/static/css/images/icons-png/forward-white.png deleted file mode 100755 index 567cc45c..00000000 Binary files a/static/css/images/icons-png/forward-white.png and /dev/null differ diff --git a/static/css/images/icons-png/gear-black.png b/static/css/images/icons-png/gear-black.png deleted file mode 100755 index 857668d6..00000000 Binary files a/static/css/images/icons-png/gear-black.png and /dev/null differ diff --git a/static/css/images/icons-png/gear-white.png b/static/css/images/icons-png/gear-white.png deleted file mode 100755 index 6e7402c9..00000000 Binary files a/static/css/images/icons-png/gear-white.png and /dev/null differ diff --git a/static/css/images/icons-png/grid-black.png b/static/css/images/icons-png/grid-black.png deleted file mode 100755 index d8964364..00000000 Binary files a/static/css/images/icons-png/grid-black.png and /dev/null differ diff --git a/static/css/images/icons-png/grid-white.png b/static/css/images/icons-png/grid-white.png deleted file mode 100755 index 575b1792..00000000 Binary files a/static/css/images/icons-png/grid-white.png and /dev/null differ diff --git a/static/css/images/icons-png/heart-black.png b/static/css/images/icons-png/heart-black.png deleted file mode 100755 index f0bd388b..00000000 Binary files a/static/css/images/icons-png/heart-black.png and /dev/null differ diff --git a/static/css/images/icons-png/heart-white.png b/static/css/images/icons-png/heart-white.png deleted file mode 100755 index dfec28e3..00000000 Binary files a/static/css/images/icons-png/heart-white.png and /dev/null differ diff --git a/static/css/images/icons-png/home-black.png b/static/css/images/icons-png/home-black.png deleted file mode 100755 index 1c40d03c..00000000 Binary files a/static/css/images/icons-png/home-black.png and /dev/null differ diff --git a/static/css/images/icons-png/home-white.png b/static/css/images/icons-png/home-white.png deleted file mode 100755 index bf8d59ec..00000000 Binary files a/static/css/images/icons-png/home-white.png and /dev/null differ diff --git a/static/css/images/icons-png/info-black.png b/static/css/images/icons-png/info-black.png deleted file mode 100755 index f0c9027c..00000000 Binary files a/static/css/images/icons-png/info-black.png and /dev/null differ diff --git a/static/css/images/icons-png/info-white.png b/static/css/images/icons-png/info-white.png deleted file mode 100755 index 2e5080aa..00000000 Binary files a/static/css/images/icons-png/info-white.png and /dev/null differ diff --git a/static/css/images/icons-png/location-black.png b/static/css/images/icons-png/location-black.png deleted file mode 100755 index 13191776..00000000 Binary files a/static/css/images/icons-png/location-black.png and /dev/null differ diff --git a/static/css/images/icons-png/location-white.png b/static/css/images/icons-png/location-white.png deleted file mode 100755 index fc3134e1..00000000 Binary files a/static/css/images/icons-png/location-white.png and /dev/null differ diff --git a/static/css/images/icons-png/lock-black.png b/static/css/images/icons-png/lock-black.png deleted file mode 100755 index 153d8ba0..00000000 Binary files a/static/css/images/icons-png/lock-black.png and /dev/null differ diff --git a/static/css/images/icons-png/lock-white.png b/static/css/images/icons-png/lock-white.png deleted file mode 100755 index fe179bca..00000000 Binary files a/static/css/images/icons-png/lock-white.png and /dev/null differ diff --git a/static/css/images/icons-png/mail-black.png b/static/css/images/icons-png/mail-black.png deleted file mode 100755 index dd4bf752..00000000 Binary files a/static/css/images/icons-png/mail-black.png and /dev/null differ diff --git a/static/css/images/icons-png/mail-white.png b/static/css/images/icons-png/mail-white.png deleted file mode 100755 index 64395a2c..00000000 Binary files a/static/css/images/icons-png/mail-white.png and /dev/null differ diff --git a/static/css/images/icons-png/minus-black.png b/static/css/images/icons-png/minus-black.png deleted file mode 100755 index fd9e5ae8..00000000 Binary files a/static/css/images/icons-png/minus-black.png and /dev/null differ diff --git a/static/css/images/icons-png/minus-white.png b/static/css/images/icons-png/minus-white.png deleted file mode 100755 index 3769eec8..00000000 Binary files a/static/css/images/icons-png/minus-white.png and /dev/null differ diff --git a/static/css/images/icons-png/navigation-black.png b/static/css/images/icons-png/navigation-black.png deleted file mode 100755 index 05fa9632..00000000 Binary files a/static/css/images/icons-png/navigation-black.png and /dev/null differ diff --git a/static/css/images/icons-png/navigation-white.png b/static/css/images/icons-png/navigation-white.png deleted file mode 100755 index b8455321..00000000 Binary files a/static/css/images/icons-png/navigation-white.png and /dev/null differ diff --git a/static/css/images/icons-png/phone-black.png b/static/css/images/icons-png/phone-black.png deleted file mode 100755 index cf8e2fcc..00000000 Binary files a/static/css/images/icons-png/phone-black.png and /dev/null differ diff --git a/static/css/images/icons-png/phone-white.png b/static/css/images/icons-png/phone-white.png deleted file mode 100755 index 122a4de6..00000000 Binary files a/static/css/images/icons-png/phone-white.png and /dev/null differ diff --git a/static/css/images/icons-png/plus-black.png b/static/css/images/icons-png/plus-black.png deleted file mode 100755 index 0d3d3819..00000000 Binary files a/static/css/images/icons-png/plus-black.png and /dev/null differ diff --git a/static/css/images/icons-png/plus-white.png b/static/css/images/icons-png/plus-white.png deleted file mode 100755 index a6aa8337..00000000 Binary files a/static/css/images/icons-png/plus-white.png and /dev/null differ diff --git a/static/css/images/icons-png/power-black.png b/static/css/images/icons-png/power-black.png deleted file mode 100755 index 27ba8bbc..00000000 Binary files a/static/css/images/icons-png/power-black.png and /dev/null differ diff --git a/static/css/images/icons-png/power-white.png b/static/css/images/icons-png/power-white.png deleted file mode 100755 index 0bfba5d1..00000000 Binary files a/static/css/images/icons-png/power-white.png and /dev/null differ diff --git a/static/css/images/icons-png/recycle-black.png b/static/css/images/icons-png/recycle-black.png deleted file mode 100755 index 41222c0f..00000000 Binary files a/static/css/images/icons-png/recycle-black.png and /dev/null differ diff --git a/static/css/images/icons-png/recycle-white.png b/static/css/images/icons-png/recycle-white.png deleted file mode 100755 index be0e07a0..00000000 Binary files a/static/css/images/icons-png/recycle-white.png and /dev/null differ diff --git a/static/css/images/icons-png/refresh-black.png b/static/css/images/icons-png/refresh-black.png deleted file mode 100755 index e89516e1..00000000 Binary files a/static/css/images/icons-png/refresh-black.png and /dev/null differ diff --git a/static/css/images/icons-png/refresh-white.png b/static/css/images/icons-png/refresh-white.png deleted file mode 100755 index d4f38f80..00000000 Binary files a/static/css/images/icons-png/refresh-white.png and /dev/null differ diff --git a/static/css/images/icons-png/search-black.png b/static/css/images/icons-png/search-black.png deleted file mode 100755 index 3538c6c4..00000000 Binary files a/static/css/images/icons-png/search-black.png and /dev/null differ diff --git a/static/css/images/icons-png/search-white.png b/static/css/images/icons-png/search-white.png deleted file mode 100755 index 530c2360..00000000 Binary files a/static/css/images/icons-png/search-white.png and /dev/null differ diff --git a/static/css/images/icons-png/shop-black.png b/static/css/images/icons-png/shop-black.png deleted file mode 100755 index 2f37a11d..00000000 Binary files a/static/css/images/icons-png/shop-black.png and /dev/null differ diff --git a/static/css/images/icons-png/shop-white.png b/static/css/images/icons-png/shop-white.png deleted file mode 100755 index 2caa811d..00000000 Binary files a/static/css/images/icons-png/shop-white.png and /dev/null differ diff --git a/static/css/images/icons-png/star-black.png b/static/css/images/icons-png/star-black.png deleted file mode 100755 index e8b6398d..00000000 Binary files a/static/css/images/icons-png/star-black.png and /dev/null differ diff --git a/static/css/images/icons-png/star-white.png b/static/css/images/icons-png/star-white.png deleted file mode 100755 index 3957d4a5..00000000 Binary files a/static/css/images/icons-png/star-white.png and /dev/null differ diff --git a/static/css/images/icons-png/tag-black.png b/static/css/images/icons-png/tag-black.png deleted file mode 100755 index 763d1eaa..00000000 Binary files a/static/css/images/icons-png/tag-black.png and /dev/null differ diff --git a/static/css/images/icons-png/tag-white.png b/static/css/images/icons-png/tag-white.png deleted file mode 100755 index a097086c..00000000 Binary files a/static/css/images/icons-png/tag-white.png and /dev/null differ diff --git a/static/css/images/icons-png/user-black.png b/static/css/images/icons-png/user-black.png deleted file mode 100755 index 9e33cdce..00000000 Binary files a/static/css/images/icons-png/user-black.png and /dev/null differ diff --git a/static/css/images/icons-png/user-white.png b/static/css/images/icons-png/user-white.png deleted file mode 100755 index bec1b9fb..00000000 Binary files a/static/css/images/icons-png/user-white.png and /dev/null differ diff --git a/static/css/images/icons-png/video-black.png b/static/css/images/icons-png/video-black.png deleted file mode 100755 index 2c873601..00000000 Binary files a/static/css/images/icons-png/video-black.png and /dev/null differ diff --git a/static/css/images/icons-png/video-white.png b/static/css/images/icons-png/video-white.png deleted file mode 100755 index 365c2dca..00000000 Binary files a/static/css/images/icons-png/video-white.png and /dev/null differ diff --git a/static/css/images/icons-svg/action-black.svg b/static/css/images/icons-svg/action-black.svg deleted file mode 100755 index 20048d83..00000000 --- a/static/css/images/icons-svg/action-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/action-white.svg b/static/css/images/icons-svg/action-white.svg deleted file mode 100755 index 23da40d6..00000000 --- a/static/css/images/icons-svg/action-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/alert-black.svg b/static/css/images/icons-svg/alert-black.svg deleted file mode 100755 index d4179feb..00000000 --- a/static/css/images/icons-svg/alert-black.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/alert-white.svg b/static/css/images/icons-svg/alert-white.svg deleted file mode 100755 index ff06604b..00000000 --- a/static/css/images/icons-svg/alert-white.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-d-black.svg b/static/css/images/icons-svg/arrow-d-black.svg deleted file mode 100755 index 7a8b7de3..00000000 --- a/static/css/images/icons-svg/arrow-d-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-d-l-black.svg b/static/css/images/icons-svg/arrow-d-l-black.svg deleted file mode 100755 index 8c8d3057..00000000 --- a/static/css/images/icons-svg/arrow-d-l-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-d-l-white.svg b/static/css/images/icons-svg/arrow-d-l-white.svg deleted file mode 100755 index f7379cd7..00000000 --- a/static/css/images/icons-svg/arrow-d-l-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-d-r-black.svg b/static/css/images/icons-svg/arrow-d-r-black.svg deleted file mode 100755 index 95861e05..00000000 --- a/static/css/images/icons-svg/arrow-d-r-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-d-r-white.svg b/static/css/images/icons-svg/arrow-d-r-white.svg deleted file mode 100755 index 7874ca89..00000000 --- a/static/css/images/icons-svg/arrow-d-r-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-d-white.svg b/static/css/images/icons-svg/arrow-d-white.svg deleted file mode 100755 index f80ad1bc..00000000 --- a/static/css/images/icons-svg/arrow-d-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-l-black.svg b/static/css/images/icons-svg/arrow-l-black.svg deleted file mode 100755 index 0190649d..00000000 --- a/static/css/images/icons-svg/arrow-l-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-l-white.svg b/static/css/images/icons-svg/arrow-l-white.svg deleted file mode 100755 index d9de81d3..00000000 --- a/static/css/images/icons-svg/arrow-l-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-r-black.svg b/static/css/images/icons-svg/arrow-r-black.svg deleted file mode 100755 index 7853c5f3..00000000 --- a/static/css/images/icons-svg/arrow-r-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-r-white.svg b/static/css/images/icons-svg/arrow-r-white.svg deleted file mode 100755 index 8c28fc7a..00000000 --- a/static/css/images/icons-svg/arrow-r-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-u-black.svg b/static/css/images/icons-svg/arrow-u-black.svg deleted file mode 100755 index abf9d90d..00000000 --- a/static/css/images/icons-svg/arrow-u-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-u-l-black.svg b/static/css/images/icons-svg/arrow-u-l-black.svg deleted file mode 100755 index 08b5c6d5..00000000 --- a/static/css/images/icons-svg/arrow-u-l-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-u-l-white.svg b/static/css/images/icons-svg/arrow-u-l-white.svg deleted file mode 100755 index 234471ea..00000000 --- a/static/css/images/icons-svg/arrow-u-l-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-u-r-black.svg b/static/css/images/icons-svg/arrow-u-r-black.svg deleted file mode 100755 index db1536d5..00000000 --- a/static/css/images/icons-svg/arrow-u-r-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-u-r-white.svg b/static/css/images/icons-svg/arrow-u-r-white.svg deleted file mode 100755 index 5a510f2f..00000000 --- a/static/css/images/icons-svg/arrow-u-r-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/arrow-u-white.svg b/static/css/images/icons-svg/arrow-u-white.svg deleted file mode 100755 index 7e2aeb22..00000000 --- a/static/css/images/icons-svg/arrow-u-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/audio-black.svg b/static/css/images/icons-svg/audio-black.svg deleted file mode 100755 index f3651d78..00000000 --- a/static/css/images/icons-svg/audio-black.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/audio-white.svg b/static/css/images/icons-svg/audio-white.svg deleted file mode 100755 index a6896994..00000000 --- a/static/css/images/icons-svg/audio-white.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/back-black.svg b/static/css/images/icons-svg/back-black.svg deleted file mode 100755 index d6f928a1..00000000 --- a/static/css/images/icons-svg/back-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/back-white.svg b/static/css/images/icons-svg/back-white.svg deleted file mode 100755 index b34d43b5..00000000 --- a/static/css/images/icons-svg/back-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/bars-black.svg b/static/css/images/icons-svg/bars-black.svg deleted file mode 100755 index 1aebe360..00000000 --- a/static/css/images/icons-svg/bars-black.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/bars-white.svg b/static/css/images/icons-svg/bars-white.svg deleted file mode 100755 index 98cd3200..00000000 --- a/static/css/images/icons-svg/bars-white.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/bullets-black.svg b/static/css/images/icons-svg/bullets-black.svg deleted file mode 100755 index 3bf96803..00000000 --- a/static/css/images/icons-svg/bullets-black.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/bullets-white.svg b/static/css/images/icons-svg/bullets-white.svg deleted file mode 100755 index ecc4f95f..00000000 --- a/static/css/images/icons-svg/bullets-white.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/calendar-black.svg b/static/css/images/icons-svg/calendar-black.svg deleted file mode 100755 index 5c3aeded..00000000 --- a/static/css/images/icons-svg/calendar-black.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/calendar-white.svg b/static/css/images/icons-svg/calendar-white.svg deleted file mode 100755 index 177dab9f..00000000 --- a/static/css/images/icons-svg/calendar-white.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/camera-black.svg b/static/css/images/icons-svg/camera-black.svg deleted file mode 100755 index 865095df..00000000 --- a/static/css/images/icons-svg/camera-black.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/camera-white.svg b/static/css/images/icons-svg/camera-white.svg deleted file mode 100755 index b84265c6..00000000 --- a/static/css/images/icons-svg/camera-white.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/carat-d-black.svg b/static/css/images/icons-svg/carat-d-black.svg deleted file mode 100755 index b6445a7c..00000000 --- a/static/css/images/icons-svg/carat-d-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/carat-d-white.svg b/static/css/images/icons-svg/carat-d-white.svg deleted file mode 100755 index 4d6d185c..00000000 --- a/static/css/images/icons-svg/carat-d-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/carat-l-black.svg b/static/css/images/icons-svg/carat-l-black.svg deleted file mode 100755 index 2c8b91fc..00000000 --- a/static/css/images/icons-svg/carat-l-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/carat-l-white.svg b/static/css/images/icons-svg/carat-l-white.svg deleted file mode 100755 index e18f613c..00000000 --- a/static/css/images/icons-svg/carat-l-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/carat-r-black.svg b/static/css/images/icons-svg/carat-r-black.svg deleted file mode 100755 index 57cf4979..00000000 --- a/static/css/images/icons-svg/carat-r-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/carat-r-white.svg b/static/css/images/icons-svg/carat-r-white.svg deleted file mode 100755 index b034d95f..00000000 --- a/static/css/images/icons-svg/carat-r-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/carat-u-black.svg b/static/css/images/icons-svg/carat-u-black.svg deleted file mode 100755 index 533a7397..00000000 --- a/static/css/images/icons-svg/carat-u-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/carat-u-white.svg b/static/css/images/icons-svg/carat-u-white.svg deleted file mode 100755 index 670e48b8..00000000 --- a/static/css/images/icons-svg/carat-u-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/cb-code.svg b/static/css/images/icons-svg/cb-code.svg deleted file mode 100755 index b9d4ea38..00000000 --- a/static/css/images/icons-svg/cb-code.svg +++ /dev/null @@ -1,305 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/static/css/images/icons-svg/cb-copy.svg b/static/css/images/icons-svg/cb-copy.svg deleted file mode 100755 index ad87483f..00000000 --- a/static/css/images/icons-svg/cb-copy.svg +++ /dev/null @@ -1,67 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/static/css/images/icons-svg/cb-load.svg b/static/css/images/icons-svg/cb-load.svg deleted file mode 100755 index 610ac490..00000000 --- a/static/css/images/icons-svg/cb-load.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/static/css/images/icons-svg/cb-new.svg b/static/css/images/icons-svg/cb-new.svg deleted file mode 100755 index 15c2cf72..00000000 --- a/static/css/images/icons-svg/cb-new.svg +++ /dev/null @@ -1,68 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/static/css/images/icons-svg/cb-record.svg b/static/css/images/icons-svg/cb-record.svg deleted file mode 100755 index d63e9bbd..00000000 --- a/static/css/images/icons-svg/cb-record.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/static/css/images/icons-svg/cb-run.svg b/static/css/images/icons-svg/cb-run.svg deleted file mode 100755 index d2bb45fd..00000000 --- a/static/css/images/icons-svg/cb-run.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/static/css/images/icons-svg/cb-save.svg b/static/css/images/icons-svg/cb-save.svg deleted file mode 100755 index a4efec77..00000000 --- a/static/css/images/icons-svg/cb-save.svg +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - diff --git a/static/css/images/icons-svg/cb-stop.svg b/static/css/images/icons-svg/cb-stop.svg deleted file mode 100755 index 124c3b1c..00000000 --- a/static/css/images/icons-svg/cb-stop.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/static/css/images/icons-svg/check-black.svg b/static/css/images/icons-svg/check-black.svg deleted file mode 100755 index db5b715c..00000000 --- a/static/css/images/icons-svg/check-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/check-white.svg b/static/css/images/icons-svg/check-white.svg deleted file mode 100755 index b257fd71..00000000 --- a/static/css/images/icons-svg/check-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/clock-black.svg b/static/css/images/icons-svg/clock-black.svg deleted file mode 100755 index c68abefb..00000000 --- a/static/css/images/icons-svg/clock-black.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/clock-white.svg b/static/css/images/icons-svg/clock-white.svg deleted file mode 100755 index 55892385..00000000 --- a/static/css/images/icons-svg/clock-white.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/cloud-black.svg b/static/css/images/icons-svg/cloud-black.svg deleted file mode 100755 index 6fa55f43..00000000 --- a/static/css/images/icons-svg/cloud-black.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/cloud-white.svg b/static/css/images/icons-svg/cloud-white.svg deleted file mode 100755 index 3e0bde31..00000000 --- a/static/css/images/icons-svg/cloud-white.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/comment-black.svg b/static/css/images/icons-svg/comment-black.svg deleted file mode 100755 index 485fcc86..00000000 --- a/static/css/images/icons-svg/comment-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/comment-white.svg b/static/css/images/icons-svg/comment-white.svg deleted file mode 100755 index 8d188db6..00000000 --- a/static/css/images/icons-svg/comment-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/delete-black.svg b/static/css/images/icons-svg/delete-black.svg deleted file mode 100755 index 74d99888..00000000 --- a/static/css/images/icons-svg/delete-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/delete-white.svg b/static/css/images/icons-svg/delete-white.svg deleted file mode 100755 index a6cc735c..00000000 --- a/static/css/images/icons-svg/delete-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/edit-black.svg b/static/css/images/icons-svg/edit-black.svg deleted file mode 100755 index d908f9d9..00000000 --- a/static/css/images/icons-svg/edit-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/edit-white.svg b/static/css/images/icons-svg/edit-white.svg deleted file mode 100755 index a88643df..00000000 --- a/static/css/images/icons-svg/edit-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/eye-black.svg b/static/css/images/icons-svg/eye-black.svg deleted file mode 100755 index 7f96a8e7..00000000 --- a/static/css/images/icons-svg/eye-black.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/eye-white.svg b/static/css/images/icons-svg/eye-white.svg deleted file mode 100755 index 7b0d0e85..00000000 --- a/static/css/images/icons-svg/eye-white.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/forbidden-black.svg b/static/css/images/icons-svg/forbidden-black.svg deleted file mode 100755 index fe831bc6..00000000 --- a/static/css/images/icons-svg/forbidden-black.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/forbidden-white.svg b/static/css/images/icons-svg/forbidden-white.svg deleted file mode 100755 index 710ac395..00000000 --- a/static/css/images/icons-svg/forbidden-white.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/forward-black.svg b/static/css/images/icons-svg/forward-black.svg deleted file mode 100755 index 35af7b68..00000000 --- a/static/css/images/icons-svg/forward-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/forward-white.svg b/static/css/images/icons-svg/forward-white.svg deleted file mode 100755 index 5cd2def3..00000000 --- a/static/css/images/icons-svg/forward-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/gear-black.svg b/static/css/images/icons-svg/gear-black.svg deleted file mode 100755 index 4f397c5f..00000000 --- a/static/css/images/icons-svg/gear-black.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/gear-white.svg b/static/css/images/icons-svg/gear-white.svg deleted file mode 100755 index 3a5668fc..00000000 --- a/static/css/images/icons-svg/gear-white.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/grid-black.svg b/static/css/images/icons-svg/grid-black.svg deleted file mode 100755 index e692e1f8..00000000 --- a/static/css/images/icons-svg/grid-black.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/grid-white.svg b/static/css/images/icons-svg/grid-white.svg deleted file mode 100755 index 5cfaa7c1..00000000 --- a/static/css/images/icons-svg/grid-white.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/heart-black.svg b/static/css/images/icons-svg/heart-black.svg deleted file mode 100755 index 77373d5f..00000000 --- a/static/css/images/icons-svg/heart-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/heart-white.svg b/static/css/images/icons-svg/heart-white.svg deleted file mode 100755 index 48fd304a..00000000 --- a/static/css/images/icons-svg/heart-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/home-black.svg b/static/css/images/icons-svg/home-black.svg deleted file mode 100755 index a4950a37..00000000 --- a/static/css/images/icons-svg/home-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/home-white.svg b/static/css/images/icons-svg/home-white.svg deleted file mode 100755 index b7c1a611..00000000 --- a/static/css/images/icons-svg/home-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/info-black.svg b/static/css/images/icons-svg/info-black.svg deleted file mode 100755 index 151cfa2b..00000000 --- a/static/css/images/icons-svg/info-black.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/info-white.svg b/static/css/images/icons-svg/info-white.svg deleted file mode 100755 index dd0f885b..00000000 --- a/static/css/images/icons-svg/info-white.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/location-black.svg b/static/css/images/icons-svg/location-black.svg deleted file mode 100755 index 16a59b8f..00000000 --- a/static/css/images/icons-svg/location-black.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/location-white.svg b/static/css/images/icons-svg/location-white.svg deleted file mode 100755 index ce48397e..00000000 --- a/static/css/images/icons-svg/location-white.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/lock-black.svg b/static/css/images/icons-svg/lock-black.svg deleted file mode 100755 index deb3d489..00000000 --- a/static/css/images/icons-svg/lock-black.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/lock-white.svg b/static/css/images/icons-svg/lock-white.svg deleted file mode 100755 index 543cfbb9..00000000 --- a/static/css/images/icons-svg/lock-white.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/mail-black.svg b/static/css/images/icons-svg/mail-black.svg deleted file mode 100755 index 827e2983..00000000 --- a/static/css/images/icons-svg/mail-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/mail-white.svg b/static/css/images/icons-svg/mail-white.svg deleted file mode 100755 index 2f0b7176..00000000 --- a/static/css/images/icons-svg/mail-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/minus-black.svg b/static/css/images/icons-svg/minus-black.svg deleted file mode 100755 index cd8aec9c..00000000 --- a/static/css/images/icons-svg/minus-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/minus-white.svg b/static/css/images/icons-svg/minus-white.svg deleted file mode 100755 index 1e33c630..00000000 --- a/static/css/images/icons-svg/minus-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/navigation-black.svg b/static/css/images/icons-svg/navigation-black.svg deleted file mode 100755 index a09c35e9..00000000 --- a/static/css/images/icons-svg/navigation-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/navigation-white.svg b/static/css/images/icons-svg/navigation-white.svg deleted file mode 100755 index 38e99c30..00000000 --- a/static/css/images/icons-svg/navigation-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/phone-black.svg b/static/css/images/icons-svg/phone-black.svg deleted file mode 100755 index 4879050f..00000000 --- a/static/css/images/icons-svg/phone-black.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/phone-white.svg b/static/css/images/icons-svg/phone-white.svg deleted file mode 100755 index d180382a..00000000 --- a/static/css/images/icons-svg/phone-white.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/plus-black.svg b/static/css/images/icons-svg/plus-black.svg deleted file mode 100755 index 2e268b01..00000000 --- a/static/css/images/icons-svg/plus-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/plus-white.svg b/static/css/images/icons-svg/plus-white.svg deleted file mode 100755 index 488129f0..00000000 --- a/static/css/images/icons-svg/plus-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/power-black.svg b/static/css/images/icons-svg/power-black.svg deleted file mode 100755 index c078e270..00000000 --- a/static/css/images/icons-svg/power-black.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/power-white.svg b/static/css/images/icons-svg/power-white.svg deleted file mode 100755 index aa5a7a17..00000000 --- a/static/css/images/icons-svg/power-white.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/recycle-black.svg b/static/css/images/icons-svg/recycle-black.svg deleted file mode 100755 index c481e295..00000000 --- a/static/css/images/icons-svg/recycle-black.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/recycle-white.svg b/static/css/images/icons-svg/recycle-white.svg deleted file mode 100755 index 11b9c128..00000000 --- a/static/css/images/icons-svg/recycle-white.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/refresh-black.svg b/static/css/images/icons-svg/refresh-black.svg deleted file mode 100755 index 16c978c4..00000000 --- a/static/css/images/icons-svg/refresh-black.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/refresh-white.svg b/static/css/images/icons-svg/refresh-white.svg deleted file mode 100755 index fa370e69..00000000 --- a/static/css/images/icons-svg/refresh-white.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/search-black.svg b/static/css/images/icons-svg/search-black.svg deleted file mode 100755 index 2b9e8637..00000000 --- a/static/css/images/icons-svg/search-black.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/search-white.svg b/static/css/images/icons-svg/search-white.svg deleted file mode 100755 index 01ccc7c1..00000000 --- a/static/css/images/icons-svg/search-white.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/shop-black.svg b/static/css/images/icons-svg/shop-black.svg deleted file mode 100755 index 9e1bd39b..00000000 --- a/static/css/images/icons-svg/shop-black.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/shop-white.svg b/static/css/images/icons-svg/shop-white.svg deleted file mode 100755 index b98cb4bd..00000000 --- a/static/css/images/icons-svg/shop-white.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/star-black.svg b/static/css/images/icons-svg/star-black.svg deleted file mode 100755 index f2c1afe4..00000000 --- a/static/css/images/icons-svg/star-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/star-white.svg b/static/css/images/icons-svg/star-white.svg deleted file mode 100755 index d15188e3..00000000 --- a/static/css/images/icons-svg/star-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/tag-black.svg b/static/css/images/icons-svg/tag-black.svg deleted file mode 100755 index bd11ae67..00000000 --- a/static/css/images/icons-svg/tag-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/tag-white.svg b/static/css/images/icons-svg/tag-white.svg deleted file mode 100755 index 7cd4a50a..00000000 --- a/static/css/images/icons-svg/tag-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/user-black.svg b/static/css/images/icons-svg/user-black.svg deleted file mode 100755 index 7530c987..00000000 --- a/static/css/images/icons-svg/user-black.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/user-white.svg b/static/css/images/icons-svg/user-white.svg deleted file mode 100755 index 5528c2e9..00000000 --- a/static/css/images/icons-svg/user-white.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/video-black.svg b/static/css/images/icons-svg/video-black.svg deleted file mode 100755 index cc501814..00000000 --- a/static/css/images/icons-svg/video-black.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/images/icons-svg/video-white.svg b/static/css/images/icons-svg/video-white.svg deleted file mode 100755 index ddcdf16d..00000000 --- a/static/css/images/icons-svg/video-white.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/css/jquery.mobile-1.4.2.min.css b/static/css/jquery.mobile-1.4.2.min.css deleted file mode 100644 index f17e1267..00000000 --- a/static/css/jquery.mobile-1.4.2.min.css +++ /dev/null @@ -1,3 +0,0 @@ -/*! jQuery Mobile 1.4.2 | Git HEAD hash: 9d9a42a <> 2014-02-28T17:32:01Z | (c) 2010, 2014 jQuery Foundation, Inc. | jquery.org/license */ - -.ui-icon-action:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C12H2V5h1l2-2H0v11h13V7l-2%2C2V12z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-alert:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8%20C6.447%2C8%2C6%2C7.553%2C6%2C7V5c0-0.553%2C0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-arrow-d-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-d-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-d:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-u-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-u-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-u:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-audio:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-back:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M5%2C3V0L1%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C13%2C4%2C8%2C3%2C5%2C3z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-bars:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M1%2C4h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C2%2C0%2C2.447%2C0%2C3S0.447%2C4%2C1%2C4z%20M13%2C6H1%20C0.447%2C6%2C0%2C6.447%2C0%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H1c-0.553%2C0-1%2C0.447-1%2C1%20s0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-bullets:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M5%2C4h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C2%2C4%2C2.447%2C4%2C3S4.447%2C4%2C5%2C4z%20M13%2C6H5%20C4.447%2C6%2C4%2C6.447%2C4%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H5c-0.553%2C0-1%2C0.447-1%2C1%20s0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%20M1%2C2C0.447%2C2%2C0%2C2.447%2C0%2C3s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C2%2C1%2C2z%20M1%2C6%20C0.447%2C6%2C0%2C6.447%2C0%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1s1-0.447%2C1-1C2%2C6.447%2C1.553%2C6%2C1%2C6z%20M1%2C10c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1%20S1.553%2C10%2C1%2C10z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-calendar:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-camera:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M12%2C2.5H9.908c-0.206-0.581-0.756-1-1.408-1h-3c-0.652%2C0-1.202%2C0.419-1.408%2C1H2c-1.104%2C0-2%2C0.896-2%2C2%20v6c0%2C1.104%2C0.896%2C2%2C2%2C2h10c1.104%2C0%2C2-0.896%2C2-2v-6C14%2C3.396%2C13.104%2C2.5%2C12%2C2.5z%20M7%2C10.5c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3C10%2C9.156%2C8.657%2C10.5%2C7%2C10.5z%20M7%2C5.5c-1.104%2C0-2%2C0.896-2%2C2c0%2C1.104%2C0.896%2C2%2C2%2C2c1.104%2C0%2C2-0.896%2C2-2%20C9%2C6.396%2C8.104%2C5.5%2C7%2C5.5z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-carat-d:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2211.949%2C3.404%207%2C8.354%202.05%2C3.404%20-0.071%2C5.525%207%2C12.596%2014.07%2C5.525%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-carat-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2210.596%2C11.949%205.646%2C7%2010.596%2C2.05%208.475%2C-0.071%201.404%2C7%208.475%2C14.07%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-carat-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%223.404%2C2.051%208.354%2C7%203.404%2C11.95%205.525%2C14.07%2012.596%2C7%205.525%2C-0.071%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-carat-u:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%222.051%2C10.596%207%2C5.646%2011.95%2C10.596%2014.07%2C8.475%207%2C1.404%20-0.071%2C8.475%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-check:after,html .ui-btn.ui-checkbox-on.ui-checkbox-on:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2214%2C4%2011%2C1%205.003%2C6.997%203%2C5%200%2C8%204.966%2C13%204.983%2C12.982%205%2C13%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-clock:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-cloud:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M14%2C9.5c0-0.793-0.465-1.473-1.134-1.795C12.949%2C7.484%2C13%2C7.249%2C13%2C7c0-1.104-0.896-2-2-2%20c-0.158%2C0-0.311%2C0.023-0.457%2C0.058C9.816%2C3.549%2C8.286%2C2.5%2C6.5%2C2.5c-2.33%2C0-4.224%2C1.777-4.454%2C4.046C0.883%2C6.76%2C0%2C7.773%2C0%2C9%20c0%2C1.381%2C1.119%2C2.5%2C2.5%2C2.5h10v-0.07C13.361%2C11.206%2C14%2C10.432%2C14%2C9.5z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-comment:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-delete:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-edit:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-eye:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C2C3%2C2%2C0%2C7%2C0%2C7s3%2C5%2C7%2C5s7-5%2C7-5S11%2C2%2C7%2C2z%20M7%2C10c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3C10%2C8.656%2C8.657%2C10%2C7%2C10z%20M7%2C6C6.448%2C6%2C6%2C6.447%2C6%2C7c0%2C0.553%2C0.448%2C1%2C1%2C1s1-0.447%2C1-1C8%2C6.447%2C7.552%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-forbidden:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-forward:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M13%2C4L9%2C0v3C6%2C3%2C1%2C4%2C1%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L13%2C4z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-gear:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-grid:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-heart:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C1.872c-2-3-7-2-7%2C2c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.479%2C3%2C3c0.583-0.521%2C3-3%2C3-3s4-4%2C4-7%20C14-0.128%2C9-1.128%2C7%2C1.872z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-home:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-info:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-location:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C0C4.791%2C0%2C3%2C1.791%2C3%2C4c0%2C2%2C4%2C10%2C4%2C10s4-8%2C4-10C11%2C1.791%2C9.209%2C0%2C7%2C0z%20M7%2C6C5.896%2C6%2C5%2C5.104%2C5%2C4%20s0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2S8.104%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-lock:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M12%2C6V5c0-2.762-2.238-5-5-5C4.239%2C0%2C2%2C2.238%2C2%2C5v1H1v8h12V6H12z%20M7.5%2C9.848V12h-1V9.848%20C6.207%2C9.673%2C6%2C9.366%2C6%2C9c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C8%2C9.366%2C7.793%2C9.673%2C7.5%2C9.848z%20M10%2C6H4V5c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3V6z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-mail:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M0%2C3.75V12h14V3.75L7%2C9L0%2C3.75z%20M14%2C2H0l7%2C5L14%2C2z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-minus:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20y%3D%225%22%20style%3D%22fill%3A%23FFFFFF%3B%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-navigation:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2213%2C1%200%2C6%207%2C7%208%2C14%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-phone:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%22-0.01%200.008%2014%2014%22%20style%3D%22enable-background%3Anew%20-0.01%200.008%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M6.939%2C9.189C6.165%2C8.557%2C5.271%2C7.705%2C4.497%2C6.744C3.953%2C6.071%2C3.473%2C5.363%2C3.969%2C4.866l-3.482-3.48%20C-0.021%2C2.02-1.146%2C5.04%2C3.675%2C9.984c5.08%2C5.211%2C8.356%2C4.097%2C8.92%2C3.511l-3.396-3.4C8.725%2C10.568%2C8.113%2C10.146%2C6.939%2C9.189z%20%20M13.82%2C11.519v-0.004c0%2C0-2.648-2.646-2.649-2.647c-0.21-0.211-0.546-0.205-0.754%2C0.002L9.455%2C9.831l3.403%2C3.407%20c0%2C0%2C0.962-0.96%2C0.961-0.961l0.002-0.001C14.043%2C12.056%2C14.021%2C11.721%2C13.82%2C11.519z%20M5.192%2C3.644V3.642%20c0.222-0.222%2C0.2-0.557%2C0-0.758V2.881c0%2C0-2.726-2.725-2.727-2.726C2.255-0.055%2C1.92-0.05%2C1.712%2C0.156L0.751%2C1.121l3.479%2C3.482%20C4.231%2C4.604%2C5.192%2C3.645%2C5.192%2C3.644z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-plus:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-power:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M11.243%2C2.408c-0.392-0.401-1.024-0.401-1.415%2C0c-0.391%2C0.401-0.391%2C1.054%2C0%2C1.455%20C10.584%2C4.642%2C11%2C5.675%2C11%2C6.773s-0.416%2C2.133-1.172%2C2.91c-1.512%2C1.558-4.145%2C1.558-5.656%2C0C3.416%2C8.904%2C3%2C7.872%2C3%2C6.773%20C3%2C5.673%2C3.416%2C4.64%2C4.172%2C3.863c0.39-0.401%2C0.39-1.054%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C1.624%2C3.574%2C1%2C5.125%2C1%2C6.773%20c0%2C1.647%2C0.624%2C3.199%2C1.757%2C4.365c1.134%2C1.166%2C2.64%2C1.809%2C4.243%2C1.809c1.604%2C0%2C3.109-0.645%2C4.243-1.811%20C12.376%2C9.975%2C13%2C8.423%2C13%2C6.773C13%2C5.125%2C12.376%2C3.574%2C11.243%2C2.408z%20M7%2C8.053c0.553%2C0%2C1-0.445%2C1-1v-6c0-0.553-0.447-1-1-1%20c-0.553%2C0-1%2C0.447-1%2C1v6C6%2C7.604%2C6.447%2C8.053%2C7%2C8.053z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-recycle:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M3%2C7h1L2%2C4L0%2C7h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.35v-2.205C8.41%2C10.789%2C7.732%2C11%2C7%2C11%20C4.791%2C11%2C3%2C9.209%2C3%2C7z%20M13%2C7c0-3.313-2.688-6-6-6C6.298%2C1%2C5.626%2C1.127%2C5%2C1.349v2.206C5.59%2C3.211%2C6.268%2C3%2C7%2C3c2.209%2C0%2C4%2C1.791%2C4%2C4%20h-1l2%2C3l2-3H13z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-refresh:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-search:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M10.171%2C8.766c0.617-0.888%2C0.979-1.964%2C0.979-3.126c0-3.037-2.463-5.5-5.5-5.5s-5.5%2C2.463-5.5%2C5.5%20s2.463%2C5.5%2C5.5%2C5.5c1.152%2C0%2C2.223-0.355%2C3.104-0.962l3.684%2C3.683l1.414-1.414L10.171%2C8.766z%20M5.649%2C9.14c-1.933%2C0-3.5-1.567-3.5-3.5%20c0-1.933%2C1.567-3.5%2C3.5-3.5c1.933%2C0%2C3.5%2C1.567%2C3.5%2C3.5C9.149%2C7.572%2C7.582%2C9.14%2C5.649%2C9.14z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-shop:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M10%2C4V3c0-1.657-1.343-3-3-3S4%2C1.343%2C4%2C3v1H1v10h12V4H10z%20M4.5%2C6C4.224%2C6%2C4%2C5.776%2C4%2C5.5%20S4.224%2C5%2C4.5%2C5S5%2C5.224%2C5%2C5.5S4.776%2C6%2C4.5%2C6z%20M5%2C3c0-1.104%2C0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2v1H5V3z%20M9.5%2C6C9.225%2C6%2C9%2C5.776%2C9%2C5.5%20S9.225%2C5%2C9.5%2C5S10%2C5.224%2C10%2C5.5S9.775%2C6%2C9.5%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-star:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-tag:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-user:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-video:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%20-2%2014%2014%22%20style%3D%22enable-background%3Anew%200%20-2%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-action:after,.ui-alt-icon .ui-icon-action:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C12H2V5h1l2-2H0v11h13V7l-2%2C2V12z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-alert:after,.ui-alt-icon .ui-icon-alert:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8C6.447%2C8%2C6%2C7.553%2C6%2C7V5%20c0-0.553%2C0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-d:after,.ui-alt-icon .ui-icon-arrow-d:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-d-l:after,.ui-alt-icon .ui-icon-arrow-d-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-d-r:after,.ui-alt-icon .ui-icon-arrow-d-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-l:after,.ui-alt-icon .ui-icon-arrow-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-r:after,.ui-alt-icon .ui-icon-arrow-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-u:after,.ui-alt-icon .ui-icon-arrow-u:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-u-l:after,.ui-alt-icon .ui-icon-arrow-u-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-u-r:after,.ui-alt-icon .ui-icon-arrow-u-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-audio:after,.ui-alt-icon .ui-icon-audio:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-back:after,.ui-alt-icon .ui-icon-back:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C3V0L1%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C13%2C4%2C8%2C3%2C5%2C3z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-bars:after,.ui-alt-icon .ui-icon-bars:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C2%2C0%2C2.447%2C0%2C3S0.447%2C4%2C1%2C4z%20M13%2C6H1C0.447%2C6%2C0%2C6.447%2C0%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H1c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1h12%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-bullets:after,.ui-alt-icon .ui-icon-bullets:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C4h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C2%2C4%2C2.447%2C4%2C3S4.447%2C4%2C5%2C4z%20M13%2C6H5C4.447%2C6%2C4%2C6.447%2C4%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H5c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1h8%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%20M1%2C2C0.447%2C2%2C0%2C2.447%2C0%2C3s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C2%2C1%2C2z%20M1%2C6C0.447%2C6%2C0%2C6.447%2C0%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1s1-0.447%2C1-1C2%2C6.447%2C1.553%2C6%2C1%2C6z%20M1%2C10c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C10%2C1%2C10z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-calendar:after,.ui-alt-icon .ui-icon-calendar:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-camera:after,.ui-alt-icon .ui-icon-camera:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C2.5H9.908c-0.206-0.581-0.756-1-1.408-1h-3c-0.652%2C0-1.202%2C0.419-1.408%2C1H2c-1.104%2C0-2%2C0.896-2%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2%20h10c1.104%2C0%2C2-0.896%2C2-2v-6C14%2C3.396%2C13.104%2C2.5%2C12%2C2.5z%20M7%2C10.5c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3%20C10%2C9.156%2C8.657%2C10.5%2C7%2C10.5z%20M7%2C5.5c-1.104%2C0-2%2C0.896-2%2C2c0%2C1.104%2C0.896%2C2%2C2%2C2c1.104%2C0%2C2-0.896%2C2-2C9%2C6.396%2C8.104%2C5.5%2C7%2C5.5z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-carat-d:after,.ui-alt-icon .ui-icon-carat-d:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2211.949%2C3.404%207%2C8.354%202.05%2C3.404%20-0.071%2C5.525%207%2C12.596%2014.07%2C5.525%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-carat-l:after,.ui-alt-icon .ui-icon-carat-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.596%2C11.949%205.646%2C7%2010.596%2C2.05%208.475%2C-0.071%201.404%2C7%208.475%2C14.07%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-carat-r:after,.ui-alt-icon .ui-icon-carat-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%223.404%2C2.051%208.354%2C7%203.404%2C11.95%205.525%2C14.07%2012.596%2C7%205.525%2C-0.071%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-carat-u:after,.ui-alt-icon .ui-icon-carat-u:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%222.051%2C10.596%207%2C5.646%2011.95%2C10.596%2014.07%2C8.475%207%2C1.404%20-0.071%2C8.475%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-check:after,.ui-alt-icon .ui-icon-check:after,html .ui-alt-icon.ui-btn.ui-checkbox-on:after,html .ui-alt-icon .ui-btn.ui-checkbox-on:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C4%2011%2C1%205.003%2C6.997%203%2C5%200%2C8%204.966%2C13%204.983%2C12.982%205%2C13%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-clock:after,.ui-alt-icon .ui-icon-clock:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-cloud:after,.ui-alt-icon .ui-icon-cloud:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14%2C9.5c0-0.793-0.465-1.473-1.134-1.795C12.949%2C7.484%2C13%2C7.249%2C13%2C7c0-1.104-0.896-2-2-2c-0.158%2C0-0.311%2C0.023-0.457%2C0.058%20C9.816%2C3.549%2C8.286%2C2.5%2C6.5%2C2.5c-2.33%2C0-4.224%2C1.777-4.454%2C4.046C0.883%2C6.76%2C0%2C7.773%2C0%2C9c0%2C1.381%2C1.119%2C2.5%2C2.5%2C2.5h10v-0.07%20C13.361%2C11.206%2C14%2C10.432%2C14%2C9.5z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-comment:after,.ui-alt-icon .ui-icon-comment:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-delete:after,.ui-alt-icon .ui-icon-delete:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-edit:after,.ui-alt-icon .ui-icon-edit:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-eye:after,.ui-alt-icon .ui-icon-eye:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C2C3%2C2%2C0%2C7%2C0%2C7s3%2C5%2C7%2C5s7-5%2C7-5S11%2C2%2C7%2C2z%20M7%2C10c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3%20C10%2C8.656%2C8.657%2C10%2C7%2C10z%20M7%2C6C6.448%2C6%2C6%2C6.447%2C6%2C7c0%2C0.553%2C0.448%2C1%2C1%2C1s1-0.447%2C1-1C8%2C6.447%2C7.552%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-forbidden:after,.ui-alt-icon .ui-icon-forbidden:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-forward:after,.ui-alt-icon .ui-icon-forward:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13%2C4L9%2C0v3C6%2C3%2C1%2C4%2C1%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L13%2C4z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-gear:after,.ui-alt-icon .ui-icon-gear:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-grid:after,.ui-alt-icon .ui-icon-grid:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-heart:after,.ui-alt-icon .ui-icon-heart:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C1.958c-2-3-7-2.128-7%2C1.872c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.48%2C3%2C3c0.583-0.52%2C3-3%2C3-3s4-4%2C4-7C14-0.169%2C9-1.042%2C7%2C1.958z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-home:after,.ui-alt-icon .ui-icon-home:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-info:after,.ui-alt-icon .ui-icon-info:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-location:after,.ui-alt-icon .ui-icon-location:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C4.791%2C0%2C3%2C1.791%2C3%2C4c0%2C2%2C4%2C10%2C4%2C10s4-8%2C4-10C11%2C1.791%2C9.209%2C0%2C7%2C0z%20M7%2C6C5.896%2C6%2C5%2C5.104%2C5%2C4s0.896-2%2C2-2%20c1.104%2C0%2C2%2C0.896%2C2%2C2S8.104%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-lock:after,.ui-alt-icon .ui-icon-lock:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C6V5c0-2.762-2.238-5-5-5C4.239%2C0%2C2%2C2.238%2C2%2C5v1H1v8h12V6H12z%20M7.5%2C9.848V12h-1V9.848C6.207%2C9.673%2C6%2C9.366%2C6%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C8%2C9.366%2C7.793%2C9.673%2C7.5%2C9.848z%20M10%2C6H4V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-mail:after,.ui-alt-icon .ui-icon-mail:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C3.75V12h14V3.75L7%2C9L0%2C3.75z%20M14%2C2H0l7%2C5L14%2C2z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-minus:after,.ui-alt-icon .ui-icon-minus:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20y%3D%225%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-navigation:after,.ui-alt-icon .ui-icon-navigation:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2213%2C1%200%2C6%207%2C7%208%2C14%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-phone:after,.ui-alt-icon .ui-icon-phone:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M6.949%2C9.182C6.175%2C8.549%2C5.281%2C7.697%2C4.507%2C6.736C3.963%2C6.063%2C3.483%2C5.355%2C3.979%2C4.858l-3.482-3.48%20c-0.508%2C0.634-1.633%2C3.654%2C3.188%2C8.598c5.08%2C5.211%2C8.356%2C4.097%2C8.92%2C3.511l-3.396-3.399C8.734%2C10.561%2C8.123%2C10.139%2C6.949%2C9.182z%20%20M13.83%2C11.512v-0.004c0%2C0-2.648-2.646-2.649-2.647c-0.21-0.212-0.546-0.205-0.754%2C0.002L9.465%2C9.823l3.402%2C3.407%20c0%2C0%2C0.963-0.961%2C0.961-0.961l0.002-0.002C14.053%2C12.049%2C14.031%2C11.713%2C13.83%2C11.512z%20M5.202%2C3.636V3.634%20c0.222-0.222%2C0.2-0.557%2C0-0.758V2.873c0%2C0-2.726-2.725-2.727-2.726c-0.21-0.21-0.545-0.205-0.753%2C0.001L0.761%2C1.113L4.24%2C4.595%20C4.241%2C4.596%2C5.202%2C3.637%2C5.202%2C3.636z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-plus:after,.ui-alt-icon .ui-icon-plus:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-power:after,.ui-alt-icon .ui-icon-power:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11.243%2C2.408c-0.392-0.401-1.024-0.401-1.415%2C0c-0.391%2C0.401-0.391%2C1.054%2C0%2C1.455C10.584%2C4.642%2C11%2C5.675%2C11%2C6.773%20s-0.416%2C2.133-1.172%2C2.91c-1.512%2C1.558-4.145%2C1.558-5.656%2C0C3.416%2C8.904%2C3%2C7.872%2C3%2C6.773C3%2C5.673%2C3.416%2C4.64%2C4.172%2C3.863%20c0.39-0.401%2C0.39-1.054%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C1.624%2C3.574%2C1%2C5.125%2C1%2C6.773c0%2C1.647%2C0.624%2C3.199%2C1.757%2C4.365%20c1.134%2C1.166%2C2.64%2C1.809%2C4.243%2C1.809c1.604%2C0%2C3.109-0.645%2C4.243-1.811C12.376%2C9.975%2C13%2C8.423%2C13%2C6.773%20C13%2C5.125%2C12.376%2C3.574%2C11.243%2C2.408z%20M7%2C8.053c0.553%2C0%2C1-0.445%2C1-1v-6c0-0.553-0.447-1-1-1c-0.553%2C0-1%2C0.447-1%2C1v6%20C6%2C7.604%2C6.447%2C8.053%2C7%2C8.053z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-recycle:after,.ui-alt-icon .ui-icon-recycle:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C7h1L2%2C4L0%2C7h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.35v-2.205C8.41%2C10.789%2C7.732%2C11%2C7%2C11C4.791%2C11%2C3%2C9.209%2C3%2C7z%20%20M13%2C7c0-3.313-2.688-6-6-6C6.298%2C1%2C5.626%2C1.127%2C5%2C1.349v2.206C5.59%2C3.211%2C6.268%2C3%2C7%2C3c2.209%2C0%2C4%2C1.791%2C4%2C4h-1l2%2C3l2-3H13z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-refresh:after,.ui-alt-icon .ui-icon-refresh:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-search:after,.ui-alt-icon .ui-icon-search:after,.ui-input-search:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10.171%2C8.766c0.617-0.888%2C0.979-1.964%2C0.979-3.126c0-3.037-2.463-5.5-5.5-5.5s-5.5%2C2.463-5.5%2C5.5s2.463%2C5.5%2C5.5%2C5.5%20c1.152%2C0%2C2.223-0.355%2C3.104-0.962l3.684%2C3.683l1.414-1.414L10.171%2C8.766z%20M5.649%2C9.14c-1.933%2C0-3.5-1.567-3.5-3.5%20c0-1.933%2C1.567-3.5%2C3.5-3.5c1.933%2C0%2C3.5%2C1.567%2C3.5%2C3.5C9.149%2C7.572%2C7.582%2C9.14%2C5.649%2C9.14z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-shop:after,.ui-alt-icon .ui-icon-shop:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10%2C4V3c0-1.657-1.343-3-3-3S4%2C1.343%2C4%2C3v1H1v10h12V4H10z%20M4.5%2C6C4.224%2C6%2C4%2C5.776%2C4%2C5.5S4.224%2C5%2C4.5%2C5S5%2C5.224%2C5%2C5.5%20S4.776%2C6%2C4.5%2C6z%20M5%2C3c0-1.104%2C0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2v1H5V3z%20M9.5%2C6C9.225%2C6%2C9%2C5.776%2C9%2C5.5S9.225%2C5%2C9.5%2C5S10%2C5.224%2C10%2C5.5%20S9.775%2C6%2C9.5%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-star:after,.ui-alt-icon .ui-icon-star:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-tag:after,.ui-alt-icon .ui-icon-tag:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-user:after,.ui-alt-icon .ui-icon-user:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-video:after,.ui-alt-icon .ui-icon-video:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%20-2%2014%2014%22%20style%3D%22enable-background%3Anew%200%20-2%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3C%2Fsvg%3E")}.ui-nosvg .ui-icon-action:after{background-image:url(https://github.com/images/icons-png/action-white.png)}.ui-nosvg .ui-icon-alert:after{background-image:url(https://github.com/images/icons-png/alert-white.png)}.ui-nosvg .ui-icon-arrow-d-l:after{background-image:url(https://github.com/images/icons-png/arrow-d-l-white.png)}.ui-nosvg .ui-icon-arrow-d-r:after{background-image:url(https://github.com/images/icons-png/arrow-d-r-white.png)}.ui-nosvg .ui-icon-arrow-d:after{background-image:url(https://github.com/images/icons-png/arrow-d-white.png)}.ui-nosvg .ui-icon-arrow-l:after{background-image:url(https://github.com/images/icons-png/arrow-l-white.png)}.ui-nosvg .ui-icon-arrow-r:after{background-image:url(https://github.com/images/icons-png/arrow-r-white.png)}.ui-nosvg .ui-icon-arrow-u-l:after{background-image:url(https://github.com/images/icons-png/arrow-u-l-white.png)}.ui-nosvg .ui-icon-arrow-u-r:after{background-image:url(https://github.com/images/icons-png/arrow-u-r-white.png)}.ui-nosvg .ui-icon-arrow-u:after{background-image:url(https://github.com/images/icons-png/arrow-u-white.png)}.ui-nosvg .ui-icon-audio:after{background-image:url(https://github.com/images/icons-png/audio-white.png)}.ui-nosvg .ui-icon-back:after{background-image:url(https://github.com/images/icons-png/back-white.png)}.ui-nosvg .ui-icon-bars:after{background-image:url(https://github.com/images/icons-png/bars-white.png)}.ui-nosvg .ui-icon-bullets:after{background-image:url(https://github.com/images/icons-png/bullets-white.png)}.ui-nosvg .ui-icon-calendar:after{background-image:url(https://github.com/images/icons-png/calendar-white.png)}.ui-nosvg .ui-icon-camera:after{background-image:url(https://github.com/images/icons-png/camera-white.png)}.ui-nosvg .ui-icon-carat-d:after{background-image:url(https://github.com/images/icons-png/carat-d-white.png)}.ui-nosvg .ui-icon-carat-l:after{background-image:url(https://github.com/images/icons-png/carat-l-white.png)}.ui-nosvg .ui-icon-carat-r:after{background-image:url(https://github.com/images/icons-png/carat-r-white.png)}.ui-nosvg .ui-icon-carat-u:after{background-image:url(https://github.com/images/icons-png/carat-u-white.png)}.ui-nosvg .ui-icon-check:after,html.ui-nosvg .ui-btn.ui-checkbox-on:after{background-image:url(https://github.com/images/icons-png/check-white.png)}.ui-nosvg .ui-icon-clock:after{background-image:url(https://github.com/images/icons-png/clock-white.png)}.ui-nosvg .ui-icon-cloud:after{background-image:url(https://github.com/images/icons-png/cloud-white.png)}.ui-nosvg .ui-icon-comment:after{background-image:url(https://github.com/images/icons-png/comment-white.png)}.ui-nosvg .ui-icon-delete:after{background-image:url(https://github.com/images/icons-png/delete-white.png)}.ui-nosvg .ui-icon-edit:after{background-image:url(https://github.com/images/icons-png/edit-white.png)}.ui-nosvg .ui-icon-eye:after{background-image:url(https://github.com/images/icons-png/eye-white.png)}.ui-nosvg .ui-icon-forbidden:after{background-image:url(https://github.com/images/icons-png/forbidden-white.png)}.ui-nosvg .ui-icon-forward:after{background-image:url(https://github.com/images/icons-png/forward-white.png)}.ui-nosvg .ui-icon-gear:after{background-image:url(https://github.com/images/icons-png/gear-white.png)}.ui-nosvg .ui-icon-grid:after{background-image:url(https://github.com/images/icons-png/grid-white.png)}.ui-nosvg .ui-icon-heart:after{background-image:url(https://github.com/images/icons-png/heart-white.png)}.ui-nosvg .ui-icon-home:after{background-image:url(https://github.com/images/icons-png/home-white.png)}.ui-nosvg .ui-icon-info:after{background-image:url(https://github.com/images/icons-png/info-white.png)}.ui-nosvg .ui-icon-location:after{background-image:url(https://github.com/images/icons-png/location-white.png)}.ui-nosvg .ui-icon-lock:after{background-image:url(https://github.com/images/icons-png/lock-white.png)}.ui-nosvg .ui-icon-mail:after{background-image:url(https://github.com/images/icons-png/mail-white.png)}.ui-nosvg .ui-icon-minus:after{background-image:url(https://github.com/images/icons-png/minus-white.png)}.ui-nosvg .ui-icon-navigation:after{background-image:url(https://github.com/images/icons-png/navigation-white.png)}.ui-nosvg .ui-icon-phone:after{background-image:url(https://github.com/images/icons-png/phone-white.png)}.ui-nosvg .ui-icon-plus:after{background-image:url(https://github.com/images/icons-png/plus-white.png)}.ui-nosvg .ui-icon-power:after{background-image:url(https://github.com/images/icons-png/power-white.png)}.ui-nosvg .ui-icon-recycle:after{background-image:url(https://github.com/images/icons-png/recycle-white.png)}.ui-nosvg .ui-icon-refresh:after{background-image:url(https://github.com/images/icons-png/refresh-white.png)}.ui-nosvg .ui-icon-search:after{background-image:url(https://github.com/images/icons-png/search-white.png)}.ui-nosvg .ui-icon-shop:after{background-image:url(https://github.com/images/icons-png/shop-white.png)}.ui-nosvg .ui-icon-star:after{background-image:url(https://github.com/images/icons-png/star-white.png)}.ui-nosvg .ui-icon-tag:after{background-image:url(https://github.com/images/icons-png/tag-white.png)}.ui-nosvg .ui-icon-user:after{background-image:url(https://github.com/images/icons-png/user-white.png)}.ui-nosvg .ui-icon-video:after{background-image:url(https://github.com/images/icons-png/video-white.png)}.ui-nosvg .ui-alt-icon.ui-icon-action:after,.ui-nosvg .ui-alt-icon .ui-icon-action:after{background-image:url(https://github.com/images/icons-png/action-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-alert:after,.ui-nosvg .ui-alt-icon .ui-icon-alert:after{background-image:url(https://github.com/images/icons-png/alert-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-d:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-d:after{background-image:url(https://github.com/images/icons-png/arrow-d-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-d-l:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-d-l:after{background-image:url(https://github.com/images/icons-png/arrow-d-l-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-d-r:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-d-r:after{background-image:url(https://github.com/images/icons-png/arrow-d-r-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-l:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-l:after{background-image:url(https://github.com/images/icons-png/arrow-l-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-r:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-r:after{background-image:url(https://github.com/images/icons-png/arrow-r-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-u:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-u:after{background-image:url(https://github.com/images/icons-png/arrow-u-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-u-l:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-u-l:after{background-image:url(https://github.com/images/icons-png/arrow-u-l-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-u-r:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-u-r:after{background-image:url(https://github.com/images/icons-png/arrow-u-r-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-audio:after,.ui-nosvg .ui-alt-icon .ui-icon-audio:after{background-image:url(https://github.com/images/icons-png/audio-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-back:after,.ui-nosvg .ui-alt-icon .ui-icon-back:after{background-image:url(https://github.com/images/icons-png/back-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-bars:after,.ui-nosvg .ui-alt-icon .ui-icon-bars:after{background-image:url(https://github.com/images/icons-png/bars-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-bullets:after,.ui-nosvg .ui-alt-icon .ui-icon-bullets:after{background-image:url(https://github.com/images/icons-png/bullets-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-calendar:after,.ui-nosvg .ui-alt-icon .ui-icon-calendar:after{background-image:url(https://github.com/images/icons-png/calendar-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-camera:after,.ui-nosvg .ui-alt-icon .ui-icon-camera:after{background-image:url(https://github.com/images/icons-png/camera-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-carat-d:after,.ui-nosvg .ui-alt-icon .ui-icon-carat-d:after{background-image:url(https://github.com/images/icons-png/carat-d-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-carat-l:after,.ui-nosvg .ui-alt-icon .ui-icon-carat-l:after{background-image:url(https://github.com/images/icons-png/carat-l-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-carat-r:after,.ui-nosvg .ui-alt-icon .ui-icon-carat-r:after{background-image:url(https://github.com/images/icons-png/carat-r-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-carat-u:after,.ui-nosvg .ui-alt-icon .ui-icon-carat-u:after{background-image:url(https://github.com/images/icons-png/carat-u-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-check:after,.ui-nosvg .ui-alt-icon .ui-icon-check:after,.ui-nosvg .ui-alt-icon.ui-btn.ui-checkbox-on:after,.ui-nosvg .ui-alt-icon .ui-btn.ui-checkbox-on:after{background-image:url(https://github.com/images/icons-png/check-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-clock:after,.ui-nosvg .ui-alt-icon .ui-icon-clock:after{background-image:url(https://github.com/images/icons-png/clock-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-cloud:after,.ui-nosvg .ui-alt-icon .ui-icon-cloud:after{background-image:url(https://github.com/images/icons-png/cloud-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-comment:after,.ui-nosvg .ui-alt-icon .ui-icon-comment:after{background-image:url(https://github.com/images/icons-png/comment-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-delete:after,.ui-nosvg .ui-alt-icon .ui-icon-delete:after{background-image:url(https://github.com/images/icons-png/delete-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-edit:after,.ui-nosvg .ui-alt-icon .ui-icon-edit:after{background-image:url(https://github.com/images/icons-png/edit-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-eye:after,.ui-nosvg .ui-alt-icon .ui-icon-eye:after{background-image:url(https://github.com/images/icons-png/eye-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-forbidden:after,.ui-nosvg .ui-alt-icon .ui-icon-forbidden:after{background-image:url(https://github.com/images/icons-png/forbidden-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-forward:after,.ui-nosvg .ui-alt-icon .ui-icon-forward:after{background-image:url(https://github.com/images/icons-png/forward-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-gear:after,.ui-nosvg .ui-alt-icon .ui-icon-gear:after{background-image:url(https://github.com/images/icons-png/gear-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-grid:after,.ui-nosvg .ui-alt-icon .ui-icon-grid:after{background-image:url(https://github.com/images/icons-png/grid-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-heart:after,.ui-nosvg .ui-alt-icon .ui-icon-heart:after{background-image:url(https://github.com/images/icons-png/heart-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-home:after,.ui-nosvg .ui-alt-icon .ui-icon-home:after{background-image:url(https://github.com/images/icons-png/home-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-info:after,.ui-nosvg .ui-alt-icon .ui-icon-info:after{background-image:url(https://github.com/images/icons-png/info-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-location:after,.ui-nosvg .ui-alt-icon .ui-icon-location:after{background-image:url(https://github.com/images/icons-png/location-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-lock:after,.ui-nosvg .ui-alt-icon .ui-icon-lock:after{background-image:url(https://github.com/images/icons-png/lock-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-mail:after,.ui-nosvg .ui-alt-icon .ui-icon-mail:after{background-image:url(https://github.com/images/icons-png/mail-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-minus:after,.ui-nosvg .ui-alt-icon .ui-icon-minus:after{background-image:url(https://github.com/images/icons-png/minus-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-navigation:after,.ui-nosvg .ui-alt-icon .ui-icon-navigation:after{background-image:url(https://github.com/images/icons-png/navigation-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-phone:after,.ui-nosvg .ui-alt-icon .ui-icon-phone:after{background-image:url(https://github.com/images/icons-png/phone-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-plus:after,.ui-nosvg .ui-alt-icon .ui-icon-plus:after{background-image:url(https://github.com/images/icons-png/plus-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-power:after,.ui-nosvg .ui-alt-icon .ui-icon-power:after{background-image:url(https://github.com/images/icons-png/power-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-recycle:after,.ui-nosvg .ui-alt-icon .ui-icon-recycle:after{background-image:url(https://github.com/images/icons-png/recycle-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-refresh:after,.ui-nosvg .ui-alt-icon .ui-icon-refresh:after{background-image:url(https://github.com/images/icons-png/refresh-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-search:after,.ui-nosvg .ui-alt-icon .ui-icon-search:after,.ui-nosvg .ui-input-search:after{background-image:url(https://github.com/images/icons-png/search-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-shop:after,.ui-nosvg .ui-alt-icon .ui-icon-shop:after{background-image:url(https://github.com/images/icons-png/shop-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-star:after,.ui-nosvg .ui-alt-icon .ui-icon-star:after{background-image:url(https://github.com/images/icons-png/star-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-tag:after,.ui-nosvg .ui-alt-icon .ui-icon-tag:after{background-image:url(https://github.com/images/icons-png/tag-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-user:after,.ui-nosvg .ui-alt-icon .ui-icon-user:after{background-image:url(https://github.com/images/icons-png/user-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-video:after,.ui-nosvg .ui-alt-icon .ui-icon-video:after{background-image:url(https://github.com/images/icons-png/video-black.png)}html{font-size:100%}body,input,select,textarea,button,.ui-btn{font-size:1em;line-height:1.3;font-family:sans-serif}legend,.ui-input-text input,.ui-input-search input{color:inherit;text-shadow:inherit}.ui-mobile label,div.ui-controlgroup-label{font-weight:400;font-size:16px}.ui-field-contain{border-bottom-color:#828282;border-bottom-color:rgba(0,0,0,.15);border-bottom-width:1px;border-bottom-style:solid}.table-stroke thead th,.table-stripe thead th,.table-stripe tbody tr:last-child{border-bottom:1px solid #d6d6d6;border-bottom:1px solid rgba(0,0,0,.1)}.table-stroke tbody th,.table-stroke tbody td{border-bottom:1px solid #e6e6e6;border-bottom:1px solid rgba(0,0,0,.05)}.table-stripe.table-stroke tbody tr:last-child th,.table-stripe.table-stroke tbody tr:last-child td{border-bottom:0}.table-stripe tbody tr:nth-child(odd) td,.table-stripe tbody tr:nth-child(odd) th{background-color:#eee;background-color:rgba(0,0,0,.04)}.ui-btn,label.ui-btn{font-weight:700;border-width:1px;border-style:solid}.ui-btn:link{text-decoration:none!important}.ui-btn-active{cursor:pointer}.ui-corner-all{-webkit-border-radius:.3125em;border-radius:.3125em}.ui-btn-corner-all,.ui-btn.ui-corner-all,.ui-slider-track.ui-corner-all,.ui-flipswitch.ui-corner-all,.ui-li-count{-webkit-border-radius:.3125em;border-radius:.3125em}.ui-btn-icon-notext.ui-btn-corner-all,.ui-btn-icon-notext.ui-corner-all{-webkit-border-radius:1em;border-radius:1em}.ui-btn-corner-all,.ui-corner-all{-webkit-background-clip:padding;background-clip:padding-box}.ui-popup.ui-corner-all>.ui-popup-arrow-guide{left:.6em;right:.6em;top:.6em;bottom:.6em}.ui-shadow{-webkit-box-shadow:0 1px 3px rgba(0,0,0,.15);-moz-box-shadow:0 1px 3px rgba(0,0,0,.15);box-shadow:0 1px 3px rgba(0,0,0,.15)}.ui-shadow-inset{-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.2);-moz-box-shadow:inset 0 1px 3px rgba(0,0,0,.2);box-shadow:inset 0 1px 3px rgba(0,0,0,.2)}.ui-overlay-shadow{-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);-moz-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)}.ui-btn-icon-left:after,.ui-btn-icon-right:after,.ui-btn-icon-top:after,.ui-btn-icon-bottom:after,.ui-btn-icon-notext:after{background-color:#666;background-color:rgba(0,0,0,.3);background-position:center center;background-repeat:no-repeat;-webkit-border-radius:1em;border-radius:1em}.ui-alt-icon.ui-btn:after,.ui-alt-icon .ui-btn:after,html .ui-alt-icon.ui-checkbox-off:after,html .ui-alt-icon.ui-radio-off:after,html .ui-alt-icon .ui-checkbox-off:after,html .ui-alt-icon .ui-radio-off:after{background-color:#666;background-color:rgba(0,0,0,.15)}.ui-nodisc-icon.ui-btn:after,.ui-nodisc-icon .ui-btn:after{background-color:transparent}.ui-shadow-icon.ui-btn:after,.ui-shadow-icon .ui-btn:after{-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.ui-btn.ui-checkbox-off:after,.ui-btn.ui-checkbox-on:after,.ui-btn.ui-radio-off:after,.ui-btn.ui-radio-on:after{display:block;width:18px;height:18px;margin:-9px 2px 0 2px}.ui-checkbox-off:after,.ui-btn.ui-radio-off:after{filter:Alpha(Opacity=30);opacity:.3}.ui-btn.ui-checkbox-off:after,.ui-btn.ui-checkbox-on:after{-webkit-border-radius:.1875em;border-radius:.1875em}.ui-radio .ui-btn.ui-radio-on:after{background-image:none;background-color:#fff;width:8px;height:8px;border-width:5px;border-style:solid}.ui-alt-icon.ui-btn.ui-radio-on:after,.ui-alt-icon .ui-btn.ui-radio-on:after{background-color:#000}.ui-icon-loading{background:url(https://github.com/images/ajax-loader.gif);background-size:2.875em 2.875em}.ui-bar-a,.ui-page-theme-a .ui-bar-inherit,html .ui-bar-a .ui-bar-inherit,html .ui-body-a .ui-bar-inherit,html body .ui-group-theme-a .ui-bar-inherit{background-color:#e9e9e9;border-color:#ddd;color:#333;text-shadow:0 1px 0 #eee;font-weight:700}.ui-bar-a{border-width:1px;border-style:solid}.ui-overlay-a,.ui-page-theme-a,.ui-page-theme-a .ui-panel-wrapper{background-color:#f9f9f9;border-color:#bbb;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-body-a,.ui-page-theme-a .ui-body-inherit,html .ui-bar-a .ui-body-inherit,html .ui-body-a .ui-body-inherit,html body .ui-group-theme-a .ui-body-inherit,html .ui-panel-page-container-a{background-color:#fff;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-body-a{border-width:1px;border-style:solid}.ui-page-theme-a a,html .ui-bar-a a,html .ui-body-a a,html body .ui-group-theme-a a{color:#38c;font-weight:700}.ui-page-theme-a a:visited,html .ui-bar-a a:visited,html .ui-body-a a:visited,html body .ui-group-theme-a a:visited{color:#38c}.ui-page-theme-a a:hover,html .ui-bar-a a:hover,html .ui-body-a a:hover,html body .ui-group-theme-a a:hover{color:#059}.ui-page-theme-a a:active,html .ui-bar-a a:active,html .ui-body-a a:active,html body .ui-group-theme-a a:active{color:#059}.ui-page-theme-a .ui-btn,html .ui-bar-a .ui-btn,html .ui-body-a .ui-btn,html body .ui-group-theme-a .ui-btn,html head+body .ui-btn.ui-btn-a,.ui-page-theme-a .ui-btn:visited,html .ui-bar-a .ui-btn:visited,html .ui-body-a .ui-btn:visited,html body .ui-group-theme-a .ui-btn:visited,html head+body .ui-btn.ui-btn-a:visited{background-color:#f6f6f6;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-page-theme-a .ui-btn:hover,html .ui-bar-a .ui-btn:hover,html .ui-body-a .ui-btn:hover,html body .ui-group-theme-a .ui-btn:hover,html head+body .ui-btn.ui-btn-a:hover{background-color:#ededed;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-page-theme-a .ui-btn:active,html .ui-bar-a .ui-btn:active,html .ui-body-a .ui-btn:active,html body .ui-group-theme-a .ui-btn:active,html head+body .ui-btn.ui-btn-a:active{background-color:#e8e8e8;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-page-theme-a .ui-btn.ui-btn-active,html .ui-bar-a .ui-btn.ui-btn-active,html .ui-body-a .ui-btn.ui-btn-active,html body .ui-group-theme-a .ui-btn.ui-btn-active,html head+body .ui-btn.ui-btn-a.ui-btn-active,.ui-page-theme-a .ui-checkbox-on:after,html .ui-bar-a .ui-checkbox-on:after,html .ui-body-a .ui-checkbox-on:after,html body .ui-group-theme-a .ui-checkbox-on:after,.ui-btn.ui-checkbox-on.ui-btn-a:after,.ui-page-theme-a .ui-flipswitch-active,html .ui-bar-a .ui-flipswitch-active,html .ui-body-a .ui-flipswitch-active,html body .ui-group-theme-a .ui-flipswitch-active,html body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,.ui-page-theme-a .ui-slider-track .ui-btn-active,html .ui-bar-a .ui-slider-track .ui-btn-active,html .ui-body-a .ui-slider-track .ui-btn-active,html body .ui-group-theme-a .ui-slider-track .ui-btn-active,html body div.ui-slider-track.ui-body-a .ui-btn-active{background-color:#38c;border-color:#38c;color:#fff;text-shadow:0 1px 0 #059}.ui-page-theme-a .ui-radio-on:after,html .ui-bar-a .ui-radio-on:after,html .ui-body-a .ui-radio-on:after,html body .ui-group-theme-a .ui-radio-on:after,.ui-btn.ui-radio-on.ui-btn-a:after{border-color:#38c}.ui-page-theme-a .ui-btn:focus,html .ui-bar-a .ui-btn:focus,html .ui-body-a .ui-btn:focus,html body .ui-group-theme-a .ui-btn:focus,html head+body .ui-btn.ui-btn-a:focus,.ui-page-theme-a .ui-focus,html .ui-bar-a .ui-focus,html .ui-body-a .ui-focus,html body .ui-group-theme-a .ui-focus,html head+body .ui-btn-a.ui-focus,html head+body .ui-body-a.ui-focus{-webkit-box-shadow:0 0 12px #38c;-moz-box-shadow:0 0 12px #38c;box-shadow:0 0 12px #38c}.ui-bar-b,.ui-page-theme-b .ui-bar-inherit,html .ui-bar-b .ui-bar-inherit,html .ui-body-b .ui-bar-inherit,html body .ui-group-theme-b .ui-bar-inherit{background-color:#1d1d1d;border-color:#1b1b1b;color:#fff;text-shadow:0 1px 0 #111;font-weight:700}.ui-bar-b{border-width:1px;border-style:solid}.ui-overlay-b,.ui-page-theme-b,.ui-page-theme-b .ui-panel-wrapper{background-color:#252525;border-color:#454545;color:#fff;text-shadow:0 1px 0 #111}.ui-body-b,.ui-page-theme-b .ui-body-inherit,html .ui-bar-b .ui-body-inherit,html .ui-body-b .ui-body-inherit,html body .ui-group-theme-b .ui-body-inherit,html .ui-panel-page-container-b{background-color:#2a2a2a;border-color:#1d1d1d;color:#fff;text-shadow:0 1px 0 #111}.ui-body-b{border-width:1px;border-style:solid}.ui-page-theme-b a,html .ui-bar-b a,html .ui-body-b a,html body .ui-group-theme-b a{color:#2ad;font-weight:700}.ui-page-theme-b a:visited,html .ui-bar-b a:visited,html .ui-body-b a:visited,html body .ui-group-theme-b a:visited{color:#2ad}.ui-page-theme-b a:hover,html .ui-bar-b a:hover,html .ui-body-b a:hover,html body .ui-group-theme-b a:hover{color:#08b}.ui-page-theme-b a:active,html .ui-bar-b a:active,html .ui-body-b a:active,html body .ui-group-theme-b a:active{color:#08b}.ui-page-theme-b .ui-btn,html .ui-bar-b .ui-btn,html .ui-body-b .ui-btn,html body .ui-group-theme-b .ui-btn,html head+body .ui-btn.ui-btn-b,.ui-page-theme-b .ui-btn:visited,html .ui-bar-b .ui-btn:visited,html .ui-body-b .ui-btn:visited,html body .ui-group-theme-b .ui-btn:visited,html head+body .ui-btn.ui-btn-b:visited{background-color:#333;border-color:#1f1f1f;color:#fff;text-shadow:0 1px 0 #111}.ui-page-theme-b .ui-btn:hover,html .ui-bar-b .ui-btn:hover,html .ui-body-b .ui-btn:hover,html body .ui-group-theme-b .ui-btn:hover,html head+body .ui-btn.ui-btn-b:hover{background-color:#373737;border-color:#1f1f1f;color:#fff;text-shadow:0 1px 0 #111}.ui-page-theme-b .ui-btn:active,html .ui-bar-b .ui-btn:active,html .ui-body-b .ui-btn:active,html body .ui-group-theme-b .ui-btn:active,html head+body .ui-btn.ui-btn-b:active{background-color:#404040;border-color:#1f1f1f;color:#fff;text-shadow:0 1px 0 #111}.ui-page-theme-b .ui-btn.ui-btn-active,html .ui-bar-b .ui-btn.ui-btn-active,html .ui-body-b .ui-btn.ui-btn-active,html body .ui-group-theme-b .ui-btn.ui-btn-active,html head+body .ui-btn.ui-btn-b.ui-btn-active,.ui-page-theme-b .ui-checkbox-on:after,html .ui-bar-b .ui-checkbox-on:after,html .ui-body-b .ui-checkbox-on:after,html body .ui-group-theme-b .ui-checkbox-on:after,.ui-btn.ui-checkbox-on.ui-btn-b:after,.ui-page-theme-b .ui-flipswitch-active,html .ui-bar-b .ui-flipswitch-active,html .ui-body-b .ui-flipswitch-active,html body .ui-group-theme-b .ui-flipswitch-active,html body .ui-flipswitch.ui-bar-b.ui-flipswitch-active,.ui-page-theme-b .ui-slider-track .ui-btn-active,html .ui-bar-b .ui-slider-track .ui-btn-active,html .ui-body-b .ui-slider-track .ui-btn-active,html body .ui-group-theme-b .ui-slider-track .ui-btn-active,html body div.ui-slider-track.ui-body-b .ui-btn-active{background-color:#2ad;border-color:#2ad;color:#fff;text-shadow:0 1px 0 #08b}.ui-page-theme-b .ui-radio-on:after,html .ui-bar-b .ui-radio-on:after,html .ui-body-b .ui-radio-on:after,html body .ui-group-theme-b .ui-radio-on:after,.ui-btn.ui-radio-on.ui-btn-b:after{border-color:#2ad}.ui-page-theme-b .ui-btn:focus,html .ui-bar-b .ui-btn:focus,html .ui-body-b .ui-btn:focus,html body .ui-group-theme-b .ui-btn:focus,html head+body .ui-btn.ui-btn-b:focus,.ui-page-theme-b .ui-focus,html .ui-bar-b .ui-focus,html .ui-body-b .ui-focus,html body .ui-group-theme-b .ui-focus,html head+body .ui-btn-b.ui-focus,html head+body .ui-body-b.ui-focus{-webkit-box-shadow:0 0 12px #2ad;-moz-box-shadow:0 0 12px #2ad;box-shadow:0 0 12px #2ad}.ui-disabled,.ui-state-disabled,button[disabled],.ui-select .ui-btn.ui-state-disabled{filter:Alpha(Opacity=30);opacity:.3;cursor:default!important;pointer-events:none}.ui-btn:focus,.ui-btn.ui-focus{outline:0}.ui-noboxshadow .ui-shadow,.ui-noboxshadow .ui-shadow-inset,.ui-noboxshadow .ui-overlay-shadow,.ui-noboxshadow .ui-shadow-icon.ui-btn:after,.ui-noboxshadow .ui-shadow-icon .ui-btn:after,.ui-noboxshadow .ui-focus,.ui-noboxshadow .ui-btn:focus,.ui-noboxshadow input:focus,.ui-noboxshadow .ui-panel{-webkit-box-shadow:none!important;-moz-box-shadow:none!important;box-shadow:none!important}.ui-noboxshadow .ui-btn:focus,.ui-noboxshadow .ui-focus{outline-width:1px;outline-style:auto}.ui-mobile,.ui-mobile body{height:99.9%}.ui-mobile fieldset,.ui-page{padding:0;margin:0}.ui-mobile a img,.ui-mobile fieldset{border-width:0}.ui-mobile fieldset{min-width:0}@-moz-document url-prefix(){.ui-mobile fieldset{display:table-column;vertical-align:middle}}.ui-mobile-viewport{margin:0;overflow-x:visible;-webkit-text-size-adjust:100%;-ms-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}body.ui-mobile-viewport,div.ui-mobile-viewport{overflow-x:hidden}.ui-mobile [data-role=page],.ui-mobile [data-role=dialog],.ui-page{top:0;left:0;width:100%;min-height:100%;position:absolute;display:none;border:0}.ui-page{outline:0}.ui-mobile .ui-page-active{display:block;overflow:visible;overflow-x:hidden}@media screen and (orientation:portrait){.ui-mobile .ui-page{min-height:420px}}@media screen and (orientation:landscape){.ui-mobile .ui-page{min-height:300px}}.ui-mobile-rendering>*{visibility:hidden}.ui-nojs{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-loading .ui-loader{display:block}.ui-loader{display:none;z-index:9999999;position:fixed;top:50%;left:50%;border:0}.ui-loader-default{background:0;filter:Alpha(Opacity=18);opacity:.18;width:2.875em;height:2.875em;margin-left:-1.4375em;margin-top:-1.4375em}.ui-loader-verbose{width:12.5em;filter:Alpha(Opacity=88);opacity:.88;box-shadow:0 1px 1px -1px #fff;height:auto;margin-left:-6.875em;margin-top:-2.6875em;padding:.625em}.ui-loader-default h1{font-size:0;width:0;height:0;overflow:hidden}.ui-loader-verbose h1{font-size:1em;margin:0;text-align:center}.ui-loader .ui-icon-loading{background-color:#000;display:block;margin:0;width:2.75em;height:2.75em;padding:.0625em;-webkit-border-radius:2.25em;border-radius:2.25em}.ui-loader-verbose .ui-icon-loading{margin:0 auto .625em;filter:Alpha(Opacity=75);opacity:.75}.ui-loader-textonly{padding:.9375em;margin-left:-7.1875em}.ui-loader-textonly .ui-icon-loading{display:none}.ui-loader-fakefix{position:absolute}.ui-bar,.ui-body{position:relative;padding:.4em 1em;overflow:hidden;display:block;clear:both}.ui-bar h1,.ui-bar h2,.ui-bar h3,.ui-bar h4,.ui-bar h5,.ui-bar h6{margin:0;padding:0;font-size:1em;display:inline-block}.ui-header,.ui-footer{border-width:1px 0;border-style:solid;position:relative}.ui-header:empty,.ui-footer:empty{min-height:2.6875em}.ui-header .ui-title,.ui-footer .ui-title{font-size:1em;min-height:1.1em;text-align:center;display:block;margin:0 30%;padding:.7em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;outline:0!important}.ui-footer .ui-title{margin:0 1em}.ui-content{border-width:0;overflow:visible;overflow-x:hidden;padding:1em}.ui-corner-all>.ui-header:first-child,.ui-corner-all>.ui-content:first-child,.ui-corner-all>.ui-footer:first-child{-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit;-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit}.ui-corner-all>.ui-header:last-child,.ui-corner-all>.ui-content:last-child,.ui-corner-all>.ui-footer:last-child{-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit;-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit}.ui-btn{font-size:16px;margin:.5em 0;padding:.7em 1em;display:block;position:relative;text-align:center;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ui-btn-icon-notext{padding:0;width:1.75em;height:1.75em;text-indent:-9999px;white-space:nowrap!important}.ui-mini{font-size:12.5px}.ui-mini .ui-btn{font-size:inherit}.ui-header .ui-btn,.ui-footer .ui-btn{font-size:12.5px;display:inline-block;vertical-align:middle}.ui-header .ui-btn-left,.ui-header .ui-btn-right{font-size:12.5px}.ui-mini.ui-btn-icon-notext,.ui-mini .ui-btn-icon-notext,.ui-header .ui-btn-icon-notext,.ui-footer .ui-btn-icon-notext{font-size:16px;padding:0}.ui-btn-inline{display:inline-block;vertical-align:middle;margin-right:.625em}.ui-btn-icon-left{padding-left:2.5em}.ui-btn-icon-right{padding-right:2.5em}.ui-btn-icon-top{padding-top:2.5em}.ui-btn-icon-bottom{padding-bottom:2.5em}.ui-header .ui-btn-icon-top,.ui-footer .ui-btn-icon-top,.ui-header .ui-btn-icon-bottom,.ui-footer .ui-btn-icon-bottom{padding-left:.3125em;padding-right:.3125em}.ui-btn-icon-left:after,.ui-btn-icon-right:after,.ui-btn-icon-top:after,.ui-btn-icon-bottom:after,.ui-btn-icon-notext:after{content:"";position:absolute;display:block;width:22px;height:22px}.ui-btn-icon-notext:after,.ui-btn-icon-left:after,.ui-btn-icon-right:after{top:50%;margin-top:-11px}.ui-btn-icon-left:after{left:.5625em}.ui-btn-icon-right:after{right:.5625em}.ui-mini.ui-btn-icon-left:after,.ui-mini .ui-btn-icon-left:after,.ui-header .ui-btn-icon-left:after,.ui-footer .ui-btn-icon-left:after{left:.37em}.ui-mini.ui-btn-icon-right:after,.ui-mini .ui-btn-icon-right:after,.ui-header .ui-btn-icon-right:after,.ui-footer .ui-btn-icon-right:after{right:.37em}.ui-btn-icon-notext:after,.ui-btn-icon-top:after,.ui-btn-icon-bottom:after{left:50%;margin-left:-11px}.ui-btn-icon-top:after{top:.5625em}.ui-btn-icon-bottom:after{top:auto;bottom:.5625em}.ui-header .ui-btn-left,.ui-header .ui-btn-right,.ui-btn-left>[class*=ui-],.ui-btn-right>[class*=ui-]{margin:0}.ui-btn-left,.ui-btn-right{position:absolute;top:.24em}.ui-btn-left{left:.4em}.ui-btn-right{right:.4em}.ui-btn-icon-notext.ui-btn-left{top:.3125em;left:.3125em}.ui-btn-icon-notext.ui-btn-right{top:.3125em;right:.3125em}button.ui-btn,.ui-controlgroup-controls button.ui-btn-icon-notext{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;width:100%}button.ui-btn-inline{width:auto}button.ui-btn::-moz-focus-inner{border:0}button.ui-btn-icon-notext,.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;width:1.75em}.ui-mobile label,.ui-controlgroup-label{display:block;margin:0 0 .4em}.ui-hide-label>label,.ui-hide-label .ui-controlgroup-label,.ui-hide-label .ui-rangeslider label,.ui-hidden-accessible{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-screen-hidden{display:none!important}.ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.ui-page-pre-in{opacity:0}.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms;animation-timing-function:ease-out;animation-duration:350ms}.out{-webkit-animation-timing-function:ease-in;-webkit-animation-duration:225ms;-moz-animation-timing-function:ease-in;-moz-animation-duration:225ms;animation-timing-function:ease-in;animation-duration:225ms}@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@-moz-keyframes fadein{from{opacity:0}to{opacity:1}}@keyframes fadein{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeout{from{opacity:1}to{opacity:0}}@-moz-keyframes fadeout{from{opacity:1}to{opacity:0}}@keyframes fadeout{from{opacity:1}to{opacity:0}}.fade.out{opacity:0;-webkit-animation-duration:125ms;-webkit-animation-name:fadeout;-moz-animation-duration:125ms;-moz-animation-name:fadeout;animation-duration:125ms;animation-name:fadeout}.fade.in{opacity:1;-webkit-animation-duration:225ms;-webkit-animation-name:fadein;-moz-animation-duration:225ms;-moz-animation-name:fadein;animation-duration:225ms;animation-name:fadein}.pop{-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%;transform-origin:50% 50%}.pop.in{-webkit-transform:scale(1);-webkit-animation-name:popin;-webkit-animation-duration:350ms;-moz-transform:scale(1);-moz-animation-name:popin;-moz-animation-duration:350ms;transform:scale(1);animation-name:popin;animation-duration:350ms;opacity:1}.pop.out{-webkit-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-name:fadeout;-moz-animation-duration:100ms;animation-name:fadeout;animation-duration:100ms;opacity:0}.pop.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;animation-name:fadein}.pop.out.reverse{-webkit-transform:scale(.8);-webkit-animation-name:popout;-moz-transform:scale(.8);-moz-animation-name:popout;transform:scale(.8);animation-name:popout}@-webkit-keyframes popin{from{-webkit-transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-moz-keyframes popin{from{-moz-transform:scale(.8);opacity:0}to{-moz-transform:scale(1);opacity:1}}@keyframes popin{from{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@-moz-keyframes popout{from{-moz-transform:scale(1);opacity:1}to{-moz-transform:scale(.8);opacity:0}}@keyframes popout{from{transform:scale(1);opacity:1}to{transform:scale(.8);opacity:0}}@-webkit-keyframes slideinfromright{from{-webkit-transform:translate3d(100%,0,0)}to{-webkit-transform:translate3d(0,0,0)}}@-moz-keyframes slideinfromright{from{-moz-transform:translateX(100%)}to{-moz-transform:translateX(0)}}@keyframes slideinfromright{from{transform:translateX(100%)}to{transform:translateX(0)}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translate3d(-100%,0,0)}to{-webkit-transform:translate3d(0,0,0)}}@-moz-keyframes slideinfromleft{from{-moz-transform:translateX(-100%)}to{-moz-transform:translateX(0)}}@keyframes slideinfromleft{from{transform:translateX(-100%)}to{transform:translateX(0)}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(-100%,0,0)}}@-moz-keyframes slideouttoleft{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(-100%)}}@keyframes slideouttoleft{from{transform:translateX(0)}to{transform:translateX(-100%)}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(100%,0,0)}}@-moz-keyframes slideouttoright{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(100%)}}@keyframes slideouttoright{from{transform:translateX(0)}to{transform:translateX(100%)}}.slide.out,.slide.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms;animation-timing-function:ease-out;animation-duration:350ms}.slide.out{-webkit-transform:translate3d(-100%,0,0);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;transform:translateX(-100%);animation-name:slideouttoleft}.slide.in{-webkit-transform:translate3d(0,0,0);-webkit-animation-name:slideinfromright;-moz-transform:translateX(0);-moz-animation-name:slideinfromright;transform:translateX(0);animation-name:slideinfromright}.slide.out.reverse{-webkit-transform:translate3d(100%,0,0);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;transform:translateX(100%);animation-name:slideouttoright}.slide.in.reverse{-webkit-transform:translate3d(0,0,0);-webkit-animation-name:slideinfromleft;-moz-transform:translateX(0);-moz-animation-name:slideinfromleft;transform:translateX(0);animation-name:slideinfromleft}.slidefade.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-webkit-animation-duration:225ms;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;-moz-animation-duration:225ms;transform:translateX(-100%);animation-name:slideouttoleft;animation-duration:225ms}.slidefade.in{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-webkit-animation-duration:200ms;-moz-transform:translateX(0);-moz-animation-name:fadein;-moz-animation-duration:200ms;transform:translateX(0);animation-name:fadein;animation-duration:200ms}.slidefade.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-webkit-animation-duration:200ms;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;-moz-animation-duration:200ms;transform:translateX(100%);animation-name:slideouttoright;animation-duration:200ms}.slidefade.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-webkit-animation-duration:200ms;-moz-transform:translateX(0);-moz-animation-name:fadein;-moz-animation-duration:200ms;transform:translateX(0);animation-name:fadein;animation-duration:200ms}.slidedown.out{-webkit-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-name:fadeout;-moz-animation-duration:100ms;animation-name:fadeout;animation-duration:100ms}.slidedown.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfromtop;-webkit-animation-duration:250ms;-moz-transform:translateY(0);-moz-animation-name:slideinfromtop;-moz-animation-duration:250ms;transform:translateY(0);animation-name:slideinfromtop;animation-duration:250ms}.slidedown.in.reverse{-webkit-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-name:fadein;-moz-animation-duration:150ms;animation-name:fadein;animation-duration:150ms}.slidedown.out.reverse{-webkit-transform:translateY(-100%);-webkit-animation-name:slideouttotop;-webkit-animation-duration:200ms;-moz-transform:translateY(-100%);-moz-animation-name:slideouttotop;-moz-animation-duration:200ms;transform:translateY(-100%);animation-name:slideouttotop;animation-duration:200ms}@-webkit-keyframes slideinfromtop{from{-webkit-transform:translateY(-100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfromtop{from{-moz-transform:translateY(-100%)}to{-moz-transform:translateY(0)}}@keyframes slideinfromtop{from{transform:translateY(-100%)}to{transform:translateY(0)}}@-webkit-keyframes slideouttotop{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(-100%)}}@-moz-keyframes slideouttotop{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(-100%)}}@keyframes slideouttotop{from{transform:translateY(0)}to{transform:translateY(-100%)}}.slideup.out{-webkit-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-name:fadeout;-moz-animation-duration:100ms;animation-name:fadeout;animation-duration:100ms}.slideup.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfrombottom;-webkit-animation-duration:250ms;-moz-transform:translateY(0);-moz-animation-name:slideinfrombottom;-moz-animation-duration:250ms;transform:translateY(0);animation-name:slideinfrombottom;animation-duration:250ms}.slideup.in.reverse{-webkit-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-name:fadein;-moz-animation-duration:150ms;animation-name:fadein;animation-duration:150ms}.slideup.out.reverse{-webkit-transform:translateY(100%);-webkit-animation-name:slideouttobottom;-webkit-animation-duration:200ms;-moz-transform:translateY(100%);-moz-animation-name:slideouttobottom;-moz-animation-duration:200ms;transform:translateY(100%);animation-name:slideouttobottom;animation-duration:200ms}@-webkit-keyframes slideinfrombottom{from{-webkit-transform:translateY(100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfrombottom{from{-moz-transform:translateY(100%)}to{-moz-transform:translateY(0)}}@keyframes slideinfrombottom{from{transform:translateY(100%)}to{transform:translateY(0)}}@-webkit-keyframes slideouttobottom{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(100%)}}@-moz-keyframes slideouttobottom{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(100%)}}@keyframes slideouttobottom{from{transform:translateY(0)}to{transform:translateY(100%)}}.viewport-flip{-webkit-perspective:1000;-moz-perspective:1000;perspective:1000;position:absolute}.flip{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-moz-backface-visibility:hidden;-moz-transform:translateX(0);backface-visibility:hidden;transform:translateX(0)}.flip.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:175ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:175ms;transform:rotateY(-90deg) scale(.9);animation-name:flipouttoleft;animation-duration:175ms}.flip.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:225ms;-moz-animation-name:flipintoright;-moz-animation-duration:225ms;animation-name:flipintoright;animation-duration:225ms}.flip.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright;transform:rotateY(90deg) scale(.9);animation-name:flipouttoright}.flip.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft;animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@keyframes flipouttoleft{from{transform:rotateY(0)}to{transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@keyframes flipouttoright{from{transform:rotateY(0)}to{transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@keyframes flipintoleft{from{transform:rotateY(-90deg) scale(.9)}to{transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@keyframes flipintoright{from{transform:rotateY(90deg) scale(.9)}to{transform:rotateY(0)}}.viewport-turn{-webkit-perspective:200px;-moz-perspective:200px;-ms-perspective:200px;perspective:200px;position:absolute}.turn{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-webkit-transform-origin:0;-moz-backface-visibility:hidden;-moz-transform:translateX(0);-moz-transform-origin:0;backface-visibility:hidden;transform:translateX(0);transform-origin:0}.turn.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:125ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:125ms;transform:rotateY(-90deg) scale(.9);animation-name:flipouttoleft;animation-duration:125ms}.turn.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:250ms;-moz-animation-name:flipintoright;-moz-animation-duration:250ms;animation-name:flipintoright;animation-duration:250ms}.turn.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright;transform:rotateY(90deg) scale(.9);animation-name:flipouttoright}.turn.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft;animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@keyframes flipouttoleft{from{transform:rotateY(0)}to{transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@keyframes flipouttoright{from{transform:rotateY(0)}to{transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@keyframes flipintoleft{from{transform:rotateY(-90deg) scale(.9)}to{transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@keyframes flipintoright{from{transform:rotateY(90deg) scale(.9)}to{transform:rotateY(0)}}.flow{-webkit-transform-origin:50% 30%;-webkit-box-shadow:0 0 20px rgba(0,0,0,.4);-moz-transform-origin:50% 30%;-moz-box-shadow:0 0 20px rgba(0,0,0,.4);transform-origin:50% 30%;box-shadow:0 0 20px rgba(0,0,0,.4)}.ui-dialog.flow{-webkit-transform-origin:none;-webkit-box-shadow:none;-moz-transform-origin:none;-moz-box-shadow:none;transform-origin:none;box-shadow:none}.flow.out{-webkit-transform:translateX(-100%) scale(.7);-webkit-animation-name:flowouttoleft;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(-100%) scale(.7);-moz-animation-name:flowouttoleft;-moz-animation-timing-function:ease;-moz-animation-duration:350ms;transform:translateX(-100%) scale(.7);animation-name:flowouttoleft;animation-timing-function:ease;animation-duration:350ms}.flow.in{-webkit-transform:translateX(0) scale(1);-webkit-animation-name:flowinfromright;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(0) scale(1);-moz-animation-name:flowinfromright;-moz-animation-timing-function:ease;-moz-animation-duration:350ms;transform:translateX(0) scale(1);animation-name:flowinfromright;animation-timing-function:ease;animation-duration:350ms}.flow.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:flowouttoright;-moz-transform:translateX(100%);-moz-animation-name:flowouttoright;transform:translateX(100%);animation-name:flowouttoright}.flow.in.reverse{-webkit-animation-name:flowinfromleft;-moz-animation-name:flowinfromleft;animation-name:flowinfromleft}@-webkit-keyframes flowouttoleft{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(-100%) scale(.7)}}@-moz-keyframes flowouttoleft{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(-100%) scale(.7)}}@keyframes flowouttoleft{0%{transform:translateX(0) scale(1)}60%,70%{transform:translateX(0) scale(.7)}100%{transform:translateX(-100%) scale(.7)}}@-webkit-keyframes flowouttoright{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(100%) scale(.7)}}@-moz-keyframes flowouttoright{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(100%) scale(.7)}}@keyframes flowouttoright{0%{transform:translateX(0) scale(1)}60%,70%{transform:translateX(0) scale(.7)}100%{transform:translateX(100%) scale(.7)}}@-webkit-keyframes flowinfromleft{0%{-webkit-transform:translateX(-100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromleft{0%{-moz-transform:translateX(-100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}@keyframes flowinfromleft{0%{transform:translateX(-100%) scale(.7)}30%,40%{transform:translateX(0) scale(.7)}100%{transform:translateX(0) scale(1)}}@-webkit-keyframes flowinfromright{0%{-webkit-transform:translateX(100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromright{0%{-moz-transform:translateX(100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}@keyframes flowinfromright{0%{transform:translateX(100%) scale(.7)}30%,40%{transform:translateX(0) scale(.7)}100%{transform:translateX(0) scale(1)}}.ui-field-contain,.ui-mobile fieldset.ui-field-contain{display:block;position:relative;overflow:visible;clear:both;padding:.8em 0}.ui-field-contain>label~[class*=ui-],.ui-field-contain .ui-controlgroup-controls{margin:0}.ui-field-contain:last-child{border-bottom-width:0}@media (min-width:28em){.ui-field-contain,.ui-mobile fieldset.ui-field-contain{padding:0;margin:1em 0;border-bottom-width:0}.ui-field-contain:before,.ui-field-contain:after{content:"";display:table}.ui-field-contain:after{clear:both}.ui-field-contain>label,.ui-field-contain .ui-controlgroup-label,.ui-field-contain>.ui-rangeslider>label{float:left;width:20%;margin:.5em 2% 0 0}.ui-popup .ui-field-contain>label,.ui-popup .ui-field-contain .ui-controlgroup-label,.ui-popup .ui-field-contain>.ui-rangeslider>label{float:none;width:auto;margin:0 0 .4em}.ui-field-contain>label~[class*=ui-],.ui-field-contain .ui-controlgroup-controls{float:left;width:78%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.ui-hide-label>label~[class*=ui-],.ui-hide-label .ui-controlgroup-controls,.ui-popup .ui-field-contain>label~[class*=ui-],.ui-popup .ui-field-contain .ui-controlgroup-controls{float:none;width:100%}.ui-field-contain>label~.ui-btn-inline{width:auto;margin-right:.625em}}.ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d,.ui-grid-solo{overflow:hidden}.ui-block-a,.ui-block-b,.ui-block-c,.ui-block-d,.ui-block-e{margin:0;padding:0;border:0;float:left;min-height:1px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.ui-block-a{clear:left}ul.ui-grid-a,ul.ui-grid-b,ul.ui-grid-c,ul.ui-grid-d,ul.ui-grid-solo,li.ui-block-a,li.ui-block-b,li.ui-block-c,li.ui-block-d,li.ui-block-e{margin-left:0;margin-right:0;padding:0;list-style:none}[class*=ui-block-]>button.ui-btn{margin-right:0;margin-left:0}[class*=ui-block-]>.ui-btn,[class*=ui-block-]>.ui-select,[class*=ui-block-]>.ui-checkbox,[class*=ui-block-]>.ui-radio,[class*=ui-block-]>button.ui-btn-inline,[class*=ui-block-]>button.ui-btn-icon-notext{margin-right:.3125em;margin-left:.3125em}.ui-grid-a>.ui-block-a,.ui-grid-a>.ui-block-b{width:50%}.ui-grid-b>.ui-block-a,.ui-grid-b>.ui-block-b,.ui-grid-b>.ui-block-c{width:33.333%}.ui-grid-c>.ui-block-a,.ui-grid-c>.ui-block-b,.ui-grid-c>.ui-block-c,.ui-grid-c>.ui-block-d{width:25%}.ui-grid-d>.ui-block-a,.ui-grid-d>.ui-block-b,.ui-grid-d>.ui-block-c,.ui-grid-d>.ui-block-d,.ui-grid-d>.ui-block-e{width:20%}.ui-grid-solo>.ui-block-a{width:100%;float:none}@media (max-width:35em){.ui-responsive>.ui-block-a,.ui-responsive>.ui-block-b,.ui-responsive>.ui-block-c,.ui-responsive>.ui-block-d,.ui-responsive>.ui-block-e{width:100%;float:none}}.ui-header-fixed,.ui-footer-fixed{left:0;right:0;width:100%;position:fixed;z-index:1000}.ui-header-fixed{top:-1px;padding-top:1px}.ui-header-fixed.ui-fixed-hidden{top:0;padding-top:0}.ui-header-fixed .ui-btn-left,.ui-header-fixed .ui-btn-right{margin-top:1px}.ui-header-fixed.ui-fixed-hidden .ui-btn-left,.ui-header-fixed.ui-fixed-hidden .ui-btn-right{margin-top:0}.ui-footer-fixed{bottom:-1px;padding-bottom:1px}.ui-footer-fixed.ui-fixed-hidden{bottom:0;padding-bottom:0}.ui-header-fullscreen,.ui-footer-fullscreen{filter:Alpha(Opacity=90);opacity:.9}.ui-page-header-fixed{padding-top:2.8125em}.ui-page-footer-fixed{padding-bottom:2.8125em}.ui-page-header-fullscreen>.ui-content,.ui-page-footer-fullscreen>.ui-content{padding:0}.ui-fixed-hidden{position:absolute}.ui-footer-fixed.ui-fixed-hidden{display:none}.ui-page .ui-footer-fixed.ui-fixed-hidden{display:block}.ui-page-header-fullscreen .ui-fixed-hidden,.ui-page-footer-fullscreen .ui-fixed-hidden{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-header-fixed .ui-btn,.ui-footer-fixed .ui-btn{z-index:10}.ui-android-2x-fixed .ui-li-has-thumb{-webkit-transform:translate3d(0,0,0)}.ui-navbar{max-width:100%}.ui-navbar ul:before,.ui-navbar ul:after{content:"";display:table}.ui-navbar ul:after{clear:both}.ui-navbar ul{list-style:none;margin:0;padding:0;position:relative;display:block;border:0;max-width:100%;overflow:visible}.ui-navbar li .ui-btn{font-size:12.5px;display:block;margin:0;border-right-width:0}.ui-navbar .ui-btn:focus{z-index:1}.ui-navbar li:last-child .ui-btn{margin-right:-4px}.ui-navbar li:last-child .ui-btn:after{margin-right:4px}.ui-content .ui-navbar li:last-child .ui-btn,.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn{border-right-width:1px;margin-right:0}.ui-content .ui-navbar li:last-child .ui-btn:after,.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn:after{margin-right:0}.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn{border-right-width:1px;margin-right:-1px}.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn:after{margin-right:1px}.ui-navbar .ui-grid-duo .ui-btn{border-top-width:0}.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,.ui-navbar .ui-grid-duo .ui-block-a:first-child+.ui-block-b .ui-btn{border-top-width:1px}.ui-header .ui-navbar .ui-btn,.ui-footer .ui-navbar .ui-btn{border-top-width:0;border-bottom-width:0}.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child+.ui-block-b .ui-btn,.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child+.ui-block-b .ui-btn{border-top-width:0}.ui-header .ui-title~.ui-navbar .ui-btn,.ui-footer .ui-title~.ui-navbar .ui-btn,.ui-header .ui-navbar .ui-grid-duo .ui-btn,.ui-footer .ui-navbar .ui-grid-duo .ui-btn,.ui-header .ui-title~.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,.ui-footer .ui-title~.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,.ui-header .ui-title~.ui-navbar .ui-grid-duo .ui-block-a:first-child+.ui-block-b .ui-btn,.ui-footer .ui-title~.ui-navbar .ui-grid-duo .ui-block-a:first-child+.ui-block-b .ui-btn{border-top-width:1px}.ui-input-btn input{position:absolute;top:0;left:0;width:100%;height:100%;padding:0;border:0;outline:0;-webkit-border-radius:inherit;border-radius:inherit;-webkit-appearance:none;-moz-appearance:none;cursor:pointer;background:#fff;background:rgba(255,255,255,0);filter:Alpha(Opacity=0);opacity:.1;font-size:1px;text-indent:-9999px;z-index:2}.ui-input-btn.ui-state-disabled input{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-collapsible{margin:0 -1em}.ui-collapsible-inset,.ui-collapsible-set{margin:.5em 0}.ui-collapsible-heading{display:block;margin:0;padding:0;position:relative}.ui-collapsible-heading .ui-btn{text-align:left;margin:0;border-left-width:0;border-right-width:0}.ui-collapsible-heading .ui-btn-icon-top,.ui-collapsible-heading .ui-btn-icon-bottom{text-align:center}.ui-collapsible-inset .ui-collapsible-heading .ui-btn{border-right-width:1px;border-left-width:1px}.ui-collapsible-collapsed+.ui-collapsible:not(.ui-collapsible-inset)>.ui-collapsible-heading .ui-btn{border-top-width:0}.ui-collapsible-set .ui-collapsible:not(.ui-collapsible-inset) .ui-collapsible-heading .ui-btn{border-top-width:1px}.ui-collapsible-heading-status{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-collapsible-content{display:block;margin:0;padding:.5em 1em}.ui-collapsible-themed-content .ui-collapsible-content{border-left-width:0;border-right-width:0;border-top-width:0;border-bottom-width:1px;border-style:solid}.ui-collapsible-inset.ui-collapsible-themed-content .ui-collapsible-content{border-left-width:1px;border-right-width:1px}.ui-collapsible-inset .ui-collapsible-content{margin:0}.ui-collapsible-content-collapsed{display:none}.ui-collapsible-set>.ui-collapsible.ui-corner-all{-webkit-border-radius:0;border-radius:0}.ui-collapsible-heading,.ui-collapsible-heading>.ui-btn{-webkit-border-radius:inherit;border-radius:inherit}.ui-collapsible-set .ui-collapsible.ui-first-child{-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit;-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit}.ui-collapsible-content,.ui-collapsible-set .ui-collapsible.ui-last-child{-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit;-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit}.ui-collapsible-themed-content:not(.ui-collapsible-collapsed)>.ui-collapsible-heading{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0}.ui-collapsible-set .ui-collapsible{margin:-1px -1em 0}.ui-collapsible-set .ui-collapsible-inset{margin:-1px 0 0}.ui-collapsible-set .ui-collapsible.ui-first-child{margin-top:0}.ui-controlgroup,fieldset.ui-controlgroup{padding:0;margin:.5em 0}.ui-field-contain .ui-controlgroup,.ui-field-contain fieldset.ui-controlgroup{margin:0}.ui-mini .ui-controlgroup-label{font-size:16px}.ui-controlgroup.ui-mini .ui-btn-icon-notext,.ui-controlgroup .ui-mini.ui-btn-icon-notext{font-size:inherit}.ui-controlgroup-controls .ui-btn,.ui-controlgroup-controls .ui-checkbox,.ui-controlgroup-controls .ui-radio,.ui-controlgroup-controls .ui-select{margin:0}.ui-controlgroup-controls .ui-btn:focus,.ui-controlgroup-controls .ui-btn.ui-focus{z-index:1}.ui-controlgroup-controls li{list-style:none}.ui-controlgroup-horizontal .ui-controlgroup-controls{display:inline-block;vertical-align:middle}.ui-controlgroup-horizontal .ui-controlgroup-controls:before,.ui-controlgroup-horizontal .ui-controlgroup-controls:after{content:"";display:table}.ui-controlgroup-horizontal .ui-controlgroup-controls:after{clear:both}.ui-controlgroup-horizontal .ui-controlgroup-controls>.ui-btn,.ui-controlgroup-horizontal .ui-controlgroup-controls li>.ui-btn,.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-checkbox,.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-radio,.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-select{float:left;clear:none}.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn,.ui-controlgroup-controls .ui-btn-icon-notext{width:auto}.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn-icon-notext,.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn-icon-notext{width:1.5em}.ui-controlgroup-controls .ui-btn-icon-notext{height:auto;padding:.7em 1em}.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn{border-bottom-width:0}.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn.ui-last-child{border-bottom-width:1px}.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn{border-right-width:0}.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn.ui-last-child{border-right-width:1px}.ui-controlgroup-controls .ui-btn-corner-all,.ui-controlgroup-controls .ui-btn.ui-corner-all{-webkit-border-radius:0;border-radius:0}.ui-controlgroup-controls,.ui-controlgroup-controls .ui-radio,.ui-controlgroup-controls .ui-checkbox,.ui-controlgroup-controls .ui-select,.ui-controlgroup-controls li{-webkit-border-radius:inherit;border-radius:inherit}.ui-controlgroup-vertical .ui-btn.ui-first-child{-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit;-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit}.ui-controlgroup-vertical .ui-btn.ui-last-child{-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit;-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit}.ui-controlgroup-horizontal .ui-btn.ui-first-child{-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit;-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit}.ui-controlgroup-horizontal .ui-btn.ui-last-child{-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit;-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit}.ui-controlgroup-controls a.ui-shadow:not(:focus),.ui-controlgroup-controls button.ui-shadow:not(:focus),.ui-controlgroup-controls div.ui-shadow:not(.ui-focus){-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.ui-controlgroup-label legend{max-width:100%}.ui-controlgroup-controls>label{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-dialog{background:none!important}.ui-dialog-contain{width:92.5%;max-width:500px;margin:10% auto 1em;padding:0;position:relative;top:-1em}.ui-dialog-contain>.ui-header,.ui-dialog-contain>.ui-content,.ui-dialog-contain>.ui-footer{display:block;position:relative;width:auto;margin:0}.ui-dialog-contain>.ui-header{overflow:hidden;z-index:10;padding:0;border-top-width:0}.ui-dialog-contain>.ui-footer{z-index:10;padding:0 1em;border-bottom-width:0}.ui-popup-open .ui-header-fixed,.ui-popup-open .ui-footer-fixed{position:absolute!important}.ui-popup-screen{background-image:url("data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==");top:0;left:0;right:0;bottom:1px;position:absolute;filter:Alpha(Opacity=0);opacity:0;z-index:1099}.ui-popup-screen.in{opacity:.5;filter:Alpha(Opacity=50)}.ui-popup-screen.out{opacity:0;filter:Alpha(Opacity=0)}.ui-popup-container{z-index:1100;display:inline-block;position:absolute;padding:0;outline:0}.ui-popup{position:relative}.ui-popup.ui-body-inherit{border-width:1px;border-style:solid}.ui-popup-hidden{left:0;top:0;position:absolute!important;visibility:hidden}.ui-popup-truncate{height:1px;width:1px;margin:-1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-popup.ui-content,.ui-popup .ui-content{overflow:visible}.ui-popup>.ui-header{border-top-width:0}.ui-popup>.ui-footer{border-bottom-width:0}.ui-popup>p,.ui-popup>h1,.ui-popup>h2,.ui-popup>h3,.ui-popup>h4,.ui-popup>h5,.ui-popup>h6{margin:.5em .4375em}.ui-popup>span{display:block;margin:.5em .4375em}.ui-popup-container .ui-content>p,.ui-popup-container .ui-content>h1,.ui-popup-container .ui-content>h2,.ui-popup-container .ui-content>h3,.ui-popup-container .ui-content>h4,.ui-popup-container .ui-content>h5,.ui-popup-container .ui-content>h6{margin:.5em 0}.ui-popup-container .ui-content>span{margin:0}.ui-popup-container .ui-content>p:first-child,.ui-popup-container .ui-content>h1:first-child,.ui-popup-container .ui-content>h2:first-child,.ui-popup-container .ui-content>h3:first-child,.ui-popup-container .ui-content>h4:first-child,.ui-popup-container .ui-content>h5:first-child,.ui-popup-container .ui-content>h6:first-child{margin-top:0}.ui-popup-container .ui-content>p:last-child,.ui-popup-container .ui-content>h1:last-child,.ui-popup-container .ui-content>h2:last-child,.ui-popup-container .ui-content>h3:last-child,.ui-popup-container .ui-content>h4:last-child,.ui-popup-container .ui-content>h5:last-child,.ui-popup-container .ui-content>h6:last-child{margin-bottom:0}.ui-popup>img{max-width:100%;max-height:100%;vertical-align:middle}.ui-popup:not(.ui-content)>img:only-child,.ui-popup:not(.ui-content)>.ui-btn-left:first-child+img:last-child,.ui-popup:not(.ui-content)>.ui-btn-right:first-child+img:last-child{-webkit-border-radius:inherit;border-radius:inherit}.ui-popup iframe{vertical-align:middle}.ui-popup>.ui-btn-left,.ui-popup>.ui-btn-right{position:absolute;top:-11px;margin:0;z-index:1101}.ui-popup>.ui-btn-left{left:-11px}.ui-popup>.ui-btn-right{right:-11px}.ui-popup-arrow-container{width:20px;height:20px}.ui-popup-arrow-container.ui-popup-arrow-l{left:-10px;clip:rect(-1000px,10px,2000px,-1000px)}.ui-popup-arrow-container.ui-popup-arrow-t{top:-10px;clip:rect(-1000px,2000px,10px,-1000px)}.ui-popup-arrow-container.ui-popup-arrow-r{right:-10px;clip:rect(-1000px,2000px,2000px,10px)}.ui-popup-arrow-container.ui-popup-arrow-b{bottom:-10px;clip:rect(10px,2000px,1000px,-1000px)}.ui-popup-arrow-container .ui-popup-arrow{width:28.284271247px;height:28.284271247px;border-width:1px;border-style:solid}.ui-popup-arrow-container.ui-popup-arrow-t .ui-popup-arrow{left:-4.142135623px;top:5.857864376px}.ui-popup-arrow-container.ui-popup-arrow-b .ui-popup-arrow{left:-4.142135623px;top:-14.142135623px}.ui-popup-arrow-container.ui-popup-arrow-l .ui-popup-arrow{left:5.857864376px;top:-4.142135623px}.ui-popup-arrow-container.ui-popup-arrow-r .ui-popup-arrow{left:-14.142135623px;top:-4.142135623px}.ui-popup-arrow-container.ui-popup-arrow-t.ie .ui-popup-arrow{margin-left:-5.857864376269049px;margin-top:-7.0710678118654755px}.ui-popup-arrow-container.ui-popup-arrow-b.ie .ui-popup-arrow{margin-left:-5.857864376269049px;margin-top:-4.142135623730951px}.ui-popup-arrow-container.ui-popup-arrow-l.ie .ui-popup-arrow{margin-left:-7.0710678118654755px;margin-top:-5.857864376269049px}.ui-popup-arrow-container.ui-popup-arrow-r.ie .ui-popup-arrow{margin-left:-4.142135623730951px;margin-top:-5.857864376269049px}.ui-popup>.ui-popup-arrow-guide{position:absolute;left:0;right:0;top:0;bottom:0;visibility:hidden}.ui-popup-arrow-container{position:absolute}.ui-popup-arrow{-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);position:absolute;overflow:hidden;box-sizing:border-box}.ui-popup-arrow-container.ie .ui-popup-arrow{-ms-filter:"progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067811865474, M12=-0.7071067811865477, M21=0.7071067811865477, M22=0.7071067811865474, SizingMethod='auto expand')";filter:progid:DXImageTransform.Microsoft.Matrix(M11=.7071067811865474, M12=-.7071067811865477, M21=.7071067811865477, M22=.7071067811865474, SizingMethod='auto expand')}.ui-checkbox,.ui-radio{margin:.5em 0;position:relative}.ui-checkbox .ui-btn,.ui-radio .ui-btn{margin:0;text-align:left;white-space:normal;z-index:2}.ui-controlgroup .ui-checkbox .ui-btn.ui-focus,.ui-controlgroup .ui-radio .ui-btn.ui-focus{z-index:3}.ui-checkbox .ui-btn-icon-top,.ui-radio .ui-btn-icon-top,.ui-checkbox .ui-btn-icon-bottom,.ui-radio .ui-btn-icon-bottom{text-align:center}.ui-controlgroup-horizontal .ui-checkbox .ui-btn:after,.ui-controlgroup-horizontal .ui-radio .ui-btn:after{content:none;display:none}.ui-checkbox input,.ui-radio input{position:absolute;left:.466em;top:50%;width:22px;height:22px;margin:-11px 0 0 0;outline:0!important;z-index:1}.ui-controlgroup-horizontal .ui-checkbox input,.ui-controlgroup-horizontal .ui-radio input{left:50%;margin-left:-9px}.ui-checkbox input:disabled,.ui-radio input:disabled{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-select{margin-top:.5em;margin-bottom:.5em;position:relative}.ui-select>select{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-select .ui-btn{margin:0;opacity:1}.ui-select .ui-btn select{position:absolute;top:0;left:0;width:100%;min-height:1.5em;min-height:100%;height:3em;max-height:100%;outline:0;-webkit-border-radius:inherit;border-radius:inherit;-webkit-appearance:none;-moz-appearance:none;cursor:pointer;filter:Alpha(Opacity=0);opacity:0;z-index:2}@-moz-document url-prefix(){.ui-select .ui-btn select{opacity:.0001}}.ui-select .ui-state-disabled select{display:none}.ui-select span.ui-state-disabled{filter:Alpha(Opacity=100);opacity:1}.ui-select .ui-btn.ui-select-nativeonly{border-radius:0;border:0}.ui-select .ui-btn.ui-select-nativeonly select{opacity:1;text-indent:0;display:block}.ui-select .ui-li-has-count.ui-btn{padding-right:2.8125em}.ui-select .ui-li-has-count.ui-btn-icon-right{padding-right:4.6875em}.ui-select .ui-btn-icon-right .ui-li-count{right:3.2em}.ui-select .ui-btn>span:not(.ui-li-count){display:block;text-overflow:ellipsis;overflow:hidden!important;white-space:nowrap}.ui-selectmenu.ui-popup{min-width:11em}.ui-selectmenu .ui-dialog-contain{overflow:hidden}.ui-selectmenu .ui-header{margin:0;padding:0;border-width:0}.ui-selectmenu.ui-dialog .ui-header{z-index:1;position:relative}.ui-selectmenu.ui-popup .ui-header{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0}.ui-selectmenu.ui-popup .ui-header h1:after{content:'.';visibility:hidden}.ui-selectmenu .ui-header .ui-title{margin:0 2.875em}.ui-selectmenu.ui-dialog .ui-content{overflow:visible;z-index:1}.ui-selectmenu .ui-selectmenu-list{margin:0;-webkit-border-radius:inherit;border-radius:inherit}.ui-header:not(.ui-screen-hidden)+.ui-selectmenu-list{-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-top-left-radius:0;border-top-left-radius:0}.ui-header.ui-screen-hidden+.ui-selectmenu-list li.ui-first-child .ui-btn{border-top-width:0}.ui-selectmenu .ui-selectmenu-list li.ui-last-child .ui-btn{border-bottom-width:0}.ui-selectmenu .ui-btn.ui-li-divider{cursor:default}.ui-selectmenu .ui-selectmenu-placeholder{display:none}.ui-listview,.ui-listview>li{margin:0;padding:0;list-style:none}.ui-content .ui-listview,.ui-panel-inner>.ui-listview{margin:-1em}.ui-content .ui-listview-inset,.ui-panel-inner>.ui-listview-inset{margin:1em 0}.ui-collapsible-content>.ui-listview{margin:-.5em -1em}.ui-collapsible-content>.ui-listview-inset{margin:.5em 0}.ui-listview>li{display:block;position:relative;overflow:visible}.ui-listview>.ui-li-static,.ui-listview>.ui-li-divider,.ui-listview>li>a.ui-btn{margin:0;display:block;position:relative;text-align:left;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-listview>li>.ui-btn:focus{z-index:1}.ui-listview>.ui-li-static,.ui-listview>.ui-li-divider,.ui-listview>li>a.ui-btn{border-width:1px 0 0;border-style:solid}.ui-listview-inset>.ui-li-static,.ui-listview-inset>.ui-li-divider,.ui-listview-inset>li>a.ui-btn{border-right-width:1px;border-left-width:1px}.ui-listview>.ui-li-static.ui-last-child,.ui-listview>.ui-li-divider.ui-last-child,.ui-listview>li.ui-last-child>a.ui-btn{border-bottom-width:1px}.ui-collapsible-content>.ui-listview:not(.ui-listview-inset)>li.ui-first-child,.ui-collapsible-content>.ui-listview:not(.ui-listview-inset)>li.ui-first-child>a.ui-btn{border-top-width:0}.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset)>li.ui-last-child,.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset)>li.ui-last-child>a.ui-btn{border-bottom-width:0}.ui-listview>li.ui-first-child,.ui-listview>li.ui-first-child>a.ui-btn{-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit;-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit}.ui-listview>li.ui-last-child,.ui-listview>li.ui-last-child>a.ui-btn{-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit;-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit}.ui-listview>li.ui-li-has-alt>a.ui-btn{-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.ui-listview>li.ui-first-child>a.ui-btn+a.ui-btn{-webkit-border-top-left-radius:0;border-top-left-radius:0;-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit}.ui-listview>li.ui-last-child>a.ui-btn+a.ui-btn{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit}.ui-listview>li.ui-first-child img:first-child:not(.ui-li-icon){-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit}.ui-listview>li.ui-last-child img:first-child:not(.ui-li-icon){-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit}.ui-collapsible-content>.ui-listview:not(.ui-listview-inset){-webkit-border-radius:inherit;border-radius:inherit}.ui-listview>.ui-li-static{padding:.7em 1em}.ui-listview>.ui-li-divider{padding:.5em 1.143em;font-size:14px;font-weight:700;cursor:default;outline:0}.ui-listview>.ui-li-has-count>.ui-btn,.ui-listview>.ui-li-static.ui-li-has-count,.ui-listview>.ui-li-divider.ui-li-has-count{padding-right:2.8125em}.ui-listview>.ui-li-has-count>.ui-btn-icon-right{padding-right:4.6875em}.ui-listview>.ui-li-has-thumb>.ui-btn,.ui-listview>.ui-li-static.ui-li-has-thumb{min-height:3.625em;padding-left:6.25em}.ui-listview>.ui-li-has-icon>.ui-btn,.ui-listview>.ui-li-static.ui-li-has-icon{min-height:1.25em;padding-left:2.5em}.ui-li-count{position:absolute;font-size:12.5px;font-weight:700;text-align:center;border-width:1px;border-style:solid;padding:0 .48em;line-height:1.6em;min-height:1.6em;min-width:.64em;right:.8em;top:50%;margin-top:-.88em}.ui-listview .ui-btn-icon-right .ui-li-count{right:3.2em}.ui-listview .ui-li-has-thumb>img:first-child,.ui-listview .ui-li-has-thumb>.ui-btn>img:first-child,.ui-listview .ui-li-has-thumb .ui-li-thumb{position:absolute;left:0;top:0;max-height:5em;max-width:5em}.ui-listview>.ui-li-has-icon>img:first-child,.ui-listview>.ui-li-has-icon>.ui-btn>img:first-child{position:absolute;left:.625em;top:.9em;max-height:1em;max-width:1em}.ui-listview>li h1,.ui-listview>li h2,.ui-listview>li h3,.ui-listview>li h4,.ui-listview>li h5,.ui-listview>li h6{font-size:1em;font-weight:700;display:block;margin:.45em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-listview>li p{font-size:.75em;font-weight:400;display:block;margin:.6em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-listview .ui-li-aside{position:absolute;top:1em;right:3.333em;margin:0;text-align:right}.ui-listview>li.ui-li-has-alt>.ui-btn{margin-right:2.5em;border-right-width:0}.ui-listview>li.ui-li-has-alt>.ui-btn+.ui-btn{position:absolute;width:2.5em;height:100%;min-height:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-left-width:1px;top:0;right:0;margin:0;padding:0;z-index:2}.ui-listview-inset>li.ui-li-has-alt>.ui-btn+.ui-btn{border-right-width:1px}.ui-listview>li.ui-li-has-alt>.ui-btn+.ui-btn:focus{z-index:3}ol.ui-listview,ol.ui-listview>.ui-li-divider{counter-reset:listnumbering}ol.ui-listview>li>.ui-btn,ol.ui-listview>li.ui-li-static{vertical-align:middle}ol.ui-listview>li>.ui-btn:first-child:before,ol.ui-listview>li.ui-li-static:before,ol.ui-listview>li.ui-field-contain>label:before,ol.ui-listview>li.ui-field-contain>.ui-controlgroup-label:before{display:inline-block;font-size:.9em;font-weight:400;padding-right:.3em;min-width:1.4em;line-height:1.5;vertical-align:middle;counter-increment:listnumbering;content:counter(listnumbering) "."}ol.ui-listview>li.ui-field-contain:before{content:none;display:none}ol.ui-listview>li h1:first-child,ol.ui-listview>li h2:first-child,ol.ui-listview>li h3:first-child,ol.ui-listview>li h4:first-child,ol.ui-listview>li h5:first-child,ol.ui-listview>li h6:first-child,ol.ui-listview>li p:first-child,ol.ui-listview>li img:first-child+*{display:inline-block;vertical-align:middle}ol.ui-listview>li h1:first-child~*,ol.ui-listview>li h2:first-child~*,ol.ui-listview>li h3:first-child~*,ol.ui-listview>li h4:first-child~*,ol.ui-listview>li h5:first-child~*,ol.ui-listview>li h6:first-child~*,ol.ui-listview>li p:first-child~*,ol.ui-listview>li img:first-child+*~*{margin-top:0;text-indent:2.04em}html .ui-filterable+.ui-listview,html .ui-filterable.ui-listview{margin-top:.5em}.ui-collapsible-content>form.ui-filterable{margin-top:-.5em}.ui-collapsible-content>.ui-input-search.ui-filterable{margin-top:0}.ui-collapsible-content>.ui-filterable+.ui-listview:not(.ui-listview-inset)>li.ui-first-child,.ui-collapsible-content>.ui-filterable+.ui-listview:not(.ui-listview-inset)>li.ui-first-child>a.ui-btn,.ui-collapsible-content>.ui-filterable.ui-listview:not(.ui-listview-inset)>li.ui-first-child,.ui-collapsible-content>.ui-filterable.ui-listview:not(.ui-listview-inset)>li.ui-first-child>a.ui-btn{border-top-width:1px}div.ui-slider{height:30px;margin:.5em 0;padding:0;-ms-touch-action:pan-y pinch-zoom double-tap-zoom}div.ui-slider:before,div.ui-slider:after{content:"";display:table}div.ui-slider:after{clear:both}input.ui-slider-input{display:block;float:left;font-size:14px;font-weight:700;margin:0;padding:4px;width:40px;height:20px;line-height:20px;border-width:1px;border-style:solid;outline:0;text-align:center;vertical-align:text-bottom;-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;-ms-box-sizing:content-box;box-sizing:content-box}.ui-slider-input::-webkit-outer-spin-button,.ui-slider-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.ui-slider-track{position:relative;overflow:visible;border-width:1px;border-style:solid;height:15px;margin:0 15px 0 68px;top:6px}.ui-slider-track.ui-mini{height:12px;top:8px}.ui-slider-track .ui-slider-bg{height:100%}.ui-slider-track .ui-btn.ui-slider-handle{position:absolute;z-index:1;top:50%;width:28px;height:28px;margin:-15px 0 0 -15px;outline:0;padding:0}.ui-slider-track.ui-mini .ui-slider-handle{height:14px;width:14px;margin:-8px 0 0 -8px}select.ui-slider-switch{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}div.ui-slider-switch{display:inline-block;height:32px;width:5.8em;top:0}div.ui-slider-switch:before,div.ui-slider-switch:after{display:none;clear:none}div.ui-slider-switch.ui-mini{height:29px;top:0}.ui-slider-inneroffset{margin:0 16px;position:relative;z-index:1}.ui-slider-switch.ui-mini .ui-slider-inneroffset{margin:0 15px 0 14px}.ui-slider-switch .ui-btn.ui-slider-handle{margin:1px 0 0 -15px}.ui-slider-switch.ui-mini .ui-slider-handle{width:25px;height:25px;margin:1px 0 0 -13px;padding:0}.ui-slider-handle-snapping{-webkit-transition:left 70ms linear;-moz-transition:left 70ms linear;transition:left 70ms linear}.ui-slider-switch .ui-slider-label{position:absolute;text-align:center;width:100%;overflow:hidden;font-size:16px;top:0;line-height:2;min-height:100%;white-space:nowrap;cursor:pointer}.ui-slider-switch.ui-mini .ui-slider-label{font-size:14px}.ui-slider-switch .ui-slider-label-a{z-index:1;left:0;text-indent:-1.5em}.ui-slider-switch .ui-slider-label-b{z-index:0;right:0;text-indent:1.5em}.ui-slider-track .ui-slider-bg,.ui-slider-switch .ui-slider-label,.ui-slider-switch .ui-slider-inneroffset,.ui-slider-handle{-webkit-border-radius:inherit;border-radius:inherit}.ui-field-contain div.ui-slider-switch{margin:0}.ui-field-contain div.ui-slider-switch,.ui-field-contain.ui-hide-label div.ui-slider-switch,html .ui-popup .ui-field-contain div.ui-slider-switch{display:inline-block;width:5.8em}.ui-slider-popup{width:64px;height:64px;font-size:36px;padding-top:14px;opacity:.8}.ui-slider-popup{position:absolute!important;text-align:center;z-index:100}.ui-slider-track .ui-btn.ui-slider-handle{font-size:.9em;line-height:30px}.ui-rangeslider{margin:.5em 0}.ui-rangeslider:before,.ui-rangeslider:after{content:"";display:table}.ui-rangeslider:after{clear:both}.ui-rangeslider .ui-slider-input.ui-rangeslider-last{float:right}.ui-rangeslider .ui-rangeslider-sliders{position:relative;overflow:visible;height:30px;margin:0 68px}.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track{position:absolute;top:6px;right:0;left:0;margin:0}.ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track{top:8px}.ui-rangeslider .ui-slider-track:first-child .ui-slider-bg{display:none}.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child{background-color:transparent;background:0;border-width:0;height:0}html >body .ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child{height:15px;border-width:1px}html >body .ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track:first-child{height:12px}div.ui-rangeslider label{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-field-contain .ui-rangeslider input.ui-slider-input,.ui-field-contain .ui-rangeslider.ui-mini input.ui-slider-input,.ui-field-contain .ui-rangeslider .ui-rangeslider-sliders,.ui-field-contain .ui-rangeslider.ui-mini .ui-rangeslider-sliders{margin-top:0;margin-bottom:0}.ui-input-text,.ui-input-search{margin:.5em 0;border-width:1px;border-style:solid}.ui-input-text input,.ui-input-search input,textarea.ui-input-text{padding:.4em;line-height:1.4em;display:block;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;outline:0}.ui-input-text input,.ui-input-search input{margin:0;min-height:2.2em;text-align:left;border:0;background:transparent none;-webkit-appearance:none;-webkit-border-radius:inherit;border-radius:inherit}textarea.ui-input-text{overflow:auto;resize:vertical}.ui-mini .ui-input-text input,.ui-mini .ui-input-search input,.ui-input-text.ui-mini input,.ui-input-search.ui-mini input,.ui-mini textarea.ui-input-text,textarea.ui-mini{font-size:14px}.ui-mini textarea.ui-input-text,textarea.ui-mini{margin:.446em 0}.ui-input-has-clear,.ui-input-search{position:relative}.ui-input-has-clear{padding-right:2.375em}.ui-mini.ui-input-has-clear{padding-right:2.923em}.ui-input-has-clear input{padding-right:0;-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.ui-input-search input{padding-left:1.75em}.ui-input-search:after{position:absolute;left:.3125em;top:50%;margin-top:-7px;content:"";background-position:center center;background-repeat:no-repeat;width:14px;height:14px;filter:Alpha(Opacity=50);opacity:.5}.ui-input-search.ui-input-has-clear .ui-btn.ui-input-clear,.ui-input-text.ui-input-has-clear .ui-btn.ui-input-clear{position:absolute;right:0;top:50%;margin:-14px .3125em 0;border:0;background-color:transparent}.ui-input-search .ui-input-clear-hidden,.ui-input-text .ui-input-clear-hidden{display:none}.ui-input-text input::-moz-placeholder,.ui-input-search input::-moz-placeholder,textarea.ui-input-text::-moz-placeholder{color:#aaa}.ui-input-text input:-ms-input-placeholder,.ui-input-search input:-ms-input-placeholder,textarea.ui-input-text:-ms-input-placeholder{color:#aaa}.ui-input-text input[type=number]::-webkit-outer-spin-button{margin:0}.ui-input-text input::-ms-clear,.ui-input-search input::-ms-clear{display:none}.ui-input-text input:focus,.ui-input-search input:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}textarea.ui-input-text.ui-textinput-autogrow{overflow:hidden}.ui-textinput-autogrow-resize{-webkit-transition:height .25s;-o-transition:height .25s;-moz-transition:height .25s;transition:height .25s}.ui-flipswitch{display:inline-block;vertical-align:middle;width:5.875em;height:1.875em;border-width:1px;border-style:solid;margin:.5em 0;overflow:hidden;-webkit-transition-property:padding,width,background-color,color,border-color;-moz-transition-property:padding,width,background-color,color,border-color;-o-transition-property:padding,width,background-color,color,border-color;transition-property:padding,width,background-color,color,border-color;-webkit-transition-duration:100ms;-moz-transition-duration:100ms;-o-transition-duration:100ms;transition-duration:100ms;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}.ui-flipswitch.ui-flipswitch-active{padding-left:4em;width:1.875em}.ui-flipswitch-input{position:absolute;height:1px;width:1px;margin:-1px;overflow:hidden;clip:rect(1px,1px,1px,1px);border:0;outline:0;filter:Alpha(Opacity=0);opacity:0}.ui-flipswitch .ui-btn.ui-flipswitch-on,.ui-flipswitch .ui-flipswitch-off{float:left;height:1.75em;margin:.0625em;line-height:1.65em}.ui-flipswitch .ui-btn.ui-flipswitch-on{width:1.75em;padding:0;text-indent:-2.6em;text-align:left;border-width:1px;border-style:solid;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;border-radius:inherit;overflow:visible;color:inherit;text-shadow:inherit}.ui-flipswitch .ui-flipswitch-off{padding:1px;text-indent:1em}html .ui-field-contain>label+.ui-flipswitch,html .ui-popup .ui-field-contain>label+.ui-flipswitch{display:inline-block;width:5.875em;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;-ms-box-sizing:content-box;box-sizing:content-box}.ui-field-contain .ui-flipswitch.ui-flipswitch-active,.ui-popup .ui-field-contain .ui-flipswitch.ui-flipswitch-active{width:1.875em}.ui-table{border:0;border-collapse:collapse;padding:0;width:100%}.ui-table th,.ui-table td{line-height:1.5em;text-align:left;padding:.4em .5em;vertical-align:top}.ui-table th .ui-btn,.ui-table td .ui-btn{line-height:normal}.ui-table th{font-weight:700}.ui-table caption{text-align:left;margin-bottom:1.4em;opacity:.5}.ui-table-columntoggle-btn{float:right;margin-bottom:.8em}.ui-table-columntoggle-popup fieldset{margin:0}.ui-table-columntoggle{clear:both}@media only all{th.ui-table-priority-6,td.ui-table-priority-6,th.ui-table-priority-5,td.ui-table-priority-5,th.ui-table-priority-4,td.ui-table-priority-4,th.ui-table-priority-3,td.ui-table-priority-3,th.ui-table-priority-2,td.ui-table-priority-2,th.ui-table-priority-1,td.ui-table-priority-1{display:none}}@media screen and (min-width:20em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-1,.ui-table-columntoggle.ui-responsive td.ui-table-priority-1{display:table-cell}}@media screen and (min-width:30em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-2,.ui-table-columntoggle.ui-responsive td.ui-table-priority-2{display:table-cell}}@media screen and (min-width:40em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-3,.ui-table-columntoggle.ui-responsive td.ui-table-priority-3{display:table-cell}}@media screen and (min-width:50em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-4,.ui-table-columntoggle.ui-responsive td.ui-table-priority-4{display:table-cell}}@media screen and (min-width:60em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-5,.ui-table-columntoggle.ui-responsive td.ui-table-priority-5{display:table-cell}}@media screen and (min-width:70em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-6,.ui-table-columntoggle.ui-responsive td.ui-table-priority-6{display:table-cell}}.ui-table-columntoggle th.ui-table-cell-hidden,.ui-table-columntoggle td.ui-table-cell-hidden,.ui-table-columntoggle.ui-responsive th.ui-table-cell-hidden,.ui-table-columntoggle.ui-responsive td.ui-table-cell-hidden{display:none}.ui-table-columntoggle th.ui-table-cell-visible,.ui-table-columntoggle td.ui-table-cell-visible,.ui-table-columntoggle.ui-responsive th.ui-table-cell-visible,.ui-table-columntoggle.ui-responsive td.ui-table-cell-visible{display:table-cell}.ui-table-reflow td .ui-table-cell-label,.ui-table-reflow th .ui-table-cell-label{display:none}@media only all{.ui-table-reflow thead td,.ui-table-reflow thead th{display:none}.ui-table-reflow td,.ui-table-reflow th{text-align:left;display:block}.ui-table-reflow tbody th{margin-top:3em}.ui-table-reflow td .ui-table-cell-label,.ui-table-reflow th .ui-table-cell-label{padding:.4em;min-width:30%;display:inline-block;margin:-.4em 1em -.4em -.4em}.ui-table-reflow th .ui-table-cell-label-top,.ui-table-reflow td .ui-table-cell-label-top{display:block;padding:.4em 0;margin:.4em 0;text-transform:uppercase;font-size:.9em;font-weight:400}}@media (min-width:35em){.ui-table-reflow.ui-responsive{display:table-row-group}.ui-table-reflow.ui-responsive td,.ui-table-reflow.ui-responsive th,.ui-table-reflow.ui-responsive tbody th,.ui-table-reflow.ui-responsive tbody td,.ui-table-reflow.ui-responsive thead td,.ui-table-reflow.ui-responsive thead th{display:table-cell;margin:0}.ui-table-reflow.ui-responsive td .ui-table-cell-label,.ui-table-reflow.ui-responsive th .ui-table-cell-label{display:none}}@media (max-width:35em){.ui-table-reflow.ui-responsive td,.ui-table-reflow.ui-responsive th{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;clear:left}}.ui-panel{width:17em;min-height:100%;max-height:none;border-width:0;position:absolute;top:0;display:block}.ui-panel-closed{width:0;max-height:100%;overflow:hidden;visibility:hidden}.ui-panel-fixed{position:fixed;bottom:-1px;padding-bottom:1px}.ui-panel-display-reveal{z-index:1}.ui-panel-display-push{z-index:999}.ui-panel-display-overlay{z-index:1001}.ui-panel-inner{padding:1em}.ui-panel-page-container{overflow-x:visible}.ui-panel-page-container-themed .ui-page-active{background:0}.ui-panel-wrapper{position:relative;min-height:inherit;border:0;overflow-x:hidden;z-index:999}.ui-panel-fixed-toolbar{overflow-x:hidden}.ui-panel-dismiss{position:absolute;top:0;left:0;right:0;height:100%;z-index:1002;display:none}.ui-panel-dismiss-open{display:block}.ui-panel-animate{-webkit-transition:-webkit-transform 300ms ease;-webkit-transition-duration:300ms;-moz-transition:-moz-transform 300ms ease;transition:transform 300ms ease}@media screen and (max-device-width:768px){.ui-page-header-fixed .ui-panel-animate.ui-panel-wrapper,.ui-page-footer-fixed .ui-panel-animate.ui-panel-wrapper,.ui-panel-animate.ui-panel-fixed-toolbar{-ms-transition:none}.ui-panel-animate.ui-panel-fixed-toolbar{-ms-transition:-ms-transform 1ms;-ms-transform:rotate(0deg)}}.ui-panel-animate.ui-panel:not(.ui-panel-display-reveal){-webkit-backface-visibility:hidden;-webkit-transform:translate3d(0,0,0)}.ui-panel-position-left{left:-17em}.ui-panel-animate.ui-panel-position-left.ui-panel-display-overlay,.ui-panel-animate.ui-panel-position-left.ui-panel-display-push{left:0;-webkit-transform:translate3d(-17em,0,0);-moz-transform:translate3d(-17em,0,0);transform:translate3d(-17em,0,0)}.ui-panel-position-left.ui-panel-display-reveal,.ui-panel-open.ui-panel-position-left{left:0}.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-overlay,.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-push{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-moz-transform:none}.ui-panel-position-right{right:-17em}.ui-panel-animate.ui-panel-position-right.ui-panel-display-overlay,.ui-panel-animate.ui-panel-position-right.ui-panel-display-push{right:0;-webkit-transform:translate3d(17em,0,0);-moz-transform:translate3d(17em,0,0);transform:translate3d(17em,0,0)}.ui-panel-position-right.ui-panel-display-reveal,.ui-panel-position-right.ui-panel-open{right:0}.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-overlay,.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-push{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-moz-transform:none}.ui-panel-page-content-position-left{left:17em;right:-17em}.ui-panel-animate.ui-panel-page-content-position-left{left:0;right:0;-webkit-transform:translate3d(17em,0,0);-moz-transform:translate3d(17em,0,0);transform:translate3d(17em,0,0)}.ui-panel-page-content-position-right{left:-17em;right:17em}.ui-panel-animate.ui-panel-page-content-position-right{left:0;right:0;-webkit-transform:translate3d(-17em,0,0);-moz-transform:translate3d(-17em,0,0);transform:translate3d(-17em,0,0)}.ui-panel-dismiss-open.ui-panel-dismiss-position-left{left:17em}.ui-panel-dismiss-open.ui-panel-dismiss-position-right{right:17em}.ui-panel-display-reveal{-webkit-box-shadow:inset -5px 0 5px rgba(0,0,0,.15);-moz-box-shadow:inset -5px 0 5px rgba(0,0,0,.15);box-shadow:inset -5px 0 5px rgba(0,0,0,.15)}.ui-panel-position-right.ui-panel-display-reveal{-webkit-box-shadow:inset 5px 0 5px rgba(0,0,0,.15);-moz-box-shadow:inset 5px 0 5px rgba(0,0,0,.15);box-shadow:inset 5px 0 5px rgba(0,0,0,.15)}.ui-panel-display-overlay{-webkit-box-shadow:5px 0 5px rgba(0,0,0,.15);-moz-box-shadow:5px 0 5px rgba(0,0,0,.15);box-shadow:5px 0 5px rgba(0,0,0,.15)}.ui-panel-position-right.ui-panel-display-overlay{-webkit-box-shadow:-5px 0 5px rgba(0,0,0,.15);-moz-box-shadow:-5px 0 5px rgba(0,0,0,.15);box-shadow:-5px 0 5px rgba(0,0,0,.15)}.ui-panel-open.ui-panel-position-left.ui-panel-display-push{border-right-width:1px;margin-right:-1px}.ui-panel-page-content-position-left.ui-panel-page-content-display-push{margin-left:1px;width:auto}.ui-panel-open.ui-panel-position-right.ui-panel-display-push{border-left-width:1px;margin-left:-1px}.ui-panel-page-content-position-right.ui-panel-page-content-display-push{margin-right:1px;width:auto}@media (min-width:55em){.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-left{margin-right:17em}.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-right{margin-left:17em}.ui-responsive-panel .ui-panel-page-content-open{width:auto}.ui-responsive-panel .ui-panel-dismiss-display-push,.ui-responsive-panel.ui-page-active~.ui-panel-dismiss-display-push{display:none}}.ui-tabs{position:relative;padding:.2em} \ No newline at end of file diff --git a/static/css/jquery.mobile-1.4.5.min.css b/static/css/jquery.mobile-1.4.5.min.css deleted file mode 100644 index 0461232d..00000000 --- a/static/css/jquery.mobile-1.4.5.min.css +++ /dev/null @@ -1,3 +0,0 @@ -/*! jQuery Mobile 1.4.5 | Git HEADhash: 68e55e7 <> 2014-10-31T17:33:30Z | (c) 2010, 2014 jQuery Foundation, Inc. | jquery.org/license */ - -.ui-icon-action:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C12H2V5h1l2-2H0v11h13V7l-2%2C2V12z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-alert:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8%20C6.447%2C8%2C6%2C7.553%2C6%2C7V5c0-0.553%2C0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-arrow-d-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-d-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-d:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-u-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-u-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-arrow-u:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-audio:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-back:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M5%2C3V0L1%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C13%2C4%2C8%2C3%2C5%2C3z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-bars:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M1%2C4h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C2%2C0%2C2.447%2C0%2C3S0.447%2C4%2C1%2C4z%20M13%2C6H1%20C0.447%2C6%2C0%2C6.447%2C0%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H1c-0.553%2C0-1%2C0.447-1%2C1%20s0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-bullets:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M5%2C4h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C2%2C4%2C2.447%2C4%2C3S4.447%2C4%2C5%2C4z%20M13%2C6H5%20C4.447%2C6%2C4%2C6.447%2C4%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H5c-0.553%2C0-1%2C0.447-1%2C1%20s0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%20M1%2C2C0.447%2C2%2C0%2C2.447%2C0%2C3s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C2%2C1%2C2z%20M1%2C6%20C0.447%2C6%2C0%2C6.447%2C0%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1s1-0.447%2C1-1C2%2C6.447%2C1.553%2C6%2C1%2C6z%20M1%2C10c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1%20S1.553%2C10%2C1%2C10z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-calendar:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-camera:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M12%2C2.5H9.908c-0.206-0.581-0.756-1-1.408-1h-3c-0.652%2C0-1.202%2C0.419-1.408%2C1H2c-1.104%2C0-2%2C0.896-2%2C2%20v6c0%2C1.104%2C0.896%2C2%2C2%2C2h10c1.104%2C0%2C2-0.896%2C2-2v-6C14%2C3.396%2C13.104%2C2.5%2C12%2C2.5z%20M7%2C10.5c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3C10%2C9.156%2C8.657%2C10.5%2C7%2C10.5z%20M7%2C5.5c-1.104%2C0-2%2C0.896-2%2C2c0%2C1.104%2C0.896%2C2%2C2%2C2c1.104%2C0%2C2-0.896%2C2-2%20C9%2C6.396%2C8.104%2C5.5%2C7%2C5.5z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-carat-d:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2211.949%2C3.404%207%2C8.354%202.05%2C3.404%20-0.071%2C5.525%207%2C12.596%2014.07%2C5.525%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-carat-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2210.596%2C11.949%205.646%2C7%2010.596%2C2.05%208.475%2C-0.071%201.404%2C7%208.475%2C14.07%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-carat-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%223.404%2C2.051%208.354%2C7%203.404%2C11.95%205.525%2C14.07%2012.596%2C7%205.525%2C-0.071%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-carat-u:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%222.051%2C10.596%207%2C5.646%2011.95%2C10.596%2014.07%2C8.475%207%2C1.404%20-0.071%2C8.475%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-check:after,html .ui-btn.ui-checkbox-on.ui-checkbox-on:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2214%2C4%2011%2C1%205.003%2C6.997%203%2C5%200%2C8%204.966%2C13%204.983%2C12.982%205%2C13%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-clock:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-cloud:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M14%2C9.5c0-0.793-0.465-1.473-1.134-1.795C12.949%2C7.484%2C13%2C7.249%2C13%2C7c0-1.104-0.896-2-2-2%20c-0.158%2C0-0.311%2C0.023-0.457%2C0.058C9.816%2C3.549%2C8.286%2C2.5%2C6.5%2C2.5c-2.33%2C0-4.224%2C1.777-4.454%2C4.046C0.883%2C6.76%2C0%2C7.773%2C0%2C9%20c0%2C1.381%2C1.119%2C2.5%2C2.5%2C2.5h10v-0.07C13.361%2C11.206%2C14%2C10.432%2C14%2C9.5z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-comment:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-delete:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-edit:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-eye:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C2C3%2C2%2C0%2C7%2C0%2C7s3%2C5%2C7%2C5s7-5%2C7-5S11%2C2%2C7%2C2z%20M7%2C10c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3C10%2C8.656%2C8.657%2C10%2C7%2C10z%20M7%2C6C6.448%2C6%2C6%2C6.447%2C6%2C7c0%2C0.553%2C0.448%2C1%2C1%2C1s1-0.447%2C1-1C8%2C6.447%2C7.552%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-forbidden:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-forward:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M13%2C4L9%2C0v3C6%2C3%2C1%2C4%2C1%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L13%2C4z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-gear:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-grid:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-heart:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C1.872c-2-3-7-2-7%2C2c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.479%2C3%2C3c0.583-0.521%2C3-3%2C3-3s4-4%2C4-7%20C14-0.128%2C9-1.128%2C7%2C1.872z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-home:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-info:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-location:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C0C4.791%2C0%2C3%2C1.791%2C3%2C4c0%2C2%2C4%2C10%2C4%2C10s4-8%2C4-10C11%2C1.791%2C9.209%2C0%2C7%2C0z%20M7%2C6C5.896%2C6%2C5%2C5.104%2C5%2C4%20s0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2S8.104%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-lock:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M12%2C6V5c0-2.762-2.238-5-5-5C4.239%2C0%2C2%2C2.238%2C2%2C5v1H1v8h12V6H12z%20M7.5%2C9.848V12h-1V9.848%20C6.207%2C9.673%2C6%2C9.366%2C6%2C9c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C8%2C9.366%2C7.793%2C9.673%2C7.5%2C9.848z%20M10%2C6H4V5c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3V6z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-mail:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M0%2C3.75V12h14V3.75L7%2C9L0%2C3.75z%20M14%2C2H0l7%2C5L14%2C2z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-minus:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20y%3D%225%22%20style%3D%22fill%3A%23FFFFFF%3B%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-navigation:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2213%2C1%200%2C6%207%2C7%208%2C14%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-phone:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%22-0.01%200.008%2014%2014%22%20style%3D%22enable-background%3Anew%20-0.01%200.008%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M6.939%2C9.189C6.165%2C8.557%2C5.271%2C7.705%2C4.497%2C6.744C3.953%2C6.071%2C3.473%2C5.363%2C3.969%2C4.866l-3.482-3.48%20C-0.021%2C2.02-1.146%2C5.04%2C3.675%2C9.984c5.08%2C5.211%2C8.356%2C4.097%2C8.92%2C3.511l-3.396-3.4C8.725%2C10.568%2C8.113%2C10.146%2C6.939%2C9.189z%20%20M13.82%2C11.519v-0.004c0%2C0-2.648-2.646-2.649-2.647c-0.21-0.211-0.546-0.205-0.754%2C0.002L9.455%2C9.831l3.403%2C3.407%20c0%2C0%2C0.962-0.96%2C0.961-0.961l0.002-0.001C14.043%2C12.056%2C14.021%2C11.721%2C13.82%2C11.519z%20M5.192%2C3.644V3.642%20c0.222-0.222%2C0.2-0.557%2C0-0.758V2.881c0%2C0-2.726-2.725-2.727-2.726C2.255-0.055%2C1.92-0.05%2C1.712%2C0.156L0.751%2C1.121l3.479%2C3.482%20C4.231%2C4.604%2C5.192%2C3.645%2C5.192%2C3.644z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-plus:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-power:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M11.243%2C2.408c-0.392-0.401-1.024-0.401-1.415%2C0c-0.391%2C0.401-0.391%2C1.054%2C0%2C1.455%20C10.584%2C4.642%2C11%2C5.675%2C11%2C6.773s-0.416%2C2.133-1.172%2C2.91c-1.512%2C1.558-4.145%2C1.558-5.656%2C0C3.416%2C8.904%2C3%2C7.872%2C3%2C6.773%20C3%2C5.673%2C3.416%2C4.64%2C4.172%2C3.863c0.39-0.401%2C0.39-1.054%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C1.624%2C3.574%2C1%2C5.125%2C1%2C6.773%20c0%2C1.647%2C0.624%2C3.199%2C1.757%2C4.365c1.134%2C1.166%2C2.64%2C1.809%2C4.243%2C1.809c1.604%2C0%2C3.109-0.645%2C4.243-1.811%20C12.376%2C9.975%2C13%2C8.423%2C13%2C6.773C13%2C5.125%2C12.376%2C3.574%2C11.243%2C2.408z%20M7%2C8.053c0.553%2C0%2C1-0.445%2C1-1v-6c0-0.553-0.447-1-1-1%20c-0.553%2C0-1%2C0.447-1%2C1v6C6%2C7.604%2C6.447%2C8.053%2C7%2C8.053z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-recycle:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M3%2C7h1L2%2C4L0%2C7h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.35v-2.205C8.41%2C10.789%2C7.732%2C11%2C7%2C11%20C4.791%2C11%2C3%2C9.209%2C3%2C7z%20M13%2C7c0-3.313-2.688-6-6-6C6.298%2C1%2C5.626%2C1.127%2C5%2C1.349v2.206C5.59%2C3.211%2C6.268%2C3%2C7%2C3c2.209%2C0%2C4%2C1.791%2C4%2C4%20h-1l2%2C3l2-3H13z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-refresh:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-search:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M10.171%2C8.766c0.617-0.888%2C0.979-1.964%2C0.979-3.126c0-3.037-2.463-5.5-5.5-5.5s-5.5%2C2.463-5.5%2C5.5%20s2.463%2C5.5%2C5.5%2C5.5c1.152%2C0%2C2.223-0.355%2C3.104-0.962l3.684%2C3.683l1.414-1.414L10.171%2C8.766z%20M5.649%2C9.14c-1.933%2C0-3.5-1.567-3.5-3.5%20c0-1.933%2C1.567-3.5%2C3.5-3.5c1.933%2C0%2C3.5%2C1.567%2C3.5%2C3.5C9.149%2C7.572%2C7.582%2C9.14%2C5.649%2C9.14z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-shop:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M10%2C4V3c0-1.657-1.343-3-3-3S4%2C1.343%2C4%2C3v1H1v10h12V4H10z%20M4.5%2C6C4.224%2C6%2C4%2C5.776%2C4%2C5.5%20S4.224%2C5%2C4.5%2C5S5%2C5.224%2C5%2C5.5S4.776%2C6%2C4.5%2C6z%20M5%2C3c0-1.104%2C0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2v1H5V3z%20M9.5%2C6C9.225%2C6%2C9%2C5.776%2C9%2C5.5%20S9.225%2C5%2C9.5%2C5S10%2C5.224%2C10%2C5.5S9.775%2C6%2C9.5%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-star:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3C%2Fsvg%3E")}.ui-icon-tag:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-user:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-icon-video:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%20-2%2014%2014%22%20style%3D%22enable-background%3Anew%200%20-2%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-action:after,.ui-alt-icon .ui-icon-action:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C12H2V5h1l2-2H0v11h13V7l-2%2C2V12z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-alert:after,.ui-alt-icon .ui-icon-alert:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8C6.447%2C8%2C6%2C7.553%2C6%2C7V5%20c0-0.553%2C0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-d:after,.ui-alt-icon .ui-icon-arrow-d:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-d-l:after,.ui-alt-icon .ui-icon-arrow-d-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-d-r:after,.ui-alt-icon .ui-icon-arrow-d-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-l:after,.ui-alt-icon .ui-icon-arrow-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-r:after,.ui-alt-icon .ui-icon-arrow-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-u:after,.ui-alt-icon .ui-icon-arrow-u:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-u-l:after,.ui-alt-icon .ui-icon-arrow-u-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-arrow-u-r:after,.ui-alt-icon .ui-icon-arrow-u-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-audio:after,.ui-alt-icon .ui-icon-audio:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-back:after,.ui-alt-icon .ui-icon-back:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C3V0L1%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C13%2C4%2C8%2C3%2C5%2C3z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-bars:after,.ui-alt-icon .ui-icon-bars:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C2%2C0%2C2.447%2C0%2C3S0.447%2C4%2C1%2C4z%20M13%2C6H1C0.447%2C6%2C0%2C6.447%2C0%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H1c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1h12%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-bullets:after,.ui-alt-icon .ui-icon-bullets:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C4h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C2%2C4%2C2.447%2C4%2C3S4.447%2C4%2C5%2C4z%20M13%2C6H5C4.447%2C6%2C4%2C6.447%2C4%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H5c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1h8%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%20M1%2C2C0.447%2C2%2C0%2C2.447%2C0%2C3s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C2%2C1%2C2z%20M1%2C6C0.447%2C6%2C0%2C6.447%2C0%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1s1-0.447%2C1-1C2%2C6.447%2C1.553%2C6%2C1%2C6z%20M1%2C10c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C10%2C1%2C10z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-calendar:after,.ui-alt-icon .ui-icon-calendar:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-camera:after,.ui-alt-icon .ui-icon-camera:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C2.5H9.908c-0.206-0.581-0.756-1-1.408-1h-3c-0.652%2C0-1.202%2C0.419-1.408%2C1H2c-1.104%2C0-2%2C0.896-2%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2%20h10c1.104%2C0%2C2-0.896%2C2-2v-6C14%2C3.396%2C13.104%2C2.5%2C12%2C2.5z%20M7%2C10.5c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3%20C10%2C9.156%2C8.657%2C10.5%2C7%2C10.5z%20M7%2C5.5c-1.104%2C0-2%2C0.896-2%2C2c0%2C1.104%2C0.896%2C2%2C2%2C2c1.104%2C0%2C2-0.896%2C2-2C9%2C6.396%2C8.104%2C5.5%2C7%2C5.5z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-carat-d:after,.ui-alt-icon .ui-icon-carat-d:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2211.949%2C3.404%207%2C8.354%202.05%2C3.404%20-0.071%2C5.525%207%2C12.596%2014.07%2C5.525%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-carat-l:after,.ui-alt-icon .ui-icon-carat-l:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.596%2C11.949%205.646%2C7%2010.596%2C2.05%208.475%2C-0.071%201.404%2C7%208.475%2C14.07%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-carat-r:after,.ui-alt-icon .ui-icon-carat-r:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%223.404%2C2.051%208.354%2C7%203.404%2C11.95%205.525%2C14.07%2012.596%2C7%205.525%2C-0.071%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-carat-u:after,.ui-alt-icon .ui-icon-carat-u:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%222.051%2C10.596%207%2C5.646%2011.95%2C10.596%2014.07%2C8.475%207%2C1.404%20-0.071%2C8.475%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-check:after,.ui-alt-icon .ui-icon-check:after,html .ui-alt-icon.ui-btn.ui-checkbox-on:after,html .ui-alt-icon .ui-btn.ui-checkbox-on:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C4%2011%2C1%205.003%2C6.997%203%2C5%200%2C8%204.966%2C13%204.983%2C12.982%205%2C13%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-clock:after,.ui-alt-icon .ui-icon-clock:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-cloud:after,.ui-alt-icon .ui-icon-cloud:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14%2C9.5c0-0.793-0.465-1.473-1.134-1.795C12.949%2C7.484%2C13%2C7.249%2C13%2C7c0-1.104-0.896-2-2-2c-0.158%2C0-0.311%2C0.023-0.457%2C0.058%20C9.816%2C3.549%2C8.286%2C2.5%2C6.5%2C2.5c-2.33%2C0-4.224%2C1.777-4.454%2C4.046C0.883%2C6.76%2C0%2C7.773%2C0%2C9c0%2C1.381%2C1.119%2C2.5%2C2.5%2C2.5h10v-0.07%20C13.361%2C11.206%2C14%2C10.432%2C14%2C9.5z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-comment:after,.ui-alt-icon .ui-icon-comment:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-delete:after,.ui-alt-icon .ui-icon-delete:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-edit:after,.ui-alt-icon .ui-icon-edit:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-eye:after,.ui-alt-icon .ui-icon-eye:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C2C3%2C2%2C0%2C7%2C0%2C7s3%2C5%2C7%2C5s7-5%2C7-5S11%2C2%2C7%2C2z%20M7%2C10c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3%20C10%2C8.656%2C8.657%2C10%2C7%2C10z%20M7%2C6C6.448%2C6%2C6%2C6.447%2C6%2C7c0%2C0.553%2C0.448%2C1%2C1%2C1s1-0.447%2C1-1C8%2C6.447%2C7.552%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-forbidden:after,.ui-alt-icon .ui-icon-forbidden:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-forward:after,.ui-alt-icon .ui-icon-forward:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13%2C4L9%2C0v3C6%2C3%2C1%2C4%2C1%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L13%2C4z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-gear:after,.ui-alt-icon .ui-icon-gear:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-grid:after,.ui-alt-icon .ui-icon-grid:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-heart:after,.ui-alt-icon .ui-icon-heart:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C1.958c-2-3-7-2.128-7%2C1.872c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.48%2C3%2C3c0.583-0.52%2C3-3%2C3-3s4-4%2C4-7C14-0.169%2C9-1.042%2C7%2C1.958z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-home:after,.ui-alt-icon .ui-icon-home:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-info:after,.ui-alt-icon .ui-icon-info:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-location:after,.ui-alt-icon .ui-icon-location:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C4.791%2C0%2C3%2C1.791%2C3%2C4c0%2C2%2C4%2C10%2C4%2C10s4-8%2C4-10C11%2C1.791%2C9.209%2C0%2C7%2C0z%20M7%2C6C5.896%2C6%2C5%2C5.104%2C5%2C4s0.896-2%2C2-2%20c1.104%2C0%2C2%2C0.896%2C2%2C2S8.104%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-lock:after,.ui-alt-icon .ui-icon-lock:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C6V5c0-2.762-2.238-5-5-5C4.239%2C0%2C2%2C2.238%2C2%2C5v1H1v8h12V6H12z%20M7.5%2C9.848V12h-1V9.848C6.207%2C9.673%2C6%2C9.366%2C6%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C8%2C9.366%2C7.793%2C9.673%2C7.5%2C9.848z%20M10%2C6H4V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-mail:after,.ui-alt-icon .ui-icon-mail:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C3.75V12h14V3.75L7%2C9L0%2C3.75z%20M14%2C2H0l7%2C5L14%2C2z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-minus:after,.ui-alt-icon .ui-icon-minus:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20y%3D%225%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-navigation:after,.ui-alt-icon .ui-icon-navigation:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2213%2C1%200%2C6%207%2C7%208%2C14%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-phone:after,.ui-alt-icon .ui-icon-phone:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M6.949%2C9.182C6.175%2C8.549%2C5.281%2C7.697%2C4.507%2C6.736C3.963%2C6.063%2C3.483%2C5.355%2C3.979%2C4.858l-3.482-3.48%20c-0.508%2C0.634-1.633%2C3.654%2C3.188%2C8.598c5.08%2C5.211%2C8.356%2C4.097%2C8.92%2C3.511l-3.396-3.399C8.734%2C10.561%2C8.123%2C10.139%2C6.949%2C9.182z%20%20M13.83%2C11.512v-0.004c0%2C0-2.648-2.646-2.649-2.647c-0.21-0.212-0.546-0.205-0.754%2C0.002L9.465%2C9.823l3.402%2C3.407%20c0%2C0%2C0.963-0.961%2C0.961-0.961l0.002-0.002C14.053%2C12.049%2C14.031%2C11.713%2C13.83%2C11.512z%20M5.202%2C3.636V3.634%20c0.222-0.222%2C0.2-0.557%2C0-0.758V2.873c0%2C0-2.726-2.725-2.727-2.726c-0.21-0.21-0.545-0.205-0.753%2C0.001L0.761%2C1.113L4.24%2C4.595%20C4.241%2C4.596%2C5.202%2C3.637%2C5.202%2C3.636z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-plus:after,.ui-alt-icon .ui-icon-plus:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-power:after,.ui-alt-icon .ui-icon-power:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11.243%2C2.408c-0.392-0.401-1.024-0.401-1.415%2C0c-0.391%2C0.401-0.391%2C1.054%2C0%2C1.455C10.584%2C4.642%2C11%2C5.675%2C11%2C6.773%20s-0.416%2C2.133-1.172%2C2.91c-1.512%2C1.558-4.145%2C1.558-5.656%2C0C3.416%2C8.904%2C3%2C7.872%2C3%2C6.773C3%2C5.673%2C3.416%2C4.64%2C4.172%2C3.863%20c0.39-0.401%2C0.39-1.054%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C1.624%2C3.574%2C1%2C5.125%2C1%2C6.773c0%2C1.647%2C0.624%2C3.199%2C1.757%2C4.365%20c1.134%2C1.166%2C2.64%2C1.809%2C4.243%2C1.809c1.604%2C0%2C3.109-0.645%2C4.243-1.811C12.376%2C9.975%2C13%2C8.423%2C13%2C6.773%20C13%2C5.125%2C12.376%2C3.574%2C11.243%2C2.408z%20M7%2C8.053c0.553%2C0%2C1-0.445%2C1-1v-6c0-0.553-0.447-1-1-1c-0.553%2C0-1%2C0.447-1%2C1v6%20C6%2C7.604%2C6.447%2C8.053%2C7%2C8.053z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-recycle:after,.ui-alt-icon .ui-icon-recycle:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C7h1L2%2C4L0%2C7h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.35v-2.205C8.41%2C10.789%2C7.732%2C11%2C7%2C11C4.791%2C11%2C3%2C9.209%2C3%2C7z%20%20M13%2C7c0-3.313-2.688-6-6-6C6.298%2C1%2C5.626%2C1.127%2C5%2C1.349v2.206C5.59%2C3.211%2C6.268%2C3%2C7%2C3c2.209%2C0%2C4%2C1.791%2C4%2C4h-1l2%2C3l2-3H13z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-refresh:after,.ui-alt-icon .ui-icon-refresh:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-search:after,.ui-alt-icon .ui-icon-search:after,.ui-input-search:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10.171%2C8.766c0.617-0.888%2C0.979-1.964%2C0.979-3.126c0-3.037-2.463-5.5-5.5-5.5s-5.5%2C2.463-5.5%2C5.5s2.463%2C5.5%2C5.5%2C5.5%20c1.152%2C0%2C2.223-0.355%2C3.104-0.962l3.684%2C3.683l1.414-1.414L10.171%2C8.766z%20M5.649%2C9.14c-1.933%2C0-3.5-1.567-3.5-3.5%20c0-1.933%2C1.567-3.5%2C3.5-3.5c1.933%2C0%2C3.5%2C1.567%2C3.5%2C3.5C9.149%2C7.572%2C7.582%2C9.14%2C5.649%2C9.14z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-shop:after,.ui-alt-icon .ui-icon-shop:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10%2C4V3c0-1.657-1.343-3-3-3S4%2C1.343%2C4%2C3v1H1v10h12V4H10z%20M4.5%2C6C4.224%2C6%2C4%2C5.776%2C4%2C5.5S4.224%2C5%2C4.5%2C5S5%2C5.224%2C5%2C5.5%20S4.776%2C6%2C4.5%2C6z%20M5%2C3c0-1.104%2C0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2v1H5V3z%20M9.5%2C6C9.225%2C6%2C9%2C5.776%2C9%2C5.5S9.225%2C5%2C9.5%2C5S10%2C5.224%2C10%2C5.5%20S9.775%2C6%2C9.5%2C6z%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-star:after,.ui-alt-icon .ui-icon-star:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-tag:after,.ui-alt-icon .ui-icon-tag:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-user:after,.ui-alt-icon .ui-icon-user:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.ui-alt-icon.ui-icon-video:after,.ui-alt-icon .ui-icon-video:after{background-image:url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%20-2%2014%2014%22%20style%3D%22enable-background%3Anew%200%20-2%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3C%2Fsvg%3E")}.ui-nosvg .ui-icon-action:after{background-image:url(https://github.com/images/icons-png/action-white.png)}.ui-nosvg .ui-icon-alert:after{background-image:url(https://github.com/images/icons-png/alert-white.png)}.ui-nosvg .ui-icon-arrow-d-l:after{background-image:url(https://github.com/images/icons-png/arrow-d-l-white.png)}.ui-nosvg .ui-icon-arrow-d-r:after{background-image:url(https://github.com/images/icons-png/arrow-d-r-white.png)}.ui-nosvg .ui-icon-arrow-d:after{background-image:url(https://github.com/images/icons-png/arrow-d-white.png)}.ui-nosvg .ui-icon-arrow-l:after{background-image:url(https://github.com/images/icons-png/arrow-l-white.png)}.ui-nosvg .ui-icon-arrow-r:after{background-image:url(https://github.com/images/icons-png/arrow-r-white.png)}.ui-nosvg .ui-icon-arrow-u-l:after{background-image:url(https://github.com/images/icons-png/arrow-u-l-white.png)}.ui-nosvg .ui-icon-arrow-u-r:after{background-image:url(https://github.com/images/icons-png/arrow-u-r-white.png)}.ui-nosvg .ui-icon-arrow-u:after{background-image:url(https://github.com/images/icons-png/arrow-u-white.png)}.ui-nosvg .ui-icon-audio:after{background-image:url(https://github.com/images/icons-png/audio-white.png)}.ui-nosvg .ui-icon-back:after{background-image:url(https://github.com/images/icons-png/back-white.png)}.ui-nosvg .ui-icon-bars:after{background-image:url(https://github.com/images/icons-png/bars-white.png)}.ui-nosvg .ui-icon-bullets:after{background-image:url(https://github.com/images/icons-png/bullets-white.png)}.ui-nosvg .ui-icon-calendar:after{background-image:url(https://github.com/images/icons-png/calendar-white.png)}.ui-nosvg .ui-icon-camera:after{background-image:url(https://github.com/images/icons-png/camera-white.png)}.ui-nosvg .ui-icon-carat-d:after{background-image:url(https://github.com/images/icons-png/carat-d-white.png)}.ui-nosvg .ui-icon-carat-l:after{background-image:url(https://github.com/images/icons-png/carat-l-white.png)}.ui-nosvg .ui-icon-carat-r:after{background-image:url(https://github.com/images/icons-png/carat-r-white.png)}.ui-nosvg .ui-icon-carat-u:after{background-image:url(https://github.com/images/icons-png/carat-u-white.png)}.ui-nosvg .ui-icon-check:after,html.ui-nosvg .ui-btn.ui-checkbox-on:after{background-image:url(https://github.com/images/icons-png/check-white.png)}.ui-nosvg .ui-icon-clock:after{background-image:url(https://github.com/images/icons-png/clock-white.png)}.ui-nosvg .ui-icon-cloud:after{background-image:url(https://github.com/images/icons-png/cloud-white.png)}.ui-nosvg .ui-icon-comment:after{background-image:url(https://github.com/images/icons-png/comment-white.png)}.ui-nosvg .ui-icon-delete:after{background-image:url(https://github.com/images/icons-png/delete-white.png)}.ui-nosvg .ui-icon-edit:after{background-image:url(https://github.com/images/icons-png/edit-white.png)}.ui-nosvg .ui-icon-eye:after{background-image:url(https://github.com/images/icons-png/eye-white.png)}.ui-nosvg .ui-icon-forbidden:after{background-image:url(https://github.com/images/icons-png/forbidden-white.png)}.ui-nosvg .ui-icon-forward:after{background-image:url(https://github.com/images/icons-png/forward-white.png)}.ui-nosvg .ui-icon-gear:after{background-image:url(https://github.com/images/icons-png/gear-white.png)}.ui-nosvg .ui-icon-grid:after{background-image:url(https://github.com/images/icons-png/grid-white.png)}.ui-nosvg .ui-icon-heart:after{background-image:url(https://github.com/images/icons-png/heart-white.png)}.ui-nosvg .ui-icon-home:after{background-image:url(https://github.com/images/icons-png/home-white.png)}.ui-nosvg .ui-icon-info:after{background-image:url(https://github.com/images/icons-png/info-white.png)}.ui-nosvg .ui-icon-location:after{background-image:url(https://github.com/images/icons-png/location-white.png)}.ui-nosvg .ui-icon-lock:after{background-image:url(https://github.com/images/icons-png/lock-white.png)}.ui-nosvg .ui-icon-mail:after{background-image:url(https://github.com/images/icons-png/mail-white.png)}.ui-nosvg .ui-icon-minus:after{background-image:url(https://github.com/images/icons-png/minus-white.png)}.ui-nosvg .ui-icon-navigation:after{background-image:url(https://github.com/images/icons-png/navigation-white.png)}.ui-nosvg .ui-icon-phone:after{background-image:url(https://github.com/images/icons-png/phone-white.png)}.ui-nosvg .ui-icon-plus:after{background-image:url(https://github.com/images/icons-png/plus-white.png)}.ui-nosvg .ui-icon-power:after{background-image:url(https://github.com/images/icons-png/power-white.png)}.ui-nosvg .ui-icon-recycle:after{background-image:url(https://github.com/images/icons-png/recycle-white.png)}.ui-nosvg .ui-icon-refresh:after{background-image:url(https://github.com/images/icons-png/refresh-white.png)}.ui-nosvg .ui-icon-search:after{background-image:url(https://github.com/images/icons-png/search-white.png)}.ui-nosvg .ui-icon-shop:after{background-image:url(https://github.com/images/icons-png/shop-white.png)}.ui-nosvg .ui-icon-star:after{background-image:url(https://github.com/images/icons-png/star-white.png)}.ui-nosvg .ui-icon-tag:after{background-image:url(https://github.com/images/icons-png/tag-white.png)}.ui-nosvg .ui-icon-user:after{background-image:url(https://github.com/images/icons-png/user-white.png)}.ui-nosvg .ui-icon-video:after{background-image:url(https://github.com/images/icons-png/video-white.png)}.ui-nosvg .ui-alt-icon.ui-icon-action:after,.ui-nosvg .ui-alt-icon .ui-icon-action:after{background-image:url(https://github.com/images/icons-png/action-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-alert:after,.ui-nosvg .ui-alt-icon .ui-icon-alert:after{background-image:url(https://github.com/images/icons-png/alert-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-d:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-d:after{background-image:url(https://github.com/images/icons-png/arrow-d-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-d-l:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-d-l:after{background-image:url(https://github.com/images/icons-png/arrow-d-l-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-d-r:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-d-r:after{background-image:url(https://github.com/images/icons-png/arrow-d-r-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-l:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-l:after{background-image:url(https://github.com/images/icons-png/arrow-l-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-r:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-r:after{background-image:url(https://github.com/images/icons-png/arrow-r-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-u:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-u:after{background-image:url(https://github.com/images/icons-png/arrow-u-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-u-l:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-u-l:after{background-image:url(https://github.com/images/icons-png/arrow-u-l-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-arrow-u-r:after,.ui-nosvg .ui-alt-icon .ui-icon-arrow-u-r:after{background-image:url(https://github.com/images/icons-png/arrow-u-r-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-audio:after,.ui-nosvg .ui-alt-icon .ui-icon-audio:after{background-image:url(https://github.com/images/icons-png/audio-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-back:after,.ui-nosvg .ui-alt-icon .ui-icon-back:after{background-image:url(https://github.com/images/icons-png/back-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-bars:after,.ui-nosvg .ui-alt-icon .ui-icon-bars:after{background-image:url(https://github.com/images/icons-png/bars-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-bullets:after,.ui-nosvg .ui-alt-icon .ui-icon-bullets:after{background-image:url(https://github.com/images/icons-png/bullets-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-calendar:after,.ui-nosvg .ui-alt-icon .ui-icon-calendar:after{background-image:url(https://github.com/images/icons-png/calendar-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-camera:after,.ui-nosvg .ui-alt-icon .ui-icon-camera:after{background-image:url(https://github.com/images/icons-png/camera-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-carat-d:after,.ui-nosvg .ui-alt-icon .ui-icon-carat-d:after{background-image:url(https://github.com/images/icons-png/carat-d-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-carat-l:after,.ui-nosvg .ui-alt-icon .ui-icon-carat-l:after{background-image:url(https://github.com/images/icons-png/carat-l-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-carat-r:after,.ui-nosvg .ui-alt-icon .ui-icon-carat-r:after{background-image:url(https://github.com/images/icons-png/carat-r-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-carat-u:after,.ui-nosvg .ui-alt-icon .ui-icon-carat-u:after{background-image:url(https://github.com/images/icons-png/carat-u-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-check:after,.ui-nosvg .ui-alt-icon .ui-icon-check:after,.ui-nosvg .ui-alt-icon.ui-btn.ui-checkbox-on:after,.ui-nosvg .ui-alt-icon .ui-btn.ui-checkbox-on:after{background-image:url(https://github.com/images/icons-png/check-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-clock:after,.ui-nosvg .ui-alt-icon .ui-icon-clock:after{background-image:url(https://github.com/images/icons-png/clock-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-cloud:after,.ui-nosvg .ui-alt-icon .ui-icon-cloud:after{background-image:url(https://github.com/images/icons-png/cloud-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-comment:after,.ui-nosvg .ui-alt-icon .ui-icon-comment:after{background-image:url(https://github.com/images/icons-png/comment-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-delete:after,.ui-nosvg .ui-alt-icon .ui-icon-delete:after{background-image:url(https://github.com/images/icons-png/delete-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-edit:after,.ui-nosvg .ui-alt-icon .ui-icon-edit:after{background-image:url(https://github.com/images/icons-png/edit-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-eye:after,.ui-nosvg .ui-alt-icon .ui-icon-eye:after{background-image:url(https://github.com/images/icons-png/eye-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-forbidden:after,.ui-nosvg .ui-alt-icon .ui-icon-forbidden:after{background-image:url(https://github.com/images/icons-png/forbidden-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-forward:after,.ui-nosvg .ui-alt-icon .ui-icon-forward:after{background-image:url(https://github.com/images/icons-png/forward-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-gear:after,.ui-nosvg .ui-alt-icon .ui-icon-gear:after{background-image:url(https://github.com/images/icons-png/gear-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-grid:after,.ui-nosvg .ui-alt-icon .ui-icon-grid:after{background-image:url(https://github.com/images/icons-png/grid-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-heart:after,.ui-nosvg .ui-alt-icon .ui-icon-heart:after{background-image:url(https://github.com/images/icons-png/heart-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-home:after,.ui-nosvg .ui-alt-icon .ui-icon-home:after{background-image:url(https://github.com/images/icons-png/home-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-info:after,.ui-nosvg .ui-alt-icon .ui-icon-info:after{background-image:url(https://github.com/images/icons-png/info-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-location:after,.ui-nosvg .ui-alt-icon .ui-icon-location:after{background-image:url(https://github.com/images/icons-png/location-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-lock:after,.ui-nosvg .ui-alt-icon .ui-icon-lock:after{background-image:url(https://github.com/images/icons-png/lock-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-mail:after,.ui-nosvg .ui-alt-icon .ui-icon-mail:after{background-image:url(https://github.com/images/icons-png/mail-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-minus:after,.ui-nosvg .ui-alt-icon .ui-icon-minus:after{background-image:url(https://github.com/images/icons-png/minus-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-navigation:after,.ui-nosvg .ui-alt-icon .ui-icon-navigation:after{background-image:url(https://github.com/images/icons-png/navigation-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-phone:after,.ui-nosvg .ui-alt-icon .ui-icon-phone:after{background-image:url(https://github.com/images/icons-png/phone-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-plus:after,.ui-nosvg .ui-alt-icon .ui-icon-plus:after{background-image:url(https://github.com/images/icons-png/plus-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-power:after,.ui-nosvg .ui-alt-icon .ui-icon-power:after{background-image:url(https://github.com/images/icons-png/power-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-recycle:after,.ui-nosvg .ui-alt-icon .ui-icon-recycle:after{background-image:url(https://github.com/images/icons-png/recycle-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-refresh:after,.ui-nosvg .ui-alt-icon .ui-icon-refresh:after{background-image:url(https://github.com/images/icons-png/refresh-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-search:after,.ui-nosvg .ui-alt-icon .ui-icon-search:after,.ui-nosvg .ui-input-search:after{background-image:url(https://github.com/images/icons-png/search-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-shop:after,.ui-nosvg .ui-alt-icon .ui-icon-shop:after{background-image:url(https://github.com/images/icons-png/shop-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-star:after,.ui-nosvg .ui-alt-icon .ui-icon-star:after{background-image:url(https://github.com/images/icons-png/star-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-tag:after,.ui-nosvg .ui-alt-icon .ui-icon-tag:after{background-image:url(https://github.com/images/icons-png/tag-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-user:after,.ui-nosvg .ui-alt-icon .ui-icon-user:after{background-image:url(https://github.com/images/icons-png/user-black.png)}.ui-nosvg .ui-alt-icon.ui-icon-video:after,.ui-nosvg .ui-alt-icon .ui-icon-video:after{background-image:url(https://github.com/images/icons-png/video-black.png)}html{font-size:100%}body,input,select,textarea,button,.ui-btn{font-size:1em;line-height:1.3;font-family:sans-serif}legend,.ui-input-text input,.ui-input-search input{color:inherit;text-shadow:inherit}.ui-mobile label,div.ui-controlgroup-label{font-weight:400;font-size:16px}.ui-field-contain{border-bottom-color:#828282;border-bottom-color:rgba(0,0,0,.15);border-bottom-width:1px;border-bottom-style:solid}.table-stroke thead th,.table-stripe thead th,.table-stripe tbody tr:last-child{border-bottom:1px solid #d6d6d6;border-bottom:1px solid rgba(0,0,0,.1)}.table-stroke tbody th,.table-stroke tbody td{border-bottom:1px solid #e6e6e6;border-bottom:1px solid rgba(0,0,0,.05)}.table-stripe.table-stroke tbody tr:last-child th,.table-stripe.table-stroke tbody tr:last-child td{border-bottom:0}.table-stripe tbody tr:nth-child(odd) td,.table-stripe tbody tr:nth-child(odd) th{background-color:#eee;background-color:rgba(0,0,0,.04)}.ui-btn,label.ui-btn{font-weight:700;border-width:1px;border-style:solid}.ui-btn{text-decoration:none!important}.ui-btn-active{cursor:pointer}.ui-corner-all{-webkit-border-radius:.3125em;border-radius:.3125em}.ui-btn-corner-all,.ui-btn.ui-corner-all,.ui-slider-track.ui-corner-all,.ui-flipswitch.ui-corner-all,.ui-li-count{-webkit-border-radius:.3125em;border-radius:.3125em}.ui-btn-icon-notext.ui-btn-corner-all,.ui-btn-icon-notext.ui-corner-all{-webkit-border-radius:1em;border-radius:1em}.ui-btn-corner-all,.ui-corner-all{-webkit-background-clip:padding;background-clip:padding-box}.ui-popup.ui-corner-all>.ui-popup-arrow-guide{left:.6em;right:.6em;top:.6em;bottom:.6em}.ui-shadow{-webkit-box-shadow:0 1px 3px rgba(0,0,0,.15);-moz-box-shadow:0 1px 3px rgba(0,0,0,.15);box-shadow:0 1px 3px rgba(0,0,0,.15)}.ui-shadow-inset{-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.2);-moz-box-shadow:inset 0 1px 3px rgba(0,0,0,.2);box-shadow:inset 0 1px 3px rgba(0,0,0,.2)}.ui-overlay-shadow{-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);-moz-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)}.ui-btn-icon-left:after,.ui-btn-icon-right:after,.ui-btn-icon-top:after,.ui-btn-icon-bottom:after,.ui-btn-icon-notext:after{background-color:#666;background-color:rgba(0,0,0,.3);background-position:center center;background-repeat:no-repeat;-webkit-border-radius:1em;border-radius:1em}.ui-alt-icon.ui-btn:after,.ui-alt-icon .ui-btn:after,html .ui-alt-icon.ui-checkbox-off:after,html .ui-alt-icon.ui-radio-off:after,html .ui-alt-icon .ui-checkbox-off:after,html .ui-alt-icon .ui-radio-off:after{background-color:#666;background-color:rgba(0,0,0,.15)}.ui-nodisc-icon.ui-btn:after,.ui-nodisc-icon .ui-btn:after{background-color:transparent}.ui-shadow-icon.ui-btn:after,.ui-shadow-icon .ui-btn:after{-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.ui-btn.ui-checkbox-off:after,.ui-btn.ui-checkbox-on:after,.ui-btn.ui-radio-off:after,.ui-btn.ui-radio-on:after{display:block;width:18px;height:18px;margin:-9px 2px 0 2px}.ui-checkbox-off:after,.ui-btn.ui-radio-off:after{filter:Alpha(Opacity=30);opacity:.3}.ui-btn.ui-checkbox-off:after,.ui-btn.ui-checkbox-on:after{-webkit-border-radius:.1875em;border-radius:.1875em}.ui-btn.ui-checkbox-off:after{background-color:#666;background-color:rgba(0,0,0,.3)}.ui-radio .ui-btn.ui-radio-on:after{background-image:none;background-color:#fff;width:8px;height:8px;border-width:5px;border-style:solid}.ui-alt-icon.ui-btn.ui-radio-on:after,.ui-alt-icon .ui-btn.ui-radio-on:after{background-color:#000}.ui-icon-loading{background:url(https://github.com/images/ajax-loader.gif);background-size:2.875em 2.875em}.ui-bar-a,.ui-page-theme-a .ui-bar-inherit,html .ui-bar-a .ui-bar-inherit,html .ui-body-a .ui-bar-inherit,html body .ui-group-theme-a .ui-bar-inherit{background-color:#e9e9e9;border-color:#ddd;color:#333;text-shadow:0 1px 0 #eee;font-weight:700}.ui-bar-a{border-width:1px;border-style:solid}.ui-overlay-a,.ui-page-theme-a,.ui-page-theme-a .ui-panel-wrapper{background-color:#f9f9f9;border-color:#bbb;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-body-a,.ui-page-theme-a .ui-body-inherit,html .ui-bar-a .ui-body-inherit,html .ui-body-a .ui-body-inherit,html body .ui-group-theme-a .ui-body-inherit,html .ui-panel-page-container-a{background-color:#fff;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-body-a{border-width:1px;border-style:solid}.ui-page-theme-a a,html .ui-bar-a a,html .ui-body-a a,html body .ui-group-theme-a a{color:#38c;font-weight:700}.ui-page-theme-a a:visited,html .ui-bar-a a:visited,html .ui-body-a a:visited,html body .ui-group-theme-a a:visited{color:#38c}.ui-page-theme-a a:hover,html .ui-bar-a a:hover,html .ui-body-a a:hover,html body .ui-group-theme-a a:hover{color:#059}.ui-page-theme-a a:active,html .ui-bar-a a:active,html .ui-body-a a:active,html body .ui-group-theme-a a:active{color:#059}.ui-page-theme-a .ui-btn,html .ui-bar-a .ui-btn,html .ui-body-a .ui-btn,html body .ui-group-theme-a .ui-btn,html head+body .ui-btn.ui-btn-a,.ui-page-theme-a .ui-btn:visited,html .ui-bar-a .ui-btn:visited,html .ui-body-a .ui-btn:visited,html body .ui-group-theme-a .ui-btn:visited,html head+body .ui-btn.ui-btn-a:visited{background-color:#f6f6f6;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-page-theme-a .ui-btn:hover,html .ui-bar-a .ui-btn:hover,html .ui-body-a .ui-btn:hover,html body .ui-group-theme-a .ui-btn:hover,html head+body .ui-btn.ui-btn-a:hover{background-color:#ededed;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-page-theme-a .ui-btn:active,html .ui-bar-a .ui-btn:active,html .ui-body-a .ui-btn:active,html body .ui-group-theme-a .ui-btn:active,html head+body .ui-btn.ui-btn-a:active{background-color:#e8e8e8;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-page-theme-a .ui-btn.ui-btn-active,html .ui-bar-a .ui-btn.ui-btn-active,html .ui-body-a .ui-btn.ui-btn-active,html body .ui-group-theme-a .ui-btn.ui-btn-active,html head+body .ui-btn.ui-btn-a.ui-btn-active,.ui-page-theme-a .ui-checkbox-on:after,html .ui-bar-a .ui-checkbox-on:after,html .ui-body-a .ui-checkbox-on:after,html body .ui-group-theme-a .ui-checkbox-on:after,.ui-btn.ui-checkbox-on.ui-btn-a:after,.ui-page-theme-a .ui-flipswitch-active,html .ui-bar-a .ui-flipswitch-active,html .ui-body-a .ui-flipswitch-active,html body .ui-group-theme-a .ui-flipswitch-active,html body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,.ui-page-theme-a .ui-slider-track .ui-btn-active,html .ui-bar-a .ui-slider-track .ui-btn-active,html .ui-body-a .ui-slider-track .ui-btn-active,html body .ui-group-theme-a .ui-slider-track .ui-btn-active,html body div.ui-slider-track.ui-body-a .ui-btn-active{background-color:#38c;border-color:#38c;color:#fff;text-shadow:0 1px 0 #059}.ui-page-theme-a .ui-radio-on:after,html .ui-bar-a .ui-radio-on:after,html .ui-body-a .ui-radio-on:after,html body .ui-group-theme-a .ui-radio-on:after,.ui-btn.ui-radio-on.ui-btn-a:after{border-color:#38c}.ui-page-theme-a .ui-btn:focus,html .ui-bar-a .ui-btn:focus,html .ui-body-a .ui-btn:focus,html body .ui-group-theme-a .ui-btn:focus,html head+body .ui-btn.ui-btn-a:focus,.ui-page-theme-a .ui-focus,html .ui-bar-a .ui-focus,html .ui-body-a .ui-focus,html body .ui-group-theme-a .ui-focus,html head+body .ui-btn-a.ui-focus,html head+body .ui-body-a.ui-focus{-webkit-box-shadow:0 0 12px #38c;-moz-box-shadow:0 0 12px #38c;box-shadow:0 0 12px #38c}.ui-bar-b,.ui-page-theme-b .ui-bar-inherit,html .ui-bar-b .ui-bar-inherit,html .ui-body-b .ui-bar-inherit,html body .ui-group-theme-b .ui-bar-inherit{background-color:#1d1d1d;border-color:#1b1b1b;color:#fff;text-shadow:0 1px 0 #111;font-weight:700}.ui-bar-b{border-width:1px;border-style:solid}.ui-overlay-b,.ui-page-theme-b,.ui-page-theme-b .ui-panel-wrapper{background-color:#252525;border-color:#454545;color:#fff;text-shadow:0 1px 0 #111}.ui-body-b,.ui-page-theme-b .ui-body-inherit,html .ui-bar-b .ui-body-inherit,html .ui-body-b .ui-body-inherit,html body .ui-group-theme-b .ui-body-inherit,html .ui-panel-page-container-b{background-color:#2a2a2a;border-color:#1d1d1d;color:#fff;text-shadow:0 1px 0 #111}.ui-body-b{border-width:1px;border-style:solid}.ui-page-theme-b a,html .ui-bar-b a,html .ui-body-b a,html body .ui-group-theme-b a{color:#2ad;font-weight:700}.ui-page-theme-b a:visited,html .ui-bar-b a:visited,html .ui-body-b a:visited,html body .ui-group-theme-b a:visited{color:#2ad}.ui-page-theme-b a:hover,html .ui-bar-b a:hover,html .ui-body-b a:hover,html body .ui-group-theme-b a:hover{color:#08b}.ui-page-theme-b a:active,html .ui-bar-b a:active,html .ui-body-b a:active,html body .ui-group-theme-b a:active{color:#08b}.ui-page-theme-b .ui-btn,html .ui-bar-b .ui-btn,html .ui-body-b .ui-btn,html body .ui-group-theme-b .ui-btn,html head+body .ui-btn.ui-btn-b,.ui-page-theme-b .ui-btn:visited,html .ui-bar-b .ui-btn:visited,html .ui-body-b .ui-btn:visited,html body .ui-group-theme-b .ui-btn:visited,html head+body .ui-btn.ui-btn-b:visited{background-color:#333;border-color:#1f1f1f;color:#fff;text-shadow:0 1px 0 #111}.ui-page-theme-b .ui-btn:hover,html .ui-bar-b .ui-btn:hover,html .ui-body-b .ui-btn:hover,html body .ui-group-theme-b .ui-btn:hover,html head+body .ui-btn.ui-btn-b:hover{background-color:#373737;border-color:#1f1f1f;color:#fff;text-shadow:0 1px 0 #111}.ui-page-theme-b .ui-btn:active,html .ui-bar-b .ui-btn:active,html .ui-body-b .ui-btn:active,html body .ui-group-theme-b .ui-btn:active,html head+body .ui-btn.ui-btn-b:active{background-color:#404040;border-color:#1f1f1f;color:#fff;text-shadow:0 1px 0 #111}.ui-page-theme-b .ui-btn.ui-btn-active,html .ui-bar-b .ui-btn.ui-btn-active,html .ui-body-b .ui-btn.ui-btn-active,html body .ui-group-theme-b .ui-btn.ui-btn-active,html head+body .ui-btn.ui-btn-b.ui-btn-active,.ui-page-theme-b .ui-checkbox-on:after,html .ui-bar-b .ui-checkbox-on:after,html .ui-body-b .ui-checkbox-on:after,html body .ui-group-theme-b .ui-checkbox-on:after,.ui-btn.ui-checkbox-on.ui-btn-b:after,.ui-page-theme-b .ui-flipswitch-active,html .ui-bar-b .ui-flipswitch-active,html .ui-body-b .ui-flipswitch-active,html body .ui-group-theme-b .ui-flipswitch-active,html body .ui-flipswitch.ui-bar-b.ui-flipswitch-active,.ui-page-theme-b .ui-slider-track .ui-btn-active,html .ui-bar-b .ui-slider-track .ui-btn-active,html .ui-body-b .ui-slider-track .ui-btn-active,html body .ui-group-theme-b .ui-slider-track .ui-btn-active,html body div.ui-slider-track.ui-body-b .ui-btn-active{background-color:#2ad;border-color:#2ad;color:#fff;text-shadow:0 1px 0 #08b}.ui-page-theme-b .ui-radio-on:after,html .ui-bar-b .ui-radio-on:after,html .ui-body-b .ui-radio-on:after,html body .ui-group-theme-b .ui-radio-on:after,.ui-btn.ui-radio-on.ui-btn-b:after{border-color:#2ad}.ui-page-theme-b .ui-btn:focus,html .ui-bar-b .ui-btn:focus,html .ui-body-b .ui-btn:focus,html body .ui-group-theme-b .ui-btn:focus,html head+body .ui-btn.ui-btn-b:focus,.ui-page-theme-b .ui-focus,html .ui-bar-b .ui-focus,html .ui-body-b .ui-focus,html body .ui-group-theme-b .ui-focus,html head+body .ui-btn-b.ui-focus,html head+body .ui-body-b.ui-focus{-webkit-box-shadow:0 0 12px #2ad;-moz-box-shadow:0 0 12px #2ad;box-shadow:0 0 12px #2ad}.ui-disabled,.ui-state-disabled,button[disabled],.ui-select .ui-btn.ui-state-disabled{filter:Alpha(Opacity=30);opacity:.3;cursor:default!important;pointer-events:none}.ui-btn:focus,.ui-btn.ui-focus{outline:0}.ui-noboxshadow .ui-shadow,.ui-noboxshadow .ui-shadow-inset,.ui-noboxshadow .ui-overlay-shadow,.ui-noboxshadow .ui-shadow-icon.ui-btn:after,.ui-noboxshadow .ui-shadow-icon .ui-btn:after,.ui-noboxshadow .ui-focus,.ui-noboxshadow .ui-btn:focus,.ui-noboxshadow input:focus,.ui-noboxshadow .ui-panel{-webkit-box-shadow:none!important;-moz-box-shadow:none!important;box-shadow:none!important}.ui-noboxshadow .ui-btn:focus,.ui-noboxshadow .ui-focus{outline-width:1px;outline-style:auto}.ui-mobile,.ui-mobile body{height:99.9%}.ui-mobile fieldset,.ui-page{padding:0;margin:0}.ui-mobile a img,.ui-mobile fieldset{border-width:0}.ui-mobile fieldset{min-width:0}@-moz-document url-prefix(){.ui-mobile fieldset{display:table-column;vertical-align:middle}}.ui-mobile-viewport{margin:0;overflow-x:visible;-webkit-text-size-adjust:100%;-ms-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}body.ui-mobile-viewport,div.ui-mobile-viewport{overflow-x:hidden}.ui-mobile [data-role=page],.ui-mobile [data-role=dialog],.ui-page{top:0;left:0;width:100%;min-height:100%;position:absolute;display:none;border:0}.ui-page{outline:0}.ui-mobile .ui-page-active{display:block;overflow:visible;overflow-x:hidden}@media screen and (orientation:portrait){.ui-mobile .ui-page{min-height:420px}}@media screen and (orientation:landscape){.ui-mobile .ui-page{min-height:300px}}.ui-mobile-rendering>*{visibility:hidden}.ui-nojs{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-loading .ui-loader{display:block}.ui-loader{display:none;z-index:9999999;position:fixed;top:50%;left:50%;border:0}.ui-loader-default{background:0;filter:Alpha(Opacity=18);opacity:.18;width:2.875em;height:2.875em;margin-left:-1.4375em;margin-top:-1.4375em}.ui-loader-verbose{width:12.5em;filter:Alpha(Opacity=88);opacity:.88;box-shadow:0 1px 1px -1px #fff;height:auto;margin-left:-6.875em;margin-top:-2.6875em;padding:.625em}.ui-loader-default h1{font-size:0;width:0;height:0;overflow:hidden}.ui-loader-verbose h1{font-size:1em;margin:0;text-align:center}.ui-loader .ui-icon-loading{background-color:#000;display:block;margin:0;width:2.75em;height:2.75em;padding:.0625em;-webkit-border-radius:2.25em;border-radius:2.25em}.ui-loader-verbose .ui-icon-loading{margin:0 auto .625em;filter:Alpha(Opacity=75);opacity:.75}.ui-loader-textonly{padding:.9375em;margin-left:-7.1875em}.ui-loader-textonly .ui-icon-loading{display:none}.ui-loader-fakefix{position:absolute}.ui-bar,.ui-body{position:relative;padding:.4em 1em;overflow:hidden;display:block;clear:both}.ui-bar h1,.ui-bar h2,.ui-bar h3,.ui-bar h4,.ui-bar h5,.ui-bar h6{margin:0;padding:0;font-size:1em;display:inline-block}.ui-header,.ui-footer{border-width:1px 0;border-style:solid;position:relative}.ui-header:empty,.ui-footer:empty{min-height:2.6875em}.ui-header .ui-title,.ui-footer .ui-title{font-size:1em;min-height:1.1em;text-align:center;display:block;margin:0 30%;padding:.7em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;outline:0!important}.ui-footer .ui-title{margin:0 1em}.ui-content{border-width:0;overflow:visible;overflow-x:hidden;padding:1em}.ui-corner-all>.ui-header:first-child,.ui-corner-all>.ui-content:first-child,.ui-corner-all>.ui-footer:first-child{-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit;-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit}.ui-corner-all>.ui-header:last-child,.ui-corner-all>.ui-content:last-child,.ui-corner-all>.ui-footer:last-child{-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit;-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit}.ui-btn{font-size:16px;margin:.5em 0;padding:.7em 1em;display:block;position:relative;text-align:center;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ui-btn-icon-notext,.ui-header button.ui-btn.ui-btn-icon-notext,.ui-footer button.ui-btn.ui-btn-icon-notext{padding:0;width:1.75em;height:1.75em;text-indent:-9999px;white-space:nowrap!important}.ui-mini{font-size:12.5px}.ui-mini .ui-btn{font-size:inherit}.ui-header .ui-btn,.ui-footer .ui-btn{font-size:12.5px;display:inline-block;vertical-align:middle}.ui-header .ui-controlgroup .ui-btn-icon-notext,.ui-footer .ui-controlgroup .ui-btn-icon-notext{font-size:12.5px}.ui-header .ui-btn-left,.ui-header .ui-btn-right{font-size:12.5px}.ui-mini.ui-btn-icon-notext,.ui-mini .ui-btn-icon-notext,.ui-header .ui-btn-icon-notext,.ui-footer .ui-btn-icon-notext{font-size:16px;padding:0}.ui-btn-inline{display:inline-block;vertical-align:middle;margin-right:.625em}.ui-btn-icon-left{padding-left:2.5em}.ui-btn-icon-right{padding-right:2.5em}.ui-btn-icon-top{padding-top:2.5em}.ui-btn-icon-bottom{padding-bottom:2.5em}.ui-header .ui-btn-icon-top,.ui-footer .ui-btn-icon-top,.ui-header .ui-btn-icon-bottom,.ui-footer .ui-btn-icon-bottom{padding-left:.3125em;padding-right:.3125em}.ui-btn-icon-left:after,.ui-btn-icon-right:after,.ui-btn-icon-top:after,.ui-btn-icon-bottom:after,.ui-btn-icon-notext:after{content:"";position:absolute;display:block;width:22px;height:22px}.ui-btn-icon-notext:after,.ui-btn-icon-left:after,.ui-btn-icon-right:after{top:50%;margin-top:-11px}.ui-btn-icon-left:after{left:.5625em}.ui-btn-icon-right:after{right:.5625em}.ui-mini.ui-btn-icon-left:after,.ui-mini .ui-btn-icon-left:after,.ui-header .ui-btn-icon-left:after,.ui-footer .ui-btn-icon-left:after{left:.37em}.ui-mini.ui-btn-icon-right:after,.ui-mini .ui-btn-icon-right:after,.ui-header .ui-btn-icon-right:after,.ui-footer .ui-btn-icon-right:after{right:.37em}.ui-btn-icon-notext:after,.ui-btn-icon-top:after,.ui-btn-icon-bottom:after{left:50%;margin-left:-11px}.ui-btn-icon-top:after{top:.5625em}.ui-btn-icon-bottom:after{top:auto;bottom:.5625em}.ui-header .ui-btn-left,.ui-header .ui-btn-right,.ui-btn-left>[class*=ui-],.ui-btn-right>[class*=ui-]{margin:0}.ui-btn-left,.ui-btn-right{position:absolute;top:.24em}.ui-btn-left{left:.4em}.ui-btn-right{right:.4em}.ui-btn-icon-notext.ui-btn-left{top:.3125em;left:.3125em}.ui-btn-icon-notext.ui-btn-right{top:.3125em;right:.3125em}button.ui-btn,.ui-controlgroup-controls button.ui-btn-icon-notext{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;width:100%}button.ui-btn-inline,.ui-header button.ui-btn,.ui-footer button.ui-btn{width:auto}button.ui-btn::-moz-focus-inner{border:0}button.ui-btn-icon-notext,.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;width:1.75em}.ui-mobile label,.ui-controlgroup-label{display:block;margin:0 0 .4em}.ui-hide-label>label,.ui-hide-label .ui-controlgroup-label,.ui-hide-label .ui-rangeslider label,.ui-hidden-accessible{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-screen-hidden{display:none!important}.ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.ui-page-pre-in{opacity:0}.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms;animation-timing-function:ease-out;animation-duration:350ms}.out{-webkit-animation-timing-function:ease-in;-webkit-animation-duration:225ms;-moz-animation-timing-function:ease-in;-moz-animation-duration:225ms;animation-timing-function:ease-in;animation-duration:225ms}@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@-moz-keyframes fadein{from{opacity:0}to{opacity:1}}@keyframes fadein{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeout{from{opacity:1}to{opacity:0}}@-moz-keyframes fadeout{from{opacity:1}to{opacity:0}}@keyframes fadeout{from{opacity:1}to{opacity:0}}.fade.out{opacity:0;-webkit-animation-duration:125ms;-webkit-animation-name:fadeout;-moz-animation-duration:125ms;-moz-animation-name:fadeout;animation-duration:125ms;animation-name:fadeout}.fade.in{opacity:1;-webkit-animation-duration:225ms;-webkit-animation-name:fadein;-moz-animation-duration:225ms;-moz-animation-name:fadein;animation-duration:225ms;animation-name:fadein}.pop{-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%;transform-origin:50% 50%}.pop.in{-webkit-transform:scale(1);-webkit-animation-name:popin;-webkit-animation-duration:350ms;-moz-transform:scale(1);-moz-animation-name:popin;-moz-animation-duration:350ms;transform:scale(1);animation-name:popin;animation-duration:350ms;opacity:1}.pop.out{-webkit-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-name:fadeout;-moz-animation-duration:100ms;animation-name:fadeout;animation-duration:100ms;opacity:0}.pop.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;animation-name:fadein}.pop.out.reverse{-webkit-transform:scale(.8);-webkit-animation-name:popout;-moz-transform:scale(.8);-moz-animation-name:popout;transform:scale(.8);animation-name:popout}@-webkit-keyframes popin{from{-webkit-transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-moz-keyframes popin{from{-moz-transform:scale(.8);opacity:0}to{-moz-transform:scale(1);opacity:1}}@keyframes popin{from{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@-moz-keyframes popout{from{-moz-transform:scale(1);opacity:1}to{-moz-transform:scale(.8);opacity:0}}@keyframes popout{from{transform:scale(1);opacity:1}to{transform:scale(.8);opacity:0}}@-webkit-keyframes slideinfromright{from{-webkit-transform:translate3d(100%,0,0)}to{-webkit-transform:translate3d(0,0,0)}}@-moz-keyframes slideinfromright{from{-moz-transform:translateX(100%)}to{-moz-transform:translateX(0)}}@keyframes slideinfromright{from{transform:translateX(100%)}to{transform:translateX(0)}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translate3d(-100%,0,0)}to{-webkit-transform:translate3d(0,0,0)}}@-moz-keyframes slideinfromleft{from{-moz-transform:translateX(-100%)}to{-moz-transform:translateX(0)}}@keyframes slideinfromleft{from{transform:translateX(-100%)}to{transform:translateX(0)}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(-100%,0,0)}}@-moz-keyframes slideouttoleft{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(-100%)}}@keyframes slideouttoleft{from{transform:translateX(0)}to{transform:translateX(-100%)}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(100%,0,0)}}@-moz-keyframes slideouttoright{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(100%)}}@keyframes slideouttoright{from{transform:translateX(0)}to{transform:translateX(100%)}}.slide.out,.slide.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms;animation-timing-function:ease-out;animation-duration:350ms}.slide.out{-webkit-transform:translate3d(-100%,0,0);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;transform:translateX(-100%);animation-name:slideouttoleft}.slide.in{-webkit-transform:translate3d(0,0,0);-webkit-animation-name:slideinfromright;-moz-transform:translateX(0);-moz-animation-name:slideinfromright;transform:translateX(0);animation-name:slideinfromright}.slide.out.reverse{-webkit-transform:translate3d(100%,0,0);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;transform:translateX(100%);animation-name:slideouttoright}.slide.in.reverse{-webkit-transform:translate3d(0,0,0);-webkit-animation-name:slideinfromleft;-moz-transform:translateX(0);-moz-animation-name:slideinfromleft;transform:translateX(0);animation-name:slideinfromleft}.slidefade.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-webkit-animation-duration:225ms;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;-moz-animation-duration:225ms;transform:translateX(-100%);animation-name:slideouttoleft;animation-duration:225ms}.slidefade.in{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-webkit-animation-duration:200ms;-moz-transform:translateX(0);-moz-animation-name:fadein;-moz-animation-duration:200ms;transform:translateX(0);animation-name:fadein;animation-duration:200ms}.slidefade.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-webkit-animation-duration:200ms;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;-moz-animation-duration:200ms;transform:translateX(100%);animation-name:slideouttoright;animation-duration:200ms}.slidefade.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-webkit-animation-duration:200ms;-moz-transform:translateX(0);-moz-animation-name:fadein;-moz-animation-duration:200ms;transform:translateX(0);animation-name:fadein;animation-duration:200ms}.slidedown.out{-webkit-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-name:fadeout;-moz-animation-duration:100ms;animation-name:fadeout;animation-duration:100ms}.slidedown.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfromtop;-webkit-animation-duration:250ms;-moz-transform:translateY(0);-moz-animation-name:slideinfromtop;-moz-animation-duration:250ms;transform:translateY(0);animation-name:slideinfromtop;animation-duration:250ms}.slidedown.in.reverse{-webkit-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-name:fadein;-moz-animation-duration:150ms;animation-name:fadein;animation-duration:150ms}.slidedown.out.reverse{-webkit-transform:translateY(-100%);-webkit-animation-name:slideouttotop;-webkit-animation-duration:200ms;-moz-transform:translateY(-100%);-moz-animation-name:slideouttotop;-moz-animation-duration:200ms;transform:translateY(-100%);animation-name:slideouttotop;animation-duration:200ms}@-webkit-keyframes slideinfromtop{from{-webkit-transform:translateY(-100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfromtop{from{-moz-transform:translateY(-100%)}to{-moz-transform:translateY(0)}}@keyframes slideinfromtop{from{transform:translateY(-100%)}to{transform:translateY(0)}}@-webkit-keyframes slideouttotop{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(-100%)}}@-moz-keyframes slideouttotop{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(-100%)}}@keyframes slideouttotop{from{transform:translateY(0)}to{transform:translateY(-100%)}}.slideup.out{-webkit-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-name:fadeout;-moz-animation-duration:100ms;animation-name:fadeout;animation-duration:100ms}.slideup.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfrombottom;-webkit-animation-duration:250ms;-moz-transform:translateY(0);-moz-animation-name:slideinfrombottom;-moz-animation-duration:250ms;transform:translateY(0);animation-name:slideinfrombottom;animation-duration:250ms}.slideup.in.reverse{-webkit-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-name:fadein;-moz-animation-duration:150ms;animation-name:fadein;animation-duration:150ms}.slideup.out.reverse{-webkit-transform:translateY(100%);-webkit-animation-name:slideouttobottom;-webkit-animation-duration:200ms;-moz-transform:translateY(100%);-moz-animation-name:slideouttobottom;-moz-animation-duration:200ms;transform:translateY(100%);animation-name:slideouttobottom;animation-duration:200ms}@-webkit-keyframes slideinfrombottom{from{-webkit-transform:translateY(100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfrombottom{from{-moz-transform:translateY(100%)}to{-moz-transform:translateY(0)}}@keyframes slideinfrombottom{from{transform:translateY(100%)}to{transform:translateY(0)}}@-webkit-keyframes slideouttobottom{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(100%)}}@-moz-keyframes slideouttobottom{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(100%)}}@keyframes slideouttobottom{from{transform:translateY(0)}to{transform:translateY(100%)}}.viewport-flip{-webkit-perspective:1000;-moz-perspective:1000;perspective:1000;position:absolute}.flip{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-moz-backface-visibility:hidden;-moz-transform:translateX(0);backface-visibility:hidden;transform:translateX(0)}.flip.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:175ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:175ms;transform:rotateY(-90deg) scale(.9);animation-name:flipouttoleft;animation-duration:175ms}.flip.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:225ms;-moz-animation-name:flipintoright;-moz-animation-duration:225ms;animation-name:flipintoright;animation-duration:225ms}.flip.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright;transform:rotateY(90deg) scale(.9);animation-name:flipouttoright}.flip.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft;animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@keyframes flipouttoleft{from{transform:rotateY(0)}to{transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@keyframes flipouttoright{from{transform:rotateY(0)}to{transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@keyframes flipintoleft{from{transform:rotateY(-90deg) scale(.9)}to{transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@keyframes flipintoright{from{transform:rotateY(90deg) scale(.9)}to{transform:rotateY(0)}}.viewport-turn{-webkit-perspective:200px;-moz-perspective:200px;-ms-perspective:200px;perspective:200px;position:absolute}.turn{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-webkit-transform-origin:0;-moz-backface-visibility:hidden;-moz-transform:translateX(0);-moz-transform-origin:0;backface-visibility:hidden;transform:translateX(0);transform-origin:0}.turn.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:125ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:125ms;transform:rotateY(-90deg) scale(.9);animation-name:flipouttoleft;animation-duration:125ms}.turn.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:250ms;-moz-animation-name:flipintoright;-moz-animation-duration:250ms;animation-name:flipintoright;animation-duration:250ms}.turn.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright;transform:rotateY(90deg) scale(.9);animation-name:flipouttoright}.turn.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft;animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@keyframes flipouttoleft{from{transform:rotateY(0)}to{transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@keyframes flipouttoright{from{transform:rotateY(0)}to{transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@keyframes flipintoleft{from{transform:rotateY(-90deg) scale(.9)}to{transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@keyframes flipintoright{from{transform:rotateY(90deg) scale(.9)}to{transform:rotateY(0)}}.flow{-webkit-transform-origin:50% 30%;-webkit-box-shadow:0 0 20px rgba(0,0,0,.4);-moz-transform-origin:50% 30%;-moz-box-shadow:0 0 20px rgba(0,0,0,.4);transform-origin:50% 30%;box-shadow:0 0 20px rgba(0,0,0,.4)}.ui-dialog.flow{-webkit-transform-origin:none;-webkit-box-shadow:none;-moz-transform-origin:none;-moz-box-shadow:none;transform-origin:none;box-shadow:none}.flow.out{-webkit-transform:translateX(-100%) scale(.7);-webkit-animation-name:flowouttoleft;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(-100%) scale(.7);-moz-animation-name:flowouttoleft;-moz-animation-timing-function:ease;-moz-animation-duration:350ms;transform:translateX(-100%) scale(.7);animation-name:flowouttoleft;animation-timing-function:ease;animation-duration:350ms}.flow.in{-webkit-transform:translateX(0) scale(1);-webkit-animation-name:flowinfromright;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(0) scale(1);-moz-animation-name:flowinfromright;-moz-animation-timing-function:ease;-moz-animation-duration:350ms;transform:translateX(0) scale(1);animation-name:flowinfromright;animation-timing-function:ease;animation-duration:350ms}.flow.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:flowouttoright;-moz-transform:translateX(100%);-moz-animation-name:flowouttoright;transform:translateX(100%);animation-name:flowouttoright}.flow.in.reverse{-webkit-animation-name:flowinfromleft;-moz-animation-name:flowinfromleft;animation-name:flowinfromleft}@-webkit-keyframes flowouttoleft{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(-100%) scale(.7)}}@-moz-keyframes flowouttoleft{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(-100%) scale(.7)}}@keyframes flowouttoleft{0%{transform:translateX(0) scale(1)}60%,70%{transform:translateX(0) scale(.7)}100%{transform:translateX(-100%) scale(.7)}}@-webkit-keyframes flowouttoright{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(100%) scale(.7)}}@-moz-keyframes flowouttoright{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(100%) scale(.7)}}@keyframes flowouttoright{0%{transform:translateX(0) scale(1)}60%,70%{transform:translateX(0) scale(.7)}100%{transform:translateX(100%) scale(.7)}}@-webkit-keyframes flowinfromleft{0%{-webkit-transform:translateX(-100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromleft{0%{-moz-transform:translateX(-100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}@keyframes flowinfromleft{0%{transform:translateX(-100%) scale(.7)}30%,40%{transform:translateX(0) scale(.7)}100%{transform:translateX(0) scale(1)}}@-webkit-keyframes flowinfromright{0%{-webkit-transform:translateX(100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromright{0%{-moz-transform:translateX(100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}@keyframes flowinfromright{0%{transform:translateX(100%) scale(.7)}30%,40%{transform:translateX(0) scale(.7)}100%{transform:translateX(0) scale(1)}}.ui-field-contain,.ui-mobile fieldset.ui-field-contain{display:block;position:relative;overflow:visible;clear:both;padding:.8em 0}.ui-field-contain>label~[class*=ui-],.ui-field-contain .ui-controlgroup-controls{margin:0}.ui-field-contain:last-child{border-bottom-width:0}@media (min-width:28em){.ui-field-contain,.ui-mobile fieldset.ui-field-contain{padding:0;margin:1em 0;border-bottom-width:0}.ui-field-contain:before,.ui-field-contain:after{content:"";display:table}.ui-field-contain:after{clear:both}.ui-field-contain>label,.ui-field-contain .ui-controlgroup-label,.ui-field-contain>.ui-rangeslider>label{float:left;width:20%;margin:.5em 2% 0 0}.ui-popup .ui-field-contain>label,.ui-popup .ui-field-contain .ui-controlgroup-label,.ui-popup .ui-field-contain>.ui-rangeslider>label{float:none;width:auto;margin:0 0 .4em}.ui-field-contain>label~[class*=ui-],.ui-field-contain .ui-controlgroup-controls{float:left;width:78%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.ui-hide-label>label~[class*=ui-],.ui-hide-label .ui-controlgroup-controls,.ui-popup .ui-field-contain>label~[class*=ui-],.ui-popup .ui-field-contain .ui-controlgroup-controls{float:none;width:100%}.ui-field-contain>label~.ui-btn-inline{width:auto;margin-right:.625em}.ui-field-contain>label~.ui-btn-inline.ui-btn-icon-notext{width:1.75em}}.ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d,.ui-grid-solo{overflow:hidden}.ui-block-a,.ui-block-b,.ui-block-c,.ui-block-d,.ui-block-e{margin:0;padding:0;border:0;float:left;min-height:1px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.ui-block-a{clear:left}ul.ui-grid-a,ul.ui-grid-b,ul.ui-grid-c,ul.ui-grid-d,ul.ui-grid-solo,li.ui-block-a,li.ui-block-b,li.ui-block-c,li.ui-block-d,li.ui-block-e{margin-left:0;margin-right:0;padding:0;list-style:none}[class*=ui-block-]>button.ui-btn{margin-right:0;margin-left:0}[class*=ui-block-]>.ui-btn,[class*=ui-block-]>.ui-select,[class*=ui-block-]>.ui-checkbox,[class*=ui-block-]>.ui-radio,[class*=ui-block-]>button.ui-btn-inline,[class*=ui-block-]>button.ui-btn-icon-notext,.ui-header [class*=ui-block-]>button.ui-btn,.ui-footer [class*=ui-block-]>button.ui-btn{margin-right:.3125em;margin-left:.3125em}.ui-grid-a>.ui-block-a,.ui-grid-a>.ui-block-b{width:50%}.ui-grid-b>.ui-block-a,.ui-grid-b>.ui-block-b,.ui-grid-b>.ui-block-c{width:33.333%}.ui-grid-c>.ui-block-a,.ui-grid-c>.ui-block-b,.ui-grid-c>.ui-block-c,.ui-grid-c>.ui-block-d{width:25%}.ui-grid-d>.ui-block-a,.ui-grid-d>.ui-block-b,.ui-grid-d>.ui-block-c,.ui-grid-d>.ui-block-d,.ui-grid-d>.ui-block-e{width:20%}.ui-grid-solo>.ui-block-a{width:100%;float:none}@media (max-width:35em){.ui-responsive>.ui-block-a,.ui-responsive>.ui-block-b,.ui-responsive>.ui-block-c,.ui-responsive>.ui-block-d,.ui-responsive>.ui-block-e{width:100%;float:none}}.ui-header-fixed,.ui-footer-fixed{left:0;right:0;width:100%;position:fixed;z-index:1000}.ui-header-fixed{top:-1px;padding-top:1px}.ui-header-fixed.ui-fixed-hidden{top:0;padding-top:0}.ui-header-fixed .ui-btn-left,.ui-header-fixed .ui-btn-right{margin-top:1px}.ui-header-fixed.ui-fixed-hidden .ui-btn-left,.ui-header-fixed.ui-fixed-hidden .ui-btn-right{margin-top:0}.ui-footer-fixed{bottom:-1px;padding-bottom:1px}.ui-footer-fixed.ui-fixed-hidden{bottom:0;padding-bottom:0}.ui-header-fullscreen,.ui-footer-fullscreen{filter:Alpha(Opacity=90);opacity:.9}.ui-page-header-fixed{padding-top:2.8125em}.ui-page-footer-fixed{padding-bottom:2.8125em}.ui-page-header-fullscreen>.ui-content,.ui-page-footer-fullscreen>.ui-content{padding:0}.ui-fixed-hidden{position:absolute}.ui-footer-fixed.ui-fixed-hidden{display:none}.ui-page .ui-footer-fixed.ui-fixed-hidden{display:block}.ui-page-header-fullscreen .ui-fixed-hidden,.ui-page-footer-fullscreen .ui-fixed-hidden{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-header-fixed .ui-btn,.ui-footer-fixed .ui-btn{z-index:10}.ui-android-2x-fixed .ui-li-has-thumb{-webkit-transform:translate3d(0,0,0)}.ui-navbar{max-width:100%}.ui-navbar ul:before,.ui-navbar ul:after{content:"";display:table}.ui-navbar ul:after{clear:both}.ui-navbar ul{list-style:none;margin:0;padding:0;position:relative;display:block;border:0;max-width:100%;overflow:visible}.ui-navbar li .ui-btn{font-size:12.5px;display:block;margin:0;border-right-width:0}.ui-header .ui-navbar li button.ui-btn,.ui-footer .ui-navbar li button.ui-btn{margin:0;width:100%}.ui-navbar .ui-btn:focus{z-index:1}.ui-navbar li:last-child .ui-btn{margin-right:-4px}.ui-navbar li:last-child .ui-btn:after{margin-right:4px}.ui-content .ui-navbar li:last-child .ui-btn,.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn{border-right-width:1px;margin-right:0}.ui-content .ui-navbar li:last-child .ui-btn:after,.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn:after{margin-right:0}.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn{border-right-width:1px;margin-right:-1px}.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn:after{margin-right:1px}.ui-navbar .ui-grid-duo .ui-btn{border-top-width:0}.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,.ui-navbar .ui-grid-duo .ui-block-a:first-child+.ui-block-b .ui-btn{border-top-width:1px}.ui-header .ui-navbar .ui-btn,.ui-footer .ui-navbar .ui-btn{border-top-width:0;border-bottom-width:0}.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child+.ui-block-b .ui-btn,.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child+.ui-block-b .ui-btn{border-top-width:0}.ui-header .ui-title~.ui-navbar .ui-btn,.ui-footer .ui-title~.ui-navbar .ui-btn,.ui-header .ui-navbar .ui-grid-duo .ui-btn,.ui-footer .ui-navbar .ui-grid-duo .ui-btn,.ui-header .ui-title~.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,.ui-footer .ui-title~.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,.ui-header .ui-title~.ui-navbar .ui-grid-duo .ui-block-a:first-child+.ui-block-b .ui-btn,.ui-footer .ui-title~.ui-navbar .ui-grid-duo .ui-block-a:first-child+.ui-block-b .ui-btn{border-top-width:1px}.ui-input-btn input{position:absolute;top:0;left:0;width:100%;height:100%;padding:0;border:0;outline:0;-webkit-border-radius:inherit;border-radius:inherit;-webkit-appearance:none;-moz-appearance:none;cursor:pointer;background:#fff;background:rgba(255,255,255,0);filter:Alpha(Opacity=0);opacity:.1;font-size:1px;text-indent:-9999px;z-index:2}.ui-input-btn.ui-state-disabled input{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-collapsible{margin:0 -1em}.ui-collapsible-inset,.ui-collapsible-set{margin:.5em 0}.ui-collapsible-heading{display:block;margin:0;padding:0;position:relative}.ui-collapsible-heading .ui-btn{text-align:left;margin:0;border-left-width:0;border-right-width:0}.ui-collapsible-heading .ui-btn-icon-top,.ui-collapsible-heading .ui-btn-icon-bottom{text-align:center}.ui-collapsible-inset .ui-collapsible-heading .ui-btn{border-right-width:1px;border-left-width:1px}.ui-collapsible-collapsed+.ui-collapsible:not(.ui-collapsible-inset)>.ui-collapsible-heading .ui-btn{border-top-width:0}.ui-collapsible-set .ui-collapsible:not(.ui-collapsible-inset) .ui-collapsible-heading .ui-btn{border-top-width:1px}.ui-collapsible-heading-status{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-collapsible-content{display:block;margin:0;padding:.5em 1em}.ui-collapsible-themed-content .ui-collapsible-content{border-left-width:0;border-right-width:0;border-top-width:0;border-bottom-width:1px;border-style:solid}.ui-collapsible-inset.ui-collapsible-themed-content .ui-collapsible-content{border-left-width:1px;border-right-width:1px}.ui-collapsible-inset .ui-collapsible-content{margin:0}.ui-collapsible-content-collapsed{display:none}.ui-collapsible-set>.ui-collapsible.ui-corner-all{-webkit-border-radius:0;border-radius:0}.ui-collapsible-heading,.ui-collapsible-heading>.ui-btn{-webkit-border-radius:inherit;border-radius:inherit}.ui-collapsible-set .ui-collapsible.ui-first-child{-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit;-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit}.ui-collapsible-content,.ui-collapsible-set .ui-collapsible.ui-last-child{-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit;-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit}.ui-collapsible-themed-content:not(.ui-collapsible-collapsed)>.ui-collapsible-heading{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0}.ui-collapsible-set .ui-collapsible{margin:-1px -1em 0}.ui-collapsible-set .ui-collapsible-inset{margin:-1px 0 0}.ui-collapsible-set .ui-collapsible.ui-first-child{margin-top:0}.ui-controlgroup,fieldset.ui-controlgroup{padding:0;margin:.5em 0}.ui-field-contain .ui-controlgroup,.ui-field-contain fieldset.ui-controlgroup{margin:0}.ui-mini .ui-controlgroup-label{font-size:16px}.ui-controlgroup.ui-mini .ui-btn-icon-notext,.ui-controlgroup .ui-mini.ui-btn-icon-notext{font-size:inherit}.ui-controlgroup-controls .ui-btn,.ui-controlgroup-controls .ui-checkbox,.ui-controlgroup-controls .ui-radio,.ui-controlgroup-controls .ui-select{margin:0}.ui-controlgroup-controls .ui-btn:focus,.ui-controlgroup-controls .ui-btn.ui-focus{z-index:1}.ui-controlgroup-controls li{list-style:none}.ui-controlgroup-horizontal .ui-controlgroup-controls{display:inline-block;vertical-align:middle}.ui-controlgroup-horizontal .ui-controlgroup-controls:before,.ui-controlgroup-horizontal .ui-controlgroup-controls:after{content:"";display:table}.ui-controlgroup-horizontal .ui-controlgroup-controls:after{clear:both}.ui-controlgroup-horizontal .ui-controlgroup-controls>.ui-btn,.ui-controlgroup-horizontal .ui-controlgroup-controls li>.ui-btn,.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-checkbox,.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-radio,.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-select{float:left;clear:none}.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn,.ui-controlgroup-controls .ui-btn-icon-notext{width:auto}.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn-icon-notext,.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn-icon-notext{width:1.5em}.ui-controlgroup-controls .ui-btn-icon-notext{height:auto;padding:.7em 1em}.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn{border-bottom-width:0}.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn.ui-last-child{border-bottom-width:1px}.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn{border-right-width:0}.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn.ui-last-child{border-right-width:1px}.ui-controlgroup-controls .ui-btn-corner-all,.ui-controlgroup-controls .ui-btn.ui-corner-all{-webkit-border-radius:0;border-radius:0}.ui-controlgroup-controls,.ui-controlgroup-controls .ui-radio,.ui-controlgroup-controls .ui-checkbox,.ui-controlgroup-controls .ui-select,.ui-controlgroup-controls li{-webkit-border-radius:inherit;border-radius:inherit}.ui-controlgroup-vertical .ui-btn.ui-first-child{-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit;-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit}.ui-controlgroup-vertical .ui-btn.ui-last-child{-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit;-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit}.ui-controlgroup-horizontal .ui-btn.ui-first-child{-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit;-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit}.ui-controlgroup-horizontal .ui-btn.ui-last-child{-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit;-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit}.ui-controlgroup-controls a.ui-shadow:not(:focus),.ui-controlgroup-controls button.ui-shadow:not(:focus),.ui-controlgroup-controls div.ui-shadow:not(.ui-focus){-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.ui-controlgroup-label legend{max-width:100%}.ui-controlgroup-controls>label{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-dialog{background:none!important}.ui-dialog-contain{width:92.5%;max-width:500px;margin:10% auto 1em;padding:0;position:relative;top:-1em}.ui-dialog-contain>.ui-header,.ui-dialog-contain>.ui-content,.ui-dialog-contain>.ui-footer{display:block;position:relative;width:auto;margin:0}.ui-dialog-contain>.ui-header{overflow:hidden;z-index:10;padding:0;border-top-width:0}.ui-dialog-contain>.ui-footer{z-index:10;padding:0 1em;border-bottom-width:0}.ui-popup-open .ui-header-fixed,.ui-popup-open .ui-footer-fixed{position:absolute!important}.ui-popup-screen{background-image:url("data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==");top:0;left:0;right:0;bottom:1px;position:absolute;filter:Alpha(Opacity=0);opacity:0;z-index:1099}.ui-popup-screen.in{opacity:.5;filter:Alpha(Opacity=50)}.ui-popup-screen.out{opacity:0;filter:Alpha(Opacity=0)}.ui-popup-container{z-index:1100;display:inline-block;position:absolute;padding:0;outline:0}.ui-popup{position:relative}.ui-popup.ui-body-inherit{border-width:1px;border-style:solid}.ui-popup-hidden{left:0;top:0;position:absolute!important;visibility:hidden}.ui-popup-truncate{height:1px;width:1px;margin:-1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-popup.ui-content,.ui-popup .ui-content{overflow:visible}.ui-popup>.ui-header{border-top-width:0}.ui-popup>.ui-footer{border-bottom-width:0}.ui-popup>p,.ui-popup>h1,.ui-popup>h2,.ui-popup>h3,.ui-popup>h4,.ui-popup>h5,.ui-popup>h6{margin:.5em .4375em}.ui-popup>span{display:block;margin:.5em .4375em}.ui-popup-container .ui-content>p,.ui-popup-container .ui-content>h1,.ui-popup-container .ui-content>h2,.ui-popup-container .ui-content>h3,.ui-popup-container .ui-content>h4,.ui-popup-container .ui-content>h5,.ui-popup-container .ui-content>h6{margin:.5em 0}.ui-popup-container .ui-content>span{margin:0}.ui-popup-container .ui-content>p:first-child,.ui-popup-container .ui-content>h1:first-child,.ui-popup-container .ui-content>h2:first-child,.ui-popup-container .ui-content>h3:first-child,.ui-popup-container .ui-content>h4:first-child,.ui-popup-container .ui-content>h5:first-child,.ui-popup-container .ui-content>h6:first-child{margin-top:0}.ui-popup-container .ui-content>p:last-child,.ui-popup-container .ui-content>h1:last-child,.ui-popup-container .ui-content>h2:last-child,.ui-popup-container .ui-content>h3:last-child,.ui-popup-container .ui-content>h4:last-child,.ui-popup-container .ui-content>h5:last-child,.ui-popup-container .ui-content>h6:last-child{margin-bottom:0}.ui-popup>img{max-width:100%;max-height:100%;vertical-align:middle}.ui-popup:not(.ui-content)>img:only-child,.ui-popup:not(.ui-content)>.ui-btn-left:first-child+img:last-child,.ui-popup:not(.ui-content)>.ui-btn-right:first-child+img:last-child{-webkit-border-radius:inherit;border-radius:inherit}.ui-popup iframe{vertical-align:middle}.ui-popup>.ui-btn-left,.ui-popup>.ui-btn-right{position:absolute;top:-11px;margin:0;z-index:1101}.ui-popup>.ui-btn-left{left:-11px}.ui-popup>.ui-btn-right{right:-11px}.ui-popup-arrow-container{width:20px;height:20px}.ui-popup-arrow-container.ui-popup-arrow-l{left:-10px;clip:rect(-1000px,10px,2000px,-1000px)}.ui-popup-arrow-container.ui-popup-arrow-t{top:-10px;clip:rect(-1000px,2000px,10px,-1000px)}.ui-popup-arrow-container.ui-popup-arrow-r{right:-10px;clip:rect(-1000px,2000px,2000px,10px)}.ui-popup-arrow-container.ui-popup-arrow-b{bottom:-10px;clip:rect(10px,2000px,1000px,-1000px)}.ui-popup-arrow-container .ui-popup-arrow{width:28.284271247px;height:28.284271247px;border-width:1px;border-style:solid}.ui-popup-arrow-container.ui-popup-arrow-t .ui-popup-arrow{left:-4.142135623px;top:5.857864376px}.ui-popup-arrow-container.ui-popup-arrow-b .ui-popup-arrow{left:-4.142135623px;top:-14.142135623px}.ui-popup-arrow-container.ui-popup-arrow-l .ui-popup-arrow{left:5.857864376px;top:-4.142135623px}.ui-popup-arrow-container.ui-popup-arrow-r .ui-popup-arrow{left:-14.142135623px;top:-4.142135623px}.ui-popup-arrow-container.ui-popup-arrow-t.ie .ui-popup-arrow{margin-left:-5.857864376269049px;margin-top:-7.0710678118654755px}.ui-popup-arrow-container.ui-popup-arrow-b.ie .ui-popup-arrow{margin-left:-5.857864376269049px;margin-top:-4.142135623730951px}.ui-popup-arrow-container.ui-popup-arrow-l.ie .ui-popup-arrow{margin-left:-7.0710678118654755px;margin-top:-5.857864376269049px}.ui-popup-arrow-container.ui-popup-arrow-r.ie .ui-popup-arrow{margin-left:-4.142135623730951px;margin-top:-5.857864376269049px}.ui-popup>.ui-popup-arrow-guide{position:absolute;left:0;right:0;top:0;bottom:0;visibility:hidden}.ui-popup-arrow-container{position:absolute}.ui-popup-arrow{-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);position:absolute;overflow:hidden;box-sizing:border-box}.ui-popup-arrow-container.ie .ui-popup-arrow{-ms-filter:"progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067811865474, M12=-0.7071067811865477, M21=0.7071067811865477, M22=0.7071067811865474, SizingMethod='auto expand')";filter:progid:DXImageTransform.Microsoft.Matrix(M11=.7071067811865474, M12=-.7071067811865477, M21=.7071067811865477, M22=.7071067811865474, SizingMethod='auto expand')}.ui-checkbox,.ui-radio{margin:.5em 0;position:relative}.ui-checkbox .ui-btn,.ui-radio .ui-btn{margin:0;text-align:left;white-space:normal;z-index:2}.ui-controlgroup .ui-checkbox .ui-btn.ui-focus,.ui-controlgroup .ui-radio .ui-btn.ui-focus{z-index:3}.ui-checkbox .ui-btn-icon-top,.ui-radio .ui-btn-icon-top,.ui-checkbox .ui-btn-icon-bottom,.ui-radio .ui-btn-icon-bottom{text-align:center}.ui-controlgroup-horizontal .ui-checkbox .ui-btn:after,.ui-controlgroup-horizontal .ui-radio .ui-btn:after{content:none;display:none}.ui-checkbox input,.ui-radio input{position:absolute;left:.466em;top:50%;width:22px;height:22px;margin:-11px 0 0 0;outline:0!important;z-index:1}.ui-controlgroup-horizontal .ui-checkbox input,.ui-controlgroup-horizontal .ui-radio input{left:50%;margin-left:-9px}.ui-checkbox input:disabled,.ui-radio input:disabled{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-select{margin-top:.5em;margin-bottom:.5em;position:relative}.ui-select>select{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-select .ui-btn{margin:0;opacity:1}.ui-select .ui-btn select{position:absolute;top:0;left:0;width:100%;min-height:1.5em;min-height:100%;height:3em;max-height:100%;outline:0;-webkit-border-radius:inherit;border-radius:inherit;-webkit-appearance:none;-moz-appearance:none;cursor:pointer;filter:Alpha(Opacity=0);opacity:0;z-index:2}@-moz-document url-prefix(){.ui-select .ui-btn select{opacity:.0001}}.ui-select .ui-state-disabled select{display:none}.ui-select span.ui-state-disabled{filter:Alpha(Opacity=100);opacity:1}.ui-select .ui-btn.ui-select-nativeonly{border-radius:0;border:0}.ui-select .ui-btn.ui-select-nativeonly select{opacity:1;text-indent:0;display:block}.ui-select .ui-li-has-count.ui-btn{padding-right:2.8125em}.ui-select .ui-li-has-count.ui-btn-icon-right{padding-right:4.6875em}.ui-select .ui-btn-icon-right .ui-li-count{right:3.2em}.ui-select .ui-btn>span:not(.ui-li-count){display:block;text-overflow:ellipsis;overflow:hidden!important;white-space:nowrap}.ui-selectmenu.ui-popup{min-width:11em}.ui-selectmenu .ui-dialog-contain{overflow:hidden}.ui-selectmenu .ui-header{margin:0;padding:0;border-width:0}.ui-selectmenu.ui-dialog .ui-header{z-index:1;position:relative}.ui-selectmenu.ui-popup .ui-header{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0}.ui-selectmenu.ui-popup .ui-header h1:after{content:'.';visibility:hidden}.ui-selectmenu .ui-header .ui-title{margin:0 2.875em}.ui-selectmenu.ui-dialog .ui-content{overflow:visible;z-index:1}.ui-selectmenu .ui-selectmenu-list{margin:0;-webkit-border-radius:inherit;border-radius:inherit}.ui-header:not(.ui-screen-hidden)+.ui-selectmenu-list{-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-top-left-radius:0;border-top-left-radius:0}.ui-header.ui-screen-hidden+.ui-selectmenu-list li.ui-first-child .ui-btn{border-top-width:0}.ui-selectmenu .ui-selectmenu-list li.ui-last-child .ui-btn{border-bottom-width:0}.ui-selectmenu .ui-btn.ui-li-divider{cursor:default}.ui-selectmenu .ui-selectmenu-placeholder{display:none}.ui-listview,.ui-listview>li{margin:0;padding:0;list-style:none}.ui-content .ui-listview,.ui-panel-inner>.ui-listview{margin:-1em}.ui-content .ui-listview-inset,.ui-panel-inner>.ui-listview-inset{margin:1em 0}.ui-collapsible-content>.ui-listview{margin:-.5em -1em}.ui-collapsible-content>.ui-listview-inset{margin:.5em 0}.ui-listview>li{display:block;position:relative;overflow:visible}.ui-listview>.ui-li-static,.ui-listview>.ui-li-divider,.ui-listview>li>a.ui-btn{margin:0;display:block;position:relative;text-align:left;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-listview>li>.ui-btn:focus{z-index:1}.ui-listview>.ui-li-static,.ui-listview>.ui-li-divider,.ui-listview>li>a.ui-btn{border-width:1px 0 0;border-style:solid}.ui-listview-inset>.ui-li-static,.ui-listview-inset>.ui-li-divider,.ui-listview-inset>li>a.ui-btn{border-right-width:1px;border-left-width:1px}.ui-listview>.ui-li-static.ui-last-child,.ui-listview>.ui-li-divider.ui-last-child,.ui-listview>li.ui-last-child>a.ui-btn{border-bottom-width:1px}.ui-collapsible-content>.ui-listview:not(.ui-listview-inset)>li.ui-first-child,.ui-collapsible-content>.ui-listview:not(.ui-listview-inset)>li.ui-first-child>a.ui-btn{border-top-width:0}.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset)>li.ui-last-child,.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset)>li.ui-last-child>a.ui-btn{border-bottom-width:0}.ui-listview>li.ui-first-child,.ui-listview>li.ui-first-child>a.ui-btn{-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit;-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit}.ui-listview>li.ui-last-child,.ui-listview>li.ui-last-child>a.ui-btn{-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit;-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit}.ui-listview>li.ui-li-has-alt>a.ui-btn{-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.ui-listview>li.ui-first-child>a.ui-btn+a.ui-btn{-webkit-border-top-left-radius:0;border-top-left-radius:0;-webkit-border-top-right-radius:inherit;border-top-right-radius:inherit}.ui-listview>li.ui-last-child>a.ui-btn+a.ui-btn{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-bottom-right-radius:inherit;border-bottom-right-radius:inherit}.ui-listview>li.ui-first-child img:first-child:not(.ui-li-icon){-webkit-border-top-left-radius:inherit;border-top-left-radius:inherit}.ui-listview>li.ui-last-child img:first-child:not(.ui-li-icon){-webkit-border-bottom-left-radius:inherit;border-bottom-left-radius:inherit}.ui-collapsible-content>.ui-listview:not(.ui-listview-inset){-webkit-border-radius:inherit;border-radius:inherit}.ui-listview>.ui-li-static{padding:.7em 1em}.ui-listview>.ui-li-divider{padding:.5em 1.143em;font-size:14px;font-weight:700;cursor:default;outline:0}.ui-listview>.ui-li-has-count>.ui-btn,.ui-listview>.ui-li-static.ui-li-has-count,.ui-listview>.ui-li-divider.ui-li-has-count{padding-right:2.8125em}.ui-listview>.ui-li-has-count>.ui-btn-icon-right{padding-right:4.6875em}.ui-listview>.ui-li-has-thumb>.ui-btn,.ui-listview>.ui-li-static.ui-li-has-thumb{min-height:3.625em;padding-left:6.25em}.ui-listview>.ui-li-has-icon>.ui-btn,.ui-listview>.ui-li-static.ui-li-has-icon{min-height:1.25em;padding-left:2.5em}.ui-li-count{position:absolute;font-size:12.5px;font-weight:700;text-align:center;border-width:1px;border-style:solid;padding:0 .48em;line-height:1.6em;min-height:1.6em;min-width:.64em;right:.8em;top:50%;margin-top:-.88em}.ui-listview .ui-btn-icon-right .ui-li-count{right:3.2em}.ui-listview .ui-li-has-thumb>img:first-child,.ui-listview .ui-li-has-thumb>.ui-btn>img:first-child,.ui-listview .ui-li-has-thumb .ui-li-thumb{position:absolute;left:0;top:0;max-height:5em;max-width:5em}.ui-listview>.ui-li-has-icon>img:first-child,.ui-listview>.ui-li-has-icon>.ui-btn>img:first-child{position:absolute;left:.625em;top:.9em;max-height:1em;max-width:1em}.ui-listview>li h1,.ui-listview>li h2,.ui-listview>li h3,.ui-listview>li h4,.ui-listview>li h5,.ui-listview>li h6{font-size:1em;font-weight:700;display:block;margin:.45em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-listview>li p{font-size:.75em;font-weight:400;display:block;margin:.6em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-listview .ui-li-aside{position:absolute;top:1em;right:3.333em;margin:0;text-align:right}.ui-listview>li.ui-li-has-alt>.ui-btn{margin-right:2.5em;border-right-width:0}.ui-listview>li.ui-li-has-alt>.ui-btn+.ui-btn{position:absolute;width:2.5em;height:100%;min-height:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-left-width:1px;top:0;right:0;margin:0;padding:0;z-index:2}.ui-listview-inset>li.ui-li-has-alt>.ui-btn+.ui-btn{border-right-width:1px}.ui-listview>li.ui-li-has-alt>.ui-btn+.ui-btn:focus{z-index:3}ol.ui-listview,ol.ui-listview>.ui-li-divider{counter-reset:listnumbering}ol.ui-listview>li>.ui-btn,ol.ui-listview>li.ui-li-static{vertical-align:middle}ol.ui-listview>li>.ui-btn:first-child:before,ol.ui-listview>li.ui-li-static:before,ol.ui-listview>li.ui-field-contain>label:before,ol.ui-listview>li.ui-field-contain>.ui-controlgroup-label:before{display:inline-block;font-size:.9em;font-weight:400;padding-right:.3em;min-width:1.4em;line-height:1.5;vertical-align:middle;counter-increment:listnumbering;content:counter(listnumbering) "."}ol.ui-listview>li.ui-field-contain:before{content:none;display:none}ol.ui-listview>li h1:first-child,ol.ui-listview>li h2:first-child,ol.ui-listview>li h3:first-child,ol.ui-listview>li h4:first-child,ol.ui-listview>li h5:first-child,ol.ui-listview>li h6:first-child,ol.ui-listview>li p:first-child,ol.ui-listview>li img:first-child+*{display:inline-block;vertical-align:middle}ol.ui-listview>li h1:first-child~*,ol.ui-listview>li h2:first-child~*,ol.ui-listview>li h3:first-child~*,ol.ui-listview>li h4:first-child~*,ol.ui-listview>li h5:first-child~*,ol.ui-listview>li h6:first-child~*,ol.ui-listview>li p:first-child~*,ol.ui-listview>li img:first-child+*~*{margin-top:0;text-indent:2.04em}html .ui-filterable+.ui-listview,html .ui-filterable.ui-listview{margin-top:.5em}.ui-collapsible-content>form.ui-filterable{margin-top:-.5em}.ui-collapsible-content>.ui-input-search.ui-filterable{margin-top:0}.ui-collapsible-content>.ui-filterable+.ui-listview:not(.ui-listview-inset)>li.ui-first-child,.ui-collapsible-content>.ui-filterable+.ui-listview:not(.ui-listview-inset)>li.ui-first-child>a.ui-btn,.ui-collapsible-content>.ui-filterable.ui-listview:not(.ui-listview-inset)>li.ui-first-child,.ui-collapsible-content>.ui-filterable.ui-listview:not(.ui-listview-inset)>li.ui-first-child>a.ui-btn{border-top-width:1px}div.ui-slider{height:30px;margin:.5em 0;padding:0;-ms-touch-action:pan-y pinch-zoom double-tap-zoom}div.ui-slider:before,div.ui-slider:after{content:"";display:table}div.ui-slider:after{clear:both}input.ui-slider-input{display:block;float:left;font-size:14px;font-weight:700;margin:0;padding:4px;width:40px;height:20px;line-height:20px;border-width:1px;border-style:solid;outline:0;text-align:center;vertical-align:text-bottom;-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.ui-slider-input::-webkit-outer-spin-button,.ui-slider-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.ui-slider-track{position:relative;overflow:visible;border-width:1px;border-style:solid;height:15px;margin:0 15px 0 68px;top:6px}.ui-slider-track.ui-mini{height:12px;top:8px}.ui-slider-track .ui-slider-bg{height:100%}.ui-slider-track .ui-btn.ui-slider-handle{position:absolute;z-index:1;top:50%;width:28px;height:28px;margin:-15px 0 0 -15px;outline:0;padding:0}.ui-slider-track.ui-mini .ui-slider-handle{height:14px;width:14px;margin:-8px 0 0 -8px}select.ui-slider-switch{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}div.ui-slider-switch{display:inline-block;height:32px;width:5.8em;top:0}div.ui-slider-switch:before,div.ui-slider-switch:after{display:none;clear:none}div.ui-slider-switch.ui-mini{height:29px;top:0}.ui-slider-inneroffset{margin:0 16px;position:relative;z-index:1}.ui-slider-switch.ui-mini .ui-slider-inneroffset{margin:0 15px 0 14px}.ui-slider-switch .ui-btn.ui-slider-handle{margin:1px 0 0 -15px}.ui-slider-switch.ui-mini .ui-slider-handle{width:25px;height:25px;margin:1px 0 0 -13px;padding:0}.ui-slider-handle-snapping{-webkit-transition:left 70ms linear;-moz-transition:left 70ms linear;transition:left 70ms linear}.ui-slider-switch .ui-slider-label{position:absolute;text-align:center;width:100%;overflow:hidden;font-size:16px;top:0;line-height:2;min-height:100%;white-space:nowrap;cursor:pointer}.ui-slider-switch.ui-mini .ui-slider-label{font-size:14px}.ui-slider-switch .ui-slider-label-a{z-index:1;left:0;text-indent:-1.5em}.ui-slider-switch .ui-slider-label-b{z-index:0;right:0;text-indent:1.5em}.ui-slider-track .ui-slider-bg,.ui-slider-switch .ui-slider-label,.ui-slider-switch .ui-slider-inneroffset,.ui-slider-handle{-webkit-border-radius:inherit;border-radius:inherit}.ui-field-contain div.ui-slider-switch{margin:0}.ui-field-contain div.ui-slider-switch,.ui-field-contain.ui-hide-label div.ui-slider-switch,html .ui-popup .ui-field-contain div.ui-slider-switch{display:inline-block;width:5.8em}.ui-slider-popup{width:64px;height:64px;font-size:36px;padding-top:14px;opacity:.8}.ui-slider-popup{position:absolute!important;text-align:center;z-index:100}.ui-slider-track .ui-btn.ui-slider-handle{font-size:.9em;line-height:30px}.ui-rangeslider{margin:.5em 0}.ui-rangeslider:before,.ui-rangeslider:after{content:"";display:table}.ui-rangeslider:after{clear:both}.ui-rangeslider .ui-slider-input.ui-rangeslider-last{float:right}.ui-rangeslider .ui-rangeslider-sliders{position:relative;overflow:visible;height:30px;margin:0 68px}.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track{position:absolute;top:6px;right:0;left:0;margin:0}.ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track{top:8px}.ui-rangeslider .ui-slider-track:first-child .ui-slider-bg{display:none}.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child{background-color:transparent;background:0;border-width:0;height:0}html >body .ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child{height:15px;border-width:1px}html >body .ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track:first-child{height:12px}div.ui-rangeslider label{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.ui-field-contain .ui-rangeslider input.ui-slider-input,.ui-field-contain .ui-rangeslider.ui-mini input.ui-slider-input,.ui-field-contain .ui-rangeslider .ui-rangeslider-sliders,.ui-field-contain .ui-rangeslider.ui-mini .ui-rangeslider-sliders{margin-top:0;margin-bottom:0}.ui-input-text,.ui-input-search{margin:.5em 0;border-width:1px;border-style:solid}.ui-mini{margin:.446em}.ui-input-text input,.ui-input-search input,textarea.ui-input-text{padding:.4em;line-height:1.4em;display:block;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;outline:0}.ui-input-text input,.ui-input-search input{margin:0;min-height:2.2em;text-align:left;border:0;background:transparent none;-webkit-appearance:none;-webkit-border-radius:inherit;border-radius:inherit}textarea.ui-input-text{overflow:auto;resize:vertical}.ui-mini .ui-input-text input,.ui-mini .ui-input-search input,.ui-input-text.ui-mini input,.ui-input-search.ui-mini input,.ui-mini textarea.ui-input-text,textarea.ui-mini{font-size:14px}.ui-mini textarea.ui-input-text,textarea.ui-mini{margin:.446em 0}.ui-input-has-clear,.ui-input-search{position:relative}.ui-input-has-clear{padding-right:2.375em}.ui-mini.ui-input-has-clear{padding-right:2.923em}.ui-input-has-clear input{padding-right:0;-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.ui-input-search input{padding-left:1.75em}.ui-input-search:after{position:absolute;left:.3125em;top:50%;margin-top:-7px;content:"";background-position:center center;background-repeat:no-repeat;width:14px;height:14px;filter:Alpha(Opacity=50);opacity:.5}.ui-input-search.ui-input-has-clear .ui-btn.ui-input-clear,.ui-input-text.ui-input-has-clear .ui-btn.ui-input-clear{position:absolute;right:0;top:50%;margin:-14px .3125em 0;border:0;background-color:transparent}.ui-input-search .ui-input-clear-hidden,.ui-input-text .ui-input-clear-hidden{display:none}.ui-input-text input::-moz-placeholder,.ui-input-search input::-moz-placeholder,textarea.ui-input-text::-moz-placeholder{color:#aaa}.ui-input-text input:-ms-input-placeholder,.ui-input-search input:-ms-input-placeholder,textarea.ui-input-text:-ms-input-placeholder{color:#aaa}.ui-input-text input[type=number]::-webkit-outer-spin-button{margin:0}.ui-input-text input::-ms-clear,.ui-input-search input::-ms-clear{display:none}.ui-input-text input:focus,.ui-input-search input:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}textarea.ui-input-text.ui-textinput-autogrow{overflow:hidden}.ui-textinput-autogrow-resize{-webkit-transition:height .25s;-o-transition:height .25s;-moz-transition:height .25s;transition:height .25s}.ui-flipswitch{display:inline-block;vertical-align:middle;width:5.875em;height:1.875em;border-width:1px;border-style:solid;margin:.5em 0;overflow:hidden;-webkit-transition-property:padding,width,background-color,color,border-color;-moz-transition-property:padding,width,background-color,color,border-color;-o-transition-property:padding,width,background-color,color,border-color;transition-property:padding,width,background-color,color,border-color;-webkit-transition-duration:100ms;-moz-transition-duration:100ms;-o-transition-duration:100ms;transition-duration:100ms;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}.ui-flipswitch.ui-flipswitch-active{padding-left:4em;width:1.875em}.ui-flipswitch-input{position:absolute;height:1px;width:1px;margin:-1px;overflow:hidden;clip:rect(1px,1px,1px,1px);border:0;outline:0;filter:Alpha(Opacity=0);opacity:0}.ui-flipswitch .ui-btn.ui-flipswitch-on,.ui-flipswitch .ui-flipswitch-off{float:left;height:1.75em;margin:.0625em;line-height:1.65em}.ui-flipswitch .ui-btn.ui-flipswitch-on{width:1.75em;padding:0;text-indent:-2.6em;text-align:left;border-width:1px;border-style:solid;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:inherit;overflow:visible;color:inherit;text-shadow:inherit}.ui-flipswitch .ui-flipswitch-off{padding:1px;text-indent:1em}html .ui-field-contain>label+.ui-flipswitch,html .ui-popup .ui-field-contain>label+.ui-flipswitch{display:inline-block;width:5.875em;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.ui-field-contain .ui-flipswitch.ui-flipswitch-active,.ui-popup .ui-field-contain .ui-flipswitch.ui-flipswitch-active{width:1.875em}.ui-table{border:0;border-collapse:collapse;padding:0;width:100%}.ui-table th,.ui-table td{line-height:1.5em;text-align:left;padding:.4em .5em;vertical-align:top}.ui-table th .ui-btn,.ui-table td .ui-btn{line-height:normal}.ui-table th{font-weight:700}.ui-table caption{text-align:left;margin-bottom:1.4em;opacity:.5}.ui-table-columntoggle-btn{float:right;margin-bottom:.8em}.ui-table-columntoggle-popup fieldset{margin:0}.ui-table-columntoggle{clear:both}@media only all{th.ui-table-priority-6,td.ui-table-priority-6,th.ui-table-priority-5,td.ui-table-priority-5,th.ui-table-priority-4,td.ui-table-priority-4,th.ui-table-priority-3,td.ui-table-priority-3,th.ui-table-priority-2,td.ui-table-priority-2,th.ui-table-priority-1,td.ui-table-priority-1{display:none}}@media screen and (min-width:20em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-1,.ui-table-columntoggle.ui-responsive td.ui-table-priority-1{display:table-cell}}@media screen and (min-width:30em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-2,.ui-table-columntoggle.ui-responsive td.ui-table-priority-2{display:table-cell}}@media screen and (min-width:40em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-3,.ui-table-columntoggle.ui-responsive td.ui-table-priority-3{display:table-cell}}@media screen and (min-width:50em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-4,.ui-table-columntoggle.ui-responsive td.ui-table-priority-4{display:table-cell}}@media screen and (min-width:60em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-5,.ui-table-columntoggle.ui-responsive td.ui-table-priority-5{display:table-cell}}@media screen and (min-width:70em){.ui-table-columntoggle.ui-responsive th.ui-table-priority-6,.ui-table-columntoggle.ui-responsive td.ui-table-priority-6{display:table-cell}}.ui-table-columntoggle th.ui-table-cell-hidden,.ui-table-columntoggle td.ui-table-cell-hidden,.ui-table-columntoggle.ui-responsive th.ui-table-cell-hidden,.ui-table-columntoggle.ui-responsive td.ui-table-cell-hidden{display:none}.ui-table-columntoggle th.ui-table-cell-visible,.ui-table-columntoggle td.ui-table-cell-visible,.ui-table-columntoggle.ui-responsive th.ui-table-cell-visible,.ui-table-columntoggle.ui-responsive td.ui-table-cell-visible{display:table-cell}.ui-table-reflow td .ui-table-cell-label,.ui-table-reflow th .ui-table-cell-label{display:none}@media only all{.ui-table-reflow thead td,.ui-table-reflow thead th{display:none}.ui-table-reflow td,.ui-table-reflow th{text-align:left;display:block}.ui-table-reflow tbody th{margin-top:3em}.ui-table-reflow td .ui-table-cell-label,.ui-table-reflow th .ui-table-cell-label{padding:.4em;min-width:30%;display:inline-block;margin:-.4em 1em -.4em -.4em}.ui-table-reflow th .ui-table-cell-label-top,.ui-table-reflow td .ui-table-cell-label-top{display:block;padding:.4em 0;margin:.4em 0;text-transform:uppercase;font-size:.9em;font-weight:400}}@media (min-width:35em){.ui-table-reflow.ui-responsive td,.ui-table-reflow.ui-responsive th,.ui-table-reflow.ui-responsive tbody th,.ui-table-reflow.ui-responsive tbody td,.ui-table-reflow.ui-responsive thead td,.ui-table-reflow.ui-responsive thead th{display:table-cell;margin:0}.ui-table-reflow.ui-responsive td .ui-table-cell-label,.ui-table-reflow.ui-responsive th .ui-table-cell-label{display:none}}@media (max-width:35em){.ui-table-reflow.ui-responsive td,.ui-table-reflow.ui-responsive th{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;clear:left}}.ui-panel{width:17em;min-height:100%;max-height:none;border-width:0;position:absolute;top:0;display:block}.ui-panel-closed{width:0;max-height:100%;overflow:hidden;visibility:hidden;left:0;clip:rect(1px,1px,1px,1px)}.ui-panel-fixed{position:fixed;bottom:-1px;padding-bottom:1px}.ui-panel-display-reveal{z-index:1}.ui-panel-display-push{z-index:999}.ui-panel-display-overlay{z-index:1001}.ui-panel-inner{padding:1em}.ui-panel-page-container{overflow-x:visible}.ui-panel-page-container-themed .ui-page-active{background:0}.ui-panel-wrapper{position:relative;min-height:inherit;border:0;overflow-x:hidden;z-index:999}.ui-panel-fixed-toolbar{overflow-x:hidden}.ui-panel-dismiss{position:absolute;top:0;left:0;right:0;height:100%;z-index:1002;display:none}.ui-panel-dismiss-open{display:block}.ui-panel-animate{-webkit-transition:-webkit-transform 300ms ease;-webkit-transition-duration:300ms;-moz-transition:-moz-transform 300ms ease;transition:transform 300ms ease}@media screen and (max-device-width:768px){.ui-page-header-fixed .ui-panel-animate.ui-panel-wrapper,.ui-page-footer-fixed .ui-panel-animate.ui-panel-wrapper,.ui-panel-animate.ui-panel-fixed-toolbar{-ms-transition:none}.ui-panel-animate.ui-panel-fixed-toolbar{-ms-transition:-ms-transform 1ms;-ms-transform:rotate(0deg)}}.ui-panel-animate.ui-panel:not(.ui-panel-display-reveal){-webkit-backface-visibility:hidden;-webkit-transform:translate3d(0,0,0)}.ui-panel-position-left{left:-17em}.ui-panel-animate.ui-panel-position-left.ui-panel-display-overlay,.ui-panel-animate.ui-panel-position-left.ui-panel-display-push{left:0;-webkit-transform:translate3d(-17em,0,0);-moz-transform:translate3d(-17em,0,0);transform:translate3d(-17em,0,0)}.ui-panel-position-left.ui-panel-display-reveal,.ui-panel-open.ui-panel-position-left{left:0}.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-overlay,.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-push{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-moz-transform:none}.ui-panel-position-right{right:-17em}.ui-panel-animate.ui-panel-position-right.ui-panel-display-overlay,.ui-panel-animate.ui-panel-position-right.ui-panel-display-push{right:0;-webkit-transform:translate3d(17em,0,0);-moz-transform:translate3d(17em,0,0);transform:translate3d(17em,0,0)}.ui-panel-position-right.ui-panel-display-reveal,.ui-panel-position-right.ui-panel-open{right:0}.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-overlay,.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-push{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-moz-transform:none}.ui-panel-page-content-position-left{left:17em;right:-17em}.ui-panel-animate.ui-panel-page-content-position-left{left:0;right:0;-webkit-transform:translate3d(17em,0,0);-moz-transform:translate3d(17em,0,0);transform:translate3d(17em,0,0)}.ui-panel-page-content-position-right{left:-17em;right:17em}.ui-panel-animate.ui-panel-page-content-position-right{left:0;right:0;-webkit-transform:translate3d(-17em,0,0);-moz-transform:translate3d(-17em,0,0);transform:translate3d(-17em,0,0)}.ui-panel-dismiss-open.ui-panel-dismiss-position-left{left:17em}.ui-panel-dismiss-open.ui-panel-dismiss-position-right{right:17em}.ui-panel-display-reveal{-webkit-box-shadow:inset -5px 0 5px rgba(0,0,0,.15);-moz-box-shadow:inset -5px 0 5px rgba(0,0,0,.15);box-shadow:inset -5px 0 5px rgba(0,0,0,.15)}.ui-panel-position-right.ui-panel-display-reveal{-webkit-box-shadow:inset 5px 0 5px rgba(0,0,0,.15);-moz-box-shadow:inset 5px 0 5px rgba(0,0,0,.15);box-shadow:inset 5px 0 5px rgba(0,0,0,.15)}.ui-panel-display-overlay{-webkit-box-shadow:5px 0 5px rgba(0,0,0,.15);-moz-box-shadow:5px 0 5px rgba(0,0,0,.15);box-shadow:5px 0 5px rgba(0,0,0,.15)}.ui-panel-position-right.ui-panel-display-overlay{-webkit-box-shadow:-5px 0 5px rgba(0,0,0,.15);-moz-box-shadow:-5px 0 5px rgba(0,0,0,.15);box-shadow:-5px 0 5px rgba(0,0,0,.15)}.ui-panel-open.ui-panel-position-left.ui-panel-display-push{border-right-width:1px;margin-right:-1px}.ui-panel-page-content-position-left.ui-panel-page-content-display-push{margin-left:1px;width:auto}.ui-panel-open.ui-panel-position-right.ui-panel-display-push{border-left-width:1px;margin-left:-1px}.ui-panel-page-content-position-right.ui-panel-page-content-display-push{margin-right:1px;width:auto}@media (min-width:55em){.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-left{margin-right:17em}.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-right{margin-left:17em}.ui-responsive-panel .ui-panel-page-content-open{width:auto}.ui-responsive-panel .ui-panel-dismiss-display-push,.ui-responsive-panel.ui-page-active~.ui-panel-dismiss-display-push{display:none}}.ui-tabs{position:relative;padding:.2em} \ No newline at end of file diff --git a/static/fonts/.DS_Store b/static/fonts/.DS_Store deleted file mode 100644 index 5008ddfc..00000000 Binary files a/static/fonts/.DS_Store and /dev/null differ diff --git a/static/fonts/glyphicons-halflings-regular.eot b/static/fonts/glyphicons-halflings-regular.eot deleted file mode 100755 index 423bd5d3..00000000 Binary files a/static/fonts/glyphicons-halflings-regular.eot and /dev/null differ diff --git a/static/fonts/glyphicons-halflings-regular.svg b/static/fonts/glyphicons-halflings-regular.svg deleted file mode 100755 index 44694887..00000000 --- a/static/fonts/glyphicons-halflings-regular.svg +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/fonts/glyphicons-halflings-regular.ttf b/static/fonts/glyphicons-halflings-regular.ttf deleted file mode 100755 index a498ef4e..00000000 Binary files a/static/fonts/glyphicons-halflings-regular.ttf and /dev/null differ diff --git a/static/fonts/glyphicons-halflings-regular.woff b/static/fonts/glyphicons-halflings-regular.woff deleted file mode 100755 index d83c539b..00000000 Binary files a/static/fonts/glyphicons-halflings-regular.woff and /dev/null differ diff --git a/static/images/blocks/eye.png b/static/images/blocks/eye.png deleted file mode 100644 index 1b33c3c8..00000000 Binary files a/static/images/blocks/eye.png and /dev/null differ diff --git a/static/images/blocks/loop_repeat.png b/static/images/blocks/loop_repeat.png deleted file mode 100644 index b1d0fd1d..00000000 Binary files a/static/images/blocks/loop_repeat.png and /dev/null differ diff --git a/static/images/blocks/move_backward.png b/static/images/blocks/move_backward.png deleted file mode 100644 index e1f85d4c..00000000 Binary files a/static/images/blocks/move_backward.png and /dev/null differ diff --git a/static/images/blocks/move_forward.png b/static/images/blocks/move_forward.png deleted file mode 100644 index 035f8356..00000000 Binary files a/static/images/blocks/move_forward.png and /dev/null differ diff --git a/static/images/blocks/move_left.png b/static/images/blocks/move_left.png deleted file mode 100644 index 40e2c867..00000000 Binary files a/static/images/blocks/move_left.png and /dev/null differ diff --git a/static/images/blocks/move_right.png b/static/images/blocks/move_right.png deleted file mode 100644 index 7b7ddad0..00000000 Binary files a/static/images/blocks/move_right.png and /dev/null differ diff --git a/static/images/blocks/photo_take.png b/static/images/blocks/photo_take.png deleted file mode 100644 index 1ac8172d..00000000 Binary files a/static/images/blocks/photo_take.png and /dev/null differ diff --git a/static/images/blocks/say.png b/static/images/blocks/say.png deleted file mode 100644 index 15dacfdd..00000000 Binary files a/static/images/blocks/say.png and /dev/null differ diff --git a/static/images/blocks/video_rec.png b/static/images/blocks/video_rec.png deleted file mode 100644 index 167e2ba5..00000000 Binary files a/static/images/blocks/video_rec.png and /dev/null differ diff --git a/static/images/blocks/video_stop.png b/static/images/blocks/video_stop.png deleted file mode 100644 index 7c8e0053..00000000 Binary files a/static/images/blocks/video_stop.png and /dev/null differ diff --git a/static/images/coderbot_hud_2.png b/static/images/coderbot_hud_2.png deleted file mode 100644 index 55e9e4db..00000000 Binary files a/static/images/coderbot_hud_2.png and /dev/null differ diff --git a/static/images/icons/coderbot_logo_79.png b/static/images/icons/coderbot_logo_79.png deleted file mode 100644 index f4f54b92..00000000 Binary files a/static/images/icons/coderbot_logo_79.png and /dev/null differ diff --git a/static/images/icons/favicon.ico b/static/images/icons/favicon.ico deleted file mode 100644 index 1fc42f97..00000000 Binary files a/static/images/icons/favicon.ico and /dev/null differ diff --git a/static/js/.DS_Store b/static/js/.DS_Store deleted file mode 100644 index 5008ddfc..00000000 Binary files a/static/js/.DS_Store and /dev/null differ diff --git a/static/js/.control.js.swo b/static/js/.control.js.swo deleted file mode 100644 index b9776a4c..00000000 Binary files a/static/js/.control.js.swo and /dev/null differ diff --git a/static/js/blockly/blockly_compressed.js b/static/js/blockly/blockly_compressed.js deleted file mode 100644 index dfa77e1b..00000000 --- a/static/js/blockly/blockly_compressed.js +++ /dev/null @@ -1,1364 +0,0 @@ -// Do not edit this file; automatically generated by build.py. -"use strict"; - -var COMPILED=!0,goog=goog||{};goog.global=this;goog.isDef=function(a){return void 0!==a};goog.exportPath_=function(a,b,c){a=a.split(".");c=c||goog.global;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&goog.isDef(b)?c[d]=b:c=c[d]?c[d]:c[d]={}}; -goog.define=function(a,b){var c=b;COMPILED||(goog.global.CLOSURE_UNCOMPILED_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_UNCOMPILED_DEFINES,a)?c=goog.global.CLOSURE_UNCOMPILED_DEFINES[a]:goog.global.CLOSURE_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES,a)&&(c=goog.global.CLOSURE_DEFINES[a]));goog.exportPath_(a,c)};goog.DEBUG=!0;goog.LOCALE="en";goog.TRUSTED_SITE=!0;goog.STRICT_MODE_COMPATIBLE=!1;goog.DISALLOW_TEST_ONLY_CODE=COMPILED&&!goog.DEBUG; -goog.provide=function(a){if(!COMPILED&&goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');goog.constructNamespace_(a)};goog.constructNamespace_=function(a,b){if(!COMPILED){delete goog.implicitNamespaces_[a];for(var c=a;(c=c.substring(0,c.lastIndexOf(".")))&&!goog.getObjectByName(c);)goog.implicitNamespaces_[c]=!0}goog.exportPath_(a,b)};goog.VALID_MODULE_RE_=/^[a-zA-Z_$][a-zA-Z0-9._$]*$/; -goog.module=function(a){if(!goog.isString(a)||!a||-1==a.search(goog.VALID_MODULE_RE_))throw Error("Invalid module identifier");if(!goog.isInModuleLoader_())throw Error("Module "+a+" has been loaded incorrectly.");if(goog.moduleLoaderState_.moduleName)throw Error("goog.module may only be called once per module.");goog.moduleLoaderState_.moduleName=a;if(!COMPILED){if(goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');delete goog.implicitNamespaces_[a]}};goog.module.get=function(a){return goog.module.getInternal_(a)}; -goog.module.getInternal_=function(a){if(!COMPILED)return goog.isProvided_(a)?a in goog.loadedModules_?goog.loadedModules_[a]:goog.getObjectByName(a):null};goog.moduleLoaderState_=null;goog.isInModuleLoader_=function(){return null!=goog.moduleLoaderState_};goog.module.declareTestMethods=function(){if(!goog.isInModuleLoader_())throw Error("goog.module.declareTestMethods must be called from within a goog.module");goog.moduleLoaderState_.declareTestMethods=!0}; -goog.module.declareLegacyNamespace=function(){if(!COMPILED&&!goog.isInModuleLoader_())throw Error("goog.module.declareLegacyNamespace must be called from within a goog.module");if(!COMPILED&&!goog.moduleLoaderState_.moduleName)throw Error("goog.module must be called prior to goog.module.declareLegacyNamespace.");goog.moduleLoaderState_.declareLegacyNamespace=!0}; -goog.setTestOnly=function(a){if(goog.DISALLOW_TEST_ONLY_CODE)throw a=a||"",Error("Importing test-only code into non-debug environment"+(a?": "+a:"."));};goog.forwardDeclare=function(a){};COMPILED||(goog.isProvided_=function(a){return a in goog.loadedModules_||!goog.implicitNamespaces_[a]&&goog.isDefAndNotNull(goog.getObjectByName(a))},goog.implicitNamespaces_={"goog.module":!0}); -goog.getObjectByName=function(a,b){for(var c=a.split("."),d=b||goog.global,e;e=c.shift();)if(goog.isDefAndNotNull(d[e]))d=d[e];else return null;return d};goog.globalize=function(a,b){var c=b||goog.global,d;for(d in a)c[d]=a[d]};goog.addDependency=function(a,b,c,d){if(goog.DEPENDENCIES_ENABLED){var e;a=a.replace(/\\/g,"/");for(var f=goog.dependencies_,g=0;e=b[g];g++)f.nameToPath[e]=a,f.pathIsModule[a]=!!d;for(d=0;b=c[d];d++)a in f.requires||(f.requires[a]={}),f.requires[a][b]=!0}}; -goog.ENABLE_DEBUG_LOADER=!0;goog.logToConsole_=function(a){goog.global.console&&goog.global.console.error(a)}; -goog.require=function(a){if(!COMPILED){goog.ENABLE_DEBUG_LOADER&&goog.IS_OLD_IE_&&goog.maybeProcessDeferredDep_(a);if(goog.isProvided_(a))return goog.isInModuleLoader_()?goog.module.getInternal_(a):null;if(goog.ENABLE_DEBUG_LOADER){var b=goog.getPathFromDeps_(a);if(b)return goog.included_[b]=!0,goog.writeScripts_(),null}a="goog.require could not find: "+a;goog.logToConsole_(a);throw Error(a);}};goog.basePath="";goog.nullFunction=function(){};goog.identityFunction=function(a,b){return a}; -goog.abstractMethod=function(){throw Error("unimplemented abstract method");};goog.addSingletonGetter=function(a){a.getInstance=function(){if(a.instance_)return a.instance_;goog.DEBUG&&(goog.instantiatedSingletons_[goog.instantiatedSingletons_.length]=a);return a.instance_=new a}};goog.instantiatedSingletons_=[];goog.LOAD_MODULE_USING_EVAL=!0;goog.SEAL_MODULE_EXPORTS=goog.DEBUG;goog.loadedModules_={};goog.DEPENDENCIES_ENABLED=!COMPILED&&goog.ENABLE_DEBUG_LOADER; -goog.DEPENDENCIES_ENABLED&&(goog.included_={},goog.dependencies_={pathIsModule:{},nameToPath:{},requires:{},visited:{},written:{},deferred:{}},goog.inHtmlDocument_=function(){var a=goog.global.document;return"undefined"!=typeof a&&"write"in a},goog.findBasePath_=function(){if(goog.isDef(goog.global.CLOSURE_BASE_PATH))goog.basePath=goog.global.CLOSURE_BASE_PATH;else if(goog.inHtmlDocument_())for(var a=goog.global.document.getElementsByTagName("script"),b=a.length-1;0<=b;--b){var c=a[b].src,d=c.lastIndexOf("?"), -d=-1==d?c.length:d;if("base.js"==c.substr(d-7,7)){goog.basePath=c.substr(0,d-7);break}}},goog.importScript_=function(a,b){(goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_)(a,b)&&(goog.dependencies_.written[a]=!0)},goog.IS_OLD_IE_=!goog.global.atob&&goog.global.document&&goog.global.document.all,goog.importModule_=function(a){goog.importScript_("",'goog.retrieveAndExecModule_("'+a+'");')&&(goog.dependencies_.written[a]=!0)},goog.queuedModules_=[],goog.wrapModule_=function(a,b){return goog.LOAD_MODULE_USING_EVAL&& -goog.isDef(goog.global.JSON)?"goog.loadModule("+goog.global.JSON.stringify(b+"\n//# sourceURL="+a+"\n")+");":'goog.loadModule(function(exports) {"use strict";'+b+"\n;return exports});\n//# sourceURL="+a+"\n"},goog.loadQueuedModules_=function(){var a=goog.queuedModules_.length;if(0\x3c/script>")):c.write(' - - - - - diff --git a/static/js/jquery-2.1.0.min.js b/static/js/jquery-2.1.0.min.js deleted file mode 100644 index cbe6abe5..00000000 --- a/static/js/jquery-2.1.0.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.1.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m=a.document,n="2.1.0",o=function(a,b){return new o.fn.init(a,b)},p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};o.fn=o.prototype={jquery:n,constructor:o,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=o.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return o.each(this,a,b)},map:function(a){return this.pushStack(o.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},o.extend=o.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||o.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(o.isPlainObject(d)||(e=o.isArray(d)))?(e?(e=!1,f=c&&o.isArray(c)?c:[]):f=c&&o.isPlainObject(c)?c:{},g[b]=o.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},o.extend({expando:"jQuery"+(n+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===o.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isPlainObject:function(a){if("object"!==o.type(a)||a.nodeType||o.isWindow(a))return!1;try{if(a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(b){return!1}return!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=o.trim(a),a&&(1===a.indexOf("use strict")?(b=m.createElement("script"),b.text=a,m.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":k.call(a)},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?o.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),o.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||o.guid++,f):void 0},now:Date.now,support:l}),o.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=o.type(a);return"function"===c||o.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);o.find=t,o.expr=t.selectors,o.expr[":"]=o.expr.pseudos,o.unique=t.uniqueSort,o.text=t.getText,o.isXMLDoc=t.isXML,o.contains=t.contains;var u=o.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(o.isFunction(b))return o.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return o.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return o.filter(b,a,c);b=o.filter(b,a)}return o.grep(a,function(a){return g.call(b,a)>=0!==c})}o.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?o.find.matchesSelector(d,a)?[d]:[]:o.find.matches(a,o.grep(b,function(a){return 1===a.nodeType}))},o.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(o(a).filter(function(){for(b=0;c>b;b++)if(o.contains(e[b],this))return!0}));for(b=0;c>b;b++)o.find(a,e[b],d);return d=this.pushStack(c>1?o.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?o(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=o.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof o?b[0]:b,o.merge(this,o.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:m,!0)),v.test(c[1])&&o.isPlainObject(b))for(c in b)o.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=m.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=m,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):o.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(o):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),o.makeArray(a,this))};A.prototype=o.fn,y=o(m);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};o.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&o(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),o.fn.extend({has:function(a){var b=o(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(o.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?o(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&o.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?o.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(o(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(o.unique(o.merge(this.get(),o(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}o.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return o.dir(a,"parentNode")},parentsUntil:function(a,b,c){return o.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return o.dir(a,"nextSibling")},prevAll:function(a){return o.dir(a,"previousSibling")},nextUntil:function(a,b,c){return o.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return o.dir(a,"previousSibling",c)},siblings:function(a){return o.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return o.sibling(a.firstChild)},contents:function(a){return a.contentDocument||o.merge([],a.childNodes)}},function(a,b){o.fn[a]=function(c,d){var e=o.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=o.filter(d,e)),this.length>1&&(C[a]||o.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return o.each(a.match(E)||[],function(a,c){b[c]=!0}),b}o.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):o.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){o.each(b,function(b,c){var d=o.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&o.each(arguments,function(a,b){var c;while((c=o.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?o.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},o.extend({Deferred:function(a){var b=[["resolve","done",o.Callbacks("once memory"),"resolved"],["reject","fail",o.Callbacks("once memory"),"rejected"],["notify","progress",o.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return o.Deferred(function(c){o.each(b,function(b,f){var g=o.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&o.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?o.extend(a,d):d}},e={};return d.pipe=d.then,o.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&o.isFunction(a.promise)?e:0,g=1===f?a:o.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&o.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;o.fn.ready=function(a){return o.ready.promise().done(a),this},o.extend({isReady:!1,readyWait:1,holdReady:function(a){a?o.readyWait++:o.ready(!0)},ready:function(a){(a===!0?--o.readyWait:o.isReady)||(o.isReady=!0,a!==!0&&--o.readyWait>0||(H.resolveWith(m,[o]),o.fn.trigger&&o(m).trigger("ready").off("ready")))}});function I(){m.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),o.ready()}o.ready.promise=function(b){return H||(H=o.Deferred(),"complete"===m.readyState?setTimeout(o.ready):(m.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},o.ready.promise();var J=o.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===o.type(c)){e=!0;for(h in c)o.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,o.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(o(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};o.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=o.expando+Math.random()}K.uid=1,K.accepts=o.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,o.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(o.isEmptyObject(f))o.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,o.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{o.isArray(b)?d=b.concat(b.map(o.camelCase)):(e=o.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!o.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?o.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}o.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),o.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length; -while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=o.camelCase(d.slice(5)),P(f,d,e[d]));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=o.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),o.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||o.isArray(c)?d=L.access(a,b,o.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=o.queue(a,b),d=c.length,e=c.shift(),f=o._queueHooks(a,b),g=function(){o.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:o.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),o.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";l.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return m.activeElement}catch(a){}}o.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=o.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof o!==U&&o.event.triggered!==b.type?o.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],n=q=h[1],p=(h[2]||"").split(".").sort(),n&&(l=o.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=o.event.special[n]||{},k=o.extend({type:n,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&o.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(n,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),o.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],n=q=h[1],p=(h[2]||"").split(".").sort(),n){l=o.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||o.removeEvent(a,n,r.handle),delete i[n])}else for(n in i)o.event.remove(a,n+b[j],c,d,!0);o.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,p=[d||m],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||m,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+o.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[o.expando]?b:new o.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:o.makeArray(c,[b]),n=o.event.special[q]||{},e||!n.trigger||n.trigger.apply(d,c)!==!1)){if(!e&&!n.noBubble&&!o.isWindow(d)){for(i=n.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||m)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:n.bindType||q,l=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),l&&l.apply(g,c),l=k&&g[k],l&&l.apply&&o.acceptData(g)&&(b.result=l.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||n._default&&n._default.apply(p.pop(),c)!==!1||!o.acceptData(d)||k&&o.isFunction(d[q])&&!o.isWindow(d)&&(h=d[k],h&&(d[k]=null),o.event.triggered=q,d[q](),o.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=o.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=o.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=o.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((o.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?o(e,this).index(i)>=0:o.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return o.nodeName(a,"table")&&o.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)o.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=o.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&o.nodeName(a,b)?o.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}o.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=o.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||o.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,n=a.length;n>m;m++)if(e=a[m],e||0===e)if("object"===o.type(e))o.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;o.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===o.inArray(e,d))&&(i=o.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f,g,h=o.event.special,i=0;void 0!==(c=a[i]);i++){if(o.acceptData(c)&&(f=c[L.expando],f&&(b=L.cache[f]))){if(d=Object.keys(b.events||{}),d.length)for(g=0;void 0!==(e=d[g]);g++)h[e]?o.event.remove(c,e):o.removeEvent(c,e,b.handle);L.cache[f]&&delete L.cache[f]}delete M.cache[c[M.expando]]}}}),o.fn.extend({text:function(a){return J(this,function(a){return void 0===a?o.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?o.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||o.cleanData(ob(c)),c.parentNode&&(b&&o.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(o.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return o.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(o.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,o.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,n=k-1,p=a[0],q=o.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(c=o.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=o.map(ob(c,"script"),kb),g=f.length;k>j;j++)h=c,j!==n&&(h=o.clone(h,!0,!0),g&&o.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,o.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&o.contains(i,h)&&(h.src?o._evalUrl&&o._evalUrl(h.src):o.globalEval(h.textContent.replace(hb,"")))}return this}}),o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){o.fn[a]=function(a){for(var c,d=[],e=o(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),o(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d=o(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:o.css(d[0],"display");return d.detach(),e}function tb(a){var b=m,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||o(" - - - - - diff --git a/templates/main.html b/templates/main.html deleted file mode 100644 index 519d6813..00000000 --- a/templates/main.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - CoderBot - - - - {%include "config_params.html"%} - - - - - - - - - - - - - - - - -{%if config.show_page_control%}{%include "control.html"%}{%endif%} -{%if config.show_page_program%}{%include "program.html"%}{%endif%} -{%include "config.html"%} - - diff --git a/templates/program.html b/templates/program.html deleted file mode 100644 index ad796070..00000000 --- a/templates/program.html +++ /dev/null @@ -1,78 +0,0 @@ -
-
- Online -

CoderBot

- {%if config.show_page_prefs%}{% trans %}Preferences{% endtrans %}{%endif%} -
- -
-
-
-{%if "basic" in config.prog_level%} -
-
-
-
-
-
-
-{%else%} -
-
-
-
-
-
-
-
-
- -
-{%endif%} -
- {%include "blocks_"+program_level+".xml"%} -
-
-
-

CoderBot {% trans %}is running{% endtrans %}

-
-
-
-
-
- -
-
-
-
-

{% trans %}New Program{% endtrans %}

- - - -
-
-
-
-

{% trans %}Save Program As{% endtrans %}

- - - -
-
-
-
-

{% trans %}Load Program{% endtrans %}

-
    -
    -
    - -
    diff --git a/test/__init__.py b/test/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/test/api_test.py b/test/api_test.py new file mode 100644 index 00000000..f345b80d --- /dev/null +++ b/test/api_test.py @@ -0,0 +1,7 @@ +import schemathesis + +schema = schemathesis.from_uri("http://192.168.1.14:8090/api/v1/openapi.json") + +@schema.parametrize() +def test_api(case): + case.call_and_validate() diff --git a/test/audio_test.py b/test/audio_test.py new file mode 100755 index 00000000..1278835f --- /dev/null +++ b/test/audio_test.py @@ -0,0 +1,31 @@ +import unittest +import os +import test.pyaudio_mock +import pyaudio +import audio + +FILENAME = "test.wav" + +class AudioTest(unittest.TestCase): + def setUp(self): + pyaudio.PyAudio = test.pyaudio_mock.PyAudioMock + self.audio = audio.Audio.get_instance() + + def tearDown(self): + pass + + def test_say(self): + self.audio.say("this is a test") + self.assertTrue(True) + + def test_record_to_file(self): + self.audio.record_to_file(FILENAME, 3) + self.assertTrue(os.path.isfile(os.path.join(audio.SOUNDDIR, FILENAME))) + + def test_play(self): + self.audio.play(FILENAME) + self.assertTrue(True) + + def test_hear(self): + self.assertTrue(True) + diff --git a/test/camera_test.py b/test/camera_test.py new file mode 100755 index 00000000..523f2c4b --- /dev/null +++ b/test/camera_test.py @@ -0,0 +1,43 @@ +import unittest +import time +import os +import picamera_mock +import picamera +import camera +import config + +class CameraTest(unittest.TestCase): + def setUp(self): + config.Config.read() + picamera.PiCamera = picamera_mock.PiCameraMock + self.cam = camera.Camera.get_instance() + + def tearDown(self): + self.cam.exit() + camera.Camera._instance = None + + def test_take_picture_jpeg(self): + pic = self.cam.get_image_jpeg() + self.assertTrue(pic is not None) + + def test_take_picture_bgr(self): + pic = self.cam.get_image() + self.assertTrue(pic is not None) + + def test_video_rec(self): + video_filename = "video_test" + self.cam.video_rec(video_filename) + time.sleep(5) + self.cam.video_stop() + v = open("data/media/VID" + video_filename + ".mp4") + t = open("data/media/VID" + video_filename + "_thumb.jpg") + self.assertTrue(v is not None and t is not None) + v.close() + t.close() + os.remove("data/media/VID" + video_filename + ".mp4") + os.remove("data/media/VID" + video_filename + "_thumb.jpg") + + def test_find_color(self): + color = 'ff0000' + dist, angle = self.cam.find_color(color) + self.assertTrue(dist > 0 and angle < 180) diff --git a/test/cnn_test.py b/test/cnn_test.py new file mode 100755 index 00000000..a40d5ab2 --- /dev/null +++ b/test/cnn_test.py @@ -0,0 +1,112 @@ +import unittest +import time +import os +import config +import camera +import cnn.cnn_manager + +class CNNTest(unittest.TestCase): + def setUp(self): + config.Config.read() + os.system("mv photos saved_photos") + os.system("wget https://github.com/CoderBotOrg/test-data/raw/master/dnn-images/coderbot-dnn-test-images-02.tar.xz") + os.system("tar xJf coderbot-dnn-test-images-02.tar.xz") + os.system("rm coderbot-dnn-test-images-02.tar.xz") + cnn = cnn_manager.CNNManager.get_instance() + + def tearDown(self): + os.system("rm -rf photos") + os.system("mv saved_photos photos") + cnn = cnn_manager.CNNManager.get_instance() + name="test_model_1" + cnn.delete_model(name) + name="test_model_2" + cnn.delete_model(name) + + def test_1_train_set_1(self): + name="test_model_1" + cam = camera.Camera.get_instance() + cnn = cnn_manager.CNNManager.get_instance() + cnn.train_new_model(model_name=name, + architecture="imagenet/mobilenet_v2_100_160/feature_vector/4", + image_tags=["orange","apple","other"], + photos_meta=cam.get_photo_list(), + training_steps=5, + learning_rate=0.0001) + start = time.time() + while True: + model_status = cnn.get_models().get(name, {"status": 0}) + if model_status.get("status") == 1 or time.time() - start > 6000: + break + time.sleep(1) + self.assertTrue(cnn.get_models().get(name).get("status") == 1.0) + mod = cnn.load_model(name) + result = mod.classify_image("data/media/DSC1.jpg") + print("result: " + str(result)) + self.assertTrue(result[0][0] == "orange" and result[0][1] > 40) + result = mod.classify_image("data/media/DSC201.jpg") + print("result: " + str(result)) + #self.assertTrue(result[0][0] == "apple" and result[0][1] > 40) + result = mod.classify_image("data/media/DSC301.jpg") + print("result: " + str(result)) + #self.assertTrue(result[0][0] == "other" and result[0][1] > 40) + t1 = time.time() + iterations = 20 + for x in range(iterations): + result = mod.classify_image("data/media/DSC1.jpg") + print("result: " + str(result) + " fps: " + str(1.0*iterations/(time.time()-t1))) + cnn.delete_model(name) + self.assertTrue(cnn.get_models().get(name) is None) + + def test_2_train_set_2(self): + name="test_model_2" + cam = camera.Camera.get_instance() + cnn = cnn_manager.CNNManager.get_instance() + cnn.train_new_model(model_name=name, + architecture="imagenet/mobilenet_v2_050_160/feature_vector/4", + image_tags=["orange","apple","other"], + photos_meta=cam.get_photo_list(), + training_steps=1, + learning_rate=0.005) + start = time.time() + while True: + model_status = cnn.get_models().get(name, {"status": 0}) + if model_status.get("status") == 1 or time.time() - start > 6000: + break + time.sleep(1) + self.assertTrue(cnn.get_models().get(name).get("status") == 1.0) + + mod = cnn.load_model(name) + result = mod.classify_image("data/media/DSC1.jpg") + print("result: " + str(result)) + self.assertTrue(result[0][0] == "orange" and result[0][1] > 40) + + def test_3_classify_1(self): + cnn = cnn_manager.CNNManager.get_instance() + mod = cnn.load_model('base_high_slow') + t1 = time.time() + iterations = 20 + for x in range(iterations): + result = mod.classify_image("data/media/DSC201.jpg") + print("result: " + str(result) + " fps: " + str(1.0*iterations/(time.time()-t1))) + self.assertTrue(len(result) and result[0][0] == "Granny Smith" and result[0][1] > 50) + + def test_4_classify_2(self): + cnn = cnn_manager.CNNManager.get_instance() + mod = cnn.load_model('base_low_fast') + t1 = time.time() + iterations = 20 + for x in range(iterations): + result = mod.classify_image("data/media/DSC201.jpg") + print("result: " + str(result) + " fps: " + str(1.0*iterations/(time.time()-t1))) + self.assertTrue(len(result) and result[0][0] == "Granny Smith" and result[0][1] > 50) + + def test_5_detect_objects_1(self): + cnn = cnn_manager.CNNManager.get_instance() + mod = cnn.load_model('object_detect') + t1 = time.time() + iterations = 20 + for x in range(iterations): + result = mod.detect_objects("data/media/DSC201.jpg") + print("result: " + str(result) + " fps: " + str(1.0*iterations/(time.time()-t1))) + self.assertTrue(len(result) and result[0] == ('apple', 78, (18, 10, 72, 82))) diff --git a/test/coderbot_test.py b/test/coderbot_test.py new file mode 100755 index 00000000..dbbd6ee0 --- /dev/null +++ b/test/coderbot_test.py @@ -0,0 +1,78 @@ +import unittest +import test.pigpio_mock +import coderbot +import logging + +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) + +sh = logging.StreamHandler() +# add a rotating handler +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +sh.setFormatter(formatter) + +logger.addHandler(sh) + +class CoderBotDCMotorTestCase(unittest.TestCase): + def setUp(self): + coderbot.pigpio.pi = test.pigpio_mock.PIGPIOMock + coderbot.CoderBot._instance = None + self.bot = coderbot.CoderBot.get_instance() + + def test_motor_forward(self): + self.bot.forward(speed=100, elapse=0.1) + + def test_motor_backward(self): + self.bot.backward(speed=100, elapse=0.1) + + def test_motor_left(self): + self.bot.left(speed=100, elapse=0.1) + + def test_motor_right(self): + self.bot.left(speed=100, elapse=0.1) + + def test_motor_move(self): + self.bot.move(speed=100, elapse=0.1) + self.bot.move(speed=-100, elapse=0.1) + + def test_motor_turn(self): + self.bot.turn(speed=100, elapse=0.1) + self.bot.turn(speed=-100, elapse=0.1) + +class CoderBotServoMotorTestCase(unittest.TestCase): + def setUp(self): + coderbot.pigpio.pi = test.pigpio_mock.PIGPIOMock + coderbot.CoderBot._instance = None + self.bot = coderbot.CoderBot.get_instance(servo=True) + + def test_motor_forward(self): + self.bot.forward(speed=100, elapse=0.1) + + def test_motor_backward(self): + self.bot.backward(speed=100, elapse=0.1) + + def test_motor_left(self): + self.bot.left(speed=100, elapse=0.1) + + def test_motor_right(self): + self.bot.left(speed=100, elapse=0.1) + + def test_motor_move(self): + self.bot.move(speed=100, elapse=0.1) + self.bot.move(speed=-100, elapse=0.1) + + def test_motor_turn(self): + self.bot.turn(speed=100, elapse=0.1) + self.bot.turn(speed=-100, elapse=0.1) + + +class CoderBotSonarTestCase(unittest.TestCase): + def setUp(self): + coderbot.pigpio.pi = test.pigpio_mock.PIGPIOMock + coderbot.CoderBot._instance = None + self.bot = coderbot.CoderBot.get_instance() + + def test_sonar(self): + for i in range(0, 3): + distance = self.bot.get_sonar_distance(i) + self.assertTrue(distance > 85 and distance < 86) diff --git a/test/mpu_test.py b/test/mpu_test.py new file mode 100644 index 00000000..c1832c8a --- /dev/null +++ b/test/mpu_test.py @@ -0,0 +1,35 @@ +import unittest +import pigpio_mock +from hw import mpu +import logging + +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) + +sh = logging.StreamHandler() +# add a rotating handler +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +sh.setFormatter(formatter) + +logger.addHandler(sh) + +class MPUTestCase(unittest.TestCase): + def setUp(self): + self.mpu = mpu.AccelGyroMag() + + def test_gyro(self): + gyro = self.mpu.get_gyro() + self.assertTrue(gyro is not None) + + def test_acc(self): + acc = self.mpu.get_acc() + self.assertTrue(acc is not None) + + def test_mag(self): + hdg = self.mpu.get_hdg() + self.assertTrue(hdg is not None) + + def test_temp(self): + temp = self.mpu.get_temp() + self.assertTrue(temp is not None) + diff --git a/test/music/snake/audio.wav b/test/music/snake/audio.wav new file mode 100644 index 00000000..39775e14 Binary files /dev/null and b/test/music/snake/audio.wav differ diff --git a/test/music/snake/snake.json b/test/music/snake/snake.json new file mode 100644 index 00000000..476eebe6 --- /dev/null +++ b/test/music/snake/snake.json @@ -0,0 +1,25 @@ +{ + "packages": { + "snake": { + "category": "animal", + "name_IT": "serpente", + "name_EN": "snake", + "version": "0.1", + "date": "2020-06-01", + "interface": { + "base": { + "available": "TRUE", + "icon": "snake.png" + }, + "intermediate": { + "available": "TRUE", + "icon": "snake.png" + }, + "advanced": { + "available": "TRUE", + "icon": "snake.png" + } + } + } + } +} \ No newline at end of file diff --git a/test/musicPackage_test.py b/test/musicPackage_test.py new file mode 100644 index 00000000..65f4823f --- /dev/null +++ b/test/musicPackage_test.py @@ -0,0 +1,41 @@ +#__import__("../musicPackages") +import json +import sys +sys.path.insert(0, './') +import musicPackages +class MusicPackage_test: + + def test_musicPackage(self): + print("sample Music Package: ") + print(" name_IT = name_it, name_EN = name_en , category = sample_category, version = sample_version, date = sample_date, interfaces = sample_interfaces, nameID = sample_id") + + mpkg = musicPackages.MusicPackage(name_IT = "name_it", name_EN = "name_en", category= "sample_category", version= "sample_version", date="sample_date", nameID="sample_id") + print("name_IT : ", mpkg.getNameIT()) + print("name_EN : ", mpkg.getNameEN()) + print("nameID : ", mpkg.getNameID()) + print("version : ", mpkg.getVersion()) + print("date : ", mpkg.getDate()) + print("category : ", mpkg.getCategory()) + print("interfaces : ", mpkg.getInterfaces()) + + def test_isPackageAvaible(self): + pkg_manager = musicPackages.MusicPackageManager() + for package_name in pkg_manager.packages: + print("Test if " + package_name + " package is available") + result = pkg_manager.isPackageAvailable(package_name) + if(result): + print(package_name + " package is available") + else: + print(package_name + " package is not available") + + print("Test if NONE package is available" ) + result = pkg_manager.isPackageAvailable("NONE") + if(result): + print("NONE package is available") + else: + print("NONE package is not available") + +test = MusicPackage_test() +test.test_musicPackage() +test.test_isPackageAvaible() + diff --git a/test/music_test.py b/test/music_test.py new file mode 100644 index 00000000..b73a6b1b --- /dev/null +++ b/test/music_test.py @@ -0,0 +1,116 @@ +import sys +import sox +import time +import os +sys.path.insert(0, './') +from musicPackages import MusicPackageManager +from music import Music + +class Music_test: + + def test_library(self): + print("testing sound playback:...") + tfm = sox.Transformer() + tfm.preview('cat.wav') + tfm.build('cat.wav', 'outMusicDemo.wav') + +# test each parametr of the function play_note + def test_play_note(self): + musicPkg = MusicPackageManager() + m = Music(musicPkg) + print('test Music.play_note') + print("m.play_note(note='C2')") + m.play_note(note='C2') + print("m.play_note(note='C2',duration=2.0)") + m.play_note(note='C2',duration=2.0) + print("m.play_note(note='C2',instrument='guitar')") + m.play_note(note='C2',instrument='guitar') + print("m.play_note(note='C2',alteration='bmolle')") + m.play_note(note='C2',alteration='bmolle') + print("m.play_note(note='C2',alteration='diesis')") + m.play_note(note='C2',alteration='diesis') + print("m.play_note(note='C2',instrument='guitar')") + m.play_note(note='C2',instrument='guitar') + print("m.play_note(note='C2',alteration='bmolle')") + m.play_note(note='C2',alteration='bmolle') + print("m.play_note(note='C2',instrument='guitar',alteration='diesis')") + m.play_note(note='C2',instrument='guitar',alteration='diesis') + print("m.play_note(note='C2',instrument='guitar',alteration='diesis',duration=2.0)") + m.play_note(note='C2',instrument='guitar',alteration='diesis',duration=2.0) + print("m.play_note(note='G3',duration=2.0)") + m.play_note(note='G3',duration=2.0) + print("m.play_note(note='G3',instrument='guitar')") + m.play_note(note='G3',instrument='guitar') + print("m.play_note(note='G3',alteration='bmolle')") + m.play_note(note='G3',alteration='bmolle') + print("m.play_note(note='G3',alteration='diesis')") + m.play_note(note='G3',alteration='diesis') + print("m.play_note(note='G3',instrument='guitar')") + m.play_note(note='G3',instrument='guitar') + print("m.play_note(note='G3',alteration='bmolle')") + m.play_note(note='G3',alteration='bmolle') + print("m.play_note(note='G3',instrument='guitar',alteration='diesis')") + m.play_note(note='G3',instrument='guitar',alteration='diesis') + print("m.play_note(note='G3',instrument='guitar',alteration='diesis',duration=2.0)") + m.play_note(note='G3',instrument='guitar',alteration='diesis',duration=2.0) + print("it's ok if print: no instrument: coderInstrument present in this coderbot!") + m.play_note(note='C2',instrument='coderInstrument',alteration='diesis',duration=2.0) + print("it's ok if print: note: coderNote not exist") + m.play_note(note='coderNote',instrument='piano',alteration='diesis',duration=2.0) + + +# test each parametr of the function play_note + def test_play_animal(self): + print('test Music.play_animal') + musicPkg = MusicPackageManager() + m = Music(musicPkg) + print("(note='C2',instrument='cat', duration=2.0)") + m.play_animal(note='C2',instrument='cat', duration=2.0) + print("m.play_animal(note='C2',instrument='dog')") + m.play_animal(note='C2',instrument='dog') + print("m.play_animal(note='C2',instrument='dog', alteration='bmolle')") + m.play_animal(note='C2',instrument='dog', alteration='bmolle') + print("m.play_animal(note='C2',instrument='cat', alteration='diesis')") + m.play_animal(note='C2',instrument='cat', alteration='diesis') + print("m.play_animal(note='C2',instrument='dinosaur')") + m.play_animal(note='C2',instrument='dinosaur') + print("m.play_animal(note='C2',alteration='bmolle')") + m.play_animal(note='C2',instrument="dinosaur", alteration='bmolle') + print("m.play_animal(note='C2',instrument='cat',alteration='diesis')") + m.play_animal(note='C2',instrument='cat',alteration='diesis') + print("m.play_animal(note='C2',instrument='cat',alteration='diesis',duration=2.0)") + m.play_animal(note='C2',instrument='cat',alteration='diesis',duration=2.0) + print("m.play_note(note='G3',duration=2.0)") + m.play_note(note='G3',duration=2.0) + print("m.play_note(note='G3',instrument='dinosaur',alteration='bmolle')") + m.play_note(note='G3',instrument='dinosaur',alteration='bmolle') + print("m.play_note(note='G3',instrument='dinosaur',alteration='diesis')") + m.play_note(note='G3',instrument='dinosaur',alteration='diesis') + print("m.play_note(note='G3',alteration='bmolle', instrument= 'cat')") + m.play_note(note='G3',alteration='bmolle', instrument= 'cat') + print("m.play_note(note='G3',instrument='cat',alteration='diesis')") + m.play_note(note='G3',instrument='cat',alteration='diesis') + print("m.play_note(note='G3',instrument='cat',alteration='diesis',duration=2.0)") + m.play_note(note='G3',instrument='cat',alteration='diesis',duration=2.0) + print("it's ok if print: no instrument: coderInstrument present in this coderbot!") + m.play_animal(note='C2',instrument='coderInstrument',alteration='diesis',duration=2.0) + print("it's ok if print: note: coderNote not exist") + m.play_animal(note='coderNote',instrument='cat',alteration='diesis',duration=2.0) + print('test Music.play_note: ENDED') + + + def test_play_pause(self): + print('test Music.play_pause') + musicPkg = MusicPackageManager() + m = Music() + prrint("play pause") + m.play_pause(1.0) + prrint("play pause and note") + m.play_note(note='C2',instrument='guitar') + m.play_pause(2.0) + m.play_note(note='C2',instrument='guitar') + +test = Music_test() +test.test_play_note() +test.test_play_animal() + diff --git a/test/picamera_mock.py b/test/picamera_mock.py new file mode 100755 index 00000000..546b9167 --- /dev/null +++ b/test/picamera_mock.py @@ -0,0 +1,75 @@ +import unittest.mock +import time +import io +import logging +import threading +from PIL import Image as PILImage +import cv2 +import numpy + +logger = logging.getLogger() + +class PiCameraMock(object): + """Implements PiCamera mock class + PiCamera is the library used to access the integrated Camera, this mock class emulates the capture functions in order to test the streamer loop. + """ + + def __init__(self): + self.resolution = None + self.framerate = None + self.exposure_mode = None + self.annotate_text = None + self.splitter_recorders = {} + self.images = {} + i = open('test/test_image.jpeg', 'rb') + image_jpeg = i.read() + i.close() + self.images["mjpeg"] = image_jpeg + self.images["bgra"] = cv2.cvtColor(numpy.array(PILImage.open(io.BytesIO(image_jpeg))), cv2.COLOR_RGB2BGRA) + + + class ImageRecorder(threading.Thread): + def __init__(self, buffer, image): + threading.Thread.__init__(self) + self.buffer = buffer + self.image = image + self.go = True + + def run(self): + while self.go: + self.buffer.write(self.image) + time.sleep(0.05) + + class VideoRecorder(object): + def __init__(self, buffer, video): + self.buffer = buffer + self.video = video + + def start_recording(self, buffer, format, splitter_port, quality=None, bitrate=None, resize=None): + """mock start_recording""" + print(format) + if format == "bgra" and resize: + self.images[format] = cv2.resize(self.images[format], resize) + if format == "h264": + f = open("test/test.h264", "rb") + video = f.read() + f.close() + self.splitter_recorders[splitter_port] = self.VideoRecorder(buffer, video) + else: + self.splitter_recorders[splitter_port] = self.ImageRecorder(buffer, self.images[format]) + self.splitter_recorders[splitter_port].start() + + def stop_recording(self, splitter_port): + if splitter_port < 2: + self.splitter_recorders[splitter_port].go = False + self.splitter_recorders[splitter_port].join() + else: + recorder = self.splitter_recorders[splitter_port] + f = open(recorder.buffer, "wb") + f.write(recorder.video) + f.close() + + def close(): + """mock close""" + pass + diff --git a/test/pigpio_mock.py b/test/pigpio_mock.py new file mode 100755 index 00000000..6916dc49 --- /dev/null +++ b/test/pigpio_mock.py @@ -0,0 +1,83 @@ +import unittest.mock +import time +import logging +import logging.handlers +import coderbot + +logger = logging.getLogger() + +class PIGPIOMock(object): + """Implements PIGPIO library mock class + PIGPIO is the library used to access digital General Purpose IO (GPIO), + this mock class emulates the behaviour of the inputs used by the sonar sensors: a fake signal is triggered to emulate a 85.1 distance. + Output (DC motor and Servo) are just no-op function, they implement basic parameters check via assertions. + """ + + def __init__(self, host="localhost", port=None): + self.callbacks = {} + logger.info("mock called") + + def set_mode(self, pin_id, pin_mode): + """mock set_mode""" + pass + + def get_mode(self, pin_id): + """mock get_mode""" + return 0 + + def callback(self, pin_id, edge, callback): + """mock callback""" + self.callbacks[pin_id] = callback + return self.Callback(pin_id) + + def write(self, pin_id, value): + """mock write""" + assert(pin_id > 0 and pin_id < 32) + assert(value == 0 or value == 1) + + def read(self, pin_id): + """mock read""" + pass + + def gpio_trigger(self, pin_id): + """mock gpio_trigger""" + assert(pin_id > 0 and pin_id < 32) + # mock sonars triger and echo + if pin_id == coderbot.GPIO_CODERBOT_V_4.PIN_SONAR_1_TRIGGER or pin_id == coderbot.GPIO_CODERBOT_V_5.PIN_SONAR_1_TRIGGER: + if pin_id == coderbot.GPIO_CODERBOT_V_4.PIN_SONAR_1_TRIGGER: + GPIOS=coderbot.GPIO_CODERBOT_V_4 + else: + GPIOS=coderbot.GPIO_CODERBOT_V_5 + self.callbacks[GPIOS.PIN_SONAR_1_ECHO](GPIOS.PIN_SONAR_1_TRIGGER, 0, 0) + self.callbacks[GPIOS.PIN_SONAR_2_ECHO](GPIOS.PIN_SONAR_1_TRIGGER, 0, 0) + self.callbacks[GPIOS.PIN_SONAR_3_ECHO](GPIOS.PIN_SONAR_1_TRIGGER, 0, 0) + self.callbacks[GPIOS.PIN_SONAR_1_ECHO](GPIOS.PIN_SONAR_1_ECHO, 1, 0) + self.callbacks[GPIOS.PIN_SONAR_2_ECHO](GPIOS.PIN_SONAR_2_ECHO, 1, 0) + self.callbacks[GPIOS.PIN_SONAR_3_ECHO](GPIOS.PIN_SONAR_3_ECHO, 1, 0) + time.sleep(0.005) + self.callbacks[GPIOS.PIN_SONAR_1_ECHO](GPIOS.PIN_SONAR_1_ECHO, 0, 5000) + self.callbacks[GPIOS.PIN_SONAR_2_ECHO](GPIOS.PIN_SONAR_2_ECHO, 0, 5000) + self.callbacks[GPIOS.PIN_SONAR_3_ECHO](GPIOS.PIN_SONAR_3_ECHO, 0, 5000) + + def set_PWM_frequency(self, pin_id, frequency): + """mock set_PWM_frequency""" + assert(pin_id > 0 and pin_id < 32) + assert(frequency > 0) + + def set_PWM_range(self, pin_id, range): + """mock set_PWM_range""" + pass + + def set_PWM_dutycycle(self, pin_id, dutycycle): + """mock set_PWM_dutycyle""" + pass + + class Callback(object): + def __init__(self, pin_id): + pass + + def cancel(self): + pass + + def set_pull_up_down(self, feedback_pin_A, mode): + pass diff --git a/test/pyaudio_mock.py b/test/pyaudio_mock.py new file mode 100755 index 00000000..92f7fc33 --- /dev/null +++ b/test/pyaudio_mock.py @@ -0,0 +1,31 @@ +import unittest.mock +import time +import io +import logging +import numpy + +logger = logging.getLogger() + +class PyAudioMock(object): + """Implements PyAudio mock class + PyAudio is the library used to access the integrated audio output and external audio source (microphone) + """ + + def __init__(self): + pass + + def open(self, format, channels, rate, frames_per_buffer, stream_callback): + return self + + def stop_stream(self): + pass + + def close(self): + pass + + def terminate(self): + pass + + def get_sample_size(format): + return format * 16 + diff --git a/test/rotary_encoder_tests/reset_motors.py b/test/rotary_encoder_tests/reset_motors.py new file mode 100644 index 00000000..b34c6ce9 --- /dev/null +++ b/test/rotary_encoder_tests/reset_motors.py @@ -0,0 +1,5 @@ +import pigpio + +pi = pigpio.pi() +pi.write(24, 0) +pi.write(17, 0) diff --git a/test/rotary_encoder_tests/rotary_encoder_PWM_test.py b/test/rotary_encoder_tests/rotary_encoder_PWM_test.py new file mode 100644 index 00000000..4b7dec5c --- /dev/null +++ b/test/rotary_encoder_tests/rotary_encoder_PWM_test.py @@ -0,0 +1,53 @@ +PIN_LEFT_FORWARD = 24 +PIN_LEFT_BACKWARD = 25 +PIN_RIGHT_FORWARD = 17 +PIN_RIGHT_BACKWARD = 4 +PIN_MOTOR_ENABLE = 22 + +PWM_FREQUENCY = 100 #Hz +PWM_RANGE = 100 #0-100 + +if __name__ == "__main__": + + import time + import pigpio + + #pi = pigpio.pi('backend.local') + pi = pigpio.pi() + print("Connected, waiting for signal") + + # FORWARD MOVEMENT + print("FORWARD") + pi.set_PWM_frequency(PIN_LEFT_FORWARD, PWM_FREQUENCY) + pi.set_PWM_range(PIN_LEFT_FORWARD, PWM_RANGE) + pi.set_PWM_frequency(PIN_RIGHT_FORWARD, PWM_FREQUENCY) + pi.set_PWM_range(PIN_RIGHT_FORWARD, PWM_RANGE) + + pi.write(PIN_MOTOR_ENABLE, 1) + + pi.set_PWM_dutycycle(PIN_LEFT_FORWARD, 100) + pi.set_PWM_dutycycle(PIN_RIGHT_FORWARD, 100) + + time.sleep(.5) + + print("STOP") + pi.write(PIN_LEFT_FORWARD, 0) + pi.write(PIN_RIGHT_FORWARD, 0) + + # BACKWARDS MOVEMENT + print("BACKWARDS") + pi.set_PWM_frequency(PIN_LEFT_BACKWARD, PWM_FREQUENCY) + pi.set_PWM_range(PIN_LEFT_BACKWARD, PWM_RANGE) + pi.set_PWM_frequency(PIN_RIGHT_BACKWARD, PWM_FREQUENCY) + pi.set_PWM_range(PIN_RIGHT_BACKWARD, PWM_RANGE) + + pi.set_PWM_dutycycle(PIN_LEFT_BACKWARD, 100) + pi.set_PWM_dutycycle(PIN_RIGHT_BACKWARD, 100) + + time.sleep(.5) + + print("STOP") + pi.write(PIN_LEFT_BACKWARD, 0) + pi.write(PIN_RIGHT_BACKWARD, 0) + + pi.stop() \ No newline at end of file diff --git a/test/rotary_encoder_tests/rotary_encoder_coderbot_test.py b/test/rotary_encoder_tests/rotary_encoder_coderbot_test.py new file mode 100644 index 00000000..f138bcb3 --- /dev/null +++ b/test/rotary_encoder_tests/rotary_encoder_coderbot_test.py @@ -0,0 +1,8 @@ +from coderbot import CoderBot + +c = CoderBot.get_instance(); + +c._twin_motors_enc.control_distance(100, 100, 200) + +#while(True): +print(c._twin_motors_enc.distance()) diff --git a/test/rotary_encoder_tests/rotary_encoder_fixed_distance_test.py b/test/rotary_encoder_tests/rotary_encoder_fixed_distance_test.py new file mode 100644 index 00000000..e8c04b36 --- /dev/null +++ b/test/rotary_encoder_tests/rotary_encoder_fixed_distance_test.py @@ -0,0 +1,65 @@ +PIN_LEFT_FORWARD = 24 +PIN_LEFT_BACKWARD = 25 +PIN_RIGHT_FORWARD = 17 +PIN_RIGHT_BACKWARD = 4 +PIN_ENCODER_LEFT = 15 +PIN_ENCODER_RIGHT = 14 + +PIN_MOTOR_ENABLE = 22 +PWM_FREQUENCY = 100 #Hz +PWM_RANGE = 100 #0-100 + +if __name__ == "__main__": + + import time + import pigpio + import signal + + import rotary_encoder + + # mm and ticks + pos = 0 + mm = 0 + + # callback function on EITHER EDGE + def callback_left(way): + global pos + global mm + pos += way + mm = 0.196 * pos + + pi = pigpio.pi() # GPIO daemon + + # decoding number of ticks for right wheel only + decoder_left = rotary_encoder.decoder(pi, PIN_ENCODER_RIGHT, callback_left) + + # setting up FORWARD MOVEMENT + print("GOING FORWARD") + pi.set_PWM_frequency(PIN_LEFT_FORWARD, PWM_FREQUENCY) + pi.set_PWM_range(PIN_LEFT_FORWARD, PWM_RANGE) + pi.set_PWM_frequency(PIN_RIGHT_FORWARD, PWM_FREQUENCY) + pi.set_PWM_range(PIN_RIGHT_FORWARD, PWM_RANGE) + + # enabling motors + pi.write(PIN_MOTOR_ENABLE, 1) + + # going forward on 30% speed + pi.set_PWM_dutycycle(PIN_LEFT_FORWARD, 30) + pi.set_PWM_dutycycle(PIN_RIGHT_FORWARD, 30) + + + try: + while(True): + # print current ticks and mm + print("You've travelled: %.3f mm, ticks: %d" %(mm, pos)) + if(mm >= 100): + break # stop if travelled Xmm + except KeyboardInterrupt: pass #handling keyboard interrupt to stop motors + finally: + # stop motors no matter what + print("STOP") + pi.write(PIN_LEFT_FORWARD, 0) + pi.write(PIN_RIGHT_FORWARD, 0) + decoder_left.cancel() + pi.stop() + time.sleep(.5) # avoiding print spamming diff --git a/test/rotary_encoder_tests/rotary_encoder_original.py b/test/rotary_encoder_tests/rotary_encoder_original.py new file mode 100644 index 00000000..59346bfd --- /dev/null +++ b/test/rotary_encoder_tests/rotary_encoder_original.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python + +import pigpio + +class decoder: + + """Class to decode mechanical rotary encoder pulses.""" + + def __init__(self, pi, gpioA, gpioB, callback): + + """ + Instantiate the class with the pi and gpios connected to + rotary encoder contacts A and B. The common contact + should be connected to ground. The callback is + called when the rotary encoder is turned. It takes + one parameter which is +1 for clockwise and -1 for + counterclockwise. + + EXAMPLE + + import time + import pigpio + + import rotary_encoder + + pos = 0 + + def callback(way): + + global pos + + pos += way + + print("pos={}".format(pos)) + + pi = pigpio.pi() + + decoder = rotary_encoder.decoder(pi, 7, 8, callback) + + time.sleep(300) + + decoder.cancel() + + pi.stop() + + """ + + self.pi = pi + self.gpioA = gpioA + self.gpioB = gpioB + self.callback = callback + + self.levA = 0 + self.levB = 0 + + self.lastGpio = None + + self.pi.set_mode(gpioA, pigpio.INPUT) + self.pi.set_mode(gpioB, pigpio.INPUT) + + self.pi.set_pull_up_down(gpioA, pigpio.PUD_UP) + self.pi.set_pull_up_down(gpioB, pigpio.PUD_UP) + + self.cbA = self.pi.callback(gpioA, pigpio.EITHER_EDGE, self._pulse) + self.cbB = self.pi.callback(gpioB, pigpio.EITHER_EDGE, self._pulse) + + def _pulse(self, gpio, level, tick): + + """ + Decode the rotary encoder pulse. + + +---------+ +---------+ 0 + | | | | + A | | | | + | | | | + +---------+ +---------+ +----- 1 + + +---------+ +---------+ 0 + | | | | + B | | | | + | | | | + ----+ +---------+ +----------+ 1 + """ + + if gpio == self.gpioA: + self.levA = level + else: + self.levB = level + + if gpio != self.lastGpio: # debounce + self.lastGpio = gpio + + if gpio == self.gpioA and level == 1: + if self.levB == 1: + self.callback(1) + elif gpio == self.gpioB and level == 1: + if self.levA == 1: + self.callback(-1) + + def cancel(self): + + """ + Cancel the rotary encoder decoder. + """ + + self.cbA.cancel() + self.cbB.cancel() + + diff --git a/test/rotary_encoder_tests/rotary_encoder_raw_test.py b/test/rotary_encoder_tests/rotary_encoder_raw_test.py new file mode 100644 index 00000000..17f58fa6 --- /dev/null +++ b/test/rotary_encoder_tests/rotary_encoder_raw_test.py @@ -0,0 +1,27 @@ +PIN_ENCODER_LEFT_A = 14 +PIN_ENCODER_LEFT_B = 15 +PIN_ENCODER_RIGHT_A = 24 +PIN_ENCODER_RIGHT_B = 25 + +from time import sleep +import pigpio + +pi = pigpio.pi() + +print("connected") + +pi.set_mode(PIN_ENCODER_LEFT_A, pigpio.INPUT) +pi.set_mode(PIN_ENCODER_LEFT_B, pigpio.INPUT) +pi.set_mode(PIN_ENCODER_RIGHT_A, pigpio.INPUT) +pi.set_mode(PIN_ENCODER_RIGHT_B, pigpio.INPUT) + +pi.set_pull_up_down(PIN_ENCODER_LEFT_A, pigpio.PUD_UP) +pi.set_pull_up_down(PIN_ENCODER_LEFT_B, pigpio.PUD_UP) +pi.set_pull_up_down(PIN_ENCODER_RIGHT_A, pigpio.PUD_UP) +pi.set_pull_up_down(PIN_ENCODER_RIGHT_B, pigpio.PUD_UP) + + +while(True): + print("LEFT: A: %d, B: %d" % (pi.read(PIN_ENCODER_LEFT_A), pi.read(PIN_ENCODER_LEFT_B))) + print("RIGHT: A: %d, B: %d" % (pi.read(PIN_ENCODER_RIGHT_A), pi.read(PIN_ENCODER_RIGHT_B))) + sleep(.05) diff --git a/test/rotary_encoder_tests/rotary_encoder_ticks_test.py b/test/rotary_encoder_tests/rotary_encoder_ticks_test.py new file mode 100644 index 00000000..b86aa64d --- /dev/null +++ b/test/rotary_encoder_tests/rotary_encoder_ticks_test.py @@ -0,0 +1,45 @@ +PIN_ENCODER_LEFT_A = 14 +PIN_ENCODER_LEFT_B = 6 +PIN_ENCODER_RIGHT_A = 15 +PIN_ENCODER_RIGHT_B = 12 + + +if __name__ == "__main__": + + import time + import pigpio + + from rotarydecoder import RotaryDecoder + + pos_left = 0 + pos_right = 0 + + def callback_left(way): + + global pos_left + + pos_left += way + + print("pos_LEFT={}".format(pos_left)) + + def callback_right(way): + + global pos_right + + pos_right += way + + print("pos_RIGHT={}".format(pos_right)) + + + # pi = pigpio.pi('backend.local') + pi = pigpio.pi() + + decoder_left = RotaryDecoder(pi, PIN_ENCODER_LEFT_B, PIN_ENCODER_LEFT_A, callback_left) + decoder_right = RotaryDecoder(pi, PIN_ENCODER_RIGHT_A, PIN_ENCODER_RIGHT_B, callback_right) + + time.sleep(1000) + + decoder_left.cancel() + decoder_right.cancel() + + pi.stop() diff --git a/test/rotary_encoder_tests/rotary_encoder_wheelsAxel_test.py b/test/rotary_encoder_tests/rotary_encoder_wheelsAxel_test.py new file mode 100644 index 00000000..ae962ed5 --- /dev/null +++ b/test/rotary_encoder_tests/rotary_encoder_wheelsAxel_test.py @@ -0,0 +1,43 @@ +from wheelsaxel import WheelsAxel +import pigpio + +# GPIO +# motors +PIN_MOTOR_ENABLE = 22 +PIN_LEFT_FORWARD = 25 +PIN_LEFT_BACKWARD = 24 +PIN_RIGHT_FORWARD = 4 +PIN_RIGHT_BACKWARD = 17 +#? +PIN_PUSHBUTTON = 11 +# servo +PIN_SERVO_3 = 9 +PIN_SERVO_4 = 10 +# sonar +PIN_SONAR_1_TRIGGER = 18 +PIN_SONAR_1_ECHO = 7 +PIN_SONAR_2_TRIGGER = 18 +PIN_SONAR_2_ECHO = 8 +PIN_SONAR_3_TRIGGER = 18 +PIN_SONAR_3_ECHO = 23 +# encoder +PIN_ENCODER_LEFT_A = 14 +PIN_ENCODER_LEFT_B = 6 +PIN_ENCODER_RIGHT_A = 15 +PIN_ENCODER_RIGHT_B = 12 + +pi = pigpio.pi() + +twin_motors_enc = WheelsAxel( + pi, + enable_pin=PIN_MOTOR_ENABLE, + left_forward_pin=PIN_LEFT_FORWARD, + left_backward_pin=PIN_LEFT_BACKWARD, + left_encoder_feedback_pin_A=PIN_ENCODER_LEFT_A, + left_encoder_feedback_pin_B=PIN_ENCODER_LEFT_B, + right_forward_pin=PIN_RIGHT_FORWARD, + right_backward_pin=PIN_RIGHT_BACKWARD, + right_encoder_feedback_pin_A=PIN_ENCODER_RIGHT_A, + right_encoder_feedback_pin_B=PIN_ENCODER_RIGHT_B) + +twin_motors_enc.control_distance(100, 100, 200) \ No newline at end of file diff --git a/test/rotary_encoder_tests/rotarydecoder.py b/test/rotary_encoder_tests/rotarydecoder.py new file mode 100644 index 00000000..34e6b30f --- /dev/null +++ b/test/rotary_encoder_tests/rotarydecoder.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +import pigpio + +class RotaryDecoder: + + """ Class to decode mechanical rotary encoder pulses """ + + def __init__(self, pi, feedback_pin_A, feedback_pin_B, callback): + + self._pi = pi + self._feedback_pin_A = feedback_pin_A # encoder feedback pin A + self._feedback_pin_B = feedback_pin_B # encoder feedback pin B + self._callback = callback # callback function on event + self._direction = 0 # direction, forward = 1, backward = -1, steady = 0 + + self._levelA = 0 # value of encoder feedback pin A + self._levelB = 0 # value of encoder feedback pin B + + # setting up GPIO + self._pi.set_mode(feedback_pin_A, pigpio.INPUT) + self._pi.set_mode(feedback_pin_B, pigpio.INPUT) + self._pi.set_pull_up_down(feedback_pin_A, pigpio.PUD_UP) + self._pi.set_pull_up_down(feedback_pin_B, pigpio.PUD_UP) + + # callback function on EITHER_EDGE for each pin + self._callback_triggerA = self._pi.callback(feedback_pin_A, pigpio.EITHER_EDGE, self._pulse) + self._callback_triggerB = self._pi.callback(feedback_pin_B, pigpio.EITHER_EDGE, self._pulse) + + self._lastGpio = None + + """ pulse is the callback function on EITHER_EDGE + We have two feedback input from pin A and B (two train waves) + it returns a 1 if the square waves have A leading B because we're moving forward + It returns a -1 if the square waves have B leading A because we're moving backwards + In either case, A is staggered from B by (+-)pi/2 radiants + + +---------+ +---------+ 0 + | | | | + A | | | | + | | | | + ----+ +---------+ +----------+ 1 # A leading B + +---------+ +---------+ 0 # forward + | | | | + B | | | | + | | | | + +---------+ +---------+ +----- 1 + """ + def _pulse(self, gpio, level, tick): + # interrupt comes from pin A + if (gpio == self._feedback_pin_A): + self._levelA = level # set level of squared wave (0, 1) on A + # interrupt comes from pin B + else: + self._levelB = level # set level of squared wave (0, 1) on B + + if (gpio != self._lastGpio): # debounce + self._lastGpio = gpio + + if (gpio == self._feedback_pin_A and level == 1): + if (self._levelB == 0): + self._callback(1) # A leading B, moving forward + self._direction = 1 # forward + elif (gpio == self._feedback_pin_A and level == 0): + if (self._levelB == 1): + self._callback(1) # A leading B, moving forward + self._direction = 1 # forward + elif (gpio == self._feedback_pin_B and level == 1): + if (self._levelA == 0): + self._callback(-1) # B leading A, moving forward + self._direction = -1 # backwards + elif (gpio == self._feedback_pin_B and level == 0): + if (self._levelA == 1): + self._callback(-1) # A leading B, moving forward + self._direction = -1 # forward + + def cancel(self): + + """ + Cancel the rotary encoder decoder callbacks. + """ + self._callback_triggerA.cancel() + self._callback_triggerB.cancel() + + diff --git a/test/rotary_encoder_tests/testPID.py b/test/rotary_encoder_tests/testPID.py new file mode 100644 index 00000000..95cf5875 --- /dev/null +++ b/test/rotary_encoder_tests/testPID.py @@ -0,0 +1,7 @@ +from coderbot import CoderBot +import sys + +DISTANCE = float(sys.argv[1]) + +c = CoderBot() +c.move(speed=70, distance=DISTANCE) diff --git a/test/rotary_encoder_tests/velocity_test.py b/test/rotary_encoder_tests/velocity_test.py new file mode 100644 index 00000000..ddd1e028 --- /dev/null +++ b/test/rotary_encoder_tests/velocity_test.py @@ -0,0 +1,15 @@ +from time import sleep +from coderbot import CoderBot + +c = CoderBot.get_instance() + +while(True): + print("Speed: %d" % (c._twin_motors_enc._left_motor._encoder_speed)) + print("Distance: %d" % (c._twin_motors_enc._left_motor._distance)) + print("Start timer: %d" % (c._twin_motors_enc._left_motor._start_timer)) + print("Current timer: %d" % (c._twin_motors_enc._left_motor._current_timer)) + print("Elapse: %d" % (c._twin_motors_enc._left_motor._current_timer - c._twin_motors_enc._left_motor._start_timer)) + print("") + sleep(0.3) + + diff --git a/test/rotary_encoder_tests/velocity_test2.py b/test/rotary_encoder_tests/velocity_test2.py new file mode 100644 index 00000000..86d4babc --- /dev/null +++ b/test/rotary_encoder_tests/velocity_test2.py @@ -0,0 +1,10 @@ +from time import sleep +from motorencoder import MotorEncoder +import pigpio + +pi = pigpio.pi() + +m = MotorEncoder(pi, 22, 25, 24, 14, 16) + +m.control(power=100.0, time_elapse=5) + diff --git a/test/rotary_encoder_tests/velocity_test3.py b/test/rotary_encoder_tests/velocity_test3.py new file mode 100644 index 00000000..5479ed4d --- /dev/null +++ b/test/rotary_encoder_tests/velocity_test3.py @@ -0,0 +1,18 @@ +from time import sleep +from motorencoder import MotorEncoder +import pigpio + +pi = pigpio.pi() + +m = MotorEncoder(pi, 22, 25, 24, 14, 16) + +while(True): + print("Speed: %d" % (m._encoder_speed)) + print("Distance: %d" % (m._distance)) + #print("Start timer: %d" % (c._twin_motors_enc._left_motor._start_timer)) + #print("Current timer: %d" % (c._twin_motors_enc._left_motor._current_timer)) + #print("Elapse: %d" % (c._twin_motors_enc._left_motor._current_timer - c._twin_motors_enc._left_motor._start_timer)) + print("") + sleep(0.05) + + diff --git a/test/test.h264 b/test/test.h264 new file mode 100755 index 00000000..a0add894 Binary files /dev/null and b/test/test.h264 differ diff --git a/test/test_image.jpeg b/test/test_image.jpeg new file mode 100755 index 00000000..00b7edcc Binary files /dev/null and b/test/test_image.jpeg differ diff --git a/translations/it/LC_MESSAGES/messages.mo b/translations/it/LC_MESSAGES/messages.mo deleted file mode 100644 index 62864c1a..00000000 Binary files a/translations/it/LC_MESSAGES/messages.mo and /dev/null differ diff --git a/translations/it/LC_MESSAGES/messages.po b/translations/it/LC_MESSAGES/messages.po deleted file mode 100644 index bd70ca66..00000000 --- a/translations/it/LC_MESSAGES/messages.po +++ /dev/null @@ -1,454 +0,0 @@ -# Italian translations for PROJECT. -# Copyright (C) 2015 ORGANIZATION -# This file is distributed under the same license as the PROJECT project. -# FIRST AUTHOR , 2015. -# -msgid "" -msgstr "" -"Project-Id-Version: PROJECT VERSION\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-04-04 00:32+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: it \n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 1.3\n" - -#: templates/blocks_adv.xml:2 templates/blocks_std.xml:13 -msgid "Logic" -msgstr "Logica" - -#: templates/blocks_adv.xml:11 -msgid "Loops" -msgstr "Cicli" - -#: templates/blocks_adv.xml:40 templates/blocks_std.xml:24 -msgid "Math" -msgstr "Matematica" - -#: templates/blocks_adv.xml:83 templates/blocks_std.xml:29 -msgid "Text" -msgstr "Testo" - -#: templates/blocks_adv.xml:96 templates/blocks_adv.xml:103 -#: templates/blocks_adv.xml:110 -msgid "text" -msgstr "Testo" - -#: templates/blocks_adv.xml:123 -msgid "Lists" -msgstr "Liste" - -#: templates/blocks_adv.xml:138 templates/blocks_adv.xml:145 -#: templates/blocks_adv.xml:152 templates/blocks_adv.xml:159 -msgid "list" -msgstr "lista" - -#: templates/blocks_adv.xml:164 -msgid "Colour" -msgstr "Colore" - -#: templates/blocks_adv.xml:170 templates/blocks_std.xml:19 -msgid "Variables" -msgstr "Variabili" - -#: templates/blocks_adv.xml:171 -msgid "Functions" -msgstr "Funzioni" - -#: templates/blocks_adv.xml:172 templates/blocks_std.xml:35 -#: templates/config.html:15 -msgid "Movement" -msgstr "Movimento" - -#: templates/blocks_adv.xml:229 -msgid "Camera" -msgstr "Camera" - -#: templates/blocks_adv.xml:234 templates/blocks_std.xml:61 -#: templates/config.html:14 -msgid "Sensor" -msgstr "Sensore" - -#: templates/blocks_adv.xml:246 templates/blocks_std.xml:73 -msgid "Sound" -msgstr "Suono" - -#: templates/blocks_std.xml:2 templates/config.html:11 templates/control.html:8 -#: templates/program.html:8 -msgid "Control" -msgstr "Controllo" - -#: templates/config.html:3 templates/control.html:63 -msgid "Back" -msgstr "Indietro" - -#: templates/config.html:12 -msgid "Programming" -msgstr "Programmazione" - -#: templates/config.html:13 -msgid "Sounds" -msgstr "Suoni" - -#: templates/config.html:16 -msgid "Start" -msgstr "Avvio" - -#: templates/config.html:17 -msgid "Button" -msgstr "Bottone" - -#: templates/config.html:18 templates/config.html:127 -msgid "User Interface" -msgstr "Interfaccia utente" - -#: templates/config.html:19 -msgid "WiFi" -msgstr "" - -#: templates/config.html:24 templates/config.html:63 -msgid "Movement assisted by vision" -msgstr "Movimento assistito da visione" - -#: templates/config.html:27 -msgid "Step timing | distance / angle" -msgstr "Durata o lunghezza step (distanza / angolo)" - -#: templates/config.html:28 templates/config.html:66 -msgid "Forward speed" -msgstr "Avanti" - -#: templates/config.html:30 templates/config.html:68 -msgid "Forward elapse / distance" -msgstr "Durata / distanza avanti" - -#: templates/config.html:32 templates/config.html:70 -msgid "Turn speed" -msgstr "Velocità di rotazione" - -#: templates/config.html:34 templates/config.html:72 -msgid "Turn elapse / angle" -msgstr "Tempo / angolo di rotazione" - -#: templates/config.html:37 -msgid "Show control counter" -msgstr "Mostra contatore mosse" - -#: templates/config.html:40 -msgid "HUD image name" -msgstr "Nome immagine HUD" - -#: templates/config.html:45 -msgid "Editor level" -msgstr "Livello editor" - -#: templates/config.html:47 -msgid "Move" -msgstr "Movimento" - -#: templates/config.html:49 -msgid "Basic" -msgstr "Base" - -#: templates/config.html:51 -msgid "Standard" -msgstr "Normale" - -#: templates/config.html:53 -msgid "Advanced" -msgstr "Avanzato" - -#: templates/config.html:56 -msgid "Program editor details" -msgstr "Dettagli editor del programma" - -#: templates/config.html:57 -msgid "Shows Editor scrollbars" -msgstr "Mostra le scrollbar dell'area di lavoro" - -#: templates/config.html:59 -msgid "Save program before every run" -msgstr "Salva il programma prima di ogni esecuzione" - -#: templates/config.html:75 -msgid "Other program parameters" -msgstr "Altri parametri del programma" - -#: templates/config.html:76 -msgid "Auto record video on program run" -msgstr "Avvia automaticamente registrazione video all'avvio del programma" - -#: templates/config.html:79 -msgid "Max number of blocks allowed" -msgstr "Numero massimo consentito di blocchi di programma" - -#: templates/config.html:83 -msgid "Start sound" -msgstr "Suono avvio" - -#: templates/config.html:85 -msgid "Stop sound" -msgstr "Suono stop" - -#: templates/config.html:87 -msgid "Shutter sound" -msgstr "Suono avvio" - -#: templates/config.html:91 -msgid "Camera parameters" -msgstr "Parametri videocamera" - -#: templates/config.html:92 -msgid "Exposure mode" -msgstr "Esposizione" - -#: templates/config.html:103 -msgid "Motor control mode" -msgstr "Tipo di motori (dc | servo)" - -#: templates/config.html:105 -msgid "Power (target angle -15)" -msgstr "Potenza (angolo target -15)" - -#: templates/config.html:107 -msgid "Power (target angle -4)" -msgstr "Potenza (angolo target -4)" - -#: templates/config.html:109 -msgid "Power (target angle -1)" -msgstr "Potenza (angolo target -1)" - -#: templates/config.html:113 -msgid "Load at start" -msgstr "Carica all'avvio" - -#: templates/config.html:118 -msgid "Button function" -msgstr "Funzione del bottone" - -#: templates/config.html:119 -msgid "None" -msgstr "Nessuno" - -#: templates/config.html:121 -msgid "Start/Stop current program" -msgstr "Avvia/Ferma il programma caricato" - -#: templates/config.html:128 -msgid "Show Control page" -msgstr "Mostra pagina Controllo" - -#: templates/config.html:130 -msgid "Show Control movement commands" -msgstr "Mostra comandi movimento in pagina Controllo" - -#: templates/config.html:132 -msgid "Show Program page" -msgstr "Nome programma" - -#: templates/config.html:134 -msgid "Show Preferences button" -msgstr "Mostra bottone Preferenze" - -#: templates/config.html:139 -msgid "WiFi Client access mode" -msgstr "WiFi in modalità Client" - -#: templates/config.html:142 templates/config.html:164 -msgid "Cancel" -msgstr "Annulla" - -#: templates/config.html:143 templates/program.html:18 -#: templates/program.html:26 -msgid "Save" -msgstr "Salva" - -#: templates/config.html:151 -msgid "WiFi Client mode access data" -msgstr "Dati di accesso alla rete WiFi" - -#: templates/config.html:153 -msgid "WiFi mode" -msgstr "Modalità WiFi" - -#: templates/config.html:155 -msgid "Access Point" -msgstr "" - -#: templates/config.html:157 -msgid "Client" -msgstr "" - -#: templates/config.html:159 -msgid "WiFi name" -msgstr "Nome rete WiFi" - -#: templates/config.html:161 -msgid "WiFi password" -msgstr "Password WiFi" - -#: templates/config.html:165 -msgid "Apply Wifi config" -msgstr "Applica le modifiche alla configurazione WiFi" - -#: templates/config.html:172 -msgid "WiFi AP mode access" -msgstr "WiFi in modalità AP" - -#: templates/config.html:184 -msgid "WiFi Client mode access" -msgstr "WiFi in modalità Client" - -#: templates/config_params.html:20 -msgid "Say what:" -msgstr "Frase:" - -#: templates/config_params.html:21 -msgid "Saved" -msgstr "Salvato" - -#: templates/config_params.html:22 -msgid "Program saved" -msgstr "Programma salvato" - -#: templates/config_params.html:23 -msgid "Program name already in use, overwrite?" -msgstr "Esiste già un programma con questo nome, sovrascriverlo?" - -#: templates/config_params.html:24 -msgid "Delete" -msgstr "Cancella" - -#: templates/config_params.html:25 -msgid "Delete photo" -msgstr "Cancellare la foto" - -#: templates/config_params.html:26 -msgid "Reset move counter?" -msgstr "Azzera contatore mosse?" - -#: templates/config_params.html:27 templates/program.html:40 -msgid "is running" -msgstr "in esecuzione" - -#: templates/config_params.html:28 -msgid "stopped" -msgstr "fermo" - -#: templates/config_params.html:29 templates/control.html:51 -#: templates/program.html:32 -msgid "Stop" -msgstr "Ferma" - -#: templates/config_params.html:30 -msgid "Close" -msgstr "Chiudi" - -#: templates/control.html:5 templates/program.html:5 -msgid "Preferences" -msgstr "Preferenze" - -#: templates/control.html:9 templates/program.html:9 -msgid "Program" -msgstr "Programma" - -#: templates/control.html:19 -msgid "Halt" -msgstr "Stop" - -#: templates/control.html:24 -msgid "Forward" -msgstr "Avanti" - -#: templates/control.html:27 -msgid "Left" -msgstr "Sinistra" - -#: templates/control.html:28 -msgid "Right" -msgstr "Destra" - -#: templates/control.html:31 -msgid "Backward" -msgstr "Indietro" - -#: templates/control.html:40 -msgid "Say" -msgstr "Parla" - -#: templates/control.html:45 -msgid "Photo" -msgstr "Foto" - -#: templates/control.html:50 -msgid "Rec" -msgstr "Registra" - -#: templates/control.html:54 -msgid "Photos" -msgstr "Album" - -#: templates/program.html:16 templates/program.html:24 -msgid "New" -msgstr "Nuovo" - -#: templates/program.html:17 templates/program.html:25 -msgid "Load" -msgstr "Carica" - -#: templates/program.html:19 templates/program.html:31 -msgid "Run" -msgstr "Esegui" - -#: templates/program.html:20 -msgid "Show last" -msgstr "Mostra ultimo" - -#: templates/program.html:27 -msgid "Save as" -msgstr "Salva come" - -#: templates/program.html:30 -msgid "Show" -msgstr "Mostra codice" - -#: templates/program.html:51 -msgid "New Program" -msgstr "Nuovo programma" - -#: templates/program.html:52 templates/program.html:53 -#: templates/program.html:60 templates/program.html:61 -msgid "Program name" -msgstr "Nome programma" - -#: templates/program.html:54 templates/program.html:62 -msgid "Create" -msgstr "Crea" - -#: templates/program.html:59 -msgid "Save Program As" -msgstr "Nuovo programma" - -#: templates/program.html:67 -msgid "Load Program" -msgstr "Carica programma" - -#~ msgid "Control mode" -#~ msgstr "Tipo di motori (dc | servo)" - -#~ msgid "Move counter" -#~ msgstr "Contatore mosse" - -#~ msgid "Forward elapse" -#~ msgstr "Durata avanti" - -#~ msgid "Turn elapse" -#~ msgstr "Tempo di rotazione" - -#~ msgid "Procedures" -#~ msgstr "Procedure" - diff --git a/viz/blob.py b/viz/blob.py deleted file mode 100644 index 92513e7b..00000000 --- a/viz/blob.py +++ /dev/null @@ -1,33 +0,0 @@ -import cv2 - -class Blob(): - - def __init__(self, contour): - self._contour = contour - - @property - def bottom(self): - return self._contour[self._contour[:,:,1].argmax()][0][1] - - @property - def top(self): - return self._contour[self._contour[:,:,1].argmin()][0][1] - - @property - def left(self): - return self._contour[self._contour[:,:,0].argmin()][0][0] - - @property - def right(self): - return self._contour[self._contour[:,:,0].argmax()][0][0] - - @property - def center(self): - return ((self.right + self.left) / 2, (self.top + self.bottom) / 2) - - def area(self): - return cv2.contourArea(self._contour) - - @classmethod - def sort_distance(cls, point, blobs): - return sorted(blobs, key=lambda blob: (point[0] - blob.bottom)) diff --git a/viz/camera.py b/viz/camera.py deleted file mode 100644 index 54fc8fda..00000000 --- a/viz/camera.py +++ /dev/null @@ -1,165 +0,0 @@ -import picamera -import picamera.array -import io -import os -import time -import copy -import logging - -class Camera(): - - FFMPEG_CMD = 'MP4Box' - PHOTO_FILE_EXT = ".jpg" - VIDEO_FILE_EXT = ".mp4" - VIDEO_FILE_EXT_H264 = '.h264' - - def __init__(self, props): - logging.info("camera init") - self.camera = picamera.PiCamera() - self.camera.resolution = (props.get('width', 640), props.get('height', 240)) - self.camera.framerate = 30 - self.camera.exposure_mode = props.get('exposure_mode') - self.out_jpeg = io.BytesIO() - self.out_rgb = picamera.array.PiRGBArray(self.camera, size=(160,120)) - self.h264_encoder = None - self.recording = None - self.video_filename = None - - def video_rec(self, filename): - self.video_filename = filename[:filename.rfind(".")] - - camera_port_2, output_port_2 = self.camera._get_ports(True, 2) - self.h264_encoder = self.camera._get_video_encoder(camera_port_2, output_port_2, 'h264', None) - - with self.camera._encoders_lock: - self.camera._encoders[2] = self.h264_encoder - - logging.debug( self.video_filename + self.VIDEO_FILE_EXT_H264 ) - - self.h264_encoder.start(self.video_filename + self.VIDEO_FILE_EXT_H264) - - def video_stop(self): - logging.debug("video_stop") - self.h264_encoder.stop() - - with self.camera._encoders_lock: - del self.camera._encoders[2] - - self.h264_encoder.close() - - # pack in mp4 container - params = " -fps 12 -add " + self.video_filename + self.VIDEO_FILE_EXT_H264 + " " + self.video_filename + self.VIDEO_FILE_EXT - #avconv_params = " -r 30 -i " + self.video_filename + self.VIDEO_FILE_EXT_H264 + " -vcodec copy " + self.video_filename + self.VIDEO_FILE_EXT - os.system(self.FFMPEG_CMD + params) - # remove h264 file - os.remove(self.video_filename + self.VIDEO_FILE_EXT_H264) - - def grab(self): - ts = time.time() - camera_port_0, output_port_0 = self.camera._get_ports(True, 0) - self.jpeg_encoder = self.camera._get_image_encoder(camera_port_0, output_port_0, 'jpeg', None, quality=40) - camera_port_1, output_port_1 = self.camera._get_ports(True, 1) - self.rgb_encoder = self.camera._get_image_encoder(camera_port_1, output_port_1, 'bgr', (160, 120)) - #print "g.1: " + str(ts - time.time()) - #ts = time.time() - - with self.camera._encoders_lock: - self.camera._encoders[0] = self.jpeg_encoder - self.camera._encoders[1] = self.rgb_encoder - - #print "g.2: " + str(ts - time.time()) - #ts = time.time() - - self.out_jpeg.seek(0) - self.out_rgb.seek(0) - - self.jpeg_encoder.start(self.out_jpeg) - self.rgb_encoder.start(self.out_rgb) - - #print "g.3: " + str(ts - time.time()) - #ts = time.time() - - if not self.jpeg_encoder.wait(10): - raise picamera.PiCameraError('Timed out') - if not self.rgb_encoder.wait(10): - raise picamera.PiCameraError('Timed out') - - #print "g.4: " + str(ts - time.time()) - #ts = time.time() - - with self.camera._encoders_lock: - del self.camera._encoders[0] - del self.camera._encoders[1] - self.jpeg_encoder.close() - self.rgb_encoder.close() - - #print "g.5: " + str(ts - time.time()) - - def grab_start(self): - logging.debug("grab_start") - - #ts = time.time() - camera_port_0, output_port_0 = self.camera._get_ports(True, 0) - self.jpeg_encoder = self.camera._get_image_encoder(camera_port_0, output_port_0, 'jpeg', None, quality=40) - camera_port_1, output_port_1 = self.camera._get_ports(True, 1) - self.rgb_encoder = self.camera._get_image_encoder(camera_port_1, output_port_1, 'bgr', (160, 120)) - - with self.camera._encoders_lock: - self.camera._encoders[0] = self.jpeg_encoder - self.camera._encoders[1] = self.rgb_encoder - - def grab_one(self): - self.out_jpeg.seek(0) - self.out_rgb.seek(0) - - self.jpeg_encoder.start(self.out_jpeg) - self.rgb_encoder.start(self.out_rgb) - - if not self.jpeg_encoder.wait(10): - raise picamera.PiCameraError('Timed out') - if not self.rgb_encoder.wait(10): - raise picamera.PiCameraError('Timed out') - - def grab_stop(self): - logging.debug("grab_stop") - - with self.camera._encoders_lock: - del self.camera._encoders[0] - del self.camera._encoders[1] - - self.jpeg_encoder.close() - self.rgb_encoder.close() - - def get_image_jpeg(self): - return self.out_jpeg.getvalue() - - def get_image_bgr(self): - return self.out_rgb.array - - def grab_jpeg(self): - ts = time.time() - self.out_jpeg.seek(0) - - self.jpeg_encoder.start(self.out_jpeg) - - if not self.jpeg_encoder.wait(10): - raise picamera.PiCameraError('Timed out') - - #print time.time() - ts - - def grab_bgr(self): - ts = time.time() - self.out_rgb.seek(0) - - self.rgb_encoder.start(self.out_rgb) - - if not self.rgb_encoder.wait(10): - raise picamera.PiCameraError('Timed out') - - #print time.time() - ts - - def set_overlay_text(self, text): - self.camera.annotate_text = text - - def close(self): - self.camera.close() diff --git a/viz/image.py b/viz/image.py deleted file mode 100644 index 09855e18..00000000 --- a/viz/image.py +++ /dev/null @@ -1,151 +0,0 @@ -import numpy as np -import cv2 -import colorsys -import copy -import blob -import logging - -r_from = np.float32([[0, 0], [160, 0], [160, 120], [0, 120]]) -r_dest = np.float32([[0, -30], [160, -30], [95, 120], [65, 120]]) -MIN_MATCH_COUNT = 10 - -class Image(): - #_face_cascade = cv2.CascadeClassifier('/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml') - _face_cascade = cv2.CascadeClassifier('/usr/local/share/OpenCV/lbpcascades/lbpcascade_frontalface.xml') - _kernel = np.ones((3,3),np.uint8) - - def __init__(self, array): - self._data = array - - @classmethod - def load(cls, filename): - return Image(cv2.imread(filename)) - - def resize(self, width, heigth): - return Image(cv2.resize(self._data, (width, heigth))) - - def crop(self, x1, y1, x2, y2): - return Image(self._data[y1:y2,x1:x2]) - - def warp(self, r_from, r_dest): - tx = cv2.getPerspectiveTransform(r_from, r_dest) - dest = cv2.warpPerspective(self._data, tx, (640,480)) - return Image(dest) - - @classmethod - def transform(cls, vector): - tx = cv2.getPerspectiveTransform(r_from, r_dest) - v = np.array(vector, dtype='float32') - v = np.array([v]) - dest = cv2.perspectiveTransform(v, tx) - return dest[0] - - def find_faces(self): - faces = self._face_cascade.detectMultiScale(self._data) - return faces - - def filter_color(self, color): - h, s, v = colorsys.rgb_to_hsv(color[0]/255.0, color[1]/255.0, color[2]/255.0) - image_hsv = cv2.cvtColor(self._data, cv2.COLOR_BGR2HSV) - h = h * 180 - s = s * 255 - v = v * 255 - logging.debug("color_hsv: " + str(h) + " " + str(s) + " " + str(v)) - #lower_color = np.array([h-10 if h>=10 else 0.0, 0, 0]) - #upper_color = np.array([h+10 if h<=170 else 179.0, 255, 255]) - lower_color = np.array([h-10, 50, 50]) - upper_color = np.array([h+10, 255, 255]) - logging.debug("lower: " + str(lower_color) + " upper: " + str(upper_color)) - mask = cv2.inRange(image_hsv, lower_color, upper_color) - return Image(mask) - - def dilate(self): - data = cv2.dilate(self._datai, self._kernel) - return Image(data) - - def erode(self): - data = cv2.erode(self._data, self._kernel) - return Image(data) - - def open(self): - data = cv2.morphologyEx(self._data, cv2.MORPH_OPEN, self._kernel) - return Image(data) - - def close(self): - data = cv2.morphologyEx(self._data, cv2.MORPH_CLOSE, self._kernel) - return Image(data) - - def grayscale(self): - data = cv2.cvtColor(self._data, cv2.cv.CV_BGR2GRAY) - return Image(data) - - def invert(self): - data = cv2.bitwise_not(self._data) - return Image(data) - - def binarize(self): - data = cv2.cvtColor(self._data, cv2.cv.CV_BGR2GRAY) - data = cv2.adaptiveThreshold(data, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 5, 3) - return Image(data) - - def find_blobs(self, minsize=0, maxsize=10000000): - blobs = [] - contours, hyerarchy = cv2.findContours(self._data, cv2.cv.CV_RETR_TREE, cv2.cv.CV_CHAIN_APPROX_SIMPLE) - for c in contours: - area = cv2.contourArea(c) - if area > minsize and area < maxsize: - if len(blobs) and area > blobs[0].area: - blobs.insert(0, blob.Blob(c)) - else: - blobs.append(blob.Blob(c)) - - return blobs - - def find_template(self, img_template): - # Initiate SIFT detector - sift = cv2.SIFT() - - # find the keypoints and descriptors with SIFT - kp1, des1 = sift.detectAndCompute(img_template._data,None) - kp2, des2 = sift.detectAndCompute(self._data,None) - - FLANN_INDEX_KDTREE = 0 - index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) - search_params = dict(checks = 50) - - flann = cv2.FlannBasedMatcher(index_params, search_params) - - matches = flann.knnMatch(des1,des2,k=2) - - # store all the good matches as per Lowe's ratio test. - good = [] - templates = [] - for m,n in matches: - if m.distance < 0.7*n.distance: - good.append(m) - - if len(good) > MIN_MATCH_COUNT: - src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2) - dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2) - - M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0) - matchesMask = mask.ravel().tolist() - - h,w = img_template.shape - pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2) - dst = cv2.perspectiveTransform(pts,M) - logging.info("found template: " + dst) - templates[0] = dst - - else: - logging.info( "Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT)) - matchesMask = None - - return templates - - - def to_jpeg(self): - ret, jpeg_array = cv2.imencode('.jpeg', self._data) - return np.array(jpeg_array).tostring() - - diff --git a/viz/streamer.py b/viz/streamer.py deleted file mode 100644 index 0ff3250f..00000000 --- a/viz/streamer.py +++ /dev/null @@ -1,160 +0,0 @@ -from SimpleHTTPServer import SimpleHTTPRequestHandler -from SocketServer import ThreadingMixIn, TCPServer -import threading -import time -import re -import socket -import numpy as np -import cv2 -import colorsys -import camera as cam -import copy - -_jpegstreamers = {} -class JpegStreamHandler(SimpleHTTPRequestHandler): - """ - The JpegStreamHandler handles requests to the threaded HTTP server. - Once initialized, any request to this port will receive a multipart/replace - jpeg. - """ - - - def do_GET(self): - global _jpegstreamers - - - if (self.path == "/" or not self.path): - - - self.send_response(200) - self.send_header('Content-type', 'text/html') - self.end_headers() - self.wfile.write(""" - - - - - -  - - - """) - return - - - elif (self.path == "/stream"): - self.send_response(200) - #self.send_header("Connection", "close") - self.send_header("Max-Age", "0") - self.send_header("Expires", "0") - self.send_header("Cache-Control", "no-cache, private") - self.send_header("Pragma", "no-cache") - self.send_header("Content-Type", "multipart/x-mixed-replace; boundary=--BOUNDARYSTRING") - self.end_headers() - (host, port) = self.server.socket.getsockname()[:2] - - - count = 0 - timeout = 0.75 - lasttimeserved = 0 - while (1): - if True: #(_jpegstreamers[port].refreshtime > lasttimeserved or time.time() - timeout > lasttimeserved): - try: - self.wfile.write("--BOUNDARYSTRING\r\n") - self.send_header("Content-type", "image/jpeg") - self.send_header("Content-Length", str(len(_jpegstreamers[port].jpgdata))) - self.end_headers() - #_jpegstreamers[port]._lock.acquire() - self.wfile.write(_jpegstreamers[port].jpgdata) - #_jpegstreamers[port]._lock.release() - self.wfile.write("\r\n") - lasttimeserved = time.time() - except socket.error, e: - print "send_response socket.error: " + str(e) - return - except IOError, e: - print "send_response generic IOError: " + str(e) - return - count = count + 1 - - - time.sleep(_jpegstreamers[port].sleeptime) - - - - -class JpegTCPServer(ThreadingMixIn, TCPServer): - allow_reuse_address = True - daemon_threads = True - - -#factory class for jpegtcpservers -class JpegStreamer(): - """ - The JpegStreamer class allows the user to stream a jpeg encoded file - to a HTTP port. Any updates to the jpg file will automatically be pushed - to the browser via multipart/replace content type. - To initialize: - js = JpegStreamer() - to update: - img.save(js) - to open a browser and display: - import webbrowser - webbrowser.open(js.url) - Note 3 optional parameters on the constructor: - - port (default 8080) which sets the TCP port you need to connect to - - sleep time (default 0.1) how often to update. Above 1 second seems to cause dropped connections in Google chrome - Once initialized, the buffer and sleeptime can be modified and will function properly -- port will not. - """ - server = "" - host = "" - port = "" - sleeptime = "" - framebuffer = "" - counter = 0 - refreshtime = 0 - _lock = threading.Lock() - - def __init__(self, hostandport = 8080, st=0.1): - global _jpegstreamers - if (type(hostandport) == int): - self.port = hostandport - self.host = "localhost" - elif (isinstance(hostandport, basestring) and re.search(":", hostandport)): - (self.host, self.port) = hostandport.split(":") - self.port = int(self.port) - elif (type(hostandport) == tuple): - (self.host, self.port) = hostandport - - self.jpgdata = [] - self.sleeptime = st - self.server = JpegTCPServer((self.host, self.port), JpegStreamHandler) - self.server_thread = threading.Thread(target = self.server.serve_forever) - _jpegstreamers[self.port] = self - - self.server_thread.daemon = True - self.server_thread.start() - self.framebuffer = self #self referential, ugh. but gives some bkcompat - - - def url(https://github.com/self): - """ - Returns the JpegStreams Webbrowser-appropriate URL, if not provided in the constructor, it defaults to "http://localhost:8080/" - """ - return "http://" + self.host + ":" + str(self.port) + "/" - - - def streamUrl(self): - """ - Returns the URL of the MJPEG stream. If host and port are not set in the constructor, defaults to "http://localhost:8080/stream/" - """ - return self.url() + "stream" - - def set_image(self, image): - _jpegstreamers[self.port]._lock.acquire() - _jpegstreamers[self.port].jpgdata = copy.copy(image) - _jpegstreamers[self.port]._lock.release() - - diff --git a/wifi.py b/wifi.py deleted file mode 100755 index aa9c2610..00000000 --- a/wifi.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/python - -import socket -import subprocess -import shutil -import sys -import os -import urllib2 -import fcntl -import struct -import json - -class WiFi(): - - CONFIG_FILE = "/etc/coderbot_wifi.conf" - adapters = ["RT5370", "RTL8188CUS"] - hostapds = {"RT5370": "hostapd.RT5370", "RTL8188CUS": "hostapd.RTL8188"} - web_url = "http://coderbotsrv.appspot.com/register_ip" - wifi_client_conf_file = "/etc/wpa_supplicant/wpa_supplicant.conf" - _config = {} - - @classmethod - def load_config(cls): - f = open(cls.CONFIG_FILE) - cls._config = json.load(f) - return cls._config - - @classmethod - def save_config(cls): - f = open(cls.CONFIG_FILE, 'w') - json.dump(cls._config, f) - return cls._config - - @classmethod - def get_config(cls): - return cls._config - - @classmethod - def get_adapter_type(cls): - lsusb_out = subprocess.check_output("lsusb") - for a in cls.adapters: - if a in lsusb_out: - return a - return None - - @classmethod - def start_hostapd(cls): - adapter = cls.get_adapter_type() - hostapd_type = cls.hostapds.get(adapter) - try: - print "starting hostapd..." - #os.system("start-stop-daemon --start --oknodo --quiet --exec /usr/sbin/" + hostapd_type + " -- /etc/hostapd/" + hostapd_type + " &") - os.system("/usr/sbin/" + hostapd_type + " /etc/hostapd/" + hostapd_type + " -B") - - except subprocess.CalledProcessError as e: - print e.output - - @classmethod - def stop_hostapd(cls): - try: - out = subprocess.check_output(["pkill", "-9", "hostapd"]) - print out - except subprocess.CalledProcessError as e: - print e.output - - @classmethod - def get_ipaddr(cls, ifname): - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - return socket.inet_ntoa(fcntl.ioctl( - s.fileno(), - 0x8915, # SIOCGIFADDR - struct.pack('256s', ifname[:15]) - )[20:24]) - ipaddr = socket.gethostbyname(socket.gethostname()) - return ipaddr - - @classmethod - def register_ipaddr(cls, ipaddr, botname): - try: - ret = urllib2.urlopen(cls.web_url + "?name=" + botname + "&ipaddr=" + ipaddr) - print str(ret.getcode()) - if ret.getcode() != 200: - raise Exception() - except URLError as e: - print e - raise - print botname, ": ", ipaddr - - @classmethod - def get_wlans(cls): - out = subprocess.check_output(["iwlist", "wlan0", "scan"]) - - @classmethod - def set_client_params(cls, wssid, wpsk): - f = open (cls.wifi_client_conf_file, "w+") - f.write("""ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev -update_config=1 -network={\n""") - f.write(" ssid=\""+wssid+"\"\n") - f.write(" psk=\""+wpsk+"\"\n") - f.write("}") - - @classmethod - def set_start_as_client(cls): - shutil.copy("/etc/network/interfaces_cli", "/etc/network/interfaces") - cls._config["wifi_mode"] = "client" - cls.save_config() - - @classmethod - def start_as_client(cls): - cls.stop_hostapd() - try: - out = subprocess.check_output(["ifdown", "wlan0"]) - out = subprocess.check_output(["ifup", "wlan0"]) - print "registering ip..." - cls.register_ipaddr(cls.get_ipaddr("wlan0"), "CoderBot") - except subprocess.CalledProcessError as e: - print e.output - raise - - @classmethod - def set_start_as_ap(cls): - shutil.copy("/etc/network/interfaces_ap", "/etc/network/interfaces") - cls._config["wifi_mode"] = "ap" - cls.save_config() - - @classmethod - def start_as_ap(cls): - out = subprocess.check_output(["ifdown", "wlan0"]) - out = subprocess.check_output(["ifup", "wlan0"]) - cls.start_hostapd() - - @classmethod - def start_service(cls): - config = cls.load_config() - if config["wifi_mode"] == "ap": - print "starting as ap..." - cls.start_as_ap() - elif config["wifi_mode"] == "client": - print "starting as client..." - try: - cls.start_as_client() - except: - print "Unable to register ip, revert to ap mode" - cls.start_as_ap() - -def main(): - w = WiFi() - if len(sys.argv) > 2 and sys.argv[1] == "updatecfg": - if len(sys.argv) > 2 and sys.argv[2] == "ap": - w.set_start_as_ap() - w.start_as_ap() - elif len(sys.argv) > 2 and sys.argv[2] == "client": - if len(sys.argv) > 3: - w.set_client_params(sys.argv[3], sys.argv[4]) - w.set_start_as_client() - w.stop_hostapd() - try: - w.start_as_client() - except: - print "Unable to register ip, revert to ap mode" - w.start_as_ap() - else: - w.start_service() - -if __name__ == "__main__": - main() -